blob: 53a11f28a1ee458d37546c7f30d2af33f8becb02 [file] [log] [blame]
Joe Onoratoc596cfe2011-08-30 17:24:17 -07001#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",
Joe Onorato4135a7d2011-09-15 21:31:15 -07009 "AndroidAtHomeServiceContainer", Type::BUILT_IN, false, false, false);
Joe Onoratoc596cfe2011-08-30 17:24:17 -070010
11static string
12format_int(int n)
13{
14 char str[20];
15 sprintf(str, "%d", n);
16 return string(str);
17}
18
19static string
20class_name_leaf(const string& str)
21{
22 string::size_type pos = str.rfind('.');
23 if (pos == string::npos) {
24 return str;
25 } else {
26 return string(str, pos+1);
27 }
28}
29
30// =================================================
31class RpcProxyClass : public Class
32{
33public:
34 RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType);
35 virtual ~RpcProxyClass();
36
37 Variable* endpoint;
38 Variable* context;
39
40private:
41 void generate_ctor();
42};
43
44RpcProxyClass::RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType)
45 :Class()
46{
47 this->comment = gather_comments(iface->comments_token->extra);
48 this->modifiers = PUBLIC;
49 this->what = Class::CLASS;
50 this->type = interfaceType;
51
52 // context
53 this->context = new Variable(CONTEXT_TYPE, "_context");
54 this->elements.push_back(new Field(PRIVATE, this->context));
55 // endpoint
56 this->endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "_endpoint");
57 this->elements.push_back(new Field(PRIVATE, this->endpoint));
58
59 // methods
60 generate_ctor();
61}
62
63RpcProxyClass::~RpcProxyClass()
64{
65}
66
67void
68RpcProxyClass::generate_ctor()
69{
70 Variable* context = new Variable(CONTEXT_TYPE, "context");
71 Variable* endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "endpoint");
72 Method* ctor = new Method;
73 ctor->modifiers = PUBLIC;
74 ctor->name = this->type->Name();
75 ctor->statements = new StatementBlock;
76 ctor->parameters.push_back(context);
77 ctor->parameters.push_back(endpoint);
78 this->elements.push_back(ctor);
79
80 ctor->statements->Add(new Assignment(this->context, context));
81 ctor->statements->Add(new Assignment(this->endpoint, endpoint));
82}
83
84// =================================================
85class ServiceBaseClass : public Class
86{
87public:
88 ServiceBaseClass(const interface_type* iface);
89 virtual ~ServiceBaseClass();
90
91 void AddMethod(const string& methodName, StatementBlock** statements);
92 void DoneWithMethods();
93
94 bool needed;
95 Method* processMethod;
96 Variable* actionParam;
Joe Onoratoe385c862011-09-14 21:12:28 -070097 Variable* requestParam;
Joe Onoratoc596cfe2011-08-30 17:24:17 -070098 Variable* errorParam;
99 Variable* requestData;
100 Variable* resultData;
101 IfStatement* dispatchIfStatement;
102
103private:
104 void generate_ctor();
105 void generate_process();
106};
107
108ServiceBaseClass::ServiceBaseClass(const interface_type* iface)
109 :Class(),
110 needed(false),
111 dispatchIfStatement(NULL)
112{
113 this->comment = "/** Extend this to implement a link service. */";
114 this->modifiers = STATIC | PUBLIC | ABSTRACT;
115 this->what = Class::CLASS;
116 this->type = NAMES.Find(iface->package, append(iface->name.data, ".ServiceBase").c_str());
117 this->extends = RPC_SERVICE_BASE_TYPE;
118
119 // methods
120 generate_ctor();
121 generate_process();
122}
123
124ServiceBaseClass::~ServiceBaseClass()
125{
126}
127
128void
129ServiceBaseClass::generate_ctor()
130{
131 Variable* container = new Variable(SERVICE_CONTAINER_TYPE, "container");
132 Variable* name = new Variable(STRING_TYPE, "name");
133 Variable* type = new Variable(STRING_TYPE, "type");
134 Variable* version = new Variable(INT_TYPE, "version");
135 Method* ctor = new Method;
136 ctor->modifiers = PUBLIC;
137 ctor->name = class_name_leaf(this->type->Name());
138 ctor->statements = new StatementBlock;
139 ctor->parameters.push_back(container);
140 ctor->parameters.push_back(name);
141 ctor->parameters.push_back(type);
142 ctor->parameters.push_back(version);
143 this->elements.push_back(ctor);
144
145 ctor->statements->Add(new MethodCall("super", 4, container, name, type, version));
146}
147
148void
149ServiceBaseClass::generate_process()
150{
151 // byte[] process(String action, byte[] params, RpcError status)
152 this->processMethod = new Method;
153 this->processMethod->modifiers = PUBLIC;
154 this->processMethod->returnType = BYTE_TYPE;
155 this->processMethod->returnTypeDimension = 1;
156 this->processMethod->name = "process";
157 this->processMethod->statements = new StatementBlock;
158 this->elements.push_back(this->processMethod);
159
160 this->actionParam = new Variable(STRING_TYPE, "action");
161 this->processMethod->parameters.push_back(this->actionParam);
162
Joe Onoratoe385c862011-09-14 21:12:28 -0700163 this->requestParam = new Variable(BYTE_TYPE, "requestParam", 1);
164 this->processMethod->parameters.push_back(this->requestParam);
Joe Onoratoc596cfe2011-08-30 17:24:17 -0700165
166 this->errorParam = new Variable(RPC_ERROR_TYPE, "errorParam", 0);
167 this->processMethod->parameters.push_back(this->errorParam);
168
169 this->requestData = new Variable(RPC_DATA_TYPE, "request");
170 this->processMethod->statements->Add(new VariableDeclaration(requestData,
Joe Onoratoe385c862011-09-14 21:12:28 -0700171 new NewExpression(RPC_DATA_TYPE, 1, this->requestParam)));
Joe Onoratoc596cfe2011-08-30 17:24:17 -0700172
Joe Onorato3d0e06f2011-09-02 15:28:36 -0700173 this->resultData = new Variable(RPC_DATA_TYPE, "resultData");
Joe Onoratoc596cfe2011-08-30 17:24:17 -0700174 this->processMethod->statements->Add(new VariableDeclaration(this->resultData,
175 NULL_VALUE));
176}
177
178void
179ServiceBaseClass::AddMethod(const string& methodName, StatementBlock** statements)
180{
181 IfStatement* ifs = new IfStatement();
182 ifs->expression = new MethodCall(new StringLiteralExpression(methodName), "equals", 1,
183 this->actionParam);
184 ifs->statements = *statements = new StatementBlock;
185 if (this->dispatchIfStatement == NULL) {
186 this->dispatchIfStatement = ifs;
187 this->processMethod->statements->Add(dispatchIfStatement);
188 } else {
189 this->dispatchIfStatement->elseif = ifs;
190 this->dispatchIfStatement = ifs;
191 }
192}
193
194void
195ServiceBaseClass::DoneWithMethods()
196{
Joe Onoratoe385c862011-09-14 21:12:28 -0700197 IfStatement* fallthrough = new IfStatement();
198 fallthrough->statements = new StatementBlock;
199 fallthrough->statements->Add(new ReturnStatement(
200 new MethodCall(SUPER_VALUE, "process", 3, this->actionParam, this->requestParam,
201 this->errorParam)));
202 this->dispatchIfStatement->elseif = fallthrough;
Joe Onoratoc596cfe2011-08-30 17:24:17 -0700203 IfStatement* s = new IfStatement;
204 s->statements = new StatementBlock;
205 this->processMethod->statements->Add(s);
206 s->expression = new Comparison(this->resultData, "!=", NULL_VALUE);
207 s->statements->Add(new ReturnStatement(new MethodCall(this->resultData, "serialize")));
208 s->elseif = new IfStatement;
209 s = s->elseif;
210 s->statements->Add(new ReturnStatement(NULL_VALUE));
211}
212
213// =================================================
214class ResultDispatcherClass : public Class
215{
216public:
217 ResultDispatcherClass();
218 virtual ~ResultDispatcherClass();
219
220 void AddMethod(int index, const string& name, Method** method, Variable** param);
221
222 bool needed;
223 Variable* methodId;
224 Variable* callback;
225 Method* onResultMethod;
226 Variable* resultParam;
227 SwitchStatement* methodSwitch;
228
229private:
230 void generate_ctor();
231 void generate_onResult();
232};
233
234ResultDispatcherClass::ResultDispatcherClass()
235 :Class(),
236 needed(false)
237{
238 this->modifiers = PRIVATE | FINAL;
239 this->what = Class::CLASS;
Joe Onorato4135a7d2011-09-15 21:31:15 -0700240 this->type = new Type("_ResultDispatcher", Type::GENERATED, false, false, false);
Joe Onoratoc596cfe2011-08-30 17:24:17 -0700241 this->interfaces.push_back(RPC_RESULT_HANDLER_TYPE);
242
243 // methodId
244 this->methodId = new Variable(INT_TYPE, "methodId");
245 this->elements.push_back(new Field(PRIVATE, this->methodId));
246 this->callback = new Variable(OBJECT_TYPE, "callback");
247 this->elements.push_back(new Field(PRIVATE, this->callback));
248
249 // methods
250 generate_ctor();
251 generate_onResult();
252}
253
254ResultDispatcherClass::~ResultDispatcherClass()
255{
256}
257
258void
259ResultDispatcherClass::generate_ctor()
260{
261 Variable* methodIdParam = new Variable(INT_TYPE, "methId");
262 Variable* callbackParam = new Variable(OBJECT_TYPE, "cbObj");
263 Method* ctor = new Method;
264 ctor->modifiers = PUBLIC;
265 ctor->name = this->type->Name();
266 ctor->statements = new StatementBlock;
267 ctor->parameters.push_back(methodIdParam);
268 ctor->parameters.push_back(callbackParam);
269 this->elements.push_back(ctor);
270
271 ctor->statements->Add(new Assignment(this->methodId, methodIdParam));
272 ctor->statements->Add(new Assignment(this->callback, callbackParam));
273}
274
275void
276ResultDispatcherClass::generate_onResult()
277{
278 this->onResultMethod = new Method;
279 this->onResultMethod->modifiers = PUBLIC;
280 this->onResultMethod->returnType = VOID_TYPE;
281 this->onResultMethod->returnTypeDimension = 0;
282 this->onResultMethod->name = "onResult";
283 this->onResultMethod->statements = new StatementBlock;
284 this->elements.push_back(this->onResultMethod);
285
286 this->resultParam = new Variable(BYTE_TYPE, "result", 1);
287 this->onResultMethod->parameters.push_back(this->resultParam);
288
289 this->methodSwitch = new SwitchStatement(this->methodId);
290 this->onResultMethod->statements->Add(this->methodSwitch);
291}
292
293void
294ResultDispatcherClass::AddMethod(int index, const string& name, Method** method, Variable** param)
295{
296 Method* m = new Method;
297 m->modifiers = PUBLIC;
298 m->returnType = VOID_TYPE;
299 m->returnTypeDimension = 0;
300 m->name = name;
301 m->statements = new StatementBlock;
302 *param = new Variable(BYTE_TYPE, "result", 1);
303 m->parameters.push_back(*param);
304 this->elements.push_back(m);
305 *method = m;
306
307 Case* c = new Case(format_int(index));
308 c->statements->Add(new MethodCall(new LiteralExpression("this"), name, 1, this->resultParam));
Joe Onorato3d0e06f2011-09-02 15:28:36 -0700309 c->statements->Add(new Break());
Joe Onoratoc596cfe2011-08-30 17:24:17 -0700310
311 this->methodSwitch->cases.push_back(c);
312}
313
314// =================================================
315static void
316generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from)
317{
318 fprintf(stderr, "aidl: implement generate_new_array %s:%d\n", __FILE__, __LINE__);
319 exit(1);
320}
321
322static void
323generate_create_from_data(Type* t, StatementBlock* addTo, const string& key, Variable* v,
324 Variable* data, Variable** cl)
325{
326 Expression* k = new StringLiteralExpression(key);
327 if (v->dimension == 0) {
328 t->CreateFromRpcData(addTo, k, v, data, cl);
329 }
330 if (v->dimension == 1) {
331 //t->ReadArrayFromRpcData(addTo, v, data, cl);
332 fprintf(stderr, "aidl: implement generate_create_from_data for arrays%s:%d\n",
333 __FILE__, __LINE__);
334 }
335}
336
337static void
338generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v, Variable* data)
339{
340 if (v->dimension == 0) {
341 t->WriteToRpcData(addTo, k, v, data, 0);
342 }
343 if (v->dimension == 1) {
344 //t->WriteArrayToParcel(addTo, v, data);
345 fprintf(stderr, "aidl: implement generate_write_to_data for arrays%s:%d\n",
346 __FILE__, __LINE__);
347 }
348}
349
350// =================================================
351static string
352results_class_name(const string& n)
353{
354 string str = n;
355 str[0] = toupper(str[0]);
356 str.insert(0, "On");
357 return str;
358}
359
360static string
361results_method_name(const string& n)
362{
363 string str = n;
364 str[0] = toupper(str[0]);
365 str.insert(0, "on");
366 return str;
367}
368
369static Type*
370generate_results_method(const method_type* method, RpcProxyClass* proxyClass)
371{
372 arg_type* arg;
373
374 string resultsMethodName = results_method_name(method->name.data);
375 Type* resultsInterfaceType = new Type(results_class_name(method->name.data),
Joe Onorato4135a7d2011-09-15 21:31:15 -0700376 Type::GENERATED, false, false, false);
Joe Onoratoc596cfe2011-08-30 17:24:17 -0700377
378 if (!method->oneway) {
379 Class* resultsClass = new Class;
380 resultsClass->modifiers = STATIC | PUBLIC;
381 resultsClass->what = Class::INTERFACE;
382 resultsClass->type = resultsInterfaceType;
383
384 Method* resultMethod = new Method;
385 resultMethod->comment = gather_comments(method->comments_token->extra);
386 resultMethod->modifiers = PUBLIC;
387 resultMethod->returnType = VOID_TYPE;
388 resultMethod->returnTypeDimension = 0;
389 resultMethod->name = resultsMethodName;
390 if (0 != strcmp("void", method->type.type.data)) {
391 resultMethod->parameters.push_back(new Variable(NAMES.Search(method->type.type.data),
392 "_result", method->type.dimension));
393 }
394 arg = method->args;
395 while (arg != NULL) {
396 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
397 resultMethod->parameters.push_back(new Variable(
398 NAMES.Search(arg->type.type.data), arg->name.data,
399 arg->type.dimension));
400 }
401 arg = arg->next;
402 }
403 resultsClass->elements.push_back(resultMethod);
404
405 if (resultMethod->parameters.size() > 0) {
406 proxyClass->elements.push_back(resultsClass);
407 return resultsInterfaceType;
408 }
409 }
410 //delete resultsInterfaceType;
411 return NULL;
412}
413
414static void
415generate_proxy_method(const method_type* method, RpcProxyClass* proxyClass,
416 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index)
417{
418 arg_type* arg;
419 Method* proxyMethod = new Method;
420 proxyMethod->comment = gather_comments(method->comments_token->extra);
421 proxyMethod->modifiers = PUBLIC;
422 proxyMethod->returnType = VOID_TYPE;
423 proxyMethod->returnTypeDimension = 0;
424 proxyMethod->name = method->name.data;
425 proxyMethod->statements = new StatementBlock;
426 proxyClass->elements.push_back(proxyMethod);
427
428 // The local variables
429 Variable* _data = new Variable(RPC_DATA_TYPE, "_data");
430 proxyMethod->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE)));
431
432 // Add the arguments
433 arg = method->args;
434 while (arg != NULL) {
435 if (convert_direction(arg->direction.data) & IN_PARAMETER) {
436 // Function signature
437 Type* t = NAMES.Search(arg->type.type.data);
438 Variable* v = new Variable(t, arg->name.data, arg->type.dimension);
439 proxyMethod->parameters.push_back(v);
440
441 // Input parameter marshalling
442 generate_write_to_data(t, proxyMethod->statements,
443 new StringLiteralExpression(arg->name.data), v, _data);
444 }
445 arg = arg->next;
446 }
447
448 // If there is a results interface for this class
449 Expression* resultParameter;
450 if (resultsInterfaceType != NULL) {
451 // Result interface parameter
452 Variable* resultListener = new Variable(resultsInterfaceType, "_result");
453 proxyMethod->parameters.push_back(resultListener);
454
455 // Add the results dispatcher callback
456 resultsDispatcherClass->needed = true;
457 resultParameter = new NewExpression(resultsDispatcherClass->type, 2,
458 new LiteralExpression(format_int(index)), resultListener);
459 } else {
460 resultParameter = NULL_VALUE;
461 }
462
463 // All proxy methods take an error parameter
464 Variable* errorListener = new Variable(RPC_ERROR_LISTENER_TYPE, "_errors");
465 proxyMethod->parameters.push_back(errorListener);
466
467 // Call the broker
468 proxyMethod->statements->Add(new MethodCall(RPC_BROKER_TYPE, "sendRequest", 6,
469 new FieldVariable(THIS_VALUE, "_context"),
470 new StringLiteralExpression(method->name.data),
471 proxyClass->endpoint,
472 new MethodCall(_data, "serialize"),
473 resultParameter,
474 errorListener));
475}
476
477static void
478generate_result_dispatcher_method(const method_type* method,
479 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index)
480{
481 arg_type* arg;
482 Method* dispatchMethod;
483 Variable* dispatchParam;
484 resultsDispatcherClass->AddMethod(index, method->name.data, &dispatchMethod, &dispatchParam);
485
486 Variable* classLoader = NULL;
487 Variable* resultData = new Variable(RPC_DATA_TYPE, "resultData");
488 dispatchMethod->statements->Add(new VariableDeclaration(resultData,
489 new NewExpression(RPC_DATA_TYPE, 1, dispatchParam)));
490
491 // The callback method itself
492 MethodCall* realCall = new MethodCall(
493 new Cast(resultsInterfaceType, new FieldVariable(THIS_VALUE, "callback")),
494 results_method_name(method->name.data));
495
496 // The return value
497 {
498 Type* t = NAMES.Search(method->type.type.data);
499 Variable* rv = new Variable(t, "rv");
500 dispatchMethod->statements->Add(new VariableDeclaration(rv));
501 generate_create_from_data(t, dispatchMethod->statements, "_result", rv,
502 resultData, &classLoader);
503 realCall->arguments.push_back(rv);
504 }
505
506 VariableFactory stubArgs("arg");
507 arg = method->args;
508 while (arg != NULL) {
509 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
510 // Unmarshall the results
511 Type* t = NAMES.Search(arg->type.type.data);
512 Variable* v = stubArgs.Get(t);
513 dispatchMethod->statements->Add(new VariableDeclaration(v));
514
515 generate_create_from_data(t, dispatchMethod->statements, arg->name.data, v,
516 resultData, &classLoader);
517
518 // Add the argument to the callback
519 realCall->arguments.push_back(v);
520 }
521 arg = arg->next;
522 }
523
524 // Call the callback method
525 dispatchMethod->statements->Add(realCall);
526}
527
528static void
529generate_service_base_methods(const method_type* method, ServiceBaseClass* serviceBaseClass)
530{
531 arg_type* arg;
532 StatementBlock* block;
533 serviceBaseClass->AddMethod(method->name.data, &block);
534
535 // The abstract method that the service developers implement
536 Method* decl = new Method;
537 decl->comment = gather_comments(method->comments_token->extra);
538 decl->modifiers = PUBLIC | ABSTRACT;
539 decl->returnType = NAMES.Search(method->type.type.data);
540 decl->returnTypeDimension = method->type.dimension;
541 decl->name = method->name.data;
542
543 arg = method->args;
544 while (arg != NULL) {
545 decl->parameters.push_back(new Variable(
546 NAMES.Search(arg->type.type.data), arg->name.data,
547 arg->type.dimension));
548 arg = arg->next;
549 }
550
551 serviceBaseClass->elements.push_back(decl);
552
553 // The call to decl (from above)
554 MethodCall* realCall = new MethodCall(THIS_VALUE, method->name.data);
555
556 // args
557 Variable* classLoader = NULL;
558 VariableFactory stubArgs("_arg");
559 arg = method->args;
560 while (arg != NULL) {
561 Type* t = NAMES.Search(arg->type.type.data);
562 Variable* v = stubArgs.Get(t);
563 v->dimension = arg->type.dimension;
564
565 // Unmarshall the parameter
566 block->Add(new VariableDeclaration(v));
567 if (convert_direction(arg->direction.data) & IN_PARAMETER) {
568 generate_create_from_data(t, block, arg->name.data, v,
569 serviceBaseClass->requestData, &classLoader);
570 } else {
571 if (arg->type.dimension == 0) {
572 block->Add(new Assignment(v, new NewExpression(v->type)));
573 }
574 else if (arg->type.dimension == 1) {
575 generate_new_array(v->type, block, v, serviceBaseClass->requestData);
576 }
577 else {
578 fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__,
579 __LINE__);
580 }
581 }
582
583 // Add that parameter to the method call
584 realCall->arguments.push_back(v);
585
586 arg = arg->next;
587 }
588
589 // the real call
Joe Onorato3d0e06f2011-09-02 15:28:36 -0700590 bool first = true;
Joe Onoratoc596cfe2011-08-30 17:24:17 -0700591 Variable* _result = NULL;
592 if (0 == strcmp(method->type.type.data, "void")) {
593 block->Add(realCall);
594 } else {
595 _result = new Variable(decl->returnType, "_result",
596 decl->returnTypeDimension);
597 block->Add(new VariableDeclaration(_result, realCall));
598
Joe Onorato3d0e06f2011-09-02 15:28:36 -0700599 // need the result RpcData
600 if (first) {
601 block->Add(new Assignment(serviceBaseClass->resultData,
602 new NewExpression(RPC_DATA_TYPE)));
603 first = false;
604 }
605
Joe Onoratoc596cfe2011-08-30 17:24:17 -0700606 // marshall the return value
607 generate_write_to_data(decl->returnType, block,
608 new StringLiteralExpression("_result"), _result, serviceBaseClass->resultData);
609 }
610
611 // out parameters
612 int i = 0;
613 arg = method->args;
614 while (arg != NULL) {
615 Type* t = NAMES.Search(arg->type.type.data);
616 Variable* v = stubArgs.Get(i++);
617
618 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
Joe Onorato3d0e06f2011-09-02 15:28:36 -0700619 // need the result RpcData
620 if (first) {
621 block->Add(new Assignment(serviceBaseClass->resultData,
622 new NewExpression(RPC_DATA_TYPE)));
623 first = false;
624 }
625
626
Joe Onoratoc596cfe2011-08-30 17:24:17 -0700627 generate_write_to_data(t, block, new StringLiteralExpression(arg->name.data),
628 v, serviceBaseClass->resultData);
629 }
630
631 arg = arg->next;
632 }
633}
634
635static void
636generate_method(const method_type* method, RpcProxyClass* proxyClass,
637 ServiceBaseClass* serviceBaseClass, ResultDispatcherClass* resultsDispatcherClass,
638 int index)
639{
640 // == the callback interface for results =================================
641 // the service base class
642 Type* resultsInterfaceType = generate_results_method(method, proxyClass);
643
644 // == the method in the proxy class =====================================
645 generate_proxy_method(method, proxyClass, resultsDispatcherClass, resultsInterfaceType, index);
646
647 // == the method in the result dispatcher class =========================
648 if (resultsInterfaceType != NULL) {
649 generate_result_dispatcher_method(method, resultsDispatcherClass, resultsInterfaceType,
650 index);
651 }
652
653 // == the dispatch method in the service base class ======================
654 generate_service_base_methods(method, serviceBaseClass);
655}
656
657Class*
658generate_rpc_interface_class(const interface_type* iface)
659{
660 // the proxy class
661 InterfaceType* interfaceType = static_cast<InterfaceType*>(
662 NAMES.Find(iface->package, iface->name.data));
663 RpcProxyClass* proxy = new RpcProxyClass(iface, interfaceType);
664
665 // the service base class
666 ServiceBaseClass* base = new ServiceBaseClass(iface);
667 proxy->elements.push_back(base);
668
669 // the result dispatcher
670 ResultDispatcherClass* results = new ResultDispatcherClass();
671
672 // all the declared methods of the proxy
673 int index = 0;
674 interface_item_type* item = iface->interface_items;
675 while (item != NULL) {
676 if (item->item_type == METHOD_TYPE) {
677 generate_method((method_type*)item, proxy, base, results, index);
678 }
679 item = item->next;
680 index++;
681 }
682 base->DoneWithMethods();
683
684 // only add this if there are methods with results / out parameters
685 if (results->needed) {
686 proxy->elements.push_back(results);
687 }
688
689 return proxy;
690}
691