blob: 21ebb1f284ed0a987c4fa9a8972f2d68e203259d [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);
Manuel Romana8744b72012-01-03 22:03:37 -080016Type* PLACE_INFO_TYPE = new Type("android.support.place.connector", "PlaceInfo",
17 Type::BUILT_IN, false, false, false);
Joe Onorato0d2a6b62011-10-09 21:51:46 -070018// TODO: Just use Endpoint, so this works for all endpoints.
Joe Onorato0c861962011-12-11 20:42:33 -080019Type* RPC_CONNECTOR_TYPE = new Type("android.support.place.connector", "Connector",
Joe Onorato0d2a6b62011-10-09 21:51:46 -070020 Type::BUILT_IN, false, false, false);
Joe Onorato0c861962011-12-11 20:42:33 -080021Type* RPC_ENDPOINT_INFO_TYPE = new UserDataType("android.support.place.rpc",
Joe Onorato0d2a6b62011-10-09 21:51:46 -070022 "EndpointInfo", true, __FILE__, __LINE__);
Joe Onorato0c861962011-12-11 20:42:33 -080023Type* RPC_RESULT_HANDLER_TYPE = new UserDataType("android.support.place.rpc", "RpcResultHandler",
Joe Onoratoe415ecb2011-09-23 15:17:52 -070024 true, __FILE__, __LINE__);
Joe Onorato0c861962011-12-11 20:42:33 -080025Type* RPC_ERROR_LISTENER_TYPE = new Type("android.support.place.rpc", "RpcErrorHandler",
Joe Onoratoe415ecb2011-09-23 15:17:52 -070026 Type::BUILT_IN, false, false, false);
Joe Onorato0c861962011-12-11 20:42:33 -080027Type* RPC_CONTEXT_TYPE = new UserDataType("android.support.place.rpc", "RpcContext", true,
Manuel Roman2c5eb262011-10-06 10:28:35 -070028 __FILE__, __LINE__);
Joe Onoratoe415ecb2011-09-23 15:17:52 -070029
30static void generate_create_from_data(Type* t, StatementBlock* addTo, const string& key,
31 Variable* v, Variable* data, Variable** cl);
32static void generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from);
33static void generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v,
34 Variable* data);
Joe Onorato7add83b2011-08-30 17:24:17 -070035
36static string
37format_int(int n)
38{
39 char str[20];
40 sprintf(str, "%d", n);
41 return string(str);
42}
43
44static string
45class_name_leaf(const string& str)
46{
47 string::size_type pos = str.rfind('.');
48 if (pos == string::npos) {
49 return str;
50 } else {
51 return string(str, pos+1);
52 }
53}
54
Joe Onoratoe415ecb2011-09-23 15:17:52 -070055static string
56results_class_name(const string& n)
57{
58 string str = n;
59 str[0] = toupper(str[0]);
60 str.insert(0, "On");
61 return str;
62}
63
64static string
65results_method_name(const string& n)
66{
67 string str = n;
68 str[0] = toupper(str[0]);
69 str.insert(0, "on");
70 return str;
71}
72
73static string
74push_method_name(const string& n)
75{
76 string str = n;
77 str[0] = toupper(str[0]);
78 str.insert(0, "push");
79 return str;
80}
81
82// =================================================
83class DispatcherClass : public Class
84{
85public:
86 DispatcherClass(const interface_type* iface, Expression* target);
87 virtual ~DispatcherClass();
88
89 void AddMethod(const method_type* method);
90 void DoneWithMethods();
91
92 Method* processMethod;
93 Variable* actionParam;
94 Variable* requestParam;
Manuel Roman2c5eb262011-10-06 10:28:35 -070095 Variable* rpcContextParam;
Joe Onoratoe415ecb2011-09-23 15:17:52 -070096 Variable* errorParam;
97 Variable* requestData;
98 Variable* resultData;
99 IfStatement* dispatchIfStatement;
100 Expression* targetExpression;
101
102private:
103 void generate_process();
104};
105
106DispatcherClass::DispatcherClass(const interface_type* iface, Expression* target)
107 :Class(),
108 dispatchIfStatement(NULL),
109 targetExpression(target)
110{
111 generate_process();
112}
113
114DispatcherClass::~DispatcherClass()
115{
116}
117
118void
119DispatcherClass::generate_process()
120{
Manuel Roman2c5eb262011-10-06 10:28:35 -0700121 // byte[] process(String action, byte[] params, RpcContext context, RpcError status)
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700122 this->processMethod = new Method;
123 this->processMethod->modifiers = PUBLIC;
124 this->processMethod->returnType = BYTE_TYPE;
125 this->processMethod->returnTypeDimension = 1;
126 this->processMethod->name = "process";
127 this->processMethod->statements = new StatementBlock;
128
129 this->actionParam = new Variable(STRING_TYPE, "action");
130 this->processMethod->parameters.push_back(this->actionParam);
131
132 this->requestParam = new Variable(BYTE_TYPE, "requestParam", 1);
133 this->processMethod->parameters.push_back(this->requestParam);
134
Manuel Roman2c5eb262011-10-06 10:28:35 -0700135 this->rpcContextParam = new Variable(RPC_CONTEXT_TYPE, "context", 0);
136 this->processMethod->parameters.push_back(this->rpcContextParam);
137
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700138 this->errorParam = new Variable(RPC_ERROR_TYPE, "errorParam", 0);
139 this->processMethod->parameters.push_back(this->errorParam);
140
141 this->requestData = new Variable(RPC_DATA_TYPE, "request");
142 this->processMethod->statements->Add(new VariableDeclaration(requestData,
143 new NewExpression(RPC_DATA_TYPE, 1, this->requestParam)));
144
145 this->resultData = new Variable(RPC_DATA_TYPE, "resultData");
146 this->processMethod->statements->Add(new VariableDeclaration(this->resultData,
147 NULL_VALUE));
148}
149
150void
151DispatcherClass::AddMethod(const method_type* method)
152{
153 arg_type* arg;
154
155 // The if/switch statement
156 IfStatement* ifs = new IfStatement();
157 ifs->expression = new MethodCall(new StringLiteralExpression(method->name.data), "equals",
158 1, this->actionParam);
159 StatementBlock* block = ifs->statements = new StatementBlock;
160 if (this->dispatchIfStatement == NULL) {
161 this->dispatchIfStatement = ifs;
162 this->processMethod->statements->Add(dispatchIfStatement);
163 } else {
164 this->dispatchIfStatement->elseif = ifs;
165 this->dispatchIfStatement = ifs;
166 }
167
168 // The call to decl (from above)
169 MethodCall* realCall = new MethodCall(this->targetExpression, method->name.data);
170
171 // args
172 Variable* classLoader = NULL;
173 VariableFactory stubArgs("_arg");
174 arg = method->args;
175 while (arg != NULL) {
176 Type* t = NAMES.Search(arg->type.type.data);
177 Variable* v = stubArgs.Get(t);
178 v->dimension = arg->type.dimension;
179
180 // Unmarshall the parameter
181 block->Add(new VariableDeclaration(v));
182 if (convert_direction(arg->direction.data) & IN_PARAMETER) {
183 generate_create_from_data(t, block, arg->name.data, v,
184 this->requestData, &classLoader);
185 } else {
186 if (arg->type.dimension == 0) {
187 block->Add(new Assignment(v, new NewExpression(v->type)));
188 }
189 else if (arg->type.dimension == 1) {
190 generate_new_array(v->type, block, v, this->requestData);
191 }
192 else {
193 fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__,
194 __LINE__);
195 }
196 }
197
198 // Add that parameter to the method call
199 realCall->arguments.push_back(v);
200
201 arg = arg->next;
202 }
203
Manuel Roman2c5eb262011-10-06 10:28:35 -0700204 // Add a final parameter: RpcContext. Contains data about
205 // incoming request (e.g., certificate)
206 realCall->arguments.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700207
208 Type* returnType = NAMES.Search(method->type.type.data);
209 if (returnType == EVENT_FAKE_TYPE) {
210 returnType = VOID_TYPE;
211 }
212
213 // the real call
214 bool first = true;
215 Variable* _result = NULL;
216 if (returnType == VOID_TYPE) {
217 block->Add(realCall);
218 } else {
219 _result = new Variable(returnType, "_result",
220 method->type.dimension);
221 block->Add(new VariableDeclaration(_result, realCall));
222
223 // need the result RpcData
224 if (first) {
225 block->Add(new Assignment(this->resultData,
226 new NewExpression(RPC_DATA_TYPE)));
227 first = false;
228 }
229
230 // marshall the return value
231 generate_write_to_data(returnType, block,
232 new StringLiteralExpression("_result"), _result, this->resultData);
233 }
234
235 // out parameters
236 int i = 0;
237 arg = method->args;
238 while (arg != NULL) {
239 Type* t = NAMES.Search(arg->type.type.data);
240 Variable* v = stubArgs.Get(i++);
241
242 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
243 // need the result RpcData
244 if (first) {
245 block->Add(new Assignment(this->resultData, new NewExpression(RPC_DATA_TYPE)));
246 first = false;
247 }
248
249 generate_write_to_data(t, block, new StringLiteralExpression(arg->name.data),
250 v, this->resultData);
251 }
252
253 arg = arg->next;
254 }
255}
256
257void
258DispatcherClass::DoneWithMethods()
259{
260 if (this->dispatchIfStatement == NULL) {
261 return;
262 }
263
264 this->elements.push_back(this->processMethod);
265
266 IfStatement* fallthrough = new IfStatement();
267 fallthrough->statements = new StatementBlock;
268 fallthrough->statements->Add(new ReturnStatement(
Manuel Roman2c5eb262011-10-06 10:28:35 -0700269 new MethodCall(SUPER_VALUE, "process", 4,
270 this->actionParam, this->requestParam,
271 this->rpcContextParam,
272 this->errorParam)));
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700273 this->dispatchIfStatement->elseif = fallthrough;
274 IfStatement* s = new IfStatement;
275 s->statements = new StatementBlock;
276 this->processMethod->statements->Add(s);
277 s->expression = new Comparison(this->resultData, "!=", NULL_VALUE);
278 s->statements->Add(new ReturnStatement(new MethodCall(this->resultData, "serialize")));
279 s->elseif = new IfStatement;
280 s = s->elseif;
281 s->statements->Add(new ReturnStatement(NULL_VALUE));
282}
283
Joe Onorato7add83b2011-08-30 17:24:17 -0700284// =================================================
285class RpcProxyClass : public Class
286{
287public:
288 RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType);
289 virtual ~RpcProxyClass();
290
291 Variable* endpoint;
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700292 Variable* broker;
Joe Onorato7add83b2011-08-30 17:24:17 -0700293
294private:
295 void generate_ctor();
Jason Simmons20e0cef2011-12-16 16:14:17 -0800296 void generate_get_endpoint_info();
Joe Onorato7add83b2011-08-30 17:24:17 -0700297};
298
299RpcProxyClass::RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType)
300 :Class()
301{
302 this->comment = gather_comments(iface->comments_token->extra);
303 this->modifiers = PUBLIC;
304 this->what = Class::CLASS;
305 this->type = interfaceType;
306
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700307 // broker
308 this->broker = new Variable(RPC_BROKER_TYPE, "_broker");
309 this->elements.push_back(new Field(PRIVATE, this->broker));
Joe Onorato7add83b2011-08-30 17:24:17 -0700310 // endpoint
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700311 this->endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "_endpoint");
Joe Onorato7add83b2011-08-30 17:24:17 -0700312 this->elements.push_back(new Field(PRIVATE, this->endpoint));
313
314 // methods
315 generate_ctor();
Jason Simmons20e0cef2011-12-16 16:14:17 -0800316 generate_get_endpoint_info();
Joe Onorato7add83b2011-08-30 17:24:17 -0700317}
318
319RpcProxyClass::~RpcProxyClass()
320{
321}
322
323void
324RpcProxyClass::generate_ctor()
325{
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700326 Variable* broker = new Variable(RPC_BROKER_TYPE, "broker");
327 Variable* endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "endpoint");
Joe Onorato7add83b2011-08-30 17:24:17 -0700328 Method* ctor = new Method;
329 ctor->modifiers = PUBLIC;
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700330 ctor->name = class_name_leaf(this->type->Name());
Joe Onorato7add83b2011-08-30 17:24:17 -0700331 ctor->statements = new StatementBlock;
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700332 ctor->parameters.push_back(broker);
Joe Onorato7add83b2011-08-30 17:24:17 -0700333 ctor->parameters.push_back(endpoint);
334 this->elements.push_back(ctor);
335
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700336 ctor->statements->Add(new Assignment(this->broker, broker));
Joe Onorato7add83b2011-08-30 17:24:17 -0700337 ctor->statements->Add(new Assignment(this->endpoint, endpoint));
338}
339
Jason Simmons20e0cef2011-12-16 16:14:17 -0800340void
341RpcProxyClass::generate_get_endpoint_info()
342{
343 Method* get = new Method;
344 get->modifiers = PUBLIC;
345 get->returnType = RPC_ENDPOINT_INFO_TYPE;
346 get->name = "getEndpointInfo";
347 get->statements = new StatementBlock;
348 this->elements.push_back(get);
349
350 get->statements->Add(new ReturnStatement(this->endpoint));
351}
352
Joe Onorato7add83b2011-08-30 17:24:17 -0700353// =================================================
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700354class EventListenerClass : public DispatcherClass
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700355{
356public:
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700357 EventListenerClass(const interface_type* iface, Type* listenerType);
358 virtual ~EventListenerClass();
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700359
360 Variable* _listener;
361
362private:
363 void generate_ctor();
364};
365
366Expression*
367generate_get_listener_expression(Type* cast)
368{
369 return new Cast(cast, new MethodCall(THIS_VALUE, "getView"));
370}
371
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700372EventListenerClass::EventListenerClass(const interface_type* iface, Type* listenerType)
373 :DispatcherClass(iface, new FieldVariable(THIS_VALUE, "_listener"))
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700374{
375 this->modifiers = PRIVATE;
376 this->what = Class::CLASS;
377 this->type = new Type(iface->package ? iface->package : "",
378 append(iface->name.data, ".Presenter"),
379 Type::GENERATED, false, false, false);
380 this->extends = PRESENTER_BASE_TYPE;
381
382 this->_listener = new Variable(listenerType, "_listener");
Tim Kilbournb8a6f222011-09-27 10:30:53 -0700383 this->elements.push_back(new Field(PRIVATE, this->_listener));
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700384
385 // methods
386 generate_ctor();
387}
388
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700389EventListenerClass::~EventListenerClass()
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700390{
391}
392
393void
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700394EventListenerClass::generate_ctor()
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700395{
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700396 Variable* broker = new Variable(RPC_BROKER_TYPE, "broker");
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700397 Variable* listener = new Variable(this->_listener->type, "listener");
398 Method* ctor = new Method;
399 ctor->modifiers = PUBLIC;
400 ctor->name = class_name_leaf(this->type->Name());
401 ctor->statements = new StatementBlock;
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700402 ctor->parameters.push_back(broker);
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700403 ctor->parameters.push_back(listener);
404 this->elements.push_back(ctor);
405
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700406 ctor->statements->Add(new MethodCall("super", 2, broker, listener));
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700407 ctor->statements->Add(new Assignment(this->_listener, listener));
408}
409
410// =================================================
411class ListenerClass : public Class
412{
413public:
414 ListenerClass(const interface_type* iface);
415 virtual ~ListenerClass();
416
417 bool needed;
418
419private:
420 void generate_ctor();
421};
422
423ListenerClass::ListenerClass(const interface_type* iface)
424 :Class(),
425 needed(false)
426{
427 this->comment = "/** Extend this to listen to the events from this class. */";
428 this->modifiers = STATIC | PUBLIC ;
429 this->what = Class::CLASS;
430 this->type = new Type(iface->package ? iface->package : "",
431 append(iface->name.data, ".Listener"),
432 Type::GENERATED, false, false, false);
433 this->extends = PRESENTER_LISTENER_BASE_TYPE;
434}
435
436ListenerClass::~ListenerClass()
437{
438}
439
440// =================================================
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700441class EndpointBaseClass : public DispatcherClass
Joe Onorato7add83b2011-08-30 17:24:17 -0700442{
443public:
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700444 EndpointBaseClass(const interface_type* iface);
445 virtual ~EndpointBaseClass();
Joe Onorato7add83b2011-08-30 17:24:17 -0700446
Joe Onorato7add83b2011-08-30 17:24:17 -0700447 bool needed;
Joe Onorato7add83b2011-08-30 17:24:17 -0700448
449private:
450 void generate_ctor();
Joe Onorato7add83b2011-08-30 17:24:17 -0700451};
452
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700453EndpointBaseClass::EndpointBaseClass(const interface_type* iface)
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700454 :DispatcherClass(iface, THIS_VALUE),
455 needed(false)
Joe Onorato7add83b2011-08-30 17:24:17 -0700456{
457 this->comment = "/** Extend this to implement a link service. */";
458 this->modifiers = STATIC | PUBLIC | ABSTRACT;
459 this->what = Class::CLASS;
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700460 this->type = new Type(iface->package ? iface->package : "",
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700461 append(iface->name.data, ".EndpointBase"),
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700462 Type::GENERATED, false, false, false);
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700463 this->extends = RPC_CONNECTOR_TYPE;
Joe Onorato7add83b2011-08-30 17:24:17 -0700464
465 // methods
466 generate_ctor();
Joe Onorato7add83b2011-08-30 17:24:17 -0700467}
468
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700469EndpointBaseClass::~EndpointBaseClass()
Joe Onorato7add83b2011-08-30 17:24:17 -0700470{
471}
472
473void
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700474EndpointBaseClass::generate_ctor()
Joe Onorato7add83b2011-08-30 17:24:17 -0700475{
Joe Onorato9a782242011-10-23 15:15:27 -0700476 Variable* container = new Variable(ANDROID_CONTEXT_TYPE, "context");
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700477 Variable* broker = new Variable(RPC_BROKER_TYPE, "broker");
Manuel Romana8744b72012-01-03 22:03:37 -0800478 Variable* place = new Variable(PLACE_INFO_TYPE, "placeInfo");
Joe Onorato7add83b2011-08-30 17:24:17 -0700479 Method* ctor = new Method;
480 ctor->modifiers = PUBLIC;
481 ctor->name = class_name_leaf(this->type->Name());
482 ctor->statements = new StatementBlock;
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700483 ctor->parameters.push_back(container);
484 ctor->parameters.push_back(broker);
Manuel Romana8744b72012-01-03 22:03:37 -0800485 ctor->parameters.push_back(place);
Joe Onorato7add83b2011-08-30 17:24:17 -0700486 this->elements.push_back(ctor);
487
Manuel Romana8744b72012-01-03 22:03:37 -0800488 ctor->statements->Add(new MethodCall("super", 3, container, broker, place));
Joe Onorato7add83b2011-08-30 17:24:17 -0700489}
490
Joe Onorato7add83b2011-08-30 17:24:17 -0700491// =================================================
492class ResultDispatcherClass : public Class
493{
494public:
495 ResultDispatcherClass();
496 virtual ~ResultDispatcherClass();
497
498 void AddMethod(int index, const string& name, Method** method, Variable** param);
499
500 bool needed;
501 Variable* methodId;
502 Variable* callback;
503 Method* onResultMethod;
504 Variable* resultParam;
505 SwitchStatement* methodSwitch;
506
507private:
508 void generate_ctor();
509 void generate_onResult();
510};
511
512ResultDispatcherClass::ResultDispatcherClass()
513 :Class(),
514 needed(false)
515{
516 this->modifiers = PRIVATE | FINAL;
517 this->what = Class::CLASS;
Joe Onorato0ca2a36d2011-09-15 21:31:15 -0700518 this->type = new Type("_ResultDispatcher", Type::GENERATED, false, false, false);
Joe Onorato7add83b2011-08-30 17:24:17 -0700519 this->interfaces.push_back(RPC_RESULT_HANDLER_TYPE);
520
521 // methodId
522 this->methodId = new Variable(INT_TYPE, "methodId");
523 this->elements.push_back(new Field(PRIVATE, this->methodId));
524 this->callback = new Variable(OBJECT_TYPE, "callback");
525 this->elements.push_back(new Field(PRIVATE, this->callback));
526
527 // methods
528 generate_ctor();
529 generate_onResult();
530}
531
532ResultDispatcherClass::~ResultDispatcherClass()
533{
534}
535
536void
537ResultDispatcherClass::generate_ctor()
538{
539 Variable* methodIdParam = new Variable(INT_TYPE, "methId");
540 Variable* callbackParam = new Variable(OBJECT_TYPE, "cbObj");
541 Method* ctor = new Method;
542 ctor->modifiers = PUBLIC;
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700543 ctor->name = class_name_leaf(this->type->Name());
Joe Onorato7add83b2011-08-30 17:24:17 -0700544 ctor->statements = new StatementBlock;
545 ctor->parameters.push_back(methodIdParam);
546 ctor->parameters.push_back(callbackParam);
547 this->elements.push_back(ctor);
548
549 ctor->statements->Add(new Assignment(this->methodId, methodIdParam));
550 ctor->statements->Add(new Assignment(this->callback, callbackParam));
551}
552
553void
554ResultDispatcherClass::generate_onResult()
555{
556 this->onResultMethod = new Method;
557 this->onResultMethod->modifiers = PUBLIC;
558 this->onResultMethod->returnType = VOID_TYPE;
559 this->onResultMethod->returnTypeDimension = 0;
560 this->onResultMethod->name = "onResult";
561 this->onResultMethod->statements = new StatementBlock;
562 this->elements.push_back(this->onResultMethod);
563
564 this->resultParam = new Variable(BYTE_TYPE, "result", 1);
565 this->onResultMethod->parameters.push_back(this->resultParam);
566
567 this->methodSwitch = new SwitchStatement(this->methodId);
568 this->onResultMethod->statements->Add(this->methodSwitch);
569}
570
571void
572ResultDispatcherClass::AddMethod(int index, const string& name, Method** method, Variable** param)
573{
574 Method* m = new Method;
575 m->modifiers = PUBLIC;
576 m->returnType = VOID_TYPE;
577 m->returnTypeDimension = 0;
578 m->name = name;
579 m->statements = new StatementBlock;
580 *param = new Variable(BYTE_TYPE, "result", 1);
581 m->parameters.push_back(*param);
582 this->elements.push_back(m);
583 *method = m;
584
585 Case* c = new Case(format_int(index));
586 c->statements->Add(new MethodCall(new LiteralExpression("this"), name, 1, this->resultParam));
Joe Onoratoa1426e62011-09-02 15:28:36 -0700587 c->statements->Add(new Break());
Joe Onorato7add83b2011-08-30 17:24:17 -0700588
589 this->methodSwitch->cases.push_back(c);
590}
591
592// =================================================
593static void
594generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from)
595{
596 fprintf(stderr, "aidl: implement generate_new_array %s:%d\n", __FILE__, __LINE__);
597 exit(1);
598}
599
600static void
601generate_create_from_data(Type* t, StatementBlock* addTo, const string& key, Variable* v,
602 Variable* data, Variable** cl)
603{
604 Expression* k = new StringLiteralExpression(key);
605 if (v->dimension == 0) {
606 t->CreateFromRpcData(addTo, k, v, data, cl);
607 }
608 if (v->dimension == 1) {
609 //t->ReadArrayFromRpcData(addTo, v, data, cl);
610 fprintf(stderr, "aidl: implement generate_create_from_data for arrays%s:%d\n",
611 __FILE__, __LINE__);
612 }
613}
614
615static void
616generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v, Variable* data)
617{
618 if (v->dimension == 0) {
619 t->WriteToRpcData(addTo, k, v, data, 0);
620 }
621 if (v->dimension == 1) {
622 //t->WriteArrayToParcel(addTo, v, data);
623 fprintf(stderr, "aidl: implement generate_write_to_data for arrays%s:%d\n",
624 __FILE__, __LINE__);
625 }
626}
627
628// =================================================
Joe Onorato7add83b2011-08-30 17:24:17 -0700629static Type*
630generate_results_method(const method_type* method, RpcProxyClass* proxyClass)
631{
632 arg_type* arg;
633
634 string resultsMethodName = results_method_name(method->name.data);
635 Type* resultsInterfaceType = new Type(results_class_name(method->name.data),
Joe Onorato0ca2a36d2011-09-15 21:31:15 -0700636 Type::GENERATED, false, false, false);
Joe Onorato7add83b2011-08-30 17:24:17 -0700637
638 if (!method->oneway) {
639 Class* resultsClass = new Class;
640 resultsClass->modifiers = STATIC | PUBLIC;
641 resultsClass->what = Class::INTERFACE;
642 resultsClass->type = resultsInterfaceType;
643
644 Method* resultMethod = new Method;
645 resultMethod->comment = gather_comments(method->comments_token->extra);
646 resultMethod->modifiers = PUBLIC;
647 resultMethod->returnType = VOID_TYPE;
648 resultMethod->returnTypeDimension = 0;
649 resultMethod->name = resultsMethodName;
650 if (0 != strcmp("void", method->type.type.data)) {
651 resultMethod->parameters.push_back(new Variable(NAMES.Search(method->type.type.data),
652 "_result", method->type.dimension));
653 }
654 arg = method->args;
655 while (arg != NULL) {
656 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
657 resultMethod->parameters.push_back(new Variable(
658 NAMES.Search(arg->type.type.data), arg->name.data,
659 arg->type.dimension));
660 }
661 arg = arg->next;
662 }
663 resultsClass->elements.push_back(resultMethod);
664
665 if (resultMethod->parameters.size() > 0) {
666 proxyClass->elements.push_back(resultsClass);
667 return resultsInterfaceType;
668 }
669 }
670 //delete resultsInterfaceType;
671 return NULL;
672}
673
674static void
675generate_proxy_method(const method_type* method, RpcProxyClass* proxyClass,
676 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index)
677{
678 arg_type* arg;
679 Method* proxyMethod = new Method;
680 proxyMethod->comment = gather_comments(method->comments_token->extra);
681 proxyMethod->modifiers = PUBLIC;
682 proxyMethod->returnType = VOID_TYPE;
683 proxyMethod->returnTypeDimension = 0;
684 proxyMethod->name = method->name.data;
685 proxyMethod->statements = new StatementBlock;
686 proxyClass->elements.push_back(proxyMethod);
687
688 // The local variables
689 Variable* _data = new Variable(RPC_DATA_TYPE, "_data");
690 proxyMethod->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE)));
691
692 // Add the arguments
693 arg = method->args;
694 while (arg != NULL) {
695 if (convert_direction(arg->direction.data) & IN_PARAMETER) {
696 // Function signature
697 Type* t = NAMES.Search(arg->type.type.data);
698 Variable* v = new Variable(t, arg->name.data, arg->type.dimension);
699 proxyMethod->parameters.push_back(v);
700
701 // Input parameter marshalling
702 generate_write_to_data(t, proxyMethod->statements,
703 new StringLiteralExpression(arg->name.data), v, _data);
704 }
705 arg = arg->next;
706 }
707
708 // If there is a results interface for this class
709 Expression* resultParameter;
710 if (resultsInterfaceType != NULL) {
711 // Result interface parameter
712 Variable* resultListener = new Variable(resultsInterfaceType, "_result");
713 proxyMethod->parameters.push_back(resultListener);
714
715 // Add the results dispatcher callback
716 resultsDispatcherClass->needed = true;
717 resultParameter = new NewExpression(resultsDispatcherClass->type, 2,
718 new LiteralExpression(format_int(index)), resultListener);
719 } else {
720 resultParameter = NULL_VALUE;
721 }
722
723 // All proxy methods take an error parameter
724 Variable* errorListener = new Variable(RPC_ERROR_LISTENER_TYPE, "_errors");
725 proxyMethod->parameters.push_back(errorListener);
726
727 // Call the broker
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700728 proxyMethod->statements->Add(new MethodCall(new FieldVariable(THIS_VALUE, "_broker"),
729 "sendRpc", 5,
Joe Onorato7add83b2011-08-30 17:24:17 -0700730 proxyClass->endpoint,
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700731 new StringLiteralExpression(method->name.data),
Joe Onorato7add83b2011-08-30 17:24:17 -0700732 new MethodCall(_data, "serialize"),
733 resultParameter,
734 errorListener));
735}
736
737static void
738generate_result_dispatcher_method(const method_type* method,
739 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index)
740{
741 arg_type* arg;
742 Method* dispatchMethod;
743 Variable* dispatchParam;
744 resultsDispatcherClass->AddMethod(index, method->name.data, &dispatchMethod, &dispatchParam);
745
746 Variable* classLoader = NULL;
747 Variable* resultData = new Variable(RPC_DATA_TYPE, "resultData");
748 dispatchMethod->statements->Add(new VariableDeclaration(resultData,
749 new NewExpression(RPC_DATA_TYPE, 1, dispatchParam)));
750
751 // The callback method itself
752 MethodCall* realCall = new MethodCall(
753 new Cast(resultsInterfaceType, new FieldVariable(THIS_VALUE, "callback")),
754 results_method_name(method->name.data));
755
756 // The return value
757 {
758 Type* t = NAMES.Search(method->type.type.data);
Joe Onorato6980de42011-11-17 16:13:49 -0800759 if (t != VOID_TYPE) {
760 Variable* rv = new Variable(t, "rv");
761 dispatchMethod->statements->Add(new VariableDeclaration(rv));
762 generate_create_from_data(t, dispatchMethod->statements, "_result", rv,
763 resultData, &classLoader);
764 realCall->arguments.push_back(rv);
765 }
Joe Onorato7add83b2011-08-30 17:24:17 -0700766 }
767
768 VariableFactory stubArgs("arg");
769 arg = method->args;
770 while (arg != NULL) {
771 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
772 // Unmarshall the results
773 Type* t = NAMES.Search(arg->type.type.data);
774 Variable* v = stubArgs.Get(t);
775 dispatchMethod->statements->Add(new VariableDeclaration(v));
776
777 generate_create_from_data(t, dispatchMethod->statements, arg->name.data, v,
778 resultData, &classLoader);
779
780 // Add the argument to the callback
781 realCall->arguments.push_back(v);
782 }
783 arg = arg->next;
784 }
785
786 // Call the callback method
Manuel Roman9d98a082012-05-23 14:25:31 -0700787 IfStatement* ifst = new IfStatement;
788 ifst->expression = new Comparison(new FieldVariable(THIS_VALUE, "callback"), "!=", NULL_VALUE);
789 dispatchMethod->statements->Add(ifst);
790 ifst->statements->Add(realCall);
Joe Onorato7add83b2011-08-30 17:24:17 -0700791}
792
793static void
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700794generate_regular_method(const method_type* method, RpcProxyClass* proxyClass,
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700795 EndpointBaseClass* serviceBaseClass, ResultDispatcherClass* resultsDispatcherClass,
Joe Onorato7add83b2011-08-30 17:24:17 -0700796 int index)
797{
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700798 arg_type* arg;
799
800 // == the callback interface for results ================================
Joe Onorato7add83b2011-08-30 17:24:17 -0700801 // the service base class
802 Type* resultsInterfaceType = generate_results_method(method, proxyClass);
803
804 // == the method in the proxy class =====================================
805 generate_proxy_method(method, proxyClass, resultsDispatcherClass, resultsInterfaceType, index);
806
807 // == the method in the result dispatcher class =========================
808 if (resultsInterfaceType != NULL) {
809 generate_result_dispatcher_method(method, resultsDispatcherClass, resultsInterfaceType,
810 index);
811 }
812
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700813 // == The abstract method that the service developers implement ==========
814 Method* decl = new Method;
815 decl->comment = gather_comments(method->comments_token->extra);
816 decl->modifiers = PUBLIC | ABSTRACT;
817 decl->returnType = NAMES.Search(method->type.type.data);
818 decl->returnTypeDimension = method->type.dimension;
819 decl->name = method->name.data;
820 arg = method->args;
821 while (arg != NULL) {
822 decl->parameters.push_back(new Variable(
823 NAMES.Search(arg->type.type.data), arg->name.data,
824 arg->type.dimension));
825 arg = arg->next;
826 }
Manuel Roman2c5eb262011-10-06 10:28:35 -0700827
828 // Add the default RpcContext param to all methods
829 decl->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
830
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700831 serviceBaseClass->elements.push_back(decl);
832
833
Joe Onorato7add83b2011-08-30 17:24:17 -0700834 // == the dispatch method in the service base class ======================
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700835 serviceBaseClass->AddMethod(method);
836}
837
838static void
839generate_event_method(const method_type* method, RpcProxyClass* proxyClass,
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700840 EndpointBaseClass* serviceBaseClass, ListenerClass* listenerClass,
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700841 EventListenerClass* presenterClass, int index)
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700842{
843 arg_type* arg;
844 listenerClass->needed = true;
845
846 // == the push method in the service base class =========================
847 Method* push = new Method;
848 push->modifiers = PUBLIC;
849 push->name = push_method_name(method->name.data);
850 push->statements = new StatementBlock;
851 push->returnType = VOID_TYPE;
852 serviceBaseClass->elements.push_back(push);
853
854 // The local variables
855 Variable* _data = new Variable(RPC_DATA_TYPE, "_data");
856 push->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE)));
857
858 // Add the arguments
859 arg = method->args;
860 while (arg != NULL) {
861 // Function signature
862 Type* t = NAMES.Search(arg->type.type.data);
863 Variable* v = new Variable(t, arg->name.data, arg->type.dimension);
864 push->parameters.push_back(v);
865
866 // Input parameter marshalling
867 generate_write_to_data(t, push->statements,
868 new StringLiteralExpression(arg->name.data), v, _data);
869
870 arg = arg->next;
871 }
872
873 // Send the notifications
874 push->statements->Add(new MethodCall("pushEvent", 2,
875 new StringLiteralExpression(method->name.data),
876 new MethodCall(_data, "serialize")));
877
878 // == the event callback dispatcher method ====================================
879 presenterClass->AddMethod(method);
880
881 // == the event method in the listener base class =====================
882 Method* event = new Method;
883 event->modifiers = PUBLIC;
884 event->name = method->name.data;
885 event->statements = new StatementBlock;
886 event->returnType = VOID_TYPE;
887 listenerClass->elements.push_back(event);
888 arg = method->args;
889 while (arg != NULL) {
890 event->parameters.push_back(new Variable(
891 NAMES.Search(arg->type.type.data), arg->name.data,
892 arg->type.dimension));
893 arg = arg->next;
894 }
Manuel Roman2c5eb262011-10-06 10:28:35 -0700895
896 // Add a final parameter: RpcContext. Contains data about
897 // incoming request (e.g., certificate)
898 event->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700899}
900
901static void
902generate_listener_methods(RpcProxyClass* proxyClass, Type* presenterType, Type* listenerType)
903{
904 // AndroidAtHomePresenter _presenter;
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700905 // void startListening(Listener listener) {
906 // stopListening();
907 // _presenter = new Presenter(_broker, listener);
908 // _presenter.startListening(_endpoint);
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700909 // }
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700910 // void stopListening() {
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700911 // if (_presenter != null) {
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700912 // _presenter.stopListening();
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700913 // }
914 // }
915
916 Variable* _presenter = new Variable(presenterType, "_presenter");
917 proxyClass->elements.push_back(new Field(PRIVATE, _presenter));
918
919 Variable* listener = new Variable(listenerType, "listener");
920
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700921 Method* startListeningMethod = new Method;
922 startListeningMethod->modifiers = PUBLIC;
923 startListeningMethod->returnType = VOID_TYPE;
924 startListeningMethod->name = "startListening";
925 startListeningMethod->statements = new StatementBlock;
926 startListeningMethod->parameters.push_back(listener);
927 proxyClass->elements.push_back(startListeningMethod);
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700928
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700929 startListeningMethod->statements->Add(new MethodCall(THIS_VALUE, "stopListening"));
930 startListeningMethod->statements->Add(new Assignment(_presenter,
931 new NewExpression(presenterType, 2, proxyClass->broker, listener)));
932 startListeningMethod->statements->Add(new MethodCall(_presenter,
933 "startListening", 1, proxyClass->endpoint));
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700934
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700935 Method* stopListeningMethod = new Method;
936 stopListeningMethod->modifiers = PUBLIC;
937 stopListeningMethod->returnType = VOID_TYPE;
938 stopListeningMethod->name = "stopListening";
939 stopListeningMethod->statements = new StatementBlock;
940 proxyClass->elements.push_back(stopListeningMethod);
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700941
942 IfStatement* ifst = new IfStatement;
943 ifst->expression = new Comparison(_presenter, "!=", NULL_VALUE);
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700944 stopListeningMethod->statements->Add(ifst);
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700945
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700946 ifst->statements->Add(new MethodCall(_presenter, "stopListening"));
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700947 ifst->statements->Add(new Assignment(_presenter, NULL_VALUE));
Joe Onorato7add83b2011-08-30 17:24:17 -0700948}
949
950Class*
951generate_rpc_interface_class(const interface_type* iface)
952{
953 // the proxy class
954 InterfaceType* interfaceType = static_cast<InterfaceType*>(
955 NAMES.Find(iface->package, iface->name.data));
956 RpcProxyClass* proxy = new RpcProxyClass(iface, interfaceType);
957
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700958 // the listener class
959 ListenerClass* listener = new ListenerClass(iface);
960
961 // the presenter class
Joe Onoratoc7ec1dc2011-10-12 23:22:42 -0700962 EventListenerClass* presenter = new EventListenerClass(iface, listener->type);
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700963
Joe Onorato7add83b2011-08-30 17:24:17 -0700964 // the service base class
Joe Onorato0d2a6b62011-10-09 21:51:46 -0700965 EndpointBaseClass* base = new EndpointBaseClass(iface);
Joe Onorato7add83b2011-08-30 17:24:17 -0700966 proxy->elements.push_back(base);
967
968 // the result dispatcher
969 ResultDispatcherClass* results = new ResultDispatcherClass();
970
971 // all the declared methods of the proxy
972 int index = 0;
973 interface_item_type* item = iface->interface_items;
974 while (item != NULL) {
975 if (item->item_type == METHOD_TYPE) {
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700976 if (NAMES.Search(((method_type*)item)->type.type.data) == EVENT_FAKE_TYPE) {
977 generate_event_method((method_type*)item, proxy, base, listener, presenter, index);
978 } else {
979 generate_regular_method((method_type*)item, proxy, base, results, index);
980 }
Joe Onorato7add83b2011-08-30 17:24:17 -0700981 }
982 item = item->next;
983 index++;
984 }
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700985 presenter->DoneWithMethods();
Joe Onorato7add83b2011-08-30 17:24:17 -0700986 base->DoneWithMethods();
987
988 // only add this if there are methods with results / out parameters
989 if (results->needed) {
990 proxy->elements.push_back(results);
991 }
Joe Onoratoe415ecb2011-09-23 15:17:52 -0700992 if (listener->needed) {
993 proxy->elements.push_back(listener);
994 proxy->elements.push_back(presenter);
995 generate_listener_methods(proxy, presenter->type, listener->type);
996 }
Joe Onorato7add83b2011-08-30 17:24:17 -0700997
998 return proxy;
999}