blob: 8353c458b2a6a098b2189bb6f2085ceeaf854991 [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);
Joe Onoratoe24dbea2011-09-23 15:17:52 -070010Type* PRESENTER_BASE_TYPE = new Type("com.android.athome.service",
11 "AndroidAtHomePresenter", Type::BUILT_IN, false, false, false);
12Type* PRESENTER_LISTENER_BASE_TYPE = new Type("com.android.athome.service",
13 "AndroidAtHomePresenter.Listener", Type::BUILT_IN, false, false, false);
14Type* RPC_BROKER_TYPE = new Type("com.android.athome.utils", "AndroidAtHomeBroker",
15 Type::BUILT_IN, false, false, false);
16Type* RPC_SERVICE_BASE_TYPE = new Type("com.android.athome.service", "AndroidAtHomeService",
17 Type::BUILT_IN, false, false, false);
18Type* RPC_SERVICE_INFO_TYPE = new ParcelableType("com.android.athome.stubs",
19 "AndroidAtHomeServiceInfo", true, __FILE__, __LINE__);
20Type* RPC_RESULT_HANDLER_TYPE = new ParcelableType("com.android.athome.rpc", "RpcResultHandler",
21 true, __FILE__, __LINE__);
22Type* RPC_ERROR_LISTENER_TYPE = new Type("com.android.athome.rpc", "RpcErrorHandler",
23 Type::BUILT_IN, false, false, false);
Manuel Romanb71287f2011-10-06 10:28:35 -070024Type* RPC_CONTEXT_TYPE = new ParcelableType("com.android.athome.rpc", "RpcContext", true,
25 __FILE__, __LINE__);
Joe Onoratoe24dbea2011-09-23 15:17:52 -070026
27static void generate_create_from_data(Type* t, StatementBlock* addTo, const string& key,
28 Variable* v, Variable* data, Variable** cl);
29static void generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from);
30static void generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v,
31 Variable* data);
Joe Onoratofdfe2ff2011-08-30 17:24:17 -070032
33static string
34format_int(int n)
35{
36 char str[20];
37 sprintf(str, "%d", n);
38 return string(str);
39}
40
41static string
42class_name_leaf(const string& str)
43{
44 string::size_type pos = str.rfind('.');
45 if (pos == string::npos) {
46 return str;
47 } else {
48 return string(str, pos+1);
49 }
50}
51
Joe Onoratoe24dbea2011-09-23 15:17:52 -070052static string
53results_class_name(const string& n)
54{
55 string str = n;
56 str[0] = toupper(str[0]);
57 str.insert(0, "On");
58 return str;
59}
60
61static string
62results_method_name(const string& n)
63{
64 string str = n;
65 str[0] = toupper(str[0]);
66 str.insert(0, "on");
67 return str;
68}
69
70static string
71push_method_name(const string& n)
72{
73 string str = n;
74 str[0] = toupper(str[0]);
75 str.insert(0, "push");
76 return str;
77}
78
79// =================================================
80class DispatcherClass : public Class
81{
82public:
83 DispatcherClass(const interface_type* iface, Expression* target);
84 virtual ~DispatcherClass();
85
86 void AddMethod(const method_type* method);
87 void DoneWithMethods();
88
89 Method* processMethod;
90 Variable* actionParam;
91 Variable* requestParam;
Manuel Romanb71287f2011-10-06 10:28:35 -070092 Variable* rpcContextParam;
Joe Onoratoe24dbea2011-09-23 15:17:52 -070093 Variable* errorParam;
94 Variable* requestData;
95 Variable* resultData;
96 IfStatement* dispatchIfStatement;
97 Expression* targetExpression;
98
99private:
100 void generate_process();
101};
102
103DispatcherClass::DispatcherClass(const interface_type* iface, Expression* target)
104 :Class(),
105 dispatchIfStatement(NULL),
106 targetExpression(target)
107{
108 generate_process();
109}
110
111DispatcherClass::~DispatcherClass()
112{
113}
114
115void
116DispatcherClass::generate_process()
117{
Manuel Romanb71287f2011-10-06 10:28:35 -0700118 // byte[] process(String action, byte[] params, RpcContext context, RpcError status)
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700119 this->processMethod = new Method;
120 this->processMethod->modifiers = PUBLIC;
121 this->processMethod->returnType = BYTE_TYPE;
122 this->processMethod->returnTypeDimension = 1;
123 this->processMethod->name = "process";
124 this->processMethod->statements = new StatementBlock;
125
126 this->actionParam = new Variable(STRING_TYPE, "action");
127 this->processMethod->parameters.push_back(this->actionParam);
128
129 this->requestParam = new Variable(BYTE_TYPE, "requestParam", 1);
130 this->processMethod->parameters.push_back(this->requestParam);
131
Manuel Romanb71287f2011-10-06 10:28:35 -0700132 this->rpcContextParam = new Variable(RPC_CONTEXT_TYPE, "context", 0);
133 this->processMethod->parameters.push_back(this->rpcContextParam);
134
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700135 this->errorParam = new Variable(RPC_ERROR_TYPE, "errorParam", 0);
136 this->processMethod->parameters.push_back(this->errorParam);
137
138 this->requestData = new Variable(RPC_DATA_TYPE, "request");
139 this->processMethod->statements->Add(new VariableDeclaration(requestData,
140 new NewExpression(RPC_DATA_TYPE, 1, this->requestParam)));
141
142 this->resultData = new Variable(RPC_DATA_TYPE, "resultData");
143 this->processMethod->statements->Add(new VariableDeclaration(this->resultData,
144 NULL_VALUE));
145}
146
147void
148DispatcherClass::AddMethod(const method_type* method)
149{
150 arg_type* arg;
151
152 // The if/switch statement
153 IfStatement* ifs = new IfStatement();
154 ifs->expression = new MethodCall(new StringLiteralExpression(method->name.data), "equals",
155 1, this->actionParam);
156 StatementBlock* block = ifs->statements = new StatementBlock;
157 if (this->dispatchIfStatement == NULL) {
158 this->dispatchIfStatement = ifs;
159 this->processMethod->statements->Add(dispatchIfStatement);
160 } else {
161 this->dispatchIfStatement->elseif = ifs;
162 this->dispatchIfStatement = ifs;
163 }
164
165 // The call to decl (from above)
166 MethodCall* realCall = new MethodCall(this->targetExpression, method->name.data);
167
168 // args
169 Variable* classLoader = NULL;
170 VariableFactory stubArgs("_arg");
171 arg = method->args;
172 while (arg != NULL) {
173 Type* t = NAMES.Search(arg->type.type.data);
174 Variable* v = stubArgs.Get(t);
175 v->dimension = arg->type.dimension;
176
177 // Unmarshall the parameter
178 block->Add(new VariableDeclaration(v));
179 if (convert_direction(arg->direction.data) & IN_PARAMETER) {
180 generate_create_from_data(t, block, arg->name.data, v,
181 this->requestData, &classLoader);
182 } else {
183 if (arg->type.dimension == 0) {
184 block->Add(new Assignment(v, new NewExpression(v->type)));
185 }
186 else if (arg->type.dimension == 1) {
187 generate_new_array(v->type, block, v, this->requestData);
188 }
189 else {
190 fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__,
191 __LINE__);
192 }
193 }
194
195 // Add that parameter to the method call
196 realCall->arguments.push_back(v);
197
198 arg = arg->next;
199 }
200
Manuel Romanb71287f2011-10-06 10:28:35 -0700201 // Add a final parameter: RpcContext. Contains data about
202 // incoming request (e.g., certificate)
203 realCall->arguments.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700204
205 Type* returnType = NAMES.Search(method->type.type.data);
206 if (returnType == EVENT_FAKE_TYPE) {
207 returnType = VOID_TYPE;
208 }
209
210 // the real call
211 bool first = true;
212 Variable* _result = NULL;
213 if (returnType == VOID_TYPE) {
214 block->Add(realCall);
215 } else {
216 _result = new Variable(returnType, "_result",
217 method->type.dimension);
218 block->Add(new VariableDeclaration(_result, realCall));
219
220 // need the result RpcData
221 if (first) {
222 block->Add(new Assignment(this->resultData,
223 new NewExpression(RPC_DATA_TYPE)));
224 first = false;
225 }
226
227 // marshall the return value
228 generate_write_to_data(returnType, block,
229 new StringLiteralExpression("_result"), _result, this->resultData);
230 }
231
232 // out parameters
233 int i = 0;
234 arg = method->args;
235 while (arg != NULL) {
236 Type* t = NAMES.Search(arg->type.type.data);
237 Variable* v = stubArgs.Get(i++);
238
239 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
240 // need the result RpcData
241 if (first) {
242 block->Add(new Assignment(this->resultData, new NewExpression(RPC_DATA_TYPE)));
243 first = false;
244 }
245
246 generate_write_to_data(t, block, new StringLiteralExpression(arg->name.data),
247 v, this->resultData);
248 }
249
250 arg = arg->next;
251 }
252}
253
254void
255DispatcherClass::DoneWithMethods()
256{
257 if (this->dispatchIfStatement == NULL) {
258 return;
259 }
260
261 this->elements.push_back(this->processMethod);
262
263 IfStatement* fallthrough = new IfStatement();
264 fallthrough->statements = new StatementBlock;
265 fallthrough->statements->Add(new ReturnStatement(
Manuel Romanb71287f2011-10-06 10:28:35 -0700266 new MethodCall(SUPER_VALUE, "process", 4,
267 this->actionParam, this->requestParam,
268 this->rpcContextParam,
269 this->errorParam)));
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700270 this->dispatchIfStatement->elseif = fallthrough;
271 IfStatement* s = new IfStatement;
272 s->statements = new StatementBlock;
273 this->processMethod->statements->Add(s);
274 s->expression = new Comparison(this->resultData, "!=", NULL_VALUE);
275 s->statements->Add(new ReturnStatement(new MethodCall(this->resultData, "serialize")));
276 s->elseif = new IfStatement;
277 s = s->elseif;
278 s->statements->Add(new ReturnStatement(NULL_VALUE));
279}
280
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700281// =================================================
282class RpcProxyClass : public Class
283{
284public:
285 RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType);
286 virtual ~RpcProxyClass();
287
288 Variable* endpoint;
289 Variable* context;
290
291private:
292 void generate_ctor();
293};
294
295RpcProxyClass::RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType)
296 :Class()
297{
298 this->comment = gather_comments(iface->comments_token->extra);
299 this->modifiers = PUBLIC;
300 this->what = Class::CLASS;
301 this->type = interfaceType;
302
303 // context
304 this->context = new Variable(CONTEXT_TYPE, "_context");
305 this->elements.push_back(new Field(PRIVATE, this->context));
306 // endpoint
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700307 this->endpoint = new Variable(RPC_SERVICE_INFO_TYPE, "_endpoint");
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700308 this->elements.push_back(new Field(PRIVATE, this->endpoint));
309
310 // methods
311 generate_ctor();
312}
313
314RpcProxyClass::~RpcProxyClass()
315{
316}
317
318void
319RpcProxyClass::generate_ctor()
320{
321 Variable* context = new Variable(CONTEXT_TYPE, "context");
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700322 Variable* endpoint = new Variable(RPC_SERVICE_INFO_TYPE, "endpoint");
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700323 Method* ctor = new Method;
324 ctor->modifiers = PUBLIC;
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700325 ctor->name = class_name_leaf(this->type->Name());
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700326 ctor->statements = new StatementBlock;
327 ctor->parameters.push_back(context);
328 ctor->parameters.push_back(endpoint);
329 this->elements.push_back(ctor);
330
331 ctor->statements->Add(new Assignment(this->context, context));
332 ctor->statements->Add(new Assignment(this->endpoint, endpoint));
333}
334
335// =================================================
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700336class PresenterClass : public DispatcherClass
337{
338public:
339 PresenterClass(const interface_type* iface, Type* listenerType);
340 virtual ~PresenterClass();
341
342 Variable* _listener;
343
344private:
345 void generate_ctor();
346};
347
348Expression*
349generate_get_listener_expression(Type* cast)
350{
351 return new Cast(cast, new MethodCall(THIS_VALUE, "getView"));
352}
353
354PresenterClass::PresenterClass(const interface_type* iface, Type* listenerType)
355 :DispatcherClass(iface, generate_get_listener_expression(listenerType))
356{
357 this->modifiers = PRIVATE;
358 this->what = Class::CLASS;
359 this->type = new Type(iface->package ? iface->package : "",
360 append(iface->name.data, ".Presenter"),
361 Type::GENERATED, false, false, false);
362 this->extends = PRESENTER_BASE_TYPE;
363
364 this->_listener = new Variable(listenerType, "_listener");
Tim Kilbourn22a7cb82011-09-27 10:30:53 -0700365 this->elements.push_back(new Field(PRIVATE, this->_listener));
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700366
367 // methods
368 generate_ctor();
369}
370
371PresenterClass::~PresenterClass()
372{
373}
374
375void
376PresenterClass::generate_ctor()
377{
378 Variable* context = new Variable(CONTEXT_TYPE, "context");
379 Variable* endpoint = new Variable(RPC_SERVICE_INFO_TYPE, "endpoint");
380 Variable* listener = new Variable(this->_listener->type, "listener");
381 Method* ctor = new Method;
382 ctor->modifiers = PUBLIC;
383 ctor->name = class_name_leaf(this->type->Name());
384 ctor->statements = new StatementBlock;
385 ctor->parameters.push_back(context);
386 ctor->parameters.push_back(endpoint);
387 ctor->parameters.push_back(listener);
388 this->elements.push_back(ctor);
389
390 ctor->statements->Add(new MethodCall("super", 3, context, endpoint, listener));
391 ctor->statements->Add(new Assignment(this->_listener, listener));
392}
393
394// =================================================
395class ListenerClass : public Class
396{
397public:
398 ListenerClass(const interface_type* iface);
399 virtual ~ListenerClass();
400
401 bool needed;
402
403private:
404 void generate_ctor();
405};
406
407ListenerClass::ListenerClass(const interface_type* iface)
408 :Class(),
409 needed(false)
410{
411 this->comment = "/** Extend this to listen to the events from this class. */";
412 this->modifiers = STATIC | PUBLIC ;
413 this->what = Class::CLASS;
414 this->type = new Type(iface->package ? iface->package : "",
415 append(iface->name.data, ".Listener"),
416 Type::GENERATED, false, false, false);
417 this->extends = PRESENTER_LISTENER_BASE_TYPE;
418}
419
420ListenerClass::~ListenerClass()
421{
422}
423
424// =================================================
425class ServiceBaseClass : public DispatcherClass
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700426{
427public:
428 ServiceBaseClass(const interface_type* iface);
429 virtual ~ServiceBaseClass();
430
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700431 bool needed;
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700432
433private:
434 void generate_ctor();
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700435};
436
437ServiceBaseClass::ServiceBaseClass(const interface_type* iface)
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700438 :DispatcherClass(iface, THIS_VALUE),
439 needed(false)
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700440{
441 this->comment = "/** Extend this to implement a link service. */";
442 this->modifiers = STATIC | PUBLIC | ABSTRACT;
443 this->what = Class::CLASS;
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700444 this->type = new Type(iface->package ? iface->package : "",
445 append(iface->name.data, ".ServiceBase"),
446 Type::GENERATED, false, false, false);
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700447 this->extends = RPC_SERVICE_BASE_TYPE;
448
449 // methods
450 generate_ctor();
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700451}
452
453ServiceBaseClass::~ServiceBaseClass()
454{
455}
456
457void
458ServiceBaseClass::generate_ctor()
459{
Manuel Romanb71287f2011-10-06 10:28:35 -0700460 Variable* context = new Variable(SERVICE_CONTEXT_TYPE, "context");
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700461 Variable* name = new Variable(STRING_TYPE, "name");
462 Variable* type = new Variable(STRING_TYPE, "type");
463 Variable* version = new Variable(INT_TYPE, "version");
464 Method* ctor = new Method;
465 ctor->modifiers = PUBLIC;
466 ctor->name = class_name_leaf(this->type->Name());
467 ctor->statements = new StatementBlock;
Manuel Romanb71287f2011-10-06 10:28:35 -0700468 ctor->parameters.push_back(context);
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700469 ctor->parameters.push_back(name);
470 ctor->parameters.push_back(type);
471 ctor->parameters.push_back(version);
472 this->elements.push_back(ctor);
473
Manuel Romanb71287f2011-10-06 10:28:35 -0700474 ctor->statements->Add(new MethodCall("super", 4, context, name, type, version));
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700475}
476
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700477// =================================================
478class ResultDispatcherClass : public Class
479{
480public:
481 ResultDispatcherClass();
482 virtual ~ResultDispatcherClass();
483
484 void AddMethod(int index, const string& name, Method** method, Variable** param);
485
486 bool needed;
487 Variable* methodId;
488 Variable* callback;
489 Method* onResultMethod;
490 Variable* resultParam;
491 SwitchStatement* methodSwitch;
492
493private:
494 void generate_ctor();
495 void generate_onResult();
496};
497
498ResultDispatcherClass::ResultDispatcherClass()
499 :Class(),
500 needed(false)
501{
502 this->modifiers = PRIVATE | FINAL;
503 this->what = Class::CLASS;
Joe Onorato7db766c2011-09-15 21:31:15 -0700504 this->type = new Type("_ResultDispatcher", Type::GENERATED, false, false, false);
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700505 this->interfaces.push_back(RPC_RESULT_HANDLER_TYPE);
506
507 // methodId
508 this->methodId = new Variable(INT_TYPE, "methodId");
509 this->elements.push_back(new Field(PRIVATE, this->methodId));
510 this->callback = new Variable(OBJECT_TYPE, "callback");
511 this->elements.push_back(new Field(PRIVATE, this->callback));
512
513 // methods
514 generate_ctor();
515 generate_onResult();
516}
517
518ResultDispatcherClass::~ResultDispatcherClass()
519{
520}
521
522void
523ResultDispatcherClass::generate_ctor()
524{
525 Variable* methodIdParam = new Variable(INT_TYPE, "methId");
526 Variable* callbackParam = new Variable(OBJECT_TYPE, "cbObj");
527 Method* ctor = new Method;
528 ctor->modifiers = PUBLIC;
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700529 ctor->name = class_name_leaf(this->type->Name());
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700530 ctor->statements = new StatementBlock;
531 ctor->parameters.push_back(methodIdParam);
532 ctor->parameters.push_back(callbackParam);
533 this->elements.push_back(ctor);
534
535 ctor->statements->Add(new Assignment(this->methodId, methodIdParam));
536 ctor->statements->Add(new Assignment(this->callback, callbackParam));
537}
538
539void
540ResultDispatcherClass::generate_onResult()
541{
542 this->onResultMethod = new Method;
543 this->onResultMethod->modifiers = PUBLIC;
544 this->onResultMethod->returnType = VOID_TYPE;
545 this->onResultMethod->returnTypeDimension = 0;
546 this->onResultMethod->name = "onResult";
547 this->onResultMethod->statements = new StatementBlock;
548 this->elements.push_back(this->onResultMethod);
549
550 this->resultParam = new Variable(BYTE_TYPE, "result", 1);
551 this->onResultMethod->parameters.push_back(this->resultParam);
552
553 this->methodSwitch = new SwitchStatement(this->methodId);
554 this->onResultMethod->statements->Add(this->methodSwitch);
555}
556
557void
558ResultDispatcherClass::AddMethod(int index, const string& name, Method** method, Variable** param)
559{
560 Method* m = new Method;
561 m->modifiers = PUBLIC;
562 m->returnType = VOID_TYPE;
563 m->returnTypeDimension = 0;
564 m->name = name;
565 m->statements = new StatementBlock;
566 *param = new Variable(BYTE_TYPE, "result", 1);
567 m->parameters.push_back(*param);
568 this->elements.push_back(m);
569 *method = m;
570
571 Case* c = new Case(format_int(index));
572 c->statements->Add(new MethodCall(new LiteralExpression("this"), name, 1, this->resultParam));
Joe Onorato05ffbe72011-09-02 15:28:36 -0700573 c->statements->Add(new Break());
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700574
575 this->methodSwitch->cases.push_back(c);
576}
577
578// =================================================
579static void
580generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from)
581{
582 fprintf(stderr, "aidl: implement generate_new_array %s:%d\n", __FILE__, __LINE__);
583 exit(1);
584}
585
586static void
587generate_create_from_data(Type* t, StatementBlock* addTo, const string& key, Variable* v,
588 Variable* data, Variable** cl)
589{
590 Expression* k = new StringLiteralExpression(key);
591 if (v->dimension == 0) {
592 t->CreateFromRpcData(addTo, k, v, data, cl);
593 }
594 if (v->dimension == 1) {
595 //t->ReadArrayFromRpcData(addTo, v, data, cl);
596 fprintf(stderr, "aidl: implement generate_create_from_data for arrays%s:%d\n",
597 __FILE__, __LINE__);
598 }
599}
600
601static void
602generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v, Variable* data)
603{
604 if (v->dimension == 0) {
605 t->WriteToRpcData(addTo, k, v, data, 0);
606 }
607 if (v->dimension == 1) {
608 //t->WriteArrayToParcel(addTo, v, data);
609 fprintf(stderr, "aidl: implement generate_write_to_data for arrays%s:%d\n",
610 __FILE__, __LINE__);
611 }
612}
613
614// =================================================
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700615static Type*
616generate_results_method(const method_type* method, RpcProxyClass* proxyClass)
617{
618 arg_type* arg;
619
620 string resultsMethodName = results_method_name(method->name.data);
621 Type* resultsInterfaceType = new Type(results_class_name(method->name.data),
Joe Onorato7db766c2011-09-15 21:31:15 -0700622 Type::GENERATED, false, false, false);
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700623
624 if (!method->oneway) {
625 Class* resultsClass = new Class;
626 resultsClass->modifiers = STATIC | PUBLIC;
627 resultsClass->what = Class::INTERFACE;
628 resultsClass->type = resultsInterfaceType;
629
630 Method* resultMethod = new Method;
631 resultMethod->comment = gather_comments(method->comments_token->extra);
632 resultMethod->modifiers = PUBLIC;
633 resultMethod->returnType = VOID_TYPE;
634 resultMethod->returnTypeDimension = 0;
635 resultMethod->name = resultsMethodName;
636 if (0 != strcmp("void", method->type.type.data)) {
637 resultMethod->parameters.push_back(new Variable(NAMES.Search(method->type.type.data),
638 "_result", method->type.dimension));
639 }
640 arg = method->args;
641 while (arg != NULL) {
642 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
643 resultMethod->parameters.push_back(new Variable(
644 NAMES.Search(arg->type.type.data), arg->name.data,
645 arg->type.dimension));
646 }
647 arg = arg->next;
648 }
649 resultsClass->elements.push_back(resultMethod);
650
651 if (resultMethod->parameters.size() > 0) {
652 proxyClass->elements.push_back(resultsClass);
653 return resultsInterfaceType;
654 }
655 }
656 //delete resultsInterfaceType;
657 return NULL;
658}
659
660static void
661generate_proxy_method(const method_type* method, RpcProxyClass* proxyClass,
662 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index)
663{
664 arg_type* arg;
665 Method* proxyMethod = new Method;
666 proxyMethod->comment = gather_comments(method->comments_token->extra);
667 proxyMethod->modifiers = PUBLIC;
668 proxyMethod->returnType = VOID_TYPE;
669 proxyMethod->returnTypeDimension = 0;
670 proxyMethod->name = method->name.data;
671 proxyMethod->statements = new StatementBlock;
672 proxyClass->elements.push_back(proxyMethod);
673
674 // The local variables
675 Variable* _data = new Variable(RPC_DATA_TYPE, "_data");
676 proxyMethod->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE)));
677
678 // Add the arguments
679 arg = method->args;
680 while (arg != NULL) {
681 if (convert_direction(arg->direction.data) & IN_PARAMETER) {
682 // Function signature
683 Type* t = NAMES.Search(arg->type.type.data);
684 Variable* v = new Variable(t, arg->name.data, arg->type.dimension);
685 proxyMethod->parameters.push_back(v);
686
687 // Input parameter marshalling
688 generate_write_to_data(t, proxyMethod->statements,
689 new StringLiteralExpression(arg->name.data), v, _data);
690 }
691 arg = arg->next;
692 }
693
694 // If there is a results interface for this class
695 Expression* resultParameter;
696 if (resultsInterfaceType != NULL) {
697 // Result interface parameter
698 Variable* resultListener = new Variable(resultsInterfaceType, "_result");
699 proxyMethod->parameters.push_back(resultListener);
700
701 // Add the results dispatcher callback
702 resultsDispatcherClass->needed = true;
703 resultParameter = new NewExpression(resultsDispatcherClass->type, 2,
704 new LiteralExpression(format_int(index)), resultListener);
705 } else {
706 resultParameter = NULL_VALUE;
707 }
708
709 // All proxy methods take an error parameter
710 Variable* errorListener = new Variable(RPC_ERROR_LISTENER_TYPE, "_errors");
711 proxyMethod->parameters.push_back(errorListener);
712
713 // Call the broker
714 proxyMethod->statements->Add(new MethodCall(RPC_BROKER_TYPE, "sendRequest", 6,
715 new FieldVariable(THIS_VALUE, "_context"),
716 new StringLiteralExpression(method->name.data),
717 proxyClass->endpoint,
718 new MethodCall(_data, "serialize"),
719 resultParameter,
720 errorListener));
721}
722
723static void
724generate_result_dispatcher_method(const method_type* method,
725 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index)
726{
727 arg_type* arg;
728 Method* dispatchMethod;
729 Variable* dispatchParam;
730 resultsDispatcherClass->AddMethod(index, method->name.data, &dispatchMethod, &dispatchParam);
731
732 Variable* classLoader = NULL;
733 Variable* resultData = new Variable(RPC_DATA_TYPE, "resultData");
734 dispatchMethod->statements->Add(new VariableDeclaration(resultData,
735 new NewExpression(RPC_DATA_TYPE, 1, dispatchParam)));
736
737 // The callback method itself
738 MethodCall* realCall = new MethodCall(
739 new Cast(resultsInterfaceType, new FieldVariable(THIS_VALUE, "callback")),
740 results_method_name(method->name.data));
741
742 // The return value
743 {
744 Type* t = NAMES.Search(method->type.type.data);
745 Variable* rv = new Variable(t, "rv");
746 dispatchMethod->statements->Add(new VariableDeclaration(rv));
747 generate_create_from_data(t, dispatchMethod->statements, "_result", rv,
748 resultData, &classLoader);
749 realCall->arguments.push_back(rv);
750 }
751
752 VariableFactory stubArgs("arg");
753 arg = method->args;
754 while (arg != NULL) {
755 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
756 // Unmarshall the results
757 Type* t = NAMES.Search(arg->type.type.data);
758 Variable* v = stubArgs.Get(t);
759 dispatchMethod->statements->Add(new VariableDeclaration(v));
760
761 generate_create_from_data(t, dispatchMethod->statements, arg->name.data, v,
762 resultData, &classLoader);
763
764 // Add the argument to the callback
765 realCall->arguments.push_back(v);
766 }
767 arg = arg->next;
768 }
769
770 // Call the callback method
771 dispatchMethod->statements->Add(realCall);
772}
773
774static void
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700775generate_regular_method(const method_type* method, RpcProxyClass* proxyClass,
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700776 ServiceBaseClass* serviceBaseClass, ResultDispatcherClass* resultsDispatcherClass,
777 int index)
778{
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700779 arg_type* arg;
780
781 // == the callback interface for results ================================
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700782 // the service base class
783 Type* resultsInterfaceType = generate_results_method(method, proxyClass);
784
785 // == the method in the proxy class =====================================
786 generate_proxy_method(method, proxyClass, resultsDispatcherClass, resultsInterfaceType, index);
787
788 // == the method in the result dispatcher class =========================
789 if (resultsInterfaceType != NULL) {
790 generate_result_dispatcher_method(method, resultsDispatcherClass, resultsInterfaceType,
791 index);
792 }
793
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700794 // == The abstract method that the service developers implement ==========
795 Method* decl = new Method;
796 decl->comment = gather_comments(method->comments_token->extra);
797 decl->modifiers = PUBLIC | ABSTRACT;
798 decl->returnType = NAMES.Search(method->type.type.data);
799 decl->returnTypeDimension = method->type.dimension;
800 decl->name = method->name.data;
801 arg = method->args;
802 while (arg != NULL) {
803 decl->parameters.push_back(new Variable(
804 NAMES.Search(arg->type.type.data), arg->name.data,
805 arg->type.dimension));
806 arg = arg->next;
807 }
Manuel Romanb71287f2011-10-06 10:28:35 -0700808
809 // Add the default RpcContext param to all methods
810 decl->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
811
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700812 serviceBaseClass->elements.push_back(decl);
813
814
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700815 // == the dispatch method in the service base class ======================
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700816 serviceBaseClass->AddMethod(method);
817}
818
819static void
820generate_event_method(const method_type* method, RpcProxyClass* proxyClass,
821 ServiceBaseClass* serviceBaseClass, ListenerClass* listenerClass,
822 PresenterClass* presenterClass, int index)
823{
824 arg_type* arg;
825 listenerClass->needed = true;
826
827 // == the push method in the service base class =========================
828 Method* push = new Method;
829 push->modifiers = PUBLIC;
830 push->name = push_method_name(method->name.data);
831 push->statements = new StatementBlock;
832 push->returnType = VOID_TYPE;
833 serviceBaseClass->elements.push_back(push);
834
835 // The local variables
836 Variable* _data = new Variable(RPC_DATA_TYPE, "_data");
837 push->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE)));
838
839 // Add the arguments
840 arg = method->args;
841 while (arg != NULL) {
842 // Function signature
843 Type* t = NAMES.Search(arg->type.type.data);
844 Variable* v = new Variable(t, arg->name.data, arg->type.dimension);
845 push->parameters.push_back(v);
846
847 // Input parameter marshalling
848 generate_write_to_data(t, push->statements,
849 new StringLiteralExpression(arg->name.data), v, _data);
850
851 arg = arg->next;
852 }
853
854 // Send the notifications
855 push->statements->Add(new MethodCall("pushEvent", 2,
856 new StringLiteralExpression(method->name.data),
857 new MethodCall(_data, "serialize")));
858
859 // == the event callback dispatcher method ====================================
860 presenterClass->AddMethod(method);
861
862 // == the event method in the listener base class =====================
863 Method* event = new Method;
864 event->modifiers = PUBLIC;
865 event->name = method->name.data;
866 event->statements = new StatementBlock;
867 event->returnType = VOID_TYPE;
868 listenerClass->elements.push_back(event);
869 arg = method->args;
870 while (arg != NULL) {
871 event->parameters.push_back(new Variable(
872 NAMES.Search(arg->type.type.data), arg->name.data,
873 arg->type.dimension));
874 arg = arg->next;
875 }
Manuel Romanb71287f2011-10-06 10:28:35 -0700876
877 // Add a final parameter: RpcContext. Contains data about
878 // incoming request (e.g., certificate)
879 event->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700880}
881
882static void
883generate_listener_methods(RpcProxyClass* proxyClass, Type* presenterType, Type* listenerType)
884{
885 // AndroidAtHomePresenter _presenter;
886 // void registerListener(Listener listener) {
887 // unregisterListener();
888 // _presenter = new Presenter(_context, _endpoint, listener);
889 // _presenter.attachToModel();
890 // }
891 // void unregisterListener() {
892 // if (_presenter != null) {
893 // _presenter.detachFromModel();
894 // }
895 // }
896
897 Variable* _presenter = new Variable(presenterType, "_presenter");
898 proxyClass->elements.push_back(new Field(PRIVATE, _presenter));
899
900 Variable* listener = new Variable(listenerType, "listener");
901
902 Method* registerMethod = new Method;
903 registerMethod->modifiers = PUBLIC;
904 registerMethod->returnType = VOID_TYPE;
905 registerMethod->name = "registerListener";
906 registerMethod->statements = new StatementBlock;
907 registerMethod->parameters.push_back(listener);
908 proxyClass->elements.push_back(registerMethod);
909
910 registerMethod->statements->Add(new MethodCall(THIS_VALUE, "unregisterListener"));
911 registerMethod->statements->Add(new Assignment(_presenter, new NewExpression(presenterType,
912 3, proxyClass->context, proxyClass->endpoint, listener)));
913 registerMethod->statements->Add(new MethodCall(_presenter, "attachToModel"));
914
915 Method* unregisterMethod = new Method;
916 unregisterMethod->modifiers = PUBLIC;
917 unregisterMethod->returnType = VOID_TYPE;
918 unregisterMethod->name = "unregisterListener";
919 unregisterMethod->statements = new StatementBlock;
920 proxyClass->elements.push_back(unregisterMethod);
921
922 IfStatement* ifst = new IfStatement;
923 ifst->expression = new Comparison(_presenter, "!=", NULL_VALUE);
924 unregisterMethod->statements->Add(ifst);
925
926 ifst->statements->Add(new MethodCall(_presenter, "detachFromModel"));
927 ifst->statements->Add(new Assignment(_presenter, NULL_VALUE));
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700928}
929
930Class*
931generate_rpc_interface_class(const interface_type* iface)
932{
933 // the proxy class
934 InterfaceType* interfaceType = static_cast<InterfaceType*>(
935 NAMES.Find(iface->package, iface->name.data));
936 RpcProxyClass* proxy = new RpcProxyClass(iface, interfaceType);
937
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700938 // the listener class
939 ListenerClass* listener = new ListenerClass(iface);
940
941 // the presenter class
942 PresenterClass* presenter = new PresenterClass(iface, listener->type);
943
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700944 // the service base class
945 ServiceBaseClass* base = new ServiceBaseClass(iface);
946 proxy->elements.push_back(base);
947
948 // the result dispatcher
949 ResultDispatcherClass* results = new ResultDispatcherClass();
950
951 // all the declared methods of the proxy
952 int index = 0;
953 interface_item_type* item = iface->interface_items;
954 while (item != NULL) {
955 if (item->item_type == METHOD_TYPE) {
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700956 if (NAMES.Search(((method_type*)item)->type.type.data) == EVENT_FAKE_TYPE) {
957 generate_event_method((method_type*)item, proxy, base, listener, presenter, index);
958 } else {
959 generate_regular_method((method_type*)item, proxy, base, results, index);
960 }
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700961 }
962 item = item->next;
963 index++;
964 }
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700965 presenter->DoneWithMethods();
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700966 base->DoneWithMethods();
967
968 // only add this if there are methods with results / out parameters
969 if (results->needed) {
970 proxy->elements.push_back(results);
971 }
Joe Onoratoe24dbea2011-09-23 15:17:52 -0700972 if (listener->needed) {
973 proxy->elements.push_back(listener);
974 proxy->elements.push_back(presenter);
975 generate_listener_methods(proxy, presenter->type, listener->type);
976 }
Joe Onoratofdfe2ff2011-08-30 17:24:17 -0700977
978 return proxy;
979}