1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "generate_java.h"
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Type.h"
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <string.h>
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <stdio.h>
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <stdlib.h>
6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <string.h>
7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiType* SERVICE_CONTEXT_TYPE = new Type("android.content",
9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "Context", Type::BUILT_IN, false, false, false);
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiType* PRESENTER_BASE_TYPE = new Type("android.support.place.connector",
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "EventListener", Type::BUILT_IN, false, false, false);
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiType* PRESENTER_LISTENER_BASE_TYPE = new Type("android.support.place.connector",
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "EventListener.Listener", Type::BUILT_IN, false, false, false);
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiType* RPC_BROKER_TYPE = new Type("android.support.place.connector", "Broker",
15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Type::BUILT_IN, false, false, false);
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiType* RPC_CONTAINER_TYPE = new Type("com.android.athome.connector", "ConnectorContainer",
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Type::BUILT_IN, false, false, false);
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiType* PLACE_INFO_TYPE = new Type("android.support.place.connector", "PlaceInfo",
19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Type::BUILT_IN, false, false, false);
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// TODO: Just use Endpoint, so this works for all endpoints.
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiType* RPC_CONNECTOR_TYPE = new Type("android.support.place.connector", "Connector",
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Type::BUILT_IN, false, false, false);
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiType* RPC_ENDPOINT_INFO_TYPE = new UserDataType("android.support.place.rpc",
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        "EndpointInfo", true, __FILE__, __LINE__);
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiType* RPC_RESULT_HANDLER_TYPE = new UserDataType("android.support.place.rpc", "RpcResultHandler",
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        true, __FILE__, __LINE__);
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiType* RPC_ERROR_LISTENER_TYPE = new Type("android.support.place.rpc", "RpcErrorHandler",
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Type::BUILT_IN, false, false, false);
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiType* RPC_CONTEXT_TYPE = new UserDataType("android.support.place.rpc", "RpcContext", true,
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        __FILE__, __LINE__);
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void generate_create_from_data(Type* t, StatementBlock* addTo, const string& key,
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Variable* v, Variable* data, Variable** cl);
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from);
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v,
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Variable* data);
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic string
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiformat_int(int n)
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    char str[20];
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sprintf(str, "%d", n);
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return string(str);
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic string
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass_name_leaf(const string& str)
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    string::size_type pos = str.rfind('.');
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (pos == string::npos) {
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return str;
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return string(str, pos+1);
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic string
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiresults_class_name(const string& n)
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    string str = n;
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    str[0] = toupper(str[0]);
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    str.insert(0, "On");
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return str;
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic string
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiresults_method_name(const string& n)
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    string str = n;
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    str[0] = toupper(str[0]);
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    str.insert(0, "on");
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return str;
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic string
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipush_method_name(const string& n)
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    string str = n;
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    str[0] = toupper(str[0]);
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    str.insert(0, "push");
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return str;
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =================================================
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass DispatcherClass : public Class
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic:
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    DispatcherClass(const interface_type* iface, Expression* target);
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    virtual ~DispatcherClass();
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void AddMethod(const method_type* method);
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void DoneWithMethods();
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* processMethod;
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* actionParam;
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* requestParam;
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* rpcContextParam;
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* errorParam;
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* requestData;
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* resultData;
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    IfStatement* dispatchIfStatement;
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Expression* targetExpression;
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiprivate:
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void generate_process();
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiDispatcherClass::DispatcherClass(const interface_type* iface, Expression* target)
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    :Class(),
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     dispatchIfStatement(NULL),
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     targetExpression(target)
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    generate_process();
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiDispatcherClass::~DispatcherClass()
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiDispatcherClass::generate_process()
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // byte[] process(String action, byte[] params, RpcContext context, RpcError status)
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->processMethod = new Method;
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this->processMethod->modifiers = PUBLIC;
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this->processMethod->returnType = BYTE_TYPE;
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this->processMethod->returnTypeDimension = 1;
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this->processMethod->name = "process";
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this->processMethod->statements = new StatementBlock;
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->actionParam = new Variable(STRING_TYPE, "action");
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->processMethod->parameters.push_back(this->actionParam);
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->requestParam = new Variable(BYTE_TYPE, "requestParam", 1);
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->processMethod->parameters.push_back(this->requestParam);
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->rpcContextParam = new Variable(RPC_CONTEXT_TYPE, "context", 0);
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->processMethod->parameters.push_back(this->rpcContextParam);
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->errorParam = new Variable(RPC_ERROR_TYPE, "errorParam", 0);
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->processMethod->parameters.push_back(this->errorParam);
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->requestData = new Variable(RPC_DATA_TYPE, "request");
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->processMethod->statements->Add(new VariableDeclaration(requestData,
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new NewExpression(RPC_DATA_TYPE, 1, this->requestParam)));
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->resultData = new Variable(RPC_DATA_TYPE, "resultData");
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->processMethod->statements->Add(new VariableDeclaration(this->resultData,
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                NULL_VALUE));
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiDispatcherClass::AddMethod(const method_type* method)
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg_type* arg;
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // The if/switch statement
158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    IfStatement* ifs = new IfStatement();
159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ifs->expression = new MethodCall(new StringLiteralExpression(method->name.data), "equals",
160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                1, this->actionParam);
161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    StatementBlock* block = ifs->statements = new StatementBlock;
162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (this->dispatchIfStatement == NULL) {
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this->dispatchIfStatement = ifs;
164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this->processMethod->statements->Add(dispatchIfStatement);
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this->dispatchIfStatement->elseif = ifs;
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this->dispatchIfStatement = ifs;
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // The call to decl (from above)
171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MethodCall* realCall = new MethodCall(this->targetExpression, method->name.data);
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // args
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* classLoader = NULL;
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VariableFactory stubArgs("_arg");
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg = method->args;
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (arg != NULL) {
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Type* t = NAMES.Search(arg->type.type.data);
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Variable* v = stubArgs.Get(t);
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        v->dimension = arg->type.dimension;
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Unmarshall the parameter
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        block->Add(new VariableDeclaration(v));
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (convert_direction(arg->direction.data) & IN_PARAMETER) {
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            generate_create_from_data(t, block, arg->name.data, v,
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    this->requestData, &classLoader);
187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (arg->type.dimension == 0) {
189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                block->Add(new Assignment(v, new NewExpression(v->type)));
190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            else if (arg->type.dimension == 1) {
192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                generate_new_array(v->type, block, v, this->requestData);
193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            else {
195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__,
196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        __LINE__);
197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Add that parameter to the method call
201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        realCall->arguments.push_back(v);
202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        arg = arg->next;
204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Add a final parameter: RpcContext. Contains data about
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // incoming request (e.g., certificate)
208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    realCall->arguments.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Type* returnType = NAMES.Search(method->type.type.data);
211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (returnType == EVENT_FAKE_TYPE) {
212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        returnType = VOID_TYPE;
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the real call
216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool first = true;
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* _result = NULL;
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (returnType == VOID_TYPE) {
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        block->Add(realCall);
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        _result = new Variable(returnType, "_result",
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                method->type.dimension);
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        block->Add(new VariableDeclaration(_result, realCall));
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // need the result RpcData
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (first) {
227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            block->Add(new Assignment(this->resultData,
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        new NewExpression(RPC_DATA_TYPE)));
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            first = false;
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // marshall the return value
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        generate_write_to_data(returnType, block,
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new StringLiteralExpression("_result"), _result, this->resultData);
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // out parameters
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int i = 0;
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg = method->args;
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (arg != NULL) {
241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Type* t = NAMES.Search(arg->type.type.data);
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Variable* v = stubArgs.Get(i++);
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // need the result RpcData
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (first) {
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                block->Add(new Assignment(this->resultData, new NewExpression(RPC_DATA_TYPE)));
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                first = false;
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            generate_write_to_data(t, block, new StringLiteralExpression(arg->name.data),
252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    v, this->resultData);
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        arg = arg->next;
256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid
260282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiDispatcherClass::DoneWithMethods()
261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (this->dispatchIfStatement == NULL) {
263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return;
264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(this->processMethod);
267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    IfStatement* fallthrough = new IfStatement();
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fallthrough->statements = new StatementBlock;
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fallthrough->statements->Add(new ReturnStatement(
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    new MethodCall(SUPER_VALUE, "process", 4,
272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    this->actionParam, this->requestParam,
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    this->rpcContextParam,
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    this->errorParam)));
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->dispatchIfStatement->elseif = fallthrough;
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    IfStatement* s = new IfStatement;
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        s->statements = new StatementBlock;
278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->processMethod->statements->Add(s);
279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    s->expression = new Comparison(this->resultData, "!=", NULL_VALUE);
280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    s->statements->Add(new ReturnStatement(new MethodCall(this->resultData, "serialize")));
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    s->elseif = new IfStatement;
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    s = s->elseif;
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    s->statements->Add(new ReturnStatement(NULL_VALUE));
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =================================================
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass RpcProxyClass : public Class
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic:
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType);
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    virtual ~RpcProxyClass();
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* endpoint;
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* broker;
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiprivate:
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void generate_ctor();
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void generate_get_endpoint_info();
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
301282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiRpcProxyClass::RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType)
302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    :Class()
303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->comment = gather_comments(iface->comments_token->extra);
305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->modifiers = PUBLIC;
306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->what = Class::CLASS;
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->type = interfaceType;
308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // broker
310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->broker = new Variable(RPC_BROKER_TYPE, "_broker");
311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(new Field(PRIVATE, this->broker));
312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // endpoint
313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "_endpoint");
314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(new Field(PRIVATE, this->endpoint));
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // methods
317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    generate_ctor();
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    generate_get_endpoint_info();
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiRpcProxyClass::~RpcProxyClass()
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiRpcProxyClass::generate_ctor()
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* broker = new Variable(RPC_BROKER_TYPE, "broker");
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "endpoint");
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* ctor = new Method;
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->modifiers = PUBLIC;
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->name = class_name_leaf(this->type->Name());
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->statements = new StatementBlock;
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->parameters.push_back(broker);
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->parameters.push_back(endpoint);
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(ctor);
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ctor->statements->Add(new Assignment(this->broker, broker));
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ctor->statements->Add(new Assignment(this->endpoint, endpoint));
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid
343282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiRpcProxyClass::generate_get_endpoint_info()
344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* get = new Method;
346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    get->modifiers = PUBLIC;
347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    get->returnType = RPC_ENDPOINT_INFO_TYPE;
348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    get->name = "getEndpointInfo";
349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    get->statements = new StatementBlock;
350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(get);
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    get->statements->Add(new ReturnStatement(this->endpoint));
353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =================================================
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass EventListenerClass : public DispatcherClass
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic:
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    EventListenerClass(const interface_type* iface, Type* listenerType);
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    virtual ~EventListenerClass();
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* _listener;
363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiprivate:
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void generate_ctor();
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiExpression*
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_get_listener_expression(Type* cast)
370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return new Cast(cast, new MethodCall(THIS_VALUE, "getView"));
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
374282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiEventListenerClass::EventListenerClass(const interface_type* iface, Type* listenerType)
375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    :DispatcherClass(iface, new FieldVariable(THIS_VALUE, "_listener"))
376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->modifiers = PRIVATE;
378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->what = Class::CLASS;
379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->type = new Type(iface->package ? iface->package : "",
380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        append(iface->name.data, ".Presenter"),
381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        Type::GENERATED, false, false, false);
382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->extends = PRESENTER_BASE_TYPE;
383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->_listener = new Variable(listenerType, "_listener");
385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(new Field(PRIVATE, this->_listener));
386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // methods
388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    generate_ctor();
389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
391282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiEventListenerClass::~EventListenerClass()
392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid
396282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiEventListenerClass::generate_ctor()
397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* broker = new Variable(RPC_BROKER_TYPE, "broker");
399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* listener = new Variable(this->_listener->type, "listener");
400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* ctor = new Method;
401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->modifiers = PUBLIC;
402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->name = class_name_leaf(this->type->Name());
403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->statements = new StatementBlock;
404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->parameters.push_back(broker);
405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->parameters.push_back(listener);
406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(ctor);
407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ctor->statements->Add(new MethodCall("super", 2, broker, listener));
409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ctor->statements->Add(new Assignment(this->_listener, listener));
410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =================================================
413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass ListenerClass : public Class
414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic:
416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ListenerClass(const interface_type* iface);
417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    virtual ~ListenerClass();
418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool needed;
420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiprivate:
422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void generate_ctor();
423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
425282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiListenerClass::ListenerClass(const interface_type* iface)
426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    :Class(),
427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     needed(false)
428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->comment = "/** Extend this to listen to the events from this class. */";
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->modifiers = STATIC | PUBLIC ;
431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->what = Class::CLASS;
432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->type = new Type(iface->package ? iface->package : "",
433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        append(iface->name.data, ".Listener"),
434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        Type::GENERATED, false, false, false);
435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->extends = PRESENTER_LISTENER_BASE_TYPE;
436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
438282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiListenerClass::~ListenerClass()
439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =================================================
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass EndpointBaseClass : public DispatcherClass
444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic:
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    EndpointBaseClass(const interface_type* iface);
447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    virtual ~EndpointBaseClass();
448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool needed;
450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiprivate:
452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void generate_ctor();
453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
455282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiEndpointBaseClass::EndpointBaseClass(const interface_type* iface)
456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    :DispatcherClass(iface, THIS_VALUE),
457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     needed(false)
458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->comment = "/** Extend this to implement a link service. */";
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->modifiers = STATIC | PUBLIC | ABSTRACT;
461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->what = Class::CLASS;
462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->type = new Type(iface->package ? iface->package : "",
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        append(iface->name.data, ".EndpointBase"),
464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        Type::GENERATED, false, false, false);
465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->extends = RPC_CONNECTOR_TYPE;
466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // methods
468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    generate_ctor();
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
471282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiEndpointBaseClass::~EndpointBaseClass()
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid
476282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiEndpointBaseClass::generate_ctor()
477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* container = new Variable(RPC_CONTAINER_TYPE, "container");
479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* broker = new Variable(RPC_BROKER_TYPE, "broker");
480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski	Variable* place = new Variable(PLACE_INFO_TYPE, "placeInfo");
481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* ctor = new Method;
482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->modifiers = PUBLIC;
483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->name = class_name_leaf(this->type->Name());
484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->statements = new StatementBlock;
485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->parameters.push_back(container);
486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->parameters.push_back(broker);
487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->parameters.push_back(place);
488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(ctor);
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ctor->statements->Add(new MethodCall("super", 3, container, broker, place));
491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =================================================
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass ResultDispatcherClass : public Class
495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic:
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResultDispatcherClass();
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    virtual ~ResultDispatcherClass();
499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void AddMethod(int index, const string& name, Method** method, Variable** param);
501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool needed;
503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* methodId;
504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* callback;
505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* onResultMethod;
506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* resultParam;
507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SwitchStatement* methodSwitch;
508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiprivate:
510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void generate_ctor();
511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void generate_onResult();
512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
514282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResultDispatcherClass::ResultDispatcherClass()
515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    :Class(),
516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     needed(false)
517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->modifiers = PRIVATE | FINAL;
519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->what = Class::CLASS;
520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->type = new Type("_ResultDispatcher", Type::GENERATED, false, false, false);
521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->interfaces.push_back(RPC_RESULT_HANDLER_TYPE);
522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // methodId
524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->methodId = new Variable(INT_TYPE, "methodId");
525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(new Field(PRIVATE, this->methodId));
526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->callback = new Variable(OBJECT_TYPE, "callback");
527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(new Field(PRIVATE, this->callback));
528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // methods
530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    generate_ctor();
531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    generate_onResult();
532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
534282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResultDispatcherClass::~ResultDispatcherClass()
535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid
539282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResultDispatcherClass::generate_ctor()
540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* methodIdParam = new Variable(INT_TYPE, "methId");
542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* callbackParam = new Variable(OBJECT_TYPE, "cbObj");
543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* ctor = new Method;
544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->modifiers = PUBLIC;
545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->name = class_name_leaf(this->type->Name());
546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->statements = new StatementBlock;
547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->parameters.push_back(methodIdParam);
548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->parameters.push_back(callbackParam);
549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(ctor);
550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ctor->statements->Add(new Assignment(this->methodId, methodIdParam));
552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ctor->statements->Add(new Assignment(this->callback, callbackParam));
553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid
556282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResultDispatcherClass::generate_onResult()
557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->onResultMethod = new Method;
559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this->onResultMethod->modifiers = PUBLIC;
560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this->onResultMethod->returnType = VOID_TYPE;
561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this->onResultMethod->returnTypeDimension = 0;
562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this->onResultMethod->name = "onResult";
563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        this->onResultMethod->statements = new StatementBlock;
564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(this->onResultMethod);
565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->resultParam = new Variable(BYTE_TYPE, "result", 1);
567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->onResultMethod->parameters.push_back(this->resultParam);
568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->methodSwitch = new SwitchStatement(this->methodId);
570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->onResultMethod->statements->Add(this->methodSwitch);
571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid
574282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResultDispatcherClass::AddMethod(int index, const string& name, Method** method, Variable** param)
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* m = new Method;
577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        m->modifiers = PUBLIC;
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        m->returnType = VOID_TYPE;
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        m->returnTypeDimension = 0;
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        m->name = name;
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        m->statements = new StatementBlock;
582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    *param = new Variable(BYTE_TYPE, "result", 1);
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    m->parameters.push_back(*param);
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(m);
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    *method = m;
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Case* c = new Case(format_int(index));
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    c->statements->Add(new MethodCall(new LiteralExpression("this"), name, 1, this->resultParam));
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    c->statements->Add(new Break());
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->methodSwitch->cases.push_back(c);
592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =================================================
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from)
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    fprintf(stderr, "aidl: implement generate_new_array %s:%d\n", __FILE__, __LINE__);
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    exit(1);
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_create_from_data(Type* t, StatementBlock* addTo, const string& key, Variable* v,
604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            Variable* data, Variable** cl)
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Expression* k = new StringLiteralExpression(key);
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (v->dimension == 0) {
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t->CreateFromRpcData(addTo, k, v, data, cl);
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (v->dimension == 1) {
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //t->ReadArrayFromRpcData(addTo, v, data, cl);
612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "aidl: implement generate_create_from_data for arrays%s:%d\n",
613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                __FILE__, __LINE__);
614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void
618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v, Variable* data)
619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (v->dimension == 0) {
621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t->WriteToRpcData(addTo, k, v, data, 0);
622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (v->dimension == 1) {
624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        //t->WriteArrayToParcel(addTo, v, data);
625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        fprintf(stderr, "aidl: implement generate_write_to_data for arrays%s:%d\n",
626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                __FILE__, __LINE__);
627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =================================================
631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic Type*
632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_results_method(const method_type* method, RpcProxyClass* proxyClass)
633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg_type* arg;
635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    string resultsMethodName = results_method_name(method->name.data);
637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Type* resultsInterfaceType = new Type(results_class_name(method->name.data),
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Type::GENERATED, false, false, false);
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!method->oneway) {
641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Class* resultsClass = new Class;
642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            resultsClass->modifiers = STATIC | PUBLIC;
643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            resultsClass->what = Class::INTERFACE;
644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            resultsClass->type = resultsInterfaceType;
645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Method* resultMethod = new Method;
647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            resultMethod->comment = gather_comments(method->comments_token->extra);
648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            resultMethod->modifiers = PUBLIC;
649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            resultMethod->returnType = VOID_TYPE;
650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            resultMethod->returnTypeDimension = 0;
651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            resultMethod->name = resultsMethodName;
652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (0 != strcmp("void", method->type.type.data)) {
653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            resultMethod->parameters.push_back(new Variable(NAMES.Search(method->type.type.data),
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "_result", method->type.dimension));
655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        arg = method->args;
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (arg != NULL) {
658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                resultMethod->parameters.push_back(new Variable(
660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    NAMES.Search(arg->type.type.data), arg->name.data,
661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    arg->type.dimension));
662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            arg = arg->next;
664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        resultsClass->elements.push_back(resultMethod);
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (resultMethod->parameters.size() > 0) {
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            proxyClass->elements.push_back(resultsClass);
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return resultsInterfaceType;
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //delete resultsInterfaceType;
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return NULL;
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_proxy_method(const method_type* method, RpcProxyClass* proxyClass,
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index)
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg_type* arg;
681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* proxyMethod = new Method;
682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxyMethod->comment = gather_comments(method->comments_token->extra);
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxyMethod->modifiers = PUBLIC;
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxyMethod->returnType = VOID_TYPE;
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxyMethod->returnTypeDimension = 0;
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxyMethod->name = method->name.data;
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxyMethod->statements = new StatementBlock;
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    proxyClass->elements.push_back(proxyMethod);
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // The local variables
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* _data = new Variable(RPC_DATA_TYPE, "_data");
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    proxyMethod->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE)));
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Add the arguments
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg = method->args;
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (arg != NULL) {
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (convert_direction(arg->direction.data) & IN_PARAMETER) {
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Function signature
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Type* t = NAMES.Search(arg->type.type.data);
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Variable* v = new Variable(t, arg->name.data, arg->type.dimension);
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            proxyMethod->parameters.push_back(v);
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Input parameter marshalling
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            generate_write_to_data(t, proxyMethod->statements,
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    new StringLiteralExpression(arg->name.data), v, _data);
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        arg = arg->next;
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // If there is a results interface for this class
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Expression* resultParameter;
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (resultsInterfaceType != NULL) {
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Result interface parameter
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Variable* resultListener = new Variable(resultsInterfaceType, "_result");
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxyMethod->parameters.push_back(resultListener);
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Add the results dispatcher callback
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        resultsDispatcherClass->needed = true;
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        resultParameter = new NewExpression(resultsDispatcherClass->type, 2,
720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new LiteralExpression(format_int(index)), resultListener);
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        resultParameter = NULL_VALUE;
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // All proxy methods take an error parameter
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* errorListener = new Variable(RPC_ERROR_LISTENER_TYPE, "_errors");
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    proxyMethod->parameters.push_back(errorListener);
728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Call the broker
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    proxyMethod->statements->Add(new MethodCall(new FieldVariable(THIS_VALUE, "_broker"),
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "sendRpc", 5,
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                proxyClass->endpoint,
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new StringLiteralExpression(method->name.data),
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new MethodCall(_data, "serialize"),
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                resultParameter,
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                errorListener));
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void
740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_result_dispatcher_method(const method_type* method,
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index)
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg_type* arg;
744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* dispatchMethod;
745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* dispatchParam;
746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    resultsDispatcherClass->AddMethod(index, method->name.data, &dispatchMethod, &dispatchParam);
747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* classLoader = NULL;
749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* resultData = new Variable(RPC_DATA_TYPE, "resultData");
750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    dispatchMethod->statements->Add(new VariableDeclaration(resultData,
751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new NewExpression(RPC_DATA_TYPE, 1, dispatchParam)));
752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // The callback method itself
754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MethodCall* realCall = new MethodCall(
755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            new Cast(resultsInterfaceType, new FieldVariable(THIS_VALUE, "callback")),
756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            results_method_name(method->name.data));
757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // The return value
759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    {
760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Type* t = NAMES.Search(method->type.type.data);
761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (t != VOID_TYPE) {
762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Variable* rv = new Variable(t, "rv");
763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dispatchMethod->statements->Add(new VariableDeclaration(rv));
764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            generate_create_from_data(t, dispatchMethod->statements, "_result", rv,
765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    resultData, &classLoader);
766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            realCall->arguments.push_back(rv);
767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VariableFactory stubArgs("arg");
771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg = method->args;
772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (arg != NULL) {
773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Unmarshall the results
775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Type* t = NAMES.Search(arg->type.type.data);
776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Variable* v = stubArgs.Get(t);
777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            dispatchMethod->statements->Add(new VariableDeclaration(v));
778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            generate_create_from_data(t, dispatchMethod->statements, arg->name.data, v,
780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    resultData, &classLoader);
781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // Add the argument to the callback
783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            realCall->arguments.push_back(v);
784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        arg = arg->next;
786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Call the callback method
789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    IfStatement* ifst = new IfStatement;
790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ifst->expression = new Comparison(new FieldVariable(THIS_VALUE, "callback"), "!=", NULL_VALUE);
791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    dispatchMethod->statements->Add(ifst);
792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ifst->statements->Add(realCall);
793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void
796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_regular_method(const method_type* method, RpcProxyClass* proxyClass,
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        EndpointBaseClass* serviceBaseClass, ResultDispatcherClass* resultsDispatcherClass,
798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int index)
799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg_type* arg;
801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // == the callback interface for results ================================
803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the service base class
804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Type* resultsInterfaceType = generate_results_method(method, proxyClass);
805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // == the method in the proxy class =====================================
807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    generate_proxy_method(method, proxyClass, resultsDispatcherClass, resultsInterfaceType, index);
808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // == the method in the result dispatcher class =========================
810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (resultsInterfaceType != NULL) {
811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        generate_result_dispatcher_method(method, resultsDispatcherClass, resultsInterfaceType,
812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                index);
813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // == The abstract method that the service developers implement ==========
816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* decl = new Method;
817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        decl->comment = gather_comments(method->comments_token->extra);
818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        decl->modifiers = PUBLIC | ABSTRACT;
819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        decl->returnType = NAMES.Search(method->type.type.data);
820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        decl->returnTypeDimension = method->type.dimension;
821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        decl->name = method->name.data;
822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg = method->args;
823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (arg != NULL) {
824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        decl->parameters.push_back(new Variable(
825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            NAMES.Search(arg->type.type.data), arg->name.data,
826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            arg->type.dimension));
827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        arg = arg->next;
828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Add the default RpcContext param to all methods
831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    decl->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    serviceBaseClass->elements.push_back(decl);
834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // == the dispatch method in the service base class ======================
837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    serviceBaseClass->AddMethod(method);
838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void
841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_event_method(const method_type* method, RpcProxyClass* proxyClass,
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        EndpointBaseClass* serviceBaseClass, ListenerClass* listenerClass,
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        EventListenerClass* presenterClass, int index)
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg_type* arg;
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    listenerClass->needed = true;
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // == the push method in the service base class =========================
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* push = new Method;
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        push->modifiers = PUBLIC;
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        push->name = push_method_name(method->name.data);
852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        push->statements = new StatementBlock;
853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        push->returnType = VOID_TYPE;
854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    serviceBaseClass->elements.push_back(push);
855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // The local variables
857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* _data = new Variable(RPC_DATA_TYPE, "_data");
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    push->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE)));
859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Add the arguments
861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg = method->args;
862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (arg != NULL) {
863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Function signature
864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Type* t = NAMES.Search(arg->type.type.data);
865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Variable* v = new Variable(t, arg->name.data, arg->type.dimension);
866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        push->parameters.push_back(v);
867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Input parameter marshalling
869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        generate_write_to_data(t, push->statements,
870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new StringLiteralExpression(arg->name.data), v, _data);
871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        arg = arg->next;
873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Send the notifications
876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    push->statements->Add(new MethodCall("pushEvent", 2,
877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new StringLiteralExpression(method->name.data),
878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new MethodCall(_data, "serialize")));
879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // == the event callback dispatcher method  ====================================
881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    presenterClass->AddMethod(method);
882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // == the event method in the listener base class =====================
884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* event = new Method;
885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        event->modifiers = PUBLIC;
886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        event->name = method->name.data;
887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        event->statements = new StatementBlock;
888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        event->returnType = VOID_TYPE;
889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    listenerClass->elements.push_back(event);
890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg = method->args;
891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (arg != NULL) {
892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        event->parameters.push_back(new Variable(
893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            NAMES.Search(arg->type.type.data), arg->name.data,
894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            arg->type.dimension));
895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        arg = arg->next;
896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Add a final parameter: RpcContext. Contains data about
899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // incoming request (e.g., certificate)
900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    event->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0));
901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void
904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_listener_methods(RpcProxyClass* proxyClass, Type* presenterType, Type* listenerType)
905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // AndroidAtHomePresenter _presenter;
907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // void startListening(Listener listener) {
908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //     stopListening();
909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //     _presenter = new Presenter(_broker, listener);
910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //     _presenter.startListening(_endpoint);
911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // }
912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // void stopListening() {
913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //     if (_presenter != null) {
914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //         _presenter.stopListening();
915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    //     }
916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // }
917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* _presenter = new Variable(presenterType, "_presenter");
919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    proxyClass->elements.push_back(new Field(PRIVATE, _presenter));
920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* listener = new Variable(listenerType, "listener");
922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* startListeningMethod = new Method;
924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        startListeningMethod->modifiers = PUBLIC;
925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        startListeningMethod->returnType = VOID_TYPE;
926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        startListeningMethod->name = "startListening";
927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        startListeningMethod->statements = new StatementBlock;
928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        startListeningMethod->parameters.push_back(listener);
929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    proxyClass->elements.push_back(startListeningMethod);
930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    startListeningMethod->statements->Add(new MethodCall(THIS_VALUE, "stopListening"));
932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    startListeningMethod->statements->Add(new Assignment(_presenter,
933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new NewExpression(presenterType, 2, proxyClass->broker, listener)));
934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    startListeningMethod->statements->Add(new MethodCall(_presenter,
935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "startListening", 1, proxyClass->endpoint));
936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* stopListeningMethod = new Method;
938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        stopListeningMethod->modifiers = PUBLIC;
939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        stopListeningMethod->returnType = VOID_TYPE;
940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        stopListeningMethod->name = "stopListening";
941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        stopListeningMethod->statements = new StatementBlock;
942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    proxyClass->elements.push_back(stopListeningMethod);
943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    IfStatement* ifst = new IfStatement;
945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ifst->expression = new Comparison(_presenter, "!=", NULL_VALUE);
946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    stopListeningMethod->statements->Add(ifst);
947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ifst->statements->Add(new MethodCall(_presenter, "stopListening"));
949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ifst->statements->Add(new Assignment(_presenter, NULL_VALUE));
950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
952282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiClass*
953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_rpc_interface_class(const interface_type* iface)
954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the proxy class
956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    InterfaceType* interfaceType = static_cast<InterfaceType*>(
957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NAMES.Find(iface->package, iface->name.data));
958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    RpcProxyClass* proxy = new RpcProxyClass(iface, interfaceType);
959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the listener class
961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ListenerClass* listener = new ListenerClass(iface);
962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the presenter class
964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    EventListenerClass* presenter = new EventListenerClass(iface, listener->type);
965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the service base class
967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    EndpointBaseClass* base = new EndpointBaseClass(iface);
968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    proxy->elements.push_back(base);
969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the result dispatcher
971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ResultDispatcherClass* results = new ResultDispatcherClass();
972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // all the declared methods of the proxy
974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int index = 0;
975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    interface_item_type* item = iface->interface_items;
976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (item != NULL) {
977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (item->item_type == METHOD_TYPE) {
978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (NAMES.Search(((method_type*)item)->type.type.data) == EVENT_FAKE_TYPE) {
979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                generate_event_method((method_type*)item, proxy, base, listener, presenter, index);
980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            } else {
981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                generate_regular_method((method_type*)item, proxy, base, results, index);
982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        item = item->next;
985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        index++;
986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    presenter->DoneWithMethods();
988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    base->DoneWithMethods();
989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // only add this if there are methods with results / out parameters
991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (results->needed) {
992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxy->elements.push_back(results);
993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (listener->needed) {
995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxy->elements.push_back(listener);
996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxy->elements.push_back(presenter);
997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        generate_listener_methods(proxy, presenter->type, listener->type);
998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return proxy;
1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
1002