generate_java_rpc.cpp revision b8a6f22e1b2b73b7ca4570ed3ce94ccea6b1c9ce
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 this->elements.push_back(new Field(PRIVATE, this->_listener)); 355 356 // methods 357 generate_ctor(); 358} 359 360PresenterClass::~PresenterClass() 361{ 362} 363 364void 365PresenterClass::generate_ctor() 366{ 367 Variable* context = new Variable(CONTEXT_TYPE, "context"); 368 Variable* endpoint = new Variable(RPC_SERVICE_INFO_TYPE, "endpoint"); 369 Variable* listener = new Variable(this->_listener->type, "listener"); 370 Method* ctor = new Method; 371 ctor->modifiers = PUBLIC; 372 ctor->name = class_name_leaf(this->type->Name()); 373 ctor->statements = new StatementBlock; 374 ctor->parameters.push_back(context); 375 ctor->parameters.push_back(endpoint); 376 ctor->parameters.push_back(listener); 377 this->elements.push_back(ctor); 378 379 ctor->statements->Add(new MethodCall("super", 3, context, endpoint, listener)); 380 ctor->statements->Add(new Assignment(this->_listener, listener)); 381} 382 383// ================================================= 384class ListenerClass : public Class 385{ 386public: 387 ListenerClass(const interface_type* iface); 388 virtual ~ListenerClass(); 389 390 bool needed; 391 392private: 393 void generate_ctor(); 394}; 395 396ListenerClass::ListenerClass(const interface_type* iface) 397 :Class(), 398 needed(false) 399{ 400 this->comment = "/** Extend this to listen to the events from this class. */"; 401 this->modifiers = STATIC | PUBLIC ; 402 this->what = Class::CLASS; 403 this->type = new Type(iface->package ? iface->package : "", 404 append(iface->name.data, ".Listener"), 405 Type::GENERATED, false, false, false); 406 this->extends = PRESENTER_LISTENER_BASE_TYPE; 407} 408 409ListenerClass::~ListenerClass() 410{ 411} 412 413// ================================================= 414class ServiceBaseClass : public DispatcherClass 415{ 416public: 417 ServiceBaseClass(const interface_type* iface); 418 virtual ~ServiceBaseClass(); 419 420 bool needed; 421 422private: 423 void generate_ctor(); 424}; 425 426ServiceBaseClass::ServiceBaseClass(const interface_type* iface) 427 :DispatcherClass(iface, THIS_VALUE), 428 needed(false) 429{ 430 this->comment = "/** Extend this to implement a link service. */"; 431 this->modifiers = STATIC | PUBLIC | ABSTRACT; 432 this->what = Class::CLASS; 433 this->type = new Type(iface->package ? iface->package : "", 434 append(iface->name.data, ".ServiceBase"), 435 Type::GENERATED, false, false, false); 436 this->extends = RPC_SERVICE_BASE_TYPE; 437 438 // methods 439 generate_ctor(); 440} 441 442ServiceBaseClass::~ServiceBaseClass() 443{ 444} 445 446void 447ServiceBaseClass::generate_ctor() 448{ 449 Variable* container = new Variable(SERVICE_CONTAINER_TYPE, "container"); 450 Variable* name = new Variable(STRING_TYPE, "name"); 451 Variable* type = new Variable(STRING_TYPE, "type"); 452 Variable* version = new Variable(INT_TYPE, "version"); 453 Method* ctor = new Method; 454 ctor->modifiers = PUBLIC; 455 ctor->name = class_name_leaf(this->type->Name()); 456 ctor->statements = new StatementBlock; 457 ctor->parameters.push_back(container); 458 ctor->parameters.push_back(name); 459 ctor->parameters.push_back(type); 460 ctor->parameters.push_back(version); 461 this->elements.push_back(ctor); 462 463 ctor->statements->Add(new MethodCall("super", 4, container, name, type, version)); 464} 465 466// ================================================= 467class ResultDispatcherClass : public Class 468{ 469public: 470 ResultDispatcherClass(); 471 virtual ~ResultDispatcherClass(); 472 473 void AddMethod(int index, const string& name, Method** method, Variable** param); 474 475 bool needed; 476 Variable* methodId; 477 Variable* callback; 478 Method* onResultMethod; 479 Variable* resultParam; 480 SwitchStatement* methodSwitch; 481 482private: 483 void generate_ctor(); 484 void generate_onResult(); 485}; 486 487ResultDispatcherClass::ResultDispatcherClass() 488 :Class(), 489 needed(false) 490{ 491 this->modifiers = PRIVATE | FINAL; 492 this->what = Class::CLASS; 493 this->type = new Type("_ResultDispatcher", Type::GENERATED, false, false, false); 494 this->interfaces.push_back(RPC_RESULT_HANDLER_TYPE); 495 496 // methodId 497 this->methodId = new Variable(INT_TYPE, "methodId"); 498 this->elements.push_back(new Field(PRIVATE, this->methodId)); 499 this->callback = new Variable(OBJECT_TYPE, "callback"); 500 this->elements.push_back(new Field(PRIVATE, this->callback)); 501 502 // methods 503 generate_ctor(); 504 generate_onResult(); 505} 506 507ResultDispatcherClass::~ResultDispatcherClass() 508{ 509} 510 511void 512ResultDispatcherClass::generate_ctor() 513{ 514 Variable* methodIdParam = new Variable(INT_TYPE, "methId"); 515 Variable* callbackParam = new Variable(OBJECT_TYPE, "cbObj"); 516 Method* ctor = new Method; 517 ctor->modifiers = PUBLIC; 518 ctor->name = class_name_leaf(this->type->Name()); 519 ctor->statements = new StatementBlock; 520 ctor->parameters.push_back(methodIdParam); 521 ctor->parameters.push_back(callbackParam); 522 this->elements.push_back(ctor); 523 524 ctor->statements->Add(new Assignment(this->methodId, methodIdParam)); 525 ctor->statements->Add(new Assignment(this->callback, callbackParam)); 526} 527 528void 529ResultDispatcherClass::generate_onResult() 530{ 531 this->onResultMethod = new Method; 532 this->onResultMethod->modifiers = PUBLIC; 533 this->onResultMethod->returnType = VOID_TYPE; 534 this->onResultMethod->returnTypeDimension = 0; 535 this->onResultMethod->name = "onResult"; 536 this->onResultMethod->statements = new StatementBlock; 537 this->elements.push_back(this->onResultMethod); 538 539 this->resultParam = new Variable(BYTE_TYPE, "result", 1); 540 this->onResultMethod->parameters.push_back(this->resultParam); 541 542 this->methodSwitch = new SwitchStatement(this->methodId); 543 this->onResultMethod->statements->Add(this->methodSwitch); 544} 545 546void 547ResultDispatcherClass::AddMethod(int index, const string& name, Method** method, Variable** param) 548{ 549 Method* m = new Method; 550 m->modifiers = PUBLIC; 551 m->returnType = VOID_TYPE; 552 m->returnTypeDimension = 0; 553 m->name = name; 554 m->statements = new StatementBlock; 555 *param = new Variable(BYTE_TYPE, "result", 1); 556 m->parameters.push_back(*param); 557 this->elements.push_back(m); 558 *method = m; 559 560 Case* c = new Case(format_int(index)); 561 c->statements->Add(new MethodCall(new LiteralExpression("this"), name, 1, this->resultParam)); 562 c->statements->Add(new Break()); 563 564 this->methodSwitch->cases.push_back(c); 565} 566 567// ================================================= 568static void 569generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from) 570{ 571 fprintf(stderr, "aidl: implement generate_new_array %s:%d\n", __FILE__, __LINE__); 572 exit(1); 573} 574 575static void 576generate_create_from_data(Type* t, StatementBlock* addTo, const string& key, Variable* v, 577 Variable* data, Variable** cl) 578{ 579 Expression* k = new StringLiteralExpression(key); 580 if (v->dimension == 0) { 581 t->CreateFromRpcData(addTo, k, v, data, cl); 582 } 583 if (v->dimension == 1) { 584 //t->ReadArrayFromRpcData(addTo, v, data, cl); 585 fprintf(stderr, "aidl: implement generate_create_from_data for arrays%s:%d\n", 586 __FILE__, __LINE__); 587 } 588} 589 590static void 591generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v, Variable* data) 592{ 593 if (v->dimension == 0) { 594 t->WriteToRpcData(addTo, k, v, data, 0); 595 } 596 if (v->dimension == 1) { 597 //t->WriteArrayToParcel(addTo, v, data); 598 fprintf(stderr, "aidl: implement generate_write_to_data for arrays%s:%d\n", 599 __FILE__, __LINE__); 600 } 601} 602 603// ================================================= 604static Type* 605generate_results_method(const method_type* method, RpcProxyClass* proxyClass) 606{ 607 arg_type* arg; 608 609 string resultsMethodName = results_method_name(method->name.data); 610 Type* resultsInterfaceType = new Type(results_class_name(method->name.data), 611 Type::GENERATED, false, false, false); 612 613 if (!method->oneway) { 614 Class* resultsClass = new Class; 615 resultsClass->modifiers = STATIC | PUBLIC; 616 resultsClass->what = Class::INTERFACE; 617 resultsClass->type = resultsInterfaceType; 618 619 Method* resultMethod = new Method; 620 resultMethod->comment = gather_comments(method->comments_token->extra); 621 resultMethod->modifiers = PUBLIC; 622 resultMethod->returnType = VOID_TYPE; 623 resultMethod->returnTypeDimension = 0; 624 resultMethod->name = resultsMethodName; 625 if (0 != strcmp("void", method->type.type.data)) { 626 resultMethod->parameters.push_back(new Variable(NAMES.Search(method->type.type.data), 627 "_result", method->type.dimension)); 628 } 629 arg = method->args; 630 while (arg != NULL) { 631 if (convert_direction(arg->direction.data) & OUT_PARAMETER) { 632 resultMethod->parameters.push_back(new Variable( 633 NAMES.Search(arg->type.type.data), arg->name.data, 634 arg->type.dimension)); 635 } 636 arg = arg->next; 637 } 638 resultsClass->elements.push_back(resultMethod); 639 640 if (resultMethod->parameters.size() > 0) { 641 proxyClass->elements.push_back(resultsClass); 642 return resultsInterfaceType; 643 } 644 } 645 //delete resultsInterfaceType; 646 return NULL; 647} 648 649static void 650generate_proxy_method(const method_type* method, RpcProxyClass* proxyClass, 651 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index) 652{ 653 arg_type* arg; 654 Method* proxyMethod = new Method; 655 proxyMethod->comment = gather_comments(method->comments_token->extra); 656 proxyMethod->modifiers = PUBLIC; 657 proxyMethod->returnType = VOID_TYPE; 658 proxyMethod->returnTypeDimension = 0; 659 proxyMethod->name = method->name.data; 660 proxyMethod->statements = new StatementBlock; 661 proxyClass->elements.push_back(proxyMethod); 662 663 // The local variables 664 Variable* _data = new Variable(RPC_DATA_TYPE, "_data"); 665 proxyMethod->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE))); 666 667 // Add the arguments 668 arg = method->args; 669 while (arg != NULL) { 670 if (convert_direction(arg->direction.data) & IN_PARAMETER) { 671 // Function signature 672 Type* t = NAMES.Search(arg->type.type.data); 673 Variable* v = new Variable(t, arg->name.data, arg->type.dimension); 674 proxyMethod->parameters.push_back(v); 675 676 // Input parameter marshalling 677 generate_write_to_data(t, proxyMethod->statements, 678 new StringLiteralExpression(arg->name.data), v, _data); 679 } 680 arg = arg->next; 681 } 682 683 // If there is a results interface for this class 684 Expression* resultParameter; 685 if (resultsInterfaceType != NULL) { 686 // Result interface parameter 687 Variable* resultListener = new Variable(resultsInterfaceType, "_result"); 688 proxyMethod->parameters.push_back(resultListener); 689 690 // Add the results dispatcher callback 691 resultsDispatcherClass->needed = true; 692 resultParameter = new NewExpression(resultsDispatcherClass->type, 2, 693 new LiteralExpression(format_int(index)), resultListener); 694 } else { 695 resultParameter = NULL_VALUE; 696 } 697 698 // All proxy methods take an error parameter 699 Variable* errorListener = new Variable(RPC_ERROR_LISTENER_TYPE, "_errors"); 700 proxyMethod->parameters.push_back(errorListener); 701 702 // Call the broker 703 proxyMethod->statements->Add(new MethodCall(RPC_BROKER_TYPE, "sendRequest", 6, 704 new FieldVariable(THIS_VALUE, "_context"), 705 new StringLiteralExpression(method->name.data), 706 proxyClass->endpoint, 707 new MethodCall(_data, "serialize"), 708 resultParameter, 709 errorListener)); 710} 711 712static void 713generate_result_dispatcher_method(const method_type* method, 714 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index) 715{ 716 arg_type* arg; 717 Method* dispatchMethod; 718 Variable* dispatchParam; 719 resultsDispatcherClass->AddMethod(index, method->name.data, &dispatchMethod, &dispatchParam); 720 721 Variable* classLoader = NULL; 722 Variable* resultData = new Variable(RPC_DATA_TYPE, "resultData"); 723 dispatchMethod->statements->Add(new VariableDeclaration(resultData, 724 new NewExpression(RPC_DATA_TYPE, 1, dispatchParam))); 725 726 // The callback method itself 727 MethodCall* realCall = new MethodCall( 728 new Cast(resultsInterfaceType, new FieldVariable(THIS_VALUE, "callback")), 729 results_method_name(method->name.data)); 730 731 // The return value 732 { 733 Type* t = NAMES.Search(method->type.type.data); 734 Variable* rv = new Variable(t, "rv"); 735 dispatchMethod->statements->Add(new VariableDeclaration(rv)); 736 generate_create_from_data(t, dispatchMethod->statements, "_result", rv, 737 resultData, &classLoader); 738 realCall->arguments.push_back(rv); 739 } 740 741 VariableFactory stubArgs("arg"); 742 arg = method->args; 743 while (arg != NULL) { 744 if (convert_direction(arg->direction.data) & OUT_PARAMETER) { 745 // Unmarshall the results 746 Type* t = NAMES.Search(arg->type.type.data); 747 Variable* v = stubArgs.Get(t); 748 dispatchMethod->statements->Add(new VariableDeclaration(v)); 749 750 generate_create_from_data(t, dispatchMethod->statements, arg->name.data, v, 751 resultData, &classLoader); 752 753 // Add the argument to the callback 754 realCall->arguments.push_back(v); 755 } 756 arg = arg->next; 757 } 758 759 // Call the callback method 760 dispatchMethod->statements->Add(realCall); 761} 762 763static void 764generate_regular_method(const method_type* method, RpcProxyClass* proxyClass, 765 ServiceBaseClass* serviceBaseClass, ResultDispatcherClass* resultsDispatcherClass, 766 int index) 767{ 768 arg_type* arg; 769 770 // == the callback interface for results ================================ 771 // the service base class 772 Type* resultsInterfaceType = generate_results_method(method, proxyClass); 773 774 // == the method in the proxy class ===================================== 775 generate_proxy_method(method, proxyClass, resultsDispatcherClass, resultsInterfaceType, index); 776 777 // == the method in the result dispatcher class ========================= 778 if (resultsInterfaceType != NULL) { 779 generate_result_dispatcher_method(method, resultsDispatcherClass, resultsInterfaceType, 780 index); 781 } 782 783 // == The abstract method that the service developers implement ========== 784 Method* decl = new Method; 785 decl->comment = gather_comments(method->comments_token->extra); 786 decl->modifiers = PUBLIC | ABSTRACT; 787 decl->returnType = NAMES.Search(method->type.type.data); 788 decl->returnTypeDimension = method->type.dimension; 789 decl->name = method->name.data; 790 arg = method->args; 791 while (arg != NULL) { 792 decl->parameters.push_back(new Variable( 793 NAMES.Search(arg->type.type.data), arg->name.data, 794 arg->type.dimension)); 795 arg = arg->next; 796 } 797 serviceBaseClass->elements.push_back(decl); 798 799 800 // == the dispatch method in the service base class ====================== 801 serviceBaseClass->AddMethod(method); 802} 803 804static void 805generate_event_method(const method_type* method, RpcProxyClass* proxyClass, 806 ServiceBaseClass* serviceBaseClass, ListenerClass* listenerClass, 807 PresenterClass* presenterClass, int index) 808{ 809 arg_type* arg; 810 listenerClass->needed = true; 811 812 // == the push method in the service base class ========================= 813 Method* push = new Method; 814 push->modifiers = PUBLIC; 815 push->name = push_method_name(method->name.data); 816 push->statements = new StatementBlock; 817 push->returnType = VOID_TYPE; 818 serviceBaseClass->elements.push_back(push); 819 820 // The local variables 821 Variable* _data = new Variable(RPC_DATA_TYPE, "_data"); 822 push->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE))); 823 824 // Add the arguments 825 arg = method->args; 826 while (arg != NULL) { 827 // Function signature 828 Type* t = NAMES.Search(arg->type.type.data); 829 Variable* v = new Variable(t, arg->name.data, arg->type.dimension); 830 push->parameters.push_back(v); 831 832 // Input parameter marshalling 833 generate_write_to_data(t, push->statements, 834 new StringLiteralExpression(arg->name.data), v, _data); 835 836 arg = arg->next; 837 } 838 839 // Send the notifications 840 push->statements->Add(new MethodCall("pushEvent", 2, 841 new StringLiteralExpression(method->name.data), 842 new MethodCall(_data, "serialize"))); 843 844 // == the event callback dispatcher method ==================================== 845 presenterClass->AddMethod(method); 846 847 // == the event method in the listener base class ===================== 848 Method* event = new Method; 849 event->modifiers = PUBLIC; 850 event->name = method->name.data; 851 event->statements = new StatementBlock; 852 event->returnType = VOID_TYPE; 853 listenerClass->elements.push_back(event); 854 arg = method->args; 855 while (arg != NULL) { 856 event->parameters.push_back(new Variable( 857 NAMES.Search(arg->type.type.data), arg->name.data, 858 arg->type.dimension)); 859 arg = arg->next; 860 } 861} 862 863static void 864generate_listener_methods(RpcProxyClass* proxyClass, Type* presenterType, Type* listenerType) 865{ 866 // AndroidAtHomePresenter _presenter; 867 // void registerListener(Listener listener) { 868 // unregisterListener(); 869 // _presenter = new Presenter(_context, _endpoint, listener); 870 // _presenter.attachToModel(); 871 // } 872 // void unregisterListener() { 873 // if (_presenter != null) { 874 // _presenter.detachFromModel(); 875 // } 876 // } 877 878 Variable* _presenter = new Variable(presenterType, "_presenter"); 879 proxyClass->elements.push_back(new Field(PRIVATE, _presenter)); 880 881 Variable* listener = new Variable(listenerType, "listener"); 882 883 Method* registerMethod = new Method; 884 registerMethod->modifiers = PUBLIC; 885 registerMethod->returnType = VOID_TYPE; 886 registerMethod->name = "registerListener"; 887 registerMethod->statements = new StatementBlock; 888 registerMethod->parameters.push_back(listener); 889 proxyClass->elements.push_back(registerMethod); 890 891 registerMethod->statements->Add(new MethodCall(THIS_VALUE, "unregisterListener")); 892 registerMethod->statements->Add(new Assignment(_presenter, new NewExpression(presenterType, 893 3, proxyClass->context, proxyClass->endpoint, listener))); 894 registerMethod->statements->Add(new MethodCall(_presenter, "attachToModel")); 895 896 Method* unregisterMethod = new Method; 897 unregisterMethod->modifiers = PUBLIC; 898 unregisterMethod->returnType = VOID_TYPE; 899 unregisterMethod->name = "unregisterListener"; 900 unregisterMethod->statements = new StatementBlock; 901 proxyClass->elements.push_back(unregisterMethod); 902 903 IfStatement* ifst = new IfStatement; 904 ifst->expression = new Comparison(_presenter, "!=", NULL_VALUE); 905 unregisterMethod->statements->Add(ifst); 906 907 ifst->statements->Add(new MethodCall(_presenter, "detachFromModel")); 908 ifst->statements->Add(new Assignment(_presenter, NULL_VALUE)); 909} 910 911Class* 912generate_rpc_interface_class(const interface_type* iface) 913{ 914 // the proxy class 915 InterfaceType* interfaceType = static_cast<InterfaceType*>( 916 NAMES.Find(iface->package, iface->name.data)); 917 RpcProxyClass* proxy = new RpcProxyClass(iface, interfaceType); 918 919 // the listener class 920 ListenerClass* listener = new ListenerClass(iface); 921 922 // the presenter class 923 PresenterClass* presenter = new PresenterClass(iface, listener->type); 924 925 // the service base class 926 ServiceBaseClass* base = new ServiceBaseClass(iface); 927 proxy->elements.push_back(base); 928 929 // the result dispatcher 930 ResultDispatcherClass* results = new ResultDispatcherClass(); 931 932 // all the declared methods of the proxy 933 int index = 0; 934 interface_item_type* item = iface->interface_items; 935 while (item != NULL) { 936 if (item->item_type == METHOD_TYPE) { 937 if (NAMES.Search(((method_type*)item)->type.type.data) == EVENT_FAKE_TYPE) { 938 generate_event_method((method_type*)item, proxy, base, listener, presenter, index); 939 } else { 940 generate_regular_method((method_type*)item, proxy, base, results, index); 941 } 942 } 943 item = item->next; 944 index++; 945 } 946 presenter->DoneWithMethods(); 947 base->DoneWithMethods(); 948 949 // only add this if there are methods with results / out parameters 950 if (results->needed) { 951 proxy->elements.push_back(results); 952 } 953 if (listener->needed) { 954 proxy->elements.push_back(listener); 955 proxy->elements.push_back(presenter); 956 generate_listener_methods(proxy, presenter->type, listener->type); 957 } 958 959 return proxy; 960} 961