generate_java_rpc.cpp revision e24dbeafe64278408b3342fcb77756bc7d091791
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 8Type* SERVICE_CONTAINER_TYPE = new Type("com.android.athome.service", 9 "AndroidAtHomeServiceContainer", Type::BUILT_IN, false, false, false); 10Type* 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); 30 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 50static 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 270// ================================================= 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 296 this->endpoint = new Variable(RPC_SERVICE_INFO_TYPE, "_endpoint"); 297 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"); 311 Variable* endpoint = new Variable(RPC_SERVICE_INFO_TYPE, "endpoint"); 312 Method* ctor = new Method; 313 ctor->modifiers = PUBLIC; 314 ctor->name = class_name_leaf(this->type->Name()); 315 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// ================================================= 325class 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 414{ 415public: 416 ServiceBaseClass(const interface_type* iface); 417 virtual ~ServiceBaseClass(); 418 419 bool needed; 420 421private: 422 void generate_ctor(); 423}; 424 425ServiceBaseClass::ServiceBaseClass(const interface_type* iface) 426 :DispatcherClass(iface, THIS_VALUE), 427 needed(false) 428{ 429 this->comment = "/** Extend this to implement a link service. */"; 430 this->modifiers = STATIC | PUBLIC | ABSTRACT; 431 this->what = Class::CLASS; 432 this->type = new Type(iface->package ? iface->package : "", 433 append(iface->name.data, ".ServiceBase"), 434 Type::GENERATED, false, false, false); 435 this->extends = RPC_SERVICE_BASE_TYPE; 436 437 // methods 438 generate_ctor(); 439} 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 465// ================================================= 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; 492 this->type = new Type("_ResultDispatcher", Type::GENERATED, false, false, false); 493 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; 517 ctor->name = class_name_leaf(this->type->Name()); 518 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)); 561 c->statements->Add(new Break()); 562 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// ================================================= 603static 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), 610 Type::GENERATED, false, false, false); 611 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 763generate_regular_method(const method_type* method, RpcProxyClass* proxyClass, 764 ServiceBaseClass* serviceBaseClass, ResultDispatcherClass* resultsDispatcherClass, 765 int index) 766{ 767 arg_type* arg; 768 769 // == the callback interface for results ================================ 770 // 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 782 // == 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 799 // == the dispatch method in the service base class ====================== 800 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)); 908} 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 918 // the listener class 919 ListenerClass* listener = new ListenerClass(iface); 920 921 // the presenter class 922 PresenterClass* presenter = new PresenterClass(iface, listener->type); 923 924 // 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) { 936 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 } 941 } 942 item = item->next; 943 index++; 944 } 945 presenter->DoneWithMethods(); 946 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 } 952 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 } 957 958 return proxy; 959} 960 961