Home | History | Annotate | Download | only in aidl
      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 }
   1002