blob: 5280ff375e72b8ffb4208516a5d6a8e76e2f8f11 [file] [log] [blame]
Joe Onorato7add83b2011-08-30 17:24:17 -07001#include "generate_java.h"
2#include "Type.h"
3#include <string.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7
Joe Onorato9a782242011-10-23 15:15:27 -07008Type* ANDROID_CONTEXT_TYPE = new Type("android.content",
Manuel Roman2c5eb262011-10-06 10:28:35 -07009 "Context", Type::BUILT_IN, false, false, false);
Joe Onorato0c861962011-12-11 20:42:33 -080010Type* PRESENTER_BASE_TYPE = new Type("android.support.place.connector",
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -070011 "EventListener", Type::BUILT_IN, false, false, false);
Joe Onorato0c861962011-12-11 20:42:33 -080012Type* PRESENTER_LISTENER_BASE_TYPE = new Type("android.support.place.connector",
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -070013 "EventListener.Listener", Type::BUILT_IN, false, false, false);
Joe Onorato0c861962011-12-11 20:42:33 -080014Type* RPC_BROKER_TYPE = new Type("android.support.place.connector", "Broker",
Joe Onoratoe415ecb2011-09-23 15:17:52 -070015 Type::BUILT_IN, false, false, false);
Joe Onorato0d2a6b62011-10-09 21:51:46 -070016// TODO: Just use Endpoint, so this works for all endpoints.
Joe Onorato0c861962011-12-11 20:42:33 -080017Type* RPC_CONNECTOR_TYPE = new Type("android.support.place.connector", "Connector",
Joe Onorato0d2a6b62011-10-09 21:51:46 -070018 Type::BUILT_IN, false, false, false);
Joe Onorato0c861962011-12-11 20:42:33 -080019Type* RPC_ENDPOINT_INFO_TYPE = new UserDataType("android.support.place.rpc",
Joe Onorato0d2a6b62011-10-09 21:51:46 -070020 "EndpointInfo", true, __FILE__, __LINE__);
Joe Onorato0c861962011-12-11 20:42:33 -080021Type* RPC_RESULT_HANDLER_TYPE = new UserDataType("android.support.place.rpc", "RpcResultHandler",
Joe Onoratoe415ecb2011-09-23 15:17:52 -070022 true, __FILE__, __LINE__);
Joe Onorato0c861962011-12-11 20:42:33 -080023Type* RPC_ERROR_LISTENER_TYPE = new Type("android.support.place.rpc", "RpcErrorHandler",
Joe Onoratoe415ecb2011-09-23 15:17:52 -070024 Type::BUILT_IN, false, false, false);
Joe Onorato0c861962011-12-11 20:42:33 -080025Type* RPC_CONTEXT_TYPE = new UserDataType("android.support.place.rpc", "RpcContext", true,
Manuel Roman2c5eb262011-10-06 10:28:35 -070026 __FILE__, __LINE__);
Joe Onoratoe415ecb2011-09-23 15:17:52 -070027
28static void generate_create_from_data(Type* t, StatementBlock* addTo, const string& key,
29 Variable* v, Variable* data, Variable** cl);
30static void generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from);
31static void generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v,
32 Variable* data);
Joe Onorato7add83b2011-08-30 17:24:17 -070033
34static string
35format_int(int n)
36{
37 char str[20];
38 sprintf(str, "%d", n);
39 return string(str);
40}
41
42static string
43class_name_leaf(const string& str)
44{
45 string::size_type pos = str.rfind('.');
46 if (pos == string::npos) {
47 return str;
48 } else {
49 return string(str, pos+1);
50 }
51}
52
Joe Onoratoe415ecb2011-09-23 15:17:52 -070053static string
54results_class_name(const string& n)
55{
56 string str = n;
57 str[0] = toupper(str[0]);
58 str.insert(0, "On");
59 return str;
60}
61
62static string
63results_method_name(const string& n)
64{
65 string str = n;
66 str[0] = toupper(str[0]);
67 str.insert(0, "on");
68 return str;
69}
70
71static string
72push_method_name(const string& n)
73{
74 string str = n;
75 str[0] = toupper(str[0]);
76 str.insert(0, "push");
77 return str;
78}
79
80// =================================================
81class DispatcherClass : public Class
82{
83public:
84 DispatcherClass(const interface_type* iface, Expression* target);
85 virtual ~DispatcherClass();
86
87 void AddMethod(const method_type* method);
88 void DoneWithMethods();
89
90 Method* processMethod;
91 Variable* actionParam;
92 Variable* requestParam;
Manuel Roman2c5eb262011-10-06 10:28:35 -070093 Variable* rpcContextParam;
Joe Onoratoe415ecb2011-09-23 15:17:52 -070094 Variable* errorParam;
95 Variable* requestData;
96 Variable* resultData;
97 IfStatement* dispatchIfStatement;
98 Expression* targetExpression;
99
100private:
101 void generate_process();
102};
103
104DispatcherClass::DispatcherClass(const interface_type* iface, Expression* target)
105 :Class(),
106 dispatchIfStatement(NULL),
107 targetExpression(target)
108{
109 generate_process();
110}
111
112DispatcherClass::~DispatcherClass()
113{
114}
115
116void
117DispatcherClass::generate_process()
118{
Manuel Roman2c5eb262011-10-06 10:28:35 -0700119 // byte[] process(String action, byte[] params, RpcContext context, RpcError status)
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700120 this->processMethod = new Method;
121 this->processMethod->modifiers = PUBLIC;
122 this->processMethod->returnType = BYTE_TYPE;
123 this->processMethod->returnTypeDimension = 1;
124 this->processMethod->name = "process";
125 this->processMethod->statements = new StatementBlock;
126
127 this->actionParam = new Variable(STRING_TYPE, "action");
128 this->processMethod->parameters.push_back(this->actionParam);
129
130 this->requestParam = new Variable(BYTE_TYPE, "requestParam", 1);
131 this->processMethod->parameters.push_back(this->requestParam);
132
Manuel Roman2c5eb262011-10-06 10:28:35 -0700133 this->rpcContextParam = new Variable(RPC_CONTEXT_TYPE, "context", 0);
134 this->processMethod->parameters.push_back(this->rpcContextParam);
135
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700136 this->errorParam = new Variable(RPC_ERROR_TYPE, "errorParam", 0);
137 this->processMethod->parameters.push_back(this->errorParam);
138
139 this->requestData = new Variable(RPC_DATA_TYPE, "request");
140 this->processMethod->statements->Add(new VariableDeclaration(requestData,
141 new NewExpression(RPC_DATA_TYPE, 1, this->requestParam)));
142
143 this->resultData = new Variable(RPC_DATA_TYPE, "resultData");
144 this->processMethod->statements->Add(new VariableDeclaration(this->resultData,
145 NULL_VALUE));
146}
147
148void
149DispatcherClass::AddMethod(const method_type* method)
150{
151 arg_type* arg;
152
153 // The if/switch statement
154 IfStatement* ifs = new IfStatement();
155 ifs->expression = new MethodCall(new StringLiteralExpression(method->name.data), "equals",
156 1, this->actionParam);
157 StatementBlock* block = ifs->statements = new StatementBlock;
158 if (this->dispatchIfStatement == NULL) {
159 this->dispatchIfStatement = ifs;
160 this->processMethod->statements->Add(dispatchIfStatement);
161 } else {
162 this->dispatchIfStatement->elseif = ifs;
163 this->dispatchIfStatement = ifs;
164 }
165
166 // The call to decl (from above)
167 MethodCall* realCall = new MethodCall(this->targetExpression, method->name.data);
168
169 // args
170 Variable* classLoader = NULL;
171 VariableFactory stubArgs("_arg");
172 arg = method->args;
173 while (arg != NULL) {
174 Type* t = NAMES.Search(arg->type.type.data);
175 Variable* v = stubArgs.Get(t);
176 v->dimension = arg->type.dimension;
177
178 // Unmarshall the parameter
179 block->Add(new VariableDeclaration(v));
180 if (convert_direction(arg->direction.data) & IN_PARAMETER) {
181 generate_create_from_data(t, block, arg->name.data, v,
182 this->requestData, &classLoader);
183 } else {
184 if (arg->type.dimension == 0) {
185 block->Add(new Assignment(v, new NewExpression(v->type)));
186 }
187 else if (arg->type.dimension == 1) {
188 generate_new_array(v->type, block, v, this->requestData);
189 }
190 else {
191 fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__,
192 __LINE__);
193 }
194 }
195
196 // Add that parameter to the method call
197 realCall->arguments.push_back(v);
198
199 arg = arg->next;
200 }
201
Manuel Roman2c5eb262011-10-06 10:28:35 -0700202 // Add a final parameter: RpcContext. Contains data about
203 // incoming request (e.g., certificate)
204 realCall->arguments.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700205
206 Type* returnType = NAMES.Search(method->type.type.data);
207 if (returnType == EVENT_FAKE_TYPE) {
208 returnType = VOID_TYPE;
209 }
210
211 // the real call
212 bool first = true;
213 Variable* _result = NULL;
214 if (returnType == VOID_TYPE) {
215 block->Add(realCall);
216 } else {
217 _result = new Variable(returnType, "_result",
218 method->type.dimension);
219 block->Add(new VariableDeclaration(_result, realCall));
220
221 // need the result RpcData
222 if (first) {
223 block->Add(new Assignment(this->resultData,
224 new NewExpression(RPC_DATA_TYPE)));
225 first = false;
226 }
227
228 // marshall the return value
229 generate_write_to_data(returnType, block,
230 new StringLiteralExpression("_result"), _result, this->resultData);
231 }
232
233 // out parameters
234 int i = 0;
235 arg = method->args;
236 while (arg != NULL) {
237 Type* t = NAMES.Search(arg->type.type.data);
238 Variable* v = stubArgs.Get(i++);
239
240 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
241 // need the result RpcData
242 if (first) {
243 block->Add(new Assignment(this->resultData, new NewExpression(RPC_DATA_TYPE)));
244 first = false;
245 }
246
247 generate_write_to_data(t, block, new StringLiteralExpression(arg->name.data),
248 v, this->resultData);
249 }
250
251 arg = arg->next;
252 }
253}
254
255void
256DispatcherClass::DoneWithMethods()
257{
258 if (this->dispatchIfStatement == NULL) {
259 return;
260 }
261
262 this->elements.push_back(this->processMethod);
263
264 IfStatement* fallthrough = new IfStatement();
265 fallthrough->statements = new StatementBlock;
266 fallthrough->statements->Add(new ReturnStatement(
Manuel Roman2c5eb262011-10-06 10:28:35 -0700267 new MethodCall(SUPER_VALUE, "process", 4,
268 this->actionParam, this->requestParam,
269 this->rpcContextParam,
270 this->errorParam)));
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700271 this->dispatchIfStatement->elseif = fallthrough;
272 IfStatement* s = new IfStatement;
273 s->statements = new StatementBlock;
274 this->processMethod->statements->Add(s);
275 s->expression = new Comparison(this->resultData, "!=", NULL_VALUE);
276 s->statements->Add(new ReturnStatement(new MethodCall(this->resultData, "serialize")));
277 s->elseif = new IfStatement;
278 s = s->elseif;
279 s->statements->Add(new ReturnStatement(NULL_VALUE));
280}
281
Joe Onorato7add83b2011-08-30 17:24:17 -0700282// =================================================
283class RpcProxyClass : public Class
284{
285public:
286 RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType);
287 virtual ~RpcProxyClass();
288
289 Variable* endpoint;
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700290 Variable* broker;
Joe Onorato7add83b2011-08-30 17:24:17 -0700291
292private:
293 void generate_ctor();
Jason Simmons20e0cef2011-12-16 16:14:17 -0800294 void generate_get_endpoint_info();
Joe Onorato7add83b2011-08-30 17:24:17 -0700295};
296
297RpcProxyClass::RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType)
298 :Class()
299{
300 this->comment = gather_comments(iface->comments_token->extra);
301 this->modifiers = PUBLIC;
302 this->what = Class::CLASS;
303 this->type = interfaceType;
304
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700305 // broker
306 this->broker = new Variable(RPC_BROKER_TYPE, "_broker");
307 this->elements.push_back(new Field(PRIVATE, this->broker));
Joe Onorato7add83b2011-08-30 17:24:17 -0700308 // endpoint
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700309 this->endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "_endpoint");
Joe Onorato7add83b2011-08-30 17:24:17 -0700310 this->elements.push_back(new Field(PRIVATE, this->endpoint));
311
312 // methods
313 generate_ctor();
Jason Simmons20e0cef2011-12-16 16:14:17 -0800314 generate_get_endpoint_info();
Joe Onorato7add83b2011-08-30 17:24:17 -0700315}
316
317RpcProxyClass::~RpcProxyClass()
318{
319}
320
321void
322RpcProxyClass::generate_ctor()
323{
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700324 Variable* broker = new Variable(RPC_BROKER_TYPE, "broker");
325 Variable* endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "endpoint");
Joe Onorato7add83b2011-08-30 17:24:17 -0700326 Method* ctor = new Method;
327 ctor->modifiers = PUBLIC;
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700328 ctor->name = class_name_leaf(this->type->Name());
Joe Onorato7add83b2011-08-30 17:24:17 -0700329 ctor->statements = new StatementBlock;
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700330 ctor->parameters.push_back(broker);
Joe Onorato7add83b2011-08-30 17:24:17 -0700331 ctor->parameters.push_back(endpoint);
332 this->elements.push_back(ctor);
333
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700334 ctor->statements->Add(new Assignment(this->broker, broker));
Joe Onorato7add83b2011-08-30 17:24:17 -0700335 ctor->statements->Add(new Assignment(this->endpoint, endpoint));
336}
337
Jason Simmons20e0cef2011-12-16 16:14:17 -0800338void
339RpcProxyClass::generate_get_endpoint_info()
340{
341 Method* get = new Method;
342 get->modifiers = PUBLIC;
343 get->returnType = RPC_ENDPOINT_INFO_TYPE;
344 get->name = "getEndpointInfo";
345 get->statements = new StatementBlock;
346 this->elements.push_back(get);
347
348 get->statements->Add(new ReturnStatement(this->endpoint));
349}
350
Joe Onorato7add83b2011-08-30 17:24:17 -0700351// =================================================
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700352class EventListenerClass : public DispatcherClass
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700353{
354public:
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700355 EventListenerClass(const interface_type* iface, Type* listenerType);
356 virtual ~EventListenerClass();
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700357
358 Variable* _listener;
359
360private:
361 void generate_ctor();
362};
363
364Expression*
365generate_get_listener_expression(Type* cast)
366{
367 return new Cast(cast, new MethodCall(THIS_VALUE, "getView"));
368}
369
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700370EventListenerClass::EventListenerClass(const interface_type* iface, Type* listenerType)
371 :DispatcherClass(iface, new FieldVariable(THIS_VALUE, "_listener"))
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700372{
373 this->modifiers = PRIVATE;
374 this->what = Class::CLASS;
375 this->type = new Type(iface->package ? iface->package : "",
376 append(iface->name.data, ".Presenter"),
377 Type::GENERATED, false, false, false);
378 this->extends = PRESENTER_BASE_TYPE;
379
380 this->_listener = new Variable(listenerType, "_listener");
Tim Kilbournb8a6f222011-09-27 10:30:53 -0700381 this->elements.push_back(new Field(PRIVATE, this->_listener));
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700382
383 // methods
384 generate_ctor();
385}
386
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700387EventListenerClass::~EventListenerClass()
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700388{
389}
390
391void
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700392EventListenerClass::generate_ctor()
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700393{
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700394 Variable* broker = new Variable(RPC_BROKER_TYPE, "broker");
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700395 Variable* listener = new Variable(this->_listener->type, "listener");
396 Method* ctor = new Method;
397 ctor->modifiers = PUBLIC;
398 ctor->name = class_name_leaf(this->type->Name());
399 ctor->statements = new StatementBlock;
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700400 ctor->parameters.push_back(broker);
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700401 ctor->parameters.push_back(listener);
402 this->elements.push_back(ctor);
403
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700404 ctor->statements->Add(new MethodCall("super", 2, broker, listener));
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700405 ctor->statements->Add(new Assignment(this->_listener, listener));
406}
407
408// =================================================
409class ListenerClass : public Class
410{
411public:
412 ListenerClass(const interface_type* iface);
413 virtual ~ListenerClass();
414
415 bool needed;
416
417private:
418 void generate_ctor();
419};
420
421ListenerClass::ListenerClass(const interface_type* iface)
422 :Class(),
423 needed(false)
424{
425 this->comment = "/** Extend this to listen to the events from this class. */";
426 this->modifiers = STATIC | PUBLIC ;
427 this->what = Class::CLASS;
428 this->type = new Type(iface->package ? iface->package : "",
429 append(iface->name.data, ".Listener"),
430 Type::GENERATED, false, false, false);
431 this->extends = PRESENTER_LISTENER_BASE_TYPE;
432}
433
434ListenerClass::~ListenerClass()
435{
436}
437
438// =================================================
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700439class EndpointBaseClass : public DispatcherClass
Joe Onorato7add83b2011-08-30 17:24:17 -0700440{
441public:
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700442 EndpointBaseClass(const interface_type* iface);
443 virtual ~EndpointBaseClass();
Joe Onorato7add83b2011-08-30 17:24:17 -0700444
Joe Onorato7add83b2011-08-30 17:24:17 -0700445 bool needed;
Joe Onorato7add83b2011-08-30 17:24:17 -0700446
447private:
448 void generate_ctor();
Joe Onorato7add83b2011-08-30 17:24:17 -0700449};
450
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700451EndpointBaseClass::EndpointBaseClass(const interface_type* iface)
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700452 :DispatcherClass(iface, THIS_VALUE),
453 needed(false)
Joe Onorato7add83b2011-08-30 17:24:17 -0700454{
455 this->comment = "/** Extend this to implement a link service. */";
456 this->modifiers = STATIC | PUBLIC | ABSTRACT;
457 this->what = Class::CLASS;
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700458 this->type = new Type(iface->package ? iface->package : "",
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700459 append(iface->name.data, ".EndpointBase"),
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700460 Type::GENERATED, false, false, false);
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700461 this->extends = RPC_CONNECTOR_TYPE;
Joe Onorato7add83b2011-08-30 17:24:17 -0700462
463 // methods
464 generate_ctor();
Joe Onorato7add83b2011-08-30 17:24:17 -0700465}
466
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700467EndpointBaseClass::~EndpointBaseClass()
Joe Onorato7add83b2011-08-30 17:24:17 -0700468{
469}
470
471void
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700472EndpointBaseClass::generate_ctor()
Joe Onorato7add83b2011-08-30 17:24:17 -0700473{
Joe Onorato9a782242011-10-23 15:15:27 -0700474 Variable* container = new Variable(ANDROID_CONTEXT_TYPE, "context");
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700475 Variable* broker = new Variable(RPC_BROKER_TYPE, "broker");
Joe Onorato7add83b2011-08-30 17:24:17 -0700476 Method* ctor = new Method;
477 ctor->modifiers = PUBLIC;
478 ctor->name = class_name_leaf(this->type->Name());
479 ctor->statements = new StatementBlock;
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700480 ctor->parameters.push_back(container);
481 ctor->parameters.push_back(broker);
Joe Onorato7add83b2011-08-30 17:24:17 -0700482 this->elements.push_back(ctor);
483
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700484 ctor->statements->Add(new MethodCall("super", 2, container, broker));
Joe Onorato7add83b2011-08-30 17:24:17 -0700485}
486
Joe Onorato7add83b2011-08-30 17:24:17 -0700487// =================================================
488class ResultDispatcherClass : public Class
489{
490public:
491 ResultDispatcherClass();
492 virtual ~ResultDispatcherClass();
493
494 void AddMethod(int index, const string& name, Method** method, Variable** param);
495
496 bool needed;
497 Variable* methodId;
498 Variable* callback;
499 Method* onResultMethod;
500 Variable* resultParam;
501 SwitchStatement* methodSwitch;
502
503private:
504 void generate_ctor();
505 void generate_onResult();
506};
507
508ResultDispatcherClass::ResultDispatcherClass()
509 :Class(),
510 needed(false)
511{
512 this->modifiers = PRIVATE | FINAL;
513 this->what = Class::CLASS;
Joe Onorato0ca2a36d2011-09-15 21:31:15 -0700514 this->type = new Type("_ResultDispatcher", Type::GENERATED, false, false, false);
Joe Onorato7add83b2011-08-30 17:24:17 -0700515 this->interfaces.push_back(RPC_RESULT_HANDLER_TYPE);
516
517 // methodId
518 this->methodId = new Variable(INT_TYPE, "methodId");
519 this->elements.push_back(new Field(PRIVATE, this->methodId));
520 this->callback = new Variable(OBJECT_TYPE, "callback");
521 this->elements.push_back(new Field(PRIVATE, this->callback));
522
523 // methods
524 generate_ctor();
525 generate_onResult();
526}
527
528ResultDispatcherClass::~ResultDispatcherClass()
529{
530}
531
532void
533ResultDispatcherClass::generate_ctor()
534{
535 Variable* methodIdParam = new Variable(INT_TYPE, "methId");
536 Variable* callbackParam = new Variable(OBJECT_TYPE, "cbObj");
537 Method* ctor = new Method;
538 ctor->modifiers = PUBLIC;
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700539 ctor->name = class_name_leaf(this->type->Name());
Joe Onorato7add83b2011-08-30 17:24:17 -0700540 ctor->statements = new StatementBlock;
541 ctor->parameters.push_back(methodIdParam);
542 ctor->parameters.push_back(callbackParam);
543 this->elements.push_back(ctor);
544
545 ctor->statements->Add(new Assignment(this->methodId, methodIdParam));
546 ctor->statements->Add(new Assignment(this->callback, callbackParam));
547}
548
549void
550ResultDispatcherClass::generate_onResult()
551{
552 this->onResultMethod = new Method;
553 this->onResultMethod->modifiers = PUBLIC;
554 this->onResultMethod->returnType = VOID_TYPE;
555 this->onResultMethod->returnTypeDimension = 0;
556 this->onResultMethod->name = "onResult";
557 this->onResultMethod->statements = new StatementBlock;
558 this->elements.push_back(this->onResultMethod);
559
560 this->resultParam = new Variable(BYTE_TYPE, "result", 1);
561 this->onResultMethod->parameters.push_back(this->resultParam);
562
563 this->methodSwitch = new SwitchStatement(this->methodId);
564 this->onResultMethod->statements->Add(this->methodSwitch);
565}
566
567void
568ResultDispatcherClass::AddMethod(int index, const string& name, Method** method, Variable** param)
569{
570 Method* m = new Method;
571 m->modifiers = PUBLIC;
572 m->returnType = VOID_TYPE;
573 m->returnTypeDimension = 0;
574 m->name = name;
575 m->statements = new StatementBlock;
576 *param = new Variable(BYTE_TYPE, "result", 1);
577 m->parameters.push_back(*param);
578 this->elements.push_back(m);
579 *method = m;
580
581 Case* c = new Case(format_int(index));
582 c->statements->Add(new MethodCall(new LiteralExpression("this"), name, 1, this->resultParam));
Joe Onoratoa1426e62011-09-02 15:28:36 -0700583 c->statements->Add(new Break());
Joe Onorato7add83b2011-08-30 17:24:17 -0700584
585 this->methodSwitch->cases.push_back(c);
586}
587
588// =================================================
589static void
590generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from)
591{
592 fprintf(stderr, "aidl: implement generate_new_array %s:%d\n", __FILE__, __LINE__);
593 exit(1);
594}
595
596static void
597generate_create_from_data(Type* t, StatementBlock* addTo, const string& key, Variable* v,
598 Variable* data, Variable** cl)
599{
600 Expression* k = new StringLiteralExpression(key);
601 if (v->dimension == 0) {
602 t->CreateFromRpcData(addTo, k, v, data, cl);
603 }
604 if (v->dimension == 1) {
605 //t->ReadArrayFromRpcData(addTo, v, data, cl);
606 fprintf(stderr, "aidl: implement generate_create_from_data for arrays%s:%d\n",
607 __FILE__, __LINE__);
608 }
609}
610
611static void
612generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v, Variable* data)
613{
614 if (v->dimension == 0) {
615 t->WriteToRpcData(addTo, k, v, data, 0);
616 }
617 if (v->dimension == 1) {
618 //t->WriteArrayToParcel(addTo, v, data);
619 fprintf(stderr, "aidl: implement generate_write_to_data for arrays%s:%d\n",
620 __FILE__, __LINE__);
621 }
622}
623
624// =================================================
Joe Onorato7add83b2011-08-30 17:24:17 -0700625static Type*
626generate_results_method(const method_type* method, RpcProxyClass* proxyClass)
627{
628 arg_type* arg;
629
630 string resultsMethodName = results_method_name(method->name.data);
631 Type* resultsInterfaceType = new Type(results_class_name(method->name.data),
Joe Onorato0ca2a36d2011-09-15 21:31:15 -0700632 Type::GENERATED, false, false, false);
Joe Onorato7add83b2011-08-30 17:24:17 -0700633
634 if (!method->oneway) {
635 Class* resultsClass = new Class;
636 resultsClass->modifiers = STATIC | PUBLIC;
637 resultsClass->what = Class::INTERFACE;
638 resultsClass->type = resultsInterfaceType;
639
640 Method* resultMethod = new Method;
641 resultMethod->comment = gather_comments(method->comments_token->extra);
642 resultMethod->modifiers = PUBLIC;
643 resultMethod->returnType = VOID_TYPE;
644 resultMethod->returnTypeDimension = 0;
645 resultMethod->name = resultsMethodName;
646 if (0 != strcmp("void", method->type.type.data)) {
647 resultMethod->parameters.push_back(new Variable(NAMES.Search(method->type.type.data),
648 "_result", method->type.dimension));
649 }
650 arg = method->args;
651 while (arg != NULL) {
652 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
653 resultMethod->parameters.push_back(new Variable(
654 NAMES.Search(arg->type.type.data), arg->name.data,
655 arg->type.dimension));
656 }
657 arg = arg->next;
658 }
659 resultsClass->elements.push_back(resultMethod);
660
661 if (resultMethod->parameters.size() > 0) {
662 proxyClass->elements.push_back(resultsClass);
663 return resultsInterfaceType;
664 }
665 }
666 //delete resultsInterfaceType;
667 return NULL;
668}
669
670static void
671generate_proxy_method(const method_type* method, RpcProxyClass* proxyClass,
672 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index)
673{
674 arg_type* arg;
675 Method* proxyMethod = new Method;
676 proxyMethod->comment = gather_comments(method->comments_token->extra);
677 proxyMethod->modifiers = PUBLIC;
678 proxyMethod->returnType = VOID_TYPE;
679 proxyMethod->returnTypeDimension = 0;
680 proxyMethod->name = method->name.data;
681 proxyMethod->statements = new StatementBlock;
682 proxyClass->elements.push_back(proxyMethod);
683
684 // The local variables
685 Variable* _data = new Variable(RPC_DATA_TYPE, "_data");
686 proxyMethod->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE)));
687
688 // Add the arguments
689 arg = method->args;
690 while (arg != NULL) {
691 if (convert_direction(arg->direction.data) & IN_PARAMETER) {
692 // Function signature
693 Type* t = NAMES.Search(arg->type.type.data);
694 Variable* v = new Variable(t, arg->name.data, arg->type.dimension);
695 proxyMethod->parameters.push_back(v);
696
697 // Input parameter marshalling
698 generate_write_to_data(t, proxyMethod->statements,
699 new StringLiteralExpression(arg->name.data), v, _data);
700 }
701 arg = arg->next;
702 }
703
704 // If there is a results interface for this class
705 Expression* resultParameter;
706 if (resultsInterfaceType != NULL) {
707 // Result interface parameter
708 Variable* resultListener = new Variable(resultsInterfaceType, "_result");
709 proxyMethod->parameters.push_back(resultListener);
710
711 // Add the results dispatcher callback
712 resultsDispatcherClass->needed = true;
713 resultParameter = new NewExpression(resultsDispatcherClass->type, 2,
714 new LiteralExpression(format_int(index)), resultListener);
715 } else {
716 resultParameter = NULL_VALUE;
717 }
718
719 // All proxy methods take an error parameter
720 Variable* errorListener = new Variable(RPC_ERROR_LISTENER_TYPE, "_errors");
721 proxyMethod->parameters.push_back(errorListener);
722
723 // Call the broker
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700724 proxyMethod->statements->Add(new MethodCall(new FieldVariable(THIS_VALUE, "_broker"),
725 "sendRpc", 5,
Joe Onorato7add83b2011-08-30 17:24:17 -0700726 proxyClass->endpoint,
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700727 new StringLiteralExpression(method->name.data),
Joe Onorato7add83b2011-08-30 17:24:17 -0700728 new MethodCall(_data, "serialize"),
729 resultParameter,
730 errorListener));
731}
732
733static void
734generate_result_dispatcher_method(const method_type* method,
735 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index)
736{
737 arg_type* arg;
738 Method* dispatchMethod;
739 Variable* dispatchParam;
740 resultsDispatcherClass->AddMethod(index, method->name.data, &dispatchMethod, &dispatchParam);
741
742 Variable* classLoader = NULL;
743 Variable* resultData = new Variable(RPC_DATA_TYPE, "resultData");
744 dispatchMethod->statements->Add(new VariableDeclaration(resultData,
745 new NewExpression(RPC_DATA_TYPE, 1, dispatchParam)));
746
747 // The callback method itself
748 MethodCall* realCall = new MethodCall(
749 new Cast(resultsInterfaceType, new FieldVariable(THIS_VALUE, "callback")),
750 results_method_name(method->name.data));
751
752 // The return value
753 {
754 Type* t = NAMES.Search(method->type.type.data);
Joe Onorato6980de42011-11-17 16:13:49 -0800755 if (t != VOID_TYPE) {
756 Variable* rv = new Variable(t, "rv");
757 dispatchMethod->statements->Add(new VariableDeclaration(rv));
758 generate_create_from_data(t, dispatchMethod->statements, "_result", rv,
759 resultData, &classLoader);
760 realCall->arguments.push_back(rv);
761 }
Joe Onorato7add83b2011-08-30 17:24:17 -0700762 }
763
764 VariableFactory stubArgs("arg");
765 arg = method->args;
766 while (arg != NULL) {
767 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
768 // Unmarshall the results
769 Type* t = NAMES.Search(arg->type.type.data);
770 Variable* v = stubArgs.Get(t);
771 dispatchMethod->statements->Add(new VariableDeclaration(v));
772
773 generate_create_from_data(t, dispatchMethod->statements, arg->name.data, v,
774 resultData, &classLoader);
775
776 // Add the argument to the callback
777 realCall->arguments.push_back(v);
778 }
779 arg = arg->next;
780 }
781
782 // Call the callback method
783 dispatchMethod->statements->Add(realCall);
784}
785
786static void
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700787generate_regular_method(const method_type* method, RpcProxyClass* proxyClass,
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700788 EndpointBaseClass* serviceBaseClass, ResultDispatcherClass* resultsDispatcherClass,
Joe Onorato7add83b2011-08-30 17:24:17 -0700789 int index)
790{
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700791 arg_type* arg;
792
793 // == the callback interface for results ================================
Joe Onorato7add83b2011-08-30 17:24:17 -0700794 // the service base class
795 Type* resultsInterfaceType = generate_results_method(method, proxyClass);
796
797 // == the method in the proxy class =====================================
798 generate_proxy_method(method, proxyClass, resultsDispatcherClass, resultsInterfaceType, index);
799
800 // == the method in the result dispatcher class =========================
801 if (resultsInterfaceType != NULL) {
802 generate_result_dispatcher_method(method, resultsDispatcherClass, resultsInterfaceType,
803 index);
804 }
805
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700806 // == The abstract method that the service developers implement ==========
807 Method* decl = new Method;
808 decl->comment = gather_comments(method->comments_token->extra);
809 decl->modifiers = PUBLIC | ABSTRACT;
810 decl->returnType = NAMES.Search(method->type.type.data);
811 decl->returnTypeDimension = method->type.dimension;
812 decl->name = method->name.data;
813 arg = method->args;
814 while (arg != NULL) {
815 decl->parameters.push_back(new Variable(
816 NAMES.Search(arg->type.type.data), arg->name.data,
817 arg->type.dimension));
818 arg = arg->next;
819 }
Manuel Roman2c5eb262011-10-06 10:28:35 -0700820
821 // Add the default RpcContext param to all methods
822 decl->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
823
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700824 serviceBaseClass->elements.push_back(decl);
825
826
Joe Onorato7add83b2011-08-30 17:24:17 -0700827 // == the dispatch method in the service base class ======================
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700828 serviceBaseClass->AddMethod(method);
829}
830
831static void
832generate_event_method(const method_type* method, RpcProxyClass* proxyClass,
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700833 EndpointBaseClass* serviceBaseClass, ListenerClass* listenerClass,
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700834 EventListenerClass* presenterClass, int index)
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700835{
836 arg_type* arg;
837 listenerClass->needed = true;
838
839 // == the push method in the service base class =========================
840 Method* push = new Method;
841 push->modifiers = PUBLIC;
842 push->name = push_method_name(method->name.data);
843 push->statements = new StatementBlock;
844 push->returnType = VOID_TYPE;
845 serviceBaseClass->elements.push_back(push);
846
847 // The local variables
848 Variable* _data = new Variable(RPC_DATA_TYPE, "_data");
849 push->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE)));
850
851 // Add the arguments
852 arg = method->args;
853 while (arg != NULL) {
854 // Function signature
855 Type* t = NAMES.Search(arg->type.type.data);
856 Variable* v = new Variable(t, arg->name.data, arg->type.dimension);
857 push->parameters.push_back(v);
858
859 // Input parameter marshalling
860 generate_write_to_data(t, push->statements,
861 new StringLiteralExpression(arg->name.data), v, _data);
862
863 arg = arg->next;
864 }
865
866 // Send the notifications
867 push->statements->Add(new MethodCall("pushEvent", 2,
868 new StringLiteralExpression(method->name.data),
869 new MethodCall(_data, "serialize")));
870
871 // == the event callback dispatcher method ====================================
872 presenterClass->AddMethod(method);
873
874 // == the event method in the listener base class =====================
875 Method* event = new Method;
876 event->modifiers = PUBLIC;
877 event->name = method->name.data;
878 event->statements = new StatementBlock;
879 event->returnType = VOID_TYPE;
880 listenerClass->elements.push_back(event);
881 arg = method->args;
882 while (arg != NULL) {
883 event->parameters.push_back(new Variable(
884 NAMES.Search(arg->type.type.data), arg->name.data,
885 arg->type.dimension));
886 arg = arg->next;
887 }
Manuel Roman2c5eb262011-10-06 10:28:35 -0700888
889 // Add a final parameter: RpcContext. Contains data about
890 // incoming request (e.g., certificate)
891 event->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700892}
893
894static void
895generate_listener_methods(RpcProxyClass* proxyClass, Type* presenterType, Type* listenerType)
896{
897 // AndroidAtHomePresenter _presenter;
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700898 // void startListening(Listener listener) {
899 // stopListening();
900 // _presenter = new Presenter(_broker, listener);
901 // _presenter.startListening(_endpoint);
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700902 // }
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700903 // void stopListening() {
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700904 // if (_presenter != null) {
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700905 // _presenter.stopListening();
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700906 // }
907 // }
908
909 Variable* _presenter = new Variable(presenterType, "_presenter");
910 proxyClass->elements.push_back(new Field(PRIVATE, _presenter));
911
912 Variable* listener = new Variable(listenerType, "listener");
913
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700914 Method* startListeningMethod = new Method;
915 startListeningMethod->modifiers = PUBLIC;
916 startListeningMethod->returnType = VOID_TYPE;
917 startListeningMethod->name = "startListening";
918 startListeningMethod->statements = new StatementBlock;
919 startListeningMethod->parameters.push_back(listener);
920 proxyClass->elements.push_back(startListeningMethod);
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700921
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700922 startListeningMethod->statements->Add(new MethodCall(THIS_VALUE, "stopListening"));
923 startListeningMethod->statements->Add(new Assignment(_presenter,
924 new NewExpression(presenterType, 2, proxyClass->broker, listener)));
925 startListeningMethod->statements->Add(new MethodCall(_presenter,
926 "startListening", 1, proxyClass->endpoint));
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700927
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700928 Method* stopListeningMethod = new Method;
929 stopListeningMethod->modifiers = PUBLIC;
930 stopListeningMethod->returnType = VOID_TYPE;
931 stopListeningMethod->name = "stopListening";
932 stopListeningMethod->statements = new StatementBlock;
933 proxyClass->elements.push_back(stopListeningMethod);
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700934
935 IfStatement* ifst = new IfStatement;
936 ifst->expression = new Comparison(_presenter, "!=", NULL_VALUE);
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700937 stopListeningMethod->statements->Add(ifst);
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700938
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700939 ifst->statements->Add(new MethodCall(_presenter, "stopListening"));
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700940 ifst->statements->Add(new Assignment(_presenter, NULL_VALUE));
Joe Onorato7add83b2011-08-30 17:24:17 -0700941}
942
943Class*
944generate_rpc_interface_class(const interface_type* iface)
945{
946 // the proxy class
947 InterfaceType* interfaceType = static_cast<InterfaceType*>(
948 NAMES.Find(iface->package, iface->name.data));
949 RpcProxyClass* proxy = new RpcProxyClass(iface, interfaceType);
950
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700951 // the listener class
952 ListenerClass* listener = new ListenerClass(iface);
953
954 // the presenter class
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700955 EventListenerClass* presenter = new EventListenerClass(iface, listener->type);
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700956
Joe Onorato7add83b2011-08-30 17:24:17 -0700957 // the service base class
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700958 EndpointBaseClass* base = new EndpointBaseClass(iface);
Joe Onorato7add83b2011-08-30 17:24:17 -0700959 proxy->elements.push_back(base);
960
961 // the result dispatcher
962 ResultDispatcherClass* results = new ResultDispatcherClass();
963
964 // all the declared methods of the proxy
965 int index = 0;
966 interface_item_type* item = iface->interface_items;
967 while (item != NULL) {
968 if (item->item_type == METHOD_TYPE) {
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700969 if (NAMES.Search(((method_type*)item)->type.type.data) == EVENT_FAKE_TYPE) {
970 generate_event_method((method_type*)item, proxy, base, listener, presenter, index);
971 } else {
972 generate_regular_method((method_type*)item, proxy, base, results, index);
973 }
Joe Onorato7add83b2011-08-30 17:24:17 -0700974 }
975 item = item->next;
976 index++;
977 }
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700978 presenter->DoneWithMethods();
Joe Onorato7add83b2011-08-30 17:24:17 -0700979 base->DoneWithMethods();
980
981 // only add this if there are methods with results / out parameters
982 if (results->needed) {
983 proxy->elements.push_back(results);
984 }
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700985 if (listener->needed) {
986 proxy->elements.push_back(listener);
987 proxy->elements.push_back(presenter);
988 generate_listener_methods(proxy, presenter->type, listener->type);
989 }
Joe Onorato7add83b2011-08-30 17:24:17 -0700990
991 return proxy;
992}