1 #include "generate_java.h"
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,
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,
42 sprintf(str, "%d", n);
47 class_name_leaf(const string& str)
49 string::size_type pos = str.rfind('.');
50 if (pos == string::npos) {
53 return string(str, pos+1);
58 results_class_name(const string& n)
61 str[0] = toupper(str[0]);
67 results_method_name(const string& n)
70 str[0] = toupper(str[0]);
76 push_method_name(const string& n)
79 str[0] = toupper(str[0]);
80 str.insert(0, "push");
84 // =================================================
85 class DispatcherClass : public Class
88 DispatcherClass(const interface_type* iface, Expression* target);
89 virtual ~DispatcherClass();
91 void AddMethod(const method_type* method);
92 void DoneWithMethods();
94 Method* processMethod;
95 Variable* actionParam;
96 Variable* requestParam;
97 Variable* rpcContextParam;
99 Variable* requestData;
100 Variable* resultData;
101 IfStatement* dispatchIfStatement;
102 Expression* targetExpression;
105 void generate_process();
108 DispatcherClass::DispatcherClass(const interface_type* iface, Expression* target)
110 dispatchIfStatement(NULL),
111 targetExpression(target)
116 DispatcherClass::~DispatcherClass()
121 DispatcherClass::generate_process()
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;
131 this->actionParam = new Variable(STRING_TYPE, "action");
132 this->processMethod->parameters.push_back(this->actionParam);
134 this->requestParam = new Variable(BYTE_TYPE, "requestParam", 1);
135 this->processMethod->parameters.push_back(this->requestParam);
137 this->rpcContextParam = new Variable(RPC_CONTEXT_TYPE, "context", 0);
138 this->processMethod->parameters.push_back(this->rpcContextParam);
140 this->errorParam = new Variable(RPC_ERROR_TYPE, "errorParam", 0);
141 this->processMethod->parameters.push_back(this->errorParam);
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)));
147 this->resultData = new Variable(RPC_DATA_TYPE, "resultData");
148 this->processMethod->statements->Add(new VariableDeclaration(this->resultData,
153 DispatcherClass::AddMethod(const method_type* method)
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);
166 this->dispatchIfStatement->elseif = ifs;
167 this->dispatchIfStatement = ifs;
170 // The call to decl (from above)
171 MethodCall* realCall = new MethodCall(this->targetExpression, method->name.data);
174 Variable* classLoader = NULL;
175 VariableFactory stubArgs("_arg");
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;
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);
188 if (arg->type.dimension == 0) {
189 block->Add(new Assignment(v, new NewExpression(v->type)));
191 else if (arg->type.dimension == 1) {
192 generate_new_array(v->type, block, v, this->requestData);
195 fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__,
200 // Add that parameter to the method call
201 realCall->arguments.push_back(v);
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));
210 Type* returnType = NAMES.Search(method->type.type.data);
211 if (returnType == EVENT_FAKE_TYPE) {
212 returnType = VOID_TYPE;
217 Variable* _result = NULL;
218 if (returnType == VOID_TYPE) {
219 block->Add(realCall);
221 _result = new Variable(returnType, "_result",
222 method->type.dimension);
223 block->Add(new VariableDeclaration(_result, realCall));
225 // need the result RpcData
227 block->Add(new Assignment(this->resultData,
228 new NewExpression(RPC_DATA_TYPE)));
232 // marshall the return value
233 generate_write_to_data(returnType, block,
234 new StringLiteralExpression("_result"), _result, this->resultData);
240 while (arg != NULL) {
241 Type* t = NAMES.Search(arg->type.type.data);
242 Variable* v = stubArgs.Get(i++);
244 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
245 // need the result RpcData
247 block->Add(new Assignment(this->resultData, new NewExpression(RPC_DATA_TYPE)));
251 generate_write_to_data(t, block, new StringLiteralExpression(arg->name.data),
252 v, this->resultData);
260 DispatcherClass::DoneWithMethods()
262 if (this->dispatchIfStatement == NULL) {
266 this->elements.push_back(this->processMethod);
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,
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;
283 s->statements->Add(new ReturnStatement(NULL_VALUE));
286 // =================================================
287 class RpcProxyClass : public Class
290 RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType);
291 virtual ~RpcProxyClass();
297 void generate_ctor();
298 void generate_get_endpoint_info();
301 RpcProxyClass::RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType)
304 this->comment = gather_comments(iface->comments_token->extra);
305 this->modifiers = PUBLIC;
306 this->what = Class::CLASS;
307 this->type = interfaceType;
310 this->broker = new Variable(RPC_BROKER_TYPE, "_broker");
311 this->elements.push_back(new Field(PRIVATE, this->broker));
313 this->endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "_endpoint");
314 this->elements.push_back(new Field(PRIVATE, this->endpoint));
318 generate_get_endpoint_info();
321 RpcProxyClass::~RpcProxyClass()
326 RpcProxyClass::generate_ctor()
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);
338 ctor->statements->Add(new Assignment(this->broker, broker));
339 ctor->statements->Add(new Assignment(this->endpoint, endpoint));
343 RpcProxyClass::generate_get_endpoint_info()
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);
352 get->statements->Add(new ReturnStatement(this->endpoint));
355 // =================================================
356 class EventListenerClass : public DispatcherClass
359 EventListenerClass(const interface_type* iface, Type* listenerType);
360 virtual ~EventListenerClass();
365 void generate_ctor();
369 generate_get_listener_expression(Type* cast)
371 return new Cast(cast, new MethodCall(THIS_VALUE, "getView"));
374 EventListenerClass::EventListenerClass(const interface_type* iface, Type* listenerType)
375 :DispatcherClass(iface, new FieldVariable(THIS_VALUE, "_listener"))
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;
384 this->_listener = new Variable(listenerType, "_listener");
385 this->elements.push_back(new Field(PRIVATE, this->_listener));
391 EventListenerClass::~EventListenerClass()
396 EventListenerClass::generate_ctor()
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);
408 ctor->statements->Add(new MethodCall("super", 2, broker, listener));
409 ctor->statements->Add(new Assignment(this->_listener, listener));
412 // =================================================
413 class ListenerClass : public Class
416 ListenerClass(const interface_type* iface);
417 virtual ~ListenerClass();
422 void generate_ctor();
425 ListenerClass::ListenerClass(const interface_type* iface)
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;
438 ListenerClass::~ListenerClass()
442 // =================================================
443 class EndpointBaseClass : public DispatcherClass
446 EndpointBaseClass(const interface_type* iface);
447 virtual ~EndpointBaseClass();
452 void generate_ctor();
455 EndpointBaseClass::EndpointBaseClass(const interface_type* iface)
456 :DispatcherClass(iface, THIS_VALUE),
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;
471 EndpointBaseClass::~EndpointBaseClass()
476 EndpointBaseClass::generate_ctor()
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);
490 ctor->statements->Add(new MethodCall("super", 3, container, broker, place));
493 // =================================================
494 class ResultDispatcherClass : public Class
497 ResultDispatcherClass();
498 virtual ~ResultDispatcherClass();
500 void AddMethod(int index, const string& name, Method** method, Variable** param);
505 Method* onResultMethod;
506 Variable* resultParam;
507 SwitchStatement* methodSwitch;
510 void generate_ctor();
511 void generate_onResult();
514 ResultDispatcherClass::ResultDispatcherClass()
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);
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));
534 ResultDispatcherClass::~ResultDispatcherClass()
539 ResultDispatcherClass::generate_ctor()
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);
551 ctor->statements->Add(new Assignment(this->methodId, methodIdParam));
552 ctor->statements->Add(new Assignment(this->callback, callbackParam));
556 ResultDispatcherClass::generate_onResult()
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);
566 this->resultParam = new Variable(BYTE_TYPE, "result", 1);
567 this->onResultMethod->parameters.push_back(this->resultParam);
569 this->methodSwitch = new SwitchStatement(this->methodId);
570 this->onResultMethod->statements->Add(this->methodSwitch);
574 ResultDispatcherClass::AddMethod(int index, const string& name, Method** method, Variable** param)
576 Method* m = new Method;
577 m->modifiers = PUBLIC;
578 m->returnType = VOID_TYPE;
579 m->returnTypeDimension = 0;
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);
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());
591 this->methodSwitch->cases.push_back(c);
594 // =================================================
596 generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from)
598 fprintf(stderr, "aidl: implement generate_new_array %s:%d\n", __FILE__, __LINE__);
603 generate_create_from_data(Type* t, StatementBlock* addTo, const string& key, Variable* v,
604 Variable* data, Variable** cl)
606 Expression* k = new StringLiteralExpression(key);
607 if (v->dimension == 0) {
608 t->CreateFromRpcData(addTo, k, v, data, cl);
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",
618 generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v, Variable* data)
620 if (v->dimension == 0) {
621 t->WriteToRpcData(addTo, k, v, data, 0);
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",
630 // =================================================
632 generate_results_method(const method_type* method, RpcProxyClass* proxyClass)
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);
640 if (!method->oneway) {
641 Class* resultsClass = new Class;
642 resultsClass->modifiers = STATIC | PUBLIC;
643 resultsClass->what = Class::INTERFACE;
644 resultsClass->type = resultsInterfaceType;
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));
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));
665 resultsClass->elements.push_back(resultMethod);
667 if (resultMethod->parameters.size() > 0) {
668 proxyClass->elements.push_back(resultsClass);
669 return resultsInterfaceType;
672 //delete resultsInterfaceType;
677 generate_proxy_method(const method_type* method, RpcProxyClass* proxyClass,
678 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index)
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);
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)));
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);
703 // Input parameter marshalling
704 generate_write_to_data(t, proxyMethod->statements,
705 new StringLiteralExpression(arg->name.data), v, _data);
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);
717 // Add the results dispatcher callback
718 resultsDispatcherClass->needed = true;
719 resultParameter = new NewExpression(resultsDispatcherClass->type, 2,
720 new LiteralExpression(format_int(index)), resultListener);
722 resultParameter = NULL_VALUE;
725 // All proxy methods take an error parameter
726 Variable* errorListener = new Variable(RPC_ERROR_LISTENER_TYPE, "_errors");
727 proxyMethod->parameters.push_back(errorListener);
730 proxyMethod->statements->Add(new MethodCall(new FieldVariable(THIS_VALUE, "_broker"),
732 proxyClass->endpoint,
733 new StringLiteralExpression(method->name.data),
734 new MethodCall(_data, "serialize"),
740 generate_result_dispatcher_method(const method_type* method,
741 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index)
744 Method* dispatchMethod;
745 Variable* dispatchParam;
746 resultsDispatcherClass->AddMethod(index, method->name.data, &dispatchMethod, &dispatchParam);
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)));
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));
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);
770 VariableFactory stubArgs("arg");
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));
779 generate_create_from_data(t, dispatchMethod->statements, arg->name.data, v,
780 resultData, &classLoader);
782 // Add the argument to the callback
783 realCall->arguments.push_back(v);
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);
796 generate_regular_method(const method_type* method, RpcProxyClass* proxyClass,
797 EndpointBaseClass* serviceBaseClass, ResultDispatcherClass* resultsDispatcherClass,
802 // == the callback interface for results ================================
803 // the service base class
804 Type* resultsInterfaceType = generate_results_method(method, proxyClass);
806 // == the method in the proxy class =====================================
807 generate_proxy_method(method, proxyClass, resultsDispatcherClass, resultsInterfaceType, index);
809 // == the method in the result dispatcher class =========================
810 if (resultsInterfaceType != NULL) {
811 generate_result_dispatcher_method(method, resultsDispatcherClass, resultsInterfaceType,
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;
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));
830 // Add the default RpcContext param to all methods
831 decl->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
833 serviceBaseClass->elements.push_back(decl);
836 // == the dispatch method in the service base class ======================
837 serviceBaseClass->AddMethod(method);
841 generate_event_method(const method_type* method, RpcProxyClass* proxyClass,
842 EndpointBaseClass* serviceBaseClass, ListenerClass* listenerClass,
843 EventListenerClass* presenterClass, int index)
846 listenerClass->needed = true;
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);
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)));
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);
868 // Input parameter marshalling
869 generate_write_to_data(t, push->statements,
870 new StringLiteralExpression(arg->name.data), v, _data);
875 // Send the notifications
876 push->statements->Add(new MethodCall("pushEvent", 2,
877 new StringLiteralExpression(method->name.data),
878 new MethodCall(_data, "serialize")));
880 // == the event callback dispatcher method ====================================
881 presenterClass->AddMethod(method);
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);
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));
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));
904 generate_listener_methods(RpcProxyClass* proxyClass, Type* presenterType, Type* listenerType)
906 // AndroidAtHomePresenter _presenter;
907 // void startListening(Listener listener) {
909 // _presenter = new Presenter(_broker, listener);
910 // _presenter.startListening(_endpoint);
912 // void stopListening() {
913 // if (_presenter != null) {
914 // _presenter.stopListening();
918 Variable* _presenter = new Variable(presenterType, "_presenter");
919 proxyClass->elements.push_back(new Field(PRIVATE, _presenter));
921 Variable* listener = new Variable(listenerType, "listener");
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);
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));
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);
944 IfStatement* ifst = new IfStatement;
945 ifst->expression = new Comparison(_presenter, "!=", NULL_VALUE);
946 stopListeningMethod->statements->Add(ifst);
948 ifst->statements->Add(new MethodCall(_presenter, "stopListening"));
949 ifst->statements->Add(new Assignment(_presenter, NULL_VALUE));
953 generate_rpc_interface_class(const interface_type* iface)
956 InterfaceType* interfaceType = static_cast<InterfaceType*>(
957 NAMES.Find(iface->package, iface->name.data));
958 RpcProxyClass* proxy = new RpcProxyClass(iface, interfaceType);
960 // the listener class
961 ListenerClass* listener = new ListenerClass(iface);
963 // the presenter class
964 EventListenerClass* presenter = new EventListenerClass(iface, listener->type);
966 // the service base class
967 EndpointBaseClass* base = new EndpointBaseClass(iface);
968 proxy->elements.push_back(base);
970 // the result dispatcher
971 ResultDispatcherClass* results = new ResultDispatcherClass();
973 // all the declared methods of the proxy
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);
981 generate_regular_method((method_type*)item, proxy, base, results, index);
987 presenter->DoneWithMethods();
988 base->DoneWithMethods();
990 // only add this if there are methods with results / out parameters
991 if (results->needed) {
992 proxy->elements.push_back(results);
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);