OSDN Git Service

GLSurfaceView: Be less picky about EGLConfig alpha sizes
[android-x86/frameworks-base.git] / tools / aidl / generate_java_rpc.cpp
1 #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
8 Type* SERVICE_CONTEXT_TYPE = new Type("android.content",
9         "Context", Type::BUILT_IN, false, false, false);
10 Type* PRESENTER_BASE_TYPE = new Type("android.support.place.connector",
11         "EventListener", Type::BUILT_IN, false, false, false);
12 Type* PRESENTER_LISTENER_BASE_TYPE = new Type("android.support.place.connector",
13         "EventListener.Listener", Type::BUILT_IN, false, false, false);
14 Type* RPC_BROKER_TYPE = new Type("android.support.place.connector", "Broker",
15         Type::BUILT_IN, false, false, false);
16 Type* RPC_CONTAINER_TYPE = new Type("com.android.athome.connector", "ConnectorContainer",
17         Type::BUILT_IN, false, false, false);
18 Type* PLACE_INFO_TYPE = new Type("android.support.place.connector", "PlaceInfo",
19         Type::BUILT_IN, false, false, false);
20 // TODO: Just use Endpoint, so this works for all endpoints.
21 Type* RPC_CONNECTOR_TYPE = new Type("android.support.place.connector", "Connector",
22         Type::BUILT_IN, false, false, false);
23 Type* RPC_ENDPOINT_INFO_TYPE = new UserDataType("android.support.place.rpc",
24         "EndpointInfo", true, __FILE__, __LINE__);
25 Type* RPC_RESULT_HANDLER_TYPE = new UserDataType("android.support.place.rpc", "RpcResultHandler",
26         true, __FILE__, __LINE__);
27 Type* RPC_ERROR_LISTENER_TYPE = new Type("android.support.place.rpc", "RpcErrorHandler",
28         Type::BUILT_IN, false, false, false);
29 Type* RPC_CONTEXT_TYPE = new UserDataType("android.support.place.rpc", "RpcContext", true,
30         __FILE__, __LINE__);
31
32 static void generate_create_from_data(Type* t, StatementBlock* addTo, const string& key,
33         Variable* v, Variable* data, Variable** cl);
34 static void generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from);
35 static void generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v,
36         Variable* data);
37
38 static string
39 format_int(int n)
40 {
41     char str[20];
42     sprintf(str, "%d", n);
43     return string(str);
44 }
45
46 static string
47 class_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
57 static string
58 results_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
66 static string
67 results_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
75 static string
76 push_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 // =================================================
85 class DispatcherClass : public Class
86 {
87 public:
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;
97     Variable* rpcContextParam;
98     Variable* errorParam;
99     Variable* requestData;
100     Variable* resultData;
101     IfStatement* dispatchIfStatement;
102     Expression* targetExpression;
103
104 private:
105     void generate_process();
106 };
107
108 DispatcherClass::DispatcherClass(const interface_type* iface, Expression* target)
109     :Class(),
110      dispatchIfStatement(NULL),
111      targetExpression(target)
112 {
113     generate_process();
114 }
115
116 DispatcherClass::~DispatcherClass()
117 {
118 }
119
120 void
121 DispatcherClass::generate_process()
122 {
123     // byte[] process(String action, byte[] params, RpcContext context, RpcError status)
124     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
137     this->rpcContextParam = new Variable(RPC_CONTEXT_TYPE, "context", 0);
138     this->processMethod->parameters.push_back(this->rpcContextParam);    
139
140     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
152 void
153 DispatcherClass::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
206     // 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));
209
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
259 void
260 DispatcherClass::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(
271                     new MethodCall(SUPER_VALUE, "process", 4, 
272                     this->actionParam, this->requestParam, 
273                     this->rpcContextParam,
274                     this->errorParam)));
275     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
286 // =================================================
287 class RpcProxyClass : public Class
288 {
289 public:
290     RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType);
291     virtual ~RpcProxyClass();
292
293     Variable* endpoint;
294     Variable* broker;
295
296 private:
297     void generate_ctor();
298     void generate_get_endpoint_info();
299 };
300
301 RpcProxyClass::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
309     // broker
310     this->broker = new Variable(RPC_BROKER_TYPE, "_broker");
311     this->elements.push_back(new Field(PRIVATE, this->broker));
312     // endpoint
313     this->endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "_endpoint");
314     this->elements.push_back(new Field(PRIVATE, this->endpoint));
315
316     // methods
317     generate_ctor();
318     generate_get_endpoint_info();
319 }
320
321 RpcProxyClass::~RpcProxyClass()
322 {
323 }
324
325 void
326 RpcProxyClass::generate_ctor()
327 {
328     Variable* broker = new Variable(RPC_BROKER_TYPE, "broker");
329     Variable* endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "endpoint");
330     Method* ctor = new Method;
331         ctor->modifiers = PUBLIC;
332         ctor->name = class_name_leaf(this->type->Name());
333         ctor->statements = new StatementBlock;
334         ctor->parameters.push_back(broker);
335         ctor->parameters.push_back(endpoint);
336     this->elements.push_back(ctor);
337
338     ctor->statements->Add(new Assignment(this->broker, broker));
339     ctor->statements->Add(new Assignment(this->endpoint, endpoint));
340 }
341
342 void
343 RpcProxyClass::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
355 // =================================================
356 class EventListenerClass : public DispatcherClass
357 {
358 public:
359     EventListenerClass(const interface_type* iface, Type* listenerType);
360     virtual ~EventListenerClass();
361
362     Variable* _listener;
363
364 private:
365     void generate_ctor();
366 };
367
368 Expression*
369 generate_get_listener_expression(Type* cast)
370 {
371     return new Cast(cast, new MethodCall(THIS_VALUE, "getView"));
372 }
373
374 EventListenerClass::EventListenerClass(const interface_type* iface, Type* listenerType)
375     :DispatcherClass(iface, new FieldVariable(THIS_VALUE, "_listener"))
376 {
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");
385     this->elements.push_back(new Field(PRIVATE, this->_listener));
386
387     // methods
388     generate_ctor();
389 }
390
391 EventListenerClass::~EventListenerClass()
392 {
393 }
394
395 void
396 EventListenerClass::generate_ctor()
397 {
398     Variable* broker = new Variable(RPC_BROKER_TYPE, "broker");
399     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;
404         ctor->parameters.push_back(broker);
405         ctor->parameters.push_back(listener);
406     this->elements.push_back(ctor);
407
408     ctor->statements->Add(new MethodCall("super", 2, broker, listener));
409     ctor->statements->Add(new Assignment(this->_listener, listener));
410 }
411
412 // =================================================
413 class ListenerClass : public Class
414 {
415 public:
416     ListenerClass(const interface_type* iface);
417     virtual ~ListenerClass();
418
419     bool needed;
420
421 private:
422     void generate_ctor();
423 };
424
425 ListenerClass::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
438 ListenerClass::~ListenerClass()
439 {
440 }
441
442 // =================================================
443 class EndpointBaseClass : public DispatcherClass
444 {
445 public:
446     EndpointBaseClass(const interface_type* iface);
447     virtual ~EndpointBaseClass();
448
449     bool needed;
450
451 private:
452     void generate_ctor();
453 };
454
455 EndpointBaseClass::EndpointBaseClass(const interface_type* iface)
456     :DispatcherClass(iface, THIS_VALUE),
457      needed(false)
458 {
459     this->comment = "/** Extend this to implement a link service. */";
460     this->modifiers = STATIC | PUBLIC | ABSTRACT;
461     this->what = Class::CLASS;
462     this->type = new Type(iface->package ? iface->package : "",
463                         append(iface->name.data, ".EndpointBase"),
464                         Type::GENERATED, false, false, false);
465     this->extends = RPC_CONNECTOR_TYPE;
466
467     // methods
468     generate_ctor();
469 }
470
471 EndpointBaseClass::~EndpointBaseClass()
472 {
473 }
474
475 void
476 EndpointBaseClass::generate_ctor()
477 {
478     Variable* container = new Variable(RPC_CONTAINER_TYPE, "container");
479     Variable* broker = new Variable(RPC_BROKER_TYPE, "broker");
480         Variable* place = new Variable(PLACE_INFO_TYPE, "placeInfo");
481     Method* ctor = new Method;
482         ctor->modifiers = PUBLIC;
483         ctor->name = class_name_leaf(this->type->Name());
484         ctor->statements = new StatementBlock;
485         ctor->parameters.push_back(container);
486         ctor->parameters.push_back(broker);
487         ctor->parameters.push_back(place);
488     this->elements.push_back(ctor);
489
490     ctor->statements->Add(new MethodCall("super", 3, container, broker, place));
491 }
492
493 // =================================================
494 class ResultDispatcherClass : public Class
495 {
496 public:
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
509 private:
510     void generate_ctor();
511     void generate_onResult();
512 };
513
514 ResultDispatcherClass::ResultDispatcherClass()
515     :Class(),
516      needed(false)
517 {
518     this->modifiers = PRIVATE | FINAL;
519     this->what = Class::CLASS;
520     this->type = new Type("_ResultDispatcher", Type::GENERATED, false, false, false);
521     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
534 ResultDispatcherClass::~ResultDispatcherClass()
535 {
536 }
537
538 void
539 ResultDispatcherClass::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;
545         ctor->name = class_name_leaf(this->type->Name());
546         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
555 void
556 ResultDispatcherClass::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
573 void
574 ResultDispatcherClass::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));
589     c->statements->Add(new Break());
590
591     this->methodSwitch->cases.push_back(c);
592 }
593
594 // =================================================
595 static void
596 generate_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
602 static void
603 generate_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
617 static void
618 generate_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 // =================================================
631 static Type*
632 generate_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),
638             Type::GENERATED, false, false, false);
639
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
676 static void
677 generate_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
730     proxyMethod->statements->Add(new MethodCall(new FieldVariable(THIS_VALUE, "_broker"),
731                 "sendRpc", 5,
732                 proxyClass->endpoint,
733                 new StringLiteralExpression(method->name.data),
734                 new MethodCall(_data, "serialize"),
735                 resultParameter,
736                 errorListener));
737 }
738
739 static void
740 generate_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);
761         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         }
768     }
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
789     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);
793 }
794
795 static void
796 generate_regular_method(const method_type* method, RpcProxyClass* proxyClass,
797         EndpointBaseClass* serviceBaseClass, ResultDispatcherClass* resultsDispatcherClass,
798         int index)
799 {
800     arg_type* arg;
801
802     // == the callback interface for results ================================
803     // 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
815     // == 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     }
829
830     // Add the default RpcContext param to all methods
831     decl->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
832         
833     serviceBaseClass->elements.push_back(decl);
834     
835
836     // == the dispatch method in the service base class ======================
837     serviceBaseClass->AddMethod(method);
838 }
839
840 static void
841 generate_event_method(const method_type* method, RpcProxyClass* proxyClass,
842         EndpointBaseClass* serviceBaseClass, ListenerClass* listenerClass,
843         EventListenerClass* presenterClass, int index)
844 {
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     }
897
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));
901 }
902
903 static void
904 generate_listener_methods(RpcProxyClass* proxyClass, Type* presenterType, Type* listenerType)
905 {
906     // AndroidAtHomePresenter _presenter;
907     // void startListening(Listener listener) {
908     //     stopListening();
909     //     _presenter = new Presenter(_broker, listener);
910     //     _presenter.startListening(_endpoint);
911     // }
912     // void stopListening() {
913     //     if (_presenter != null) {
914     //         _presenter.stopListening();
915     //     }
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
923     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);
930
931     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));
936
937     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);
943
944     IfStatement* ifst = new IfStatement;
945         ifst->expression = new Comparison(_presenter, "!=", NULL_VALUE);
946     stopListeningMethod->statements->Add(ifst);
947
948     ifst->statements->Add(new MethodCall(_presenter, "stopListening"));
949     ifst->statements->Add(new Assignment(_presenter, NULL_VALUE));
950 }
951
952 Class*
953 generate_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
960     // the listener class
961     ListenerClass* listener = new ListenerClass(iface);
962
963     // the presenter class
964     EventListenerClass* presenter = new EventListenerClass(iface, listener->type);
965
966     // the service base class
967     EndpointBaseClass* base = new EndpointBaseClass(iface);
968     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) {
978             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             }
983         }
984         item = item->next;
985         index++;
986     }
987     presenter->DoneWithMethods();
988     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     }
994     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     }
999
1000     return proxy;
1001 }