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