blob: 5e4daccf6334811c1b9eedacedcb7a8ebd1ad2df [file] [log] [blame]
Joe Onoratofdfe2ff2011-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
Manuel Romanb71287f2011-10-06 10:28:35 -07008Type* SERVICE_CONTEXT_TYPE = new Type("android.content",
9 "Context", Type::BUILT_IN, false, false, false);
Mike Lockwood17a452f2012-02-17 10:38:00 -080010Type* PRESENTER_BASE_TYPE = new Type("android.support.place.connector",
Joe Onorato28087c62011-10-12 23:22:42 -070011 "EventListener", Type::BUILT_IN, false, false, false);
Mike Lockwood17a452f2012-02-17 10:38:00 -080012Type* PRESENTER_LISTENER_BASE_TYPE = new Type("android.support.place.connector",
Joe Onorato28087c62011-10-12 23:22:42 -070013 "EventListener.Listener", Type::BUILT_IN, false, false, false);
Mike Lockwood17a452f2012-02-17 10:38:00 -080014Type* RPC_BROKER_TYPE = new Type("android.support.place.connector", "Broker",
Joe Onoratoe24dbea2011-09-23 15:17:52 -070015 Type::BUILT_IN, false, false, false);
Joe Onorato95a766d2011-10-09 21:51:46 -070016Type* RPC_CONTAINER_TYPE = new Type("com.android.athome.connector", "ConnectorContainer",
Joe Onoratoe24dbea2011-09-23 15:17:52 -070017 Type::BUILT_IN, false, false, false);
Manuel Roman01060b02012-01-03 22:03:37 -080018Type* PLACE_INFO_TYPE = new Type("android.support.place.connector", "PlaceInfo",
19 Type::BUILT_IN, false, false, false);
Joe Onorato95a766d2011-10-09 21:51:46 -070020// TODO: Just use Endpoint, so this works for all endpoints.
Mike Lockwood17a452f2012-02-17 10:38:00 -080021Type* RPC_CONNECTOR_TYPE = new Type("android.support.place.connector", "Connector",
Joe Onorato95a766d2011-10-09 21:51:46 -070022 Type::BUILT_IN, false, false, false);
Mike Lockwood17a452f2012-02-17 10:38:00 -080023Type* RPC_ENDPOINT_INFO_TYPE = new UserDataType("android.support.place.rpc",
Joe Onorato95a766d2011-10-09 21:51:46 -070024 "EndpointInfo", true, __FILE__, __LINE__);
Mike Lockwood17a452f2012-02-17 10:38:00 -080025Type* RPC_RESULT_HANDLER_TYPE = new UserDataType("android.support.place.rpc", "RpcResultHandler",
Joe Onoratoe24dbea2011-09-23 15:17:52 -070026 true, __FILE__, __LINE__);
Mike Lockwood17a452f2012-02-17 10:38:00 -080027Type* RPC_ERROR_LISTENER_TYPE = new Type("android.support.place.rpc", "RpcErrorHandler",
Joe Onoratoe24dbea2011-09-23 15:17:52 -070028 Type::BUILT_IN, false, false, false);
Mike Lockwood17a452f2012-02-17 10:38:00 -080029Type* RPC_CONTEXT_TYPE = new UserDataType("android.support.place.rpc", "RpcContext", true,
Manuel Romanb71287f2011-10-06 10:28:35 -070030 __FILE__, __LINE__);
Joe Onoratoe24dbea2011-09-23 15:17:52 -070031
32static void generate_create_from_data(Type* t, StatementBlock* addTo, const string& key,
33 Variable* v, Variable* data, Variable** cl);
34static void generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from);
35static void generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v,
36 Variable* data);
Joe Onoratofdfe2ff2011-08-30 17:24:17 -070037
38static string
39format_int(int n)
40{
41 char str[20];
42 sprintf(str, "%d", n);
43 return string(str);
44}
45
46static string
47class_name_leaf(const string& str)
48{
49 string::size_type pos = str.rfind('.');
50 if (pos == string::npos) {
51 return str;
52 } else {
53 return string(str, pos+1);
54 }
55}
56
Joe Onoratoe24dbea2011-09-23 15:17:52 -070057static string
58results_class_name(const string& n)
59{
60 string str = n;
61 str[0] = toupper(str[0]);
62 str.insert(0, "On");
63 return str;
64}
65
66static string
67results_method_name(const string& n)
68{
69 string str = n;
70 str[0] = toupper(str[0]);
71 str.insert(0, "on");
72 return str;
73}
74
75static string
76push_method_name(const string& n)
77{
78 string str = n;
79 str[0] = toupper(str[0]);
80 str.insert(0, "push");
81 return str;
82}
83
84// =================================================
85class DispatcherClass : public Class
86{
87public:
88 DispatcherClass(const interface_type* iface, Expression* target);
89 virtual ~DispatcherClass();
90
91 void AddMethod(const method_type* method);
92 void DoneWithMethods();
93
94 Method* processMethod;
95 Variable* actionParam;
96 Variable* requestParam;
Manuel Romanb71287f2011-10-06 10:28:35 -070097 Variable* rpcContextParam;
Joe Onoratoe24dbea2011-09-23 15:17:52 -070098 Variable* errorParam;
99 Variable* requestData;
100 Variable* resultData;
101 IfStatement* dispatchIfStatement;
102 Expression* targetExpression;
103
104private:
105 void generate_process();
106};
107
108DispatcherClass::DispatcherClass(const interface_type* iface, Expression* target)
109 :Class(),
110 dispatchIfStatement(NULL),
111 targetExpression(target)
112{
113 generate_process();
114}
115
116DispatcherClass::~DispatcherClass()
117{
118}
119
120void
121DispatcherClass::generate_process()
122{
Manuel Romanb71287f2011-10-06 10:28:35 -0700123 // byte[] process(String action, byte[] params, RpcContext context, RpcError status)
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700124 this->processMethod = new Method;
125 this->processMethod->modifiers = PUBLIC;
126 this->processMethod->returnType = BYTE_TYPE;
127 this->processMethod->returnTypeDimension = 1;
128 this->processMethod->name = "process";
129 this->processMethod->statements = new StatementBlock;
130
131 this->actionParam = new Variable(STRING_TYPE, "action");
132 this->processMethod->parameters.push_back(this->actionParam);
133
134 this->requestParam = new Variable(BYTE_TYPE, "requestParam", 1);
135 this->processMethod->parameters.push_back(this->requestParam);
136
Manuel Romanb71287f2011-10-06 10:28:35 -0700137 this->rpcContextParam = new Variable(RPC_CONTEXT_TYPE, "context", 0);
138 this->processMethod->parameters.push_back(this->rpcContextParam);
139
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700140 this->errorParam = new Variable(RPC_ERROR_TYPE, "errorParam", 0);
141 this->processMethod->parameters.push_back(this->errorParam);
142
143 this->requestData = new Variable(RPC_DATA_TYPE, "request");
144 this->processMethod->statements->Add(new VariableDeclaration(requestData,
145 new NewExpression(RPC_DATA_TYPE, 1, this->requestParam)));
146
147 this->resultData = new Variable(RPC_DATA_TYPE, "resultData");
148 this->processMethod->statements->Add(new VariableDeclaration(this->resultData,
149 NULL_VALUE));
150}
151
152void
153DispatcherClass::AddMethod(const method_type* method)
154{
155 arg_type* arg;
156
157 // The if/switch statement
158 IfStatement* ifs = new IfStatement();
159 ifs->expression = new MethodCall(new StringLiteralExpression(method->name.data), "equals",
160 1, this->actionParam);
161 StatementBlock* block = ifs->statements = new StatementBlock;
162 if (this->dispatchIfStatement == NULL) {
163 this->dispatchIfStatement = ifs;
164 this->processMethod->statements->Add(dispatchIfStatement);
165 } else {
166 this->dispatchIfStatement->elseif = ifs;
167 this->dispatchIfStatement = ifs;
168 }
169
170 // The call to decl (from above)
171 MethodCall* realCall = new MethodCall(this->targetExpression, method->name.data);
172
173 // args
174 Variable* classLoader = NULL;
175 VariableFactory stubArgs("_arg");
176 arg = method->args;
177 while (arg != NULL) {
178 Type* t = NAMES.Search(arg->type.type.data);
179 Variable* v = stubArgs.Get(t);
180 v->dimension = arg->type.dimension;
181
182 // Unmarshall the parameter
183 block->Add(new VariableDeclaration(v));
184 if (convert_direction(arg->direction.data) & IN_PARAMETER) {
185 generate_create_from_data(t, block, arg->name.data, v,
186 this->requestData, &classLoader);
187 } else {
188 if (arg->type.dimension == 0) {
189 block->Add(new Assignment(v, new NewExpression(v->type)));
190 }
191 else if (arg->type.dimension == 1) {
192 generate_new_array(v->type, block, v, this->requestData);
193 }
194 else {
195 fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__,
196 __LINE__);
197 }
198 }
199
200 // Add that parameter to the method call
201 realCall->arguments.push_back(v);
202
203 arg = arg->next;
204 }
205
Manuel Romanb71287f2011-10-06 10:28:35 -0700206 // Add a final parameter: RpcContext. Contains data about
207 // incoming request (e.g., certificate)
208 realCall->arguments.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700209
210 Type* returnType = NAMES.Search(method->type.type.data);
211 if (returnType == EVENT_FAKE_TYPE) {
212 returnType = VOID_TYPE;
213 }
214
215 // the real call
216 bool first = true;
217 Variable* _result = NULL;
218 if (returnType == VOID_TYPE) {
219 block->Add(realCall);
220 } else {
221 _result = new Variable(returnType, "_result",
222 method->type.dimension);
223 block->Add(new VariableDeclaration(_result, realCall));
224
225 // need the result RpcData
226 if (first) {
227 block->Add(new Assignment(this->resultData,
228 new NewExpression(RPC_DATA_TYPE)));
229 first = false;
230 }
231
232 // marshall the return value
233 generate_write_to_data(returnType, block,
234 new StringLiteralExpression("_result"), _result, this->resultData);
235 }
236
237 // out parameters
238 int i = 0;
239 arg = method->args;
240 while (arg != NULL) {
241 Type* t = NAMES.Search(arg->type.type.data);
242 Variable* v = stubArgs.Get(i++);
243
244 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
245 // need the result RpcData
246 if (first) {
247 block->Add(new Assignment(this->resultData, new NewExpression(RPC_DATA_TYPE)));
248 first = false;
249 }
250
251 generate_write_to_data(t, block, new StringLiteralExpression(arg->name.data),
252 v, this->resultData);
253 }
254
255 arg = arg->next;
256 }
257}
258
259void
260DispatcherClass::DoneWithMethods()
261{
262 if (this->dispatchIfStatement == NULL) {
263 return;
264 }
265
266 this->elements.push_back(this->processMethod);
267
268 IfStatement* fallthrough = new IfStatement();
269 fallthrough->statements = new StatementBlock;
270 fallthrough->statements->Add(new ReturnStatement(
Manuel Romanb71287f2011-10-06 10:28:35 -0700271 new MethodCall(SUPER_VALUE, "process", 4,
272 this->actionParam, this->requestParam,
273 this->rpcContextParam,
274 this->errorParam)));
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700275 this->dispatchIfStatement->elseif = fallthrough;
276 IfStatement* s = new IfStatement;
277 s->statements = new StatementBlock;
278 this->processMethod->statements->Add(s);
279 s->expression = new Comparison(this->resultData, "!=", NULL_VALUE);
280 s->statements->Add(new ReturnStatement(new MethodCall(this->resultData, "serialize")));
281 s->elseif = new IfStatement;
282 s = s->elseif;
283 s->statements->Add(new ReturnStatement(NULL_VALUE));
284}
285
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700286// =================================================
287class RpcProxyClass : public Class
288{
289public:
290 RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType);
291 virtual ~RpcProxyClass();
292
293 Variable* endpoint;
Joe Onorato95a766d2011-10-09 21:51:46 -0700294 Variable* broker;
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700295
296private:
297 void generate_ctor();
Jason Simmons7dc29732011-12-16 16:14:17 -0800298 void generate_get_endpoint_info();
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700299};
300
301RpcProxyClass::RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType)
302 :Class()
303{
304 this->comment = gather_comments(iface->comments_token->extra);
305 this->modifiers = PUBLIC;
306 this->what = Class::CLASS;
307 this->type = interfaceType;
308
Joe Onorato95a766d2011-10-09 21:51:46 -0700309 // broker
310 this->broker = new Variable(RPC_BROKER_TYPE, "_broker");
311 this->elements.push_back(new Field(PRIVATE, this->broker));
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700312 // endpoint
Joe Onorato95a766d2011-10-09 21:51:46 -0700313 this->endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "_endpoint");
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700314 this->elements.push_back(new Field(PRIVATE, this->endpoint));
315
316 // methods
317 generate_ctor();
Jason Simmons7dc29732011-12-16 16:14:17 -0800318 generate_get_endpoint_info();
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700319}
320
321RpcProxyClass::~RpcProxyClass()
322{
323}
324
325void
326RpcProxyClass::generate_ctor()
327{
Joe Onorato95a766d2011-10-09 21:51:46 -0700328 Variable* broker = new Variable(RPC_BROKER_TYPE, "broker");
329 Variable* endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "endpoint");
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700330 Method* ctor = new Method;
331 ctor->modifiers = PUBLIC;
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700332 ctor->name = class_name_leaf(this->type->Name());
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700333 ctor->statements = new StatementBlock;
Joe Onorato95a766d2011-10-09 21:51:46 -0700334 ctor->parameters.push_back(broker);
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700335 ctor->parameters.push_back(endpoint);
336 this->elements.push_back(ctor);
337
Joe Onorato95a766d2011-10-09 21:51:46 -0700338 ctor->statements->Add(new Assignment(this->broker, broker));
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700339 ctor->statements->Add(new Assignment(this->endpoint, endpoint));
340}
341
Jason Simmons7dc29732011-12-16 16:14:17 -0800342void
343RpcProxyClass::generate_get_endpoint_info()
344{
345 Method* get = new Method;
346 get->modifiers = PUBLIC;
347 get->returnType = RPC_ENDPOINT_INFO_TYPE;
348 get->name = "getEndpointInfo";
349 get->statements = new StatementBlock;
350 this->elements.push_back(get);
351
352 get->statements->Add(new ReturnStatement(this->endpoint));
353}
354
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700355// =================================================
Joe Onorato28087c62011-10-12 23:22:42 -0700356class EventListenerClass : public DispatcherClass
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700357{
358public:
Joe Onorato28087c62011-10-12 23:22:42 -0700359 EventListenerClass(const interface_type* iface, Type* listenerType);
360 virtual ~EventListenerClass();
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700361
362 Variable* _listener;
363
364private:
365 void generate_ctor();
366};
367
368Expression*
369generate_get_listener_expression(Type* cast)
370{
371 return new Cast(cast, new MethodCall(THIS_VALUE, "getView"));
372}
373
Joe Onorato28087c62011-10-12 23:22:42 -0700374EventListenerClass::EventListenerClass(const interface_type* iface, Type* listenerType)
375 :DispatcherClass(iface, new FieldVariable(THIS_VALUE, "_listener"))
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700376{
377 this->modifiers = PRIVATE;
378 this->what = Class::CLASS;
379 this->type = new Type(iface->package ? iface->package : "",
380 append(iface->name.data, ".Presenter"),
381 Type::GENERATED, false, false, false);
382 this->extends = PRESENTER_BASE_TYPE;
383
384 this->_listener = new Variable(listenerType, "_listener");
Tim Kilbourn22a7cb82011-09-27 10:30:53 -0700385 this->elements.push_back(new Field(PRIVATE, this->_listener));
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700386
387 // methods
388 generate_ctor();
389}
390
Joe Onorato28087c62011-10-12 23:22:42 -0700391EventListenerClass::~EventListenerClass()
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700392{
393}
394
395void
Joe Onorato28087c62011-10-12 23:22:42 -0700396EventListenerClass::generate_ctor()
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700397{
Joe Onorato95a766d2011-10-09 21:51:46 -0700398 Variable* broker = new Variable(RPC_BROKER_TYPE, "broker");
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700399 Variable* listener = new Variable(this->_listener->type, "listener");
400 Method* ctor = new Method;
401 ctor->modifiers = PUBLIC;
402 ctor->name = class_name_leaf(this->type->Name());
403 ctor->statements = new StatementBlock;
Joe Onorato95a766d2011-10-09 21:51:46 -0700404 ctor->parameters.push_back(broker);
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700405 ctor->parameters.push_back(listener);
406 this->elements.push_back(ctor);
407
Joe Onorato28087c62011-10-12 23:22:42 -0700408 ctor->statements->Add(new MethodCall("super", 2, broker, listener));
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700409 ctor->statements->Add(new Assignment(this->_listener, listener));
410}
411
412// =================================================
413class ListenerClass : public Class
414{
415public:
416 ListenerClass(const interface_type* iface);
417 virtual ~ListenerClass();
418
419 bool needed;
420
421private:
422 void generate_ctor();
423};
424
425ListenerClass::ListenerClass(const interface_type* iface)
426 :Class(),
427 needed(false)
428{
429 this->comment = "/** Extend this to listen to the events from this class. */";
430 this->modifiers = STATIC | PUBLIC ;
431 this->what = Class::CLASS;
432 this->type = new Type(iface->package ? iface->package : "",
433 append(iface->name.data, ".Listener"),
434 Type::GENERATED, false, false, false);
435 this->extends = PRESENTER_LISTENER_BASE_TYPE;
436}
437
438ListenerClass::~ListenerClass()
439{
440}
441
442// =================================================
Joe Onorato95a766d2011-10-09 21:51:46 -0700443class EndpointBaseClass : public DispatcherClass
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700444{
445public:
Joe Onorato95a766d2011-10-09 21:51:46 -0700446 EndpointBaseClass(const interface_type* iface);
447 virtual ~EndpointBaseClass();
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700448
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700449 bool needed;
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700450
451private:
452 void generate_ctor();
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700453};
454
Joe Onorato95a766d2011-10-09 21:51:46 -0700455EndpointBaseClass::EndpointBaseClass(const interface_type* iface)
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700456 :DispatcherClass(iface, THIS_VALUE),
457 needed(false)
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700458{
459 this->comment = "/** Extend this to implement a link service. */";
460 this->modifiers = STATIC | PUBLIC | ABSTRACT;
461 this->what = Class::CLASS;
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700462 this->type = new Type(iface->package ? iface->package : "",
Joe Onorato95a766d2011-10-09 21:51:46 -0700463 append(iface->name.data, ".EndpointBase"),
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700464 Type::GENERATED, false, false, false);
Joe Onorato95a766d2011-10-09 21:51:46 -0700465 this->extends = RPC_CONNECTOR_TYPE;
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700466
467 // methods
468 generate_ctor();
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700469}
470
Joe Onorato95a766d2011-10-09 21:51:46 -0700471EndpointBaseClass::~EndpointBaseClass()
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700472{
473}
474
475void
Joe Onorato95a766d2011-10-09 21:51:46 -0700476EndpointBaseClass::generate_ctor()
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700477{
Joe Onorato95a766d2011-10-09 21:51:46 -0700478 Variable* container = new Variable(RPC_CONTAINER_TYPE, "container");
479 Variable* broker = new Variable(RPC_BROKER_TYPE, "broker");
Manuel Roman01060b02012-01-03 22:03:37 -0800480 Variable* place = new Variable(PLACE_INFO_TYPE, "placeInfo");
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700481 Method* ctor = new Method;
482 ctor->modifiers = PUBLIC;
483 ctor->name = class_name_leaf(this->type->Name());
484 ctor->statements = new StatementBlock;
Joe Onorato95a766d2011-10-09 21:51:46 -0700485 ctor->parameters.push_back(container);
486 ctor->parameters.push_back(broker);
Manuel Roman01060b02012-01-03 22:03:37 -0800487 ctor->parameters.push_back(place);
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700488 this->elements.push_back(ctor);
489
Manuel Roman01060b02012-01-03 22:03:37 -0800490 ctor->statements->Add(new MethodCall("super", 3, container, broker, place));
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700491}
492
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700493// =================================================
494class ResultDispatcherClass : public Class
495{
496public:
497 ResultDispatcherClass();
498 virtual ~ResultDispatcherClass();
499
500 void AddMethod(int index, const string& name, Method** method, Variable** param);
501
502 bool needed;
503 Variable* methodId;
504 Variable* callback;
505 Method* onResultMethod;
506 Variable* resultParam;
507 SwitchStatement* methodSwitch;
508
509private:
510 void generate_ctor();
511 void generate_onResult();
512};
513
514ResultDispatcherClass::ResultDispatcherClass()
515 :Class(),
516 needed(false)
517{
518 this->modifiers = PRIVATE | FINAL;
519 this->what = Class::CLASS;
Joe Onorato7db766c2011-09-15 21:31:15 -0700520 this->type = new Type("_ResultDispatcher", Type::GENERATED, false, false, false);
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700521 this->interfaces.push_back(RPC_RESULT_HANDLER_TYPE);
522
523 // methodId
524 this->methodId = new Variable(INT_TYPE, "methodId");
525 this->elements.push_back(new Field(PRIVATE, this->methodId));
526 this->callback = new Variable(OBJECT_TYPE, "callback");
527 this->elements.push_back(new Field(PRIVATE, this->callback));
528
529 // methods
530 generate_ctor();
531 generate_onResult();
532}
533
534ResultDispatcherClass::~ResultDispatcherClass()
535{
536}
537
538void
539ResultDispatcherClass::generate_ctor()
540{
541 Variable* methodIdParam = new Variable(INT_TYPE, "methId");
542 Variable* callbackParam = new Variable(OBJECT_TYPE, "cbObj");
543 Method* ctor = new Method;
544 ctor->modifiers = PUBLIC;
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700545 ctor->name = class_name_leaf(this->type->Name());
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700546 ctor->statements = new StatementBlock;
547 ctor->parameters.push_back(methodIdParam);
548 ctor->parameters.push_back(callbackParam);
549 this->elements.push_back(ctor);
550
551 ctor->statements->Add(new Assignment(this->methodId, methodIdParam));
552 ctor->statements->Add(new Assignment(this->callback, callbackParam));
553}
554
555void
556ResultDispatcherClass::generate_onResult()
557{
558 this->onResultMethod = new Method;
559 this->onResultMethod->modifiers = PUBLIC;
560 this->onResultMethod->returnType = VOID_TYPE;
561 this->onResultMethod->returnTypeDimension = 0;
562 this->onResultMethod->name = "onResult";
563 this->onResultMethod->statements = new StatementBlock;
564 this->elements.push_back(this->onResultMethod);
565
566 this->resultParam = new Variable(BYTE_TYPE, "result", 1);
567 this->onResultMethod->parameters.push_back(this->resultParam);
568
569 this->methodSwitch = new SwitchStatement(this->methodId);
570 this->onResultMethod->statements->Add(this->methodSwitch);
571}
572
573void
574ResultDispatcherClass::AddMethod(int index, const string& name, Method** method, Variable** param)
575{
576 Method* m = new Method;
577 m->modifiers = PUBLIC;
578 m->returnType = VOID_TYPE;
579 m->returnTypeDimension = 0;
580 m->name = name;
581 m->statements = new StatementBlock;
582 *param = new Variable(BYTE_TYPE, "result", 1);
583 m->parameters.push_back(*param);
584 this->elements.push_back(m);
585 *method = m;
586
587 Case* c = new Case(format_int(index));
588 c->statements->Add(new MethodCall(new LiteralExpression("this"), name, 1, this->resultParam));
Joe Onorato05ffbe72011-09-02 15:28:36 -0700589 c->statements->Add(new Break());
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700590
591 this->methodSwitch->cases.push_back(c);
592}
593
594// =================================================
595static void
596generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from)
597{
598 fprintf(stderr, "aidl: implement generate_new_array %s:%d\n", __FILE__, __LINE__);
599 exit(1);
600}
601
602static void
603generate_create_from_data(Type* t, StatementBlock* addTo, const string& key, Variable* v,
604 Variable* data, Variable** cl)
605{
606 Expression* k = new StringLiteralExpression(key);
607 if (v->dimension == 0) {
608 t->CreateFromRpcData(addTo, k, v, data, cl);
609 }
610 if (v->dimension == 1) {
611 //t->ReadArrayFromRpcData(addTo, v, data, cl);
612 fprintf(stderr, "aidl: implement generate_create_from_data for arrays%s:%d\n",
613 __FILE__, __LINE__);
614 }
615}
616
617static void
618generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v, Variable* data)
619{
620 if (v->dimension == 0) {
621 t->WriteToRpcData(addTo, k, v, data, 0);
622 }
623 if (v->dimension == 1) {
624 //t->WriteArrayToParcel(addTo, v, data);
625 fprintf(stderr, "aidl: implement generate_write_to_data for arrays%s:%d\n",
626 __FILE__, __LINE__);
627 }
628}
629
630// =================================================
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700631static Type*
632generate_results_method(const method_type* method, RpcProxyClass* proxyClass)
633{
634 arg_type* arg;
635
636 string resultsMethodName = results_method_name(method->name.data);
637 Type* resultsInterfaceType = new Type(results_class_name(method->name.data),
Joe Onorato7db766c2011-09-15 21:31:15 -0700638 Type::GENERATED, false, false, false);
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700639
640 if (!method->oneway) {
641 Class* resultsClass = new Class;
642 resultsClass->modifiers = STATIC | PUBLIC;
643 resultsClass->what = Class::INTERFACE;
644 resultsClass->type = resultsInterfaceType;
645
646 Method* resultMethod = new Method;
647 resultMethod->comment = gather_comments(method->comments_token->extra);
648 resultMethod->modifiers = PUBLIC;
649 resultMethod->returnType = VOID_TYPE;
650 resultMethod->returnTypeDimension = 0;
651 resultMethod->name = resultsMethodName;
652 if (0 != strcmp("void", method->type.type.data)) {
653 resultMethod->parameters.push_back(new Variable(NAMES.Search(method->type.type.data),
654 "_result", method->type.dimension));
655 }
656 arg = method->args;
657 while (arg != NULL) {
658 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
659 resultMethod->parameters.push_back(new Variable(
660 NAMES.Search(arg->type.type.data), arg->name.data,
661 arg->type.dimension));
662 }
663 arg = arg->next;
664 }
665 resultsClass->elements.push_back(resultMethod);
666
667 if (resultMethod->parameters.size() > 0) {
668 proxyClass->elements.push_back(resultsClass);
669 return resultsInterfaceType;
670 }
671 }
672 //delete resultsInterfaceType;
673 return NULL;
674}
675
676static void
677generate_proxy_method(const method_type* method, RpcProxyClass* proxyClass,
678 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index)
679{
680 arg_type* arg;
681 Method* proxyMethod = new Method;
682 proxyMethod->comment = gather_comments(method->comments_token->extra);
683 proxyMethod->modifiers = PUBLIC;
684 proxyMethod->returnType = VOID_TYPE;
685 proxyMethod->returnTypeDimension = 0;
686 proxyMethod->name = method->name.data;
687 proxyMethod->statements = new StatementBlock;
688 proxyClass->elements.push_back(proxyMethod);
689
690 // The local variables
691 Variable* _data = new Variable(RPC_DATA_TYPE, "_data");
692 proxyMethod->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE)));
693
694 // Add the arguments
695 arg = method->args;
696 while (arg != NULL) {
697 if (convert_direction(arg->direction.data) & IN_PARAMETER) {
698 // Function signature
699 Type* t = NAMES.Search(arg->type.type.data);
700 Variable* v = new Variable(t, arg->name.data, arg->type.dimension);
701 proxyMethod->parameters.push_back(v);
702
703 // Input parameter marshalling
704 generate_write_to_data(t, proxyMethod->statements,
705 new StringLiteralExpression(arg->name.data), v, _data);
706 }
707 arg = arg->next;
708 }
709
710 // If there is a results interface for this class
711 Expression* resultParameter;
712 if (resultsInterfaceType != NULL) {
713 // Result interface parameter
714 Variable* resultListener = new Variable(resultsInterfaceType, "_result");
715 proxyMethod->parameters.push_back(resultListener);
716
717 // Add the results dispatcher callback
718 resultsDispatcherClass->needed = true;
719 resultParameter = new NewExpression(resultsDispatcherClass->type, 2,
720 new LiteralExpression(format_int(index)), resultListener);
721 } else {
722 resultParameter = NULL_VALUE;
723 }
724
725 // All proxy methods take an error parameter
726 Variable* errorListener = new Variable(RPC_ERROR_LISTENER_TYPE, "_errors");
727 proxyMethod->parameters.push_back(errorListener);
728
729 // Call the broker
Joe Onorato95a766d2011-10-09 21:51:46 -0700730 proxyMethod->statements->Add(new MethodCall(new FieldVariable(THIS_VALUE, "_broker"),
731 "sendRpc", 5,
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700732 proxyClass->endpoint,
Joe Onorato95a766d2011-10-09 21:51:46 -0700733 new StringLiteralExpression(method->name.data),
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700734 new MethodCall(_data, "serialize"),
735 resultParameter,
736 errorListener));
737}
738
739static void
740generate_result_dispatcher_method(const method_type* method,
741 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index)
742{
743 arg_type* arg;
744 Method* dispatchMethod;
745 Variable* dispatchParam;
746 resultsDispatcherClass->AddMethod(index, method->name.data, &dispatchMethod, &dispatchParam);
747
748 Variable* classLoader = NULL;
749 Variable* resultData = new Variable(RPC_DATA_TYPE, "resultData");
750 dispatchMethod->statements->Add(new VariableDeclaration(resultData,
751 new NewExpression(RPC_DATA_TYPE, 1, dispatchParam)));
752
753 // The callback method itself
754 MethodCall* realCall = new MethodCall(
755 new Cast(resultsInterfaceType, new FieldVariable(THIS_VALUE, "callback")),
756 results_method_name(method->name.data));
757
758 // The return value
759 {
760 Type* t = NAMES.Search(method->type.type.data);
Joe Onorato0a7eaec2011-11-17 16:13:49 -0800761 if (t != VOID_TYPE) {
762 Variable* rv = new Variable(t, "rv");
763 dispatchMethod->statements->Add(new VariableDeclaration(rv));
764 generate_create_from_data(t, dispatchMethod->statements, "_result", rv,
765 resultData, &classLoader);
766 realCall->arguments.push_back(rv);
767 }
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700768 }
769
770 VariableFactory stubArgs("arg");
771 arg = method->args;
772 while (arg != NULL) {
773 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
774 // Unmarshall the results
775 Type* t = NAMES.Search(arg->type.type.data);
776 Variable* v = stubArgs.Get(t);
777 dispatchMethod->statements->Add(new VariableDeclaration(v));
778
779 generate_create_from_data(t, dispatchMethod->statements, arg->name.data, v,
780 resultData, &classLoader);
781
782 // Add the argument to the callback
783 realCall->arguments.push_back(v);
784 }
785 arg = arg->next;
786 }
787
788 // Call the callback method
Manuel Roman9d98a082012-05-23 14:25:31 -0700789 IfStatement* ifst = new IfStatement;
790 ifst->expression = new Comparison(new FieldVariable(THIS_VALUE, "callback"), "!=", NULL_VALUE);
791 dispatchMethod->statements->Add(ifst);
792 ifst->statements->Add(realCall);
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700793}
794
795static void
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700796generate_regular_method(const method_type* method, RpcProxyClass* proxyClass,
Joe Onorato95a766d2011-10-09 21:51:46 -0700797 EndpointBaseClass* serviceBaseClass, ResultDispatcherClass* resultsDispatcherClass,
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700798 int index)
799{
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700800 arg_type* arg;
801
802 // == the callback interface for results ================================
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700803 // the service base class
804 Type* resultsInterfaceType = generate_results_method(method, proxyClass);
805
806 // == the method in the proxy class =====================================
807 generate_proxy_method(method, proxyClass, resultsDispatcherClass, resultsInterfaceType, index);
808
809 // == the method in the result dispatcher class =========================
810 if (resultsInterfaceType != NULL) {
811 generate_result_dispatcher_method(method, resultsDispatcherClass, resultsInterfaceType,
812 index);
813 }
814
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700815 // == The abstract method that the service developers implement ==========
816 Method* decl = new Method;
817 decl->comment = gather_comments(method->comments_token->extra);
818 decl->modifiers = PUBLIC | ABSTRACT;
819 decl->returnType = NAMES.Search(method->type.type.data);
820 decl->returnTypeDimension = method->type.dimension;
821 decl->name = method->name.data;
822 arg = method->args;
823 while (arg != NULL) {
824 decl->parameters.push_back(new Variable(
825 NAMES.Search(arg->type.type.data), arg->name.data,
826 arg->type.dimension));
827 arg = arg->next;
828 }
Manuel Romanb71287f2011-10-06 10:28:35 -0700829
830 // Add the default RpcContext param to all methods
831 decl->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
832
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700833 serviceBaseClass->elements.push_back(decl);
834
835
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700836 // == the dispatch method in the service base class ======================
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700837 serviceBaseClass->AddMethod(method);
838}
839
840static void
841generate_event_method(const method_type* method, RpcProxyClass* proxyClass,
Joe Onorato95a766d2011-10-09 21:51:46 -0700842 EndpointBaseClass* serviceBaseClass, ListenerClass* listenerClass,
Joe Onorato28087c62011-10-12 23:22:42 -0700843 EventListenerClass* presenterClass, int index)
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700844{
845 arg_type* arg;
846 listenerClass->needed = true;
847
848 // == the push method in the service base class =========================
849 Method* push = new Method;
850 push->modifiers = PUBLIC;
851 push->name = push_method_name(method->name.data);
852 push->statements = new StatementBlock;
853 push->returnType = VOID_TYPE;
854 serviceBaseClass->elements.push_back(push);
855
856 // The local variables
857 Variable* _data = new Variable(RPC_DATA_TYPE, "_data");
858 push->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE)));
859
860 // Add the arguments
861 arg = method->args;
862 while (arg != NULL) {
863 // Function signature
864 Type* t = NAMES.Search(arg->type.type.data);
865 Variable* v = new Variable(t, arg->name.data, arg->type.dimension);
866 push->parameters.push_back(v);
867
868 // Input parameter marshalling
869 generate_write_to_data(t, push->statements,
870 new StringLiteralExpression(arg->name.data), v, _data);
871
872 arg = arg->next;
873 }
874
875 // Send the notifications
876 push->statements->Add(new MethodCall("pushEvent", 2,
877 new StringLiteralExpression(method->name.data),
878 new MethodCall(_data, "serialize")));
879
880 // == the event callback dispatcher method ====================================
881 presenterClass->AddMethod(method);
882
883 // == the event method in the listener base class =====================
884 Method* event = new Method;
885 event->modifiers = PUBLIC;
886 event->name = method->name.data;
887 event->statements = new StatementBlock;
888 event->returnType = VOID_TYPE;
889 listenerClass->elements.push_back(event);
890 arg = method->args;
891 while (arg != NULL) {
892 event->parameters.push_back(new Variable(
893 NAMES.Search(arg->type.type.data), arg->name.data,
894 arg->type.dimension));
895 arg = arg->next;
896 }
Manuel Romanb71287f2011-10-06 10:28:35 -0700897
898 // Add a final parameter: RpcContext. Contains data about
899 // incoming request (e.g., certificate)
900 event->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700901}
902
903static void
904generate_listener_methods(RpcProxyClass* proxyClass, Type* presenterType, Type* listenerType)
905{
906 // AndroidAtHomePresenter _presenter;
Joe Onorato28087c62011-10-12 23:22:42 -0700907 // void startListening(Listener listener) {
908 // stopListening();
909 // _presenter = new Presenter(_broker, listener);
910 // _presenter.startListening(_endpoint);
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700911 // }
Joe Onorato28087c62011-10-12 23:22:42 -0700912 // void stopListening() {
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700913 // if (_presenter != null) {
Joe Onorato28087c62011-10-12 23:22:42 -0700914 // _presenter.stopListening();
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700915 // }
916 // }
917
918 Variable* _presenter = new Variable(presenterType, "_presenter");
919 proxyClass->elements.push_back(new Field(PRIVATE, _presenter));
920
921 Variable* listener = new Variable(listenerType, "listener");
922
Joe Onorato28087c62011-10-12 23:22:42 -0700923 Method* startListeningMethod = new Method;
924 startListeningMethod->modifiers = PUBLIC;
925 startListeningMethod->returnType = VOID_TYPE;
926 startListeningMethod->name = "startListening";
927 startListeningMethod->statements = new StatementBlock;
928 startListeningMethod->parameters.push_back(listener);
929 proxyClass->elements.push_back(startListeningMethod);
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700930
Joe Onorato28087c62011-10-12 23:22:42 -0700931 startListeningMethod->statements->Add(new MethodCall(THIS_VALUE, "stopListening"));
932 startListeningMethod->statements->Add(new Assignment(_presenter,
933 new NewExpression(presenterType, 2, proxyClass->broker, listener)));
934 startListeningMethod->statements->Add(new MethodCall(_presenter,
935 "startListening", 1, proxyClass->endpoint));
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700936
Joe Onorato28087c62011-10-12 23:22:42 -0700937 Method* stopListeningMethod = new Method;
938 stopListeningMethod->modifiers = PUBLIC;
939 stopListeningMethod->returnType = VOID_TYPE;
940 stopListeningMethod->name = "stopListening";
941 stopListeningMethod->statements = new StatementBlock;
942 proxyClass->elements.push_back(stopListeningMethod);
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700943
944 IfStatement* ifst = new IfStatement;
945 ifst->expression = new Comparison(_presenter, "!=", NULL_VALUE);
Joe Onorato28087c62011-10-12 23:22:42 -0700946 stopListeningMethod->statements->Add(ifst);
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700947
Joe Onorato28087c62011-10-12 23:22:42 -0700948 ifst->statements->Add(new MethodCall(_presenter, "stopListening"));
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700949 ifst->statements->Add(new Assignment(_presenter, NULL_VALUE));
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700950}
951
952Class*
953generate_rpc_interface_class(const interface_type* iface)
954{
955 // the proxy class
956 InterfaceType* interfaceType = static_cast<InterfaceType*>(
957 NAMES.Find(iface->package, iface->name.data));
958 RpcProxyClass* proxy = new RpcProxyClass(iface, interfaceType);
959
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700960 // the listener class
961 ListenerClass* listener = new ListenerClass(iface);
962
963 // the presenter class
Joe Onorato28087c62011-10-12 23:22:42 -0700964 EventListenerClass* presenter = new EventListenerClass(iface, listener->type);
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700965
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700966 // the service base class
Joe Onorato95a766d2011-10-09 21:51:46 -0700967 EndpointBaseClass* base = new EndpointBaseClass(iface);
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700968 proxy->elements.push_back(base);
969
970 // the result dispatcher
971 ResultDispatcherClass* results = new ResultDispatcherClass();
972
973 // all the declared methods of the proxy
974 int index = 0;
975 interface_item_type* item = iface->interface_items;
976 while (item != NULL) {
977 if (item->item_type == METHOD_TYPE) {
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700978 if (NAMES.Search(((method_type*)item)->type.type.data) == EVENT_FAKE_TYPE) {
979 generate_event_method((method_type*)item, proxy, base, listener, presenter, index);
980 } else {
981 generate_regular_method((method_type*)item, proxy, base, results, index);
982 }
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700983 }
984 item = item->next;
985 index++;
986 }
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700987 presenter->DoneWithMethods();
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700988 base->DoneWithMethods();
989
990 // only add this if there are methods with results / out parameters
991 if (results->needed) {
992 proxy->elements.push_back(results);
993 }
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700994 if (listener->needed) {
995 proxy->elements.push_back(listener);
996 proxy->elements.push_back(presenter);
997 generate_listener_methods(proxy, presenter->type, listener->type);
998 }
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700999
1000 return proxy;
1001}