1 /***************************************************************************
2 GenClientMethod.cpp - generate class with client methods
3 -------------------
4 begin : Thu Juk 19 2007
5 copyright : (C) 2002-2007 by Ewald Arnold
6 email : ulxmlrpcpp@ewald-arnold.de
7
8 $Id: GenClientFunction.cpp 1164 2010-01-06 10:03:51Z ewald-arnold $
9
10 ***************************************************************************/
11
12 /**************************************************************************
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License as
16 * published by the Free Software Foundation; either version 2 of the License,
17 * or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 *
28 ***************************************************************************/
29
30 #include "GenClientFunction.h"
31
32 #include <fstream>
33 #include <iostream>
34
35 #include <sys/stat.h>
36
37
GenerateClientFunctions(const std::vector<Method> & methods)38 GenerateClientFunctions::GenerateClientFunctions(const std::vector<Method> &methods)
39 : theMethods(methods)
40 {
41 Method::resolveOverloaded(theMethods);
42 }
43
44
generate_H(const std::string & destdir,const std::string & name)45 void GenerateClientFunctions::generate_H(const std::string &destdir, const std::string &name)
46 {
47 const std::string h_name = destdir + name + "_ulxr_client.h";
48 std::ofstream h_file(h_name.c_str());
49 std::cout << "Header file will be created: " << h_name << std::endl;
50
51 generateHeaderHead(h_file, name + "UlxrClient");
52 generateHeaderMethods(h_file, name);
53 h_file << "#endif // " << name + "UlxrClient" + "_H\n\n";
54 }
55
56
generate_CPP(const std::string & destdir,const std::string & name)57 void GenerateClientFunctions::generate_CPP(const std::string &destdir, const std::string &name)
58 {
59 const std::string h_name = name + "_ulxr_client.h";
60 const std::string cpp_name = destdir + name + "_ulxr_client.cpp";
61 std::ofstream cpp_file(cpp_name.c_str());
62 std::cout << "Source file will be created: " << cpp_name << std::endl;
63
64 generateSourceHead(cpp_file, h_name);
65 generateSourceMethods(destdir, cpp_file, name);
66 }
67
68
generate_CPP_USER(const std::string & destdir,const std::string & name)69 void GenerateClientFunctions::generate_CPP_USER(const std::string &destdir, const std::string &name)
70 {
71 const std::string h_name = name + "_ulxr_client.h";
72 std::string cpp_name = destdir + name + "_ulxr_client_user.cpp";
73
74 struct stat statbuf;
75 if (stat(cpp_name.c_str(), &statbuf) >= 0)
76 {
77 std::cout << "User file already exists: " << cpp_name << std::endl;
78 cpp_name += ".new";
79 std::cout << "New template will be created: " << cpp_name << std::endl;
80 }
81
82 std::ofstream cpp_file(cpp_name.c_str());
83 std::cout << "User file will be created: " << cpp_name << std::endl;
84
85 generateUserSourceHead(cpp_file, h_name);
86
87 cpp_file << "// #include <ulxmlrpcpp/ulxr_response.h>\n";
88 cpp_file << "// #include <ulxmlrpcpp/ulxr_requester.h>\n";
89 cpp_file << "// #include <ulxmlrpcpp/ulxr_except.h>\n\n";
90
91 cpp_file << "// #include \"" << name + "_ulxr_names.h" << "\"\n\n";
92 }
93
94
generate(const std::string & destdir,const std::string & name)95 void GenerateClientFunctions::generate(const std::string &destdir, const std::string &name)
96 {
97 generate_NameDefines(destdir, name, theMethods, name + "_");
98 generate_H(destdir, name);
99 generate_CPP(destdir, name);
100 generate_CPP_USER(destdir, name);
101 }
102
103
generateHeaderMethods(std::ostream & h_file,const std::string & name)104 void GenerateClientFunctions::generateHeaderMethods(std::ostream & h_file,
105 const std::string &name)
106 {
107 h_file << "namespace ulxr\n"
108 "{\n"
109 " class Requester;\n"
110 "}\n\n";
111
112 for (unsigned i = 0; i < theMethods.size(); ++i)
113 {
114 Method method = theMethods[i];
115 std::string nspart = method.extractNamespace();
116 if (nspart.length() != 0)
117 h_file << "namespace " << nspart << " {\n";
118
119 h_file << "// mapped to " << method.getOverloadName();
120 if (method.getName() != method.getOverloadName())
121 h_file << " (there are overloaded methods)";
122
123 h_file << "\n" << method.getCppString(0, false, "") << "\n";
124
125 if (nspart.length() != 0)
126 h_file << "}\n";
127 h_file << "\n";
128 }
129
130 h_file << "void "
131 << name << "_setClientCredentials\n"
132 << " (ulxr::Requester &in_requester, const ulxr::CppString &realm,\n"
133 " const ulxr::CppString &user, const ulxr::CppString &pass);\n\n";
134 }
135
136
generateSourceMethods(const std::string & destdir,std::ostream & cpp_file,const std::string & name)137 void GenerateClientFunctions::generateSourceMethods(const std::string &destdir,
138 std::ostream & cpp_file,
139 const std::string &name)
140 {
141 cpp_file << "#include <ulxmlrpcpp/ulxr_response.h>\n";
142 cpp_file << "#include <ulxmlrpcpp/ulxr_requester.h>\n";
143 cpp_file << "#include <ulxmlrpcpp/ulxr_except.h>\n\n";
144
145 cpp_file << "#include <memory>\n";
146 cpp_file << "#include <cassert>\n\n";
147
148 cpp_file << "#include \"" << name + "_ulxr_names.h" << "\"\n\n";
149
150 cpp_file << "namespace {\n\n"
151
152 << "ulxr::Requester *requester = 0;\n"
153 "ulxr::CppString rpc_realm;\n"
154 "ulxr::CppString rpc_user;\n"
155 "ulxr::CppString rpc_pass;\n\n"
156
157 << "ulxr::MethodResponse\n "
158 << "sendCall(const ulxr::MethodCall &calldata)\n"
159 << "{\n"
160 << " assert(requester != 0);\n"
161 << " ulxr::MethodResponse resp = requester->call(calldata, rpc_realm, rpc_user, rpc_pass);\n"
162 << "\n"
163 << " if (!resp.isOK())\n"
164 << " {\n"
165 << " ulxr::Struct st = resp.getResult();\n"
166 << " int ec = ulxr::Integer(st.getMember(ULXR_PCHAR(\"faultCode\"))).getInteger();\n"
167 << " ulxr::CppString es = ulxr::RpcString(st.getMember(ULXR_PCHAR(\"faultString\"))).getString();\n"
168 << " throw ulxr::RuntimeException(ec, es);\n"
169 << " }\n"
170 << "\n"
171 << " return resp;\n"
172 << "}\n\n";
173
174
175 for (unsigned i = 0; i < theMethods.size(); ++i)
176 {
177 const Method &method = theMethods[i];
178 const bool reftype = method.getType().isReference();
179 const bool ptrtype = method.getType().isPointer();
180 if (reftype || ptrtype)
181 cpp_file << method.getType().getProxyType() << " ulxr_refFor_" << name << method.getOverloadName() << ";\n";
182 }
183
184 for (unsigned i = 0; i < theMethods.size(); ++i)
185 {
186 const Method &method = theMethods[i];
187
188 cpp_file << "ulxr::MethodCall callTo_" << method.getOverloadName()
189 << "(ULXR_CALLTO_" << name << "_" << method.getOverloadName(false, "", "_")
190 << "); // mapped to: " << method.getCppString(0, true, "");
191
192 if (method.getName() != method.getOverloadName())
193 cpp_file << " (there are overloaded methods)";
194
195 cpp_file << "\n";
196 }
197
198 cpp_file << "\n} // namespace\n\n\n"
199 << "void " << name << "_setClientCredentials\n"
200 << " (ulxr::Requester &in_requester, const ulxr::CppString &realm,\n"
201 " const ulxr::CppString &user, const ulxr::CppString &pass)\n"
202 "{\n"
203 " requester = &in_requester;\n"
204 " rpc_realm = realm;\n"
205 " rpc_user = user;\n"
206 " rpc_pass = pass;\n"
207 "}\n\n";
208
209 for (unsigned i = 0; i < theMethods.size(); ++i)
210 {
211 Method method = theMethods[i];
212 std::string nspart = method.extractNamespace();
213 if (nspart.length() != 0)
214 cpp_file << "namespace " << nspart << " {\n\n";
215
216 cpp_file << "// mapped to " << method.getOverloadName(false);
217 if (method.getName() != method.getOverloadName())
218 cpp_file << " (there are overloaded methods)";
219
220 cpp_file << "\n"
221 << method.getCppString(0, true, "") << "\n"
222 << "{\n";
223
224 cpp_file << " callTo_" << method.getOverloadName() << ".clear();\n";
225
226 for (unsigned iarg = 0; iarg < method.numArgs(); ++iarg)
227 {
228 std::string adap = method.getArg(iarg).getType().getInversTypeAdapter();
229 std::string adap2;
230 if (adap.length() != 0)
231 {
232 adap += "(";
233 adap2 = ")";
234 }
235
236 cpp_file << " callTo_" << method.getOverloadName() << ".addParam("
237 << method.getArg(iarg).getType().getRpcName() << "(" << adap
238 << method.getArg(iarg).getType().getTypeDereference() << method.getArg(iarg).getName()
239 << adap2
240 << "));\n";
241
242 }
243
244 bool have_retval = false;
245 if (method.getType().getName() != "void" || method.getType().getLeft() != "" || method.getType().getRight() != "")
246 have_retval = true;
247
248 if (have_retval)
249 cpp_file << " ulxr::MethodResponse resp = sendCall(callTo_" << method.getOverloadName() << ");\n";
250 else
251 cpp_file << " sendCall(callTo_" << method.getOverloadName() << ");\n";
252
253 if (have_retval)
254 {
255 std::string adap = method.getType().getTypeAdapter();
256 std::string adap2;
257 if (adap.length() != 0)
258 {
259 adap += "(";
260 adap2 = ")";
261 }
262
263 const bool reftype = method.getType().isReference();
264 const bool ptrtype = method.getType().isPointer();
265 if (reftype || ptrtype)
266 cpp_file << " ulxr_refFor_" << name
267 << method.getOverloadName() << " = ";
268 else
269 cpp_file << " return ";
270
271 cpp_file << "(" << method.getType().getProxyType() << ") "
272 << adap + method.getType().getRpcName() << "(resp.getResult())." << method.getType().getRpcAccessor()
273 << "()" << adap2 << ";\n";
274
275 if (reftype)
276 cpp_file << " return ulxr_refFor_" << name
277 << method.getOverloadName() << ";\n";
278
279 else if (ptrtype)
280 {
281 std::string acc = "&";
282 std::string acc2 = method.getType().getTypeAccessor();
283 if (acc2.length() != 0)
284 acc = "";
285
286 cpp_file << " return "
287 << "(" << method.getType().getCppString() << ") "
288 << acc << "ulxr_refFor_" << name
289 << method.getOverloadName() << acc2 << ";\n";
290 }
291 }
292
293 cpp_file << "}\n\n";
294
295 if (nspart.length() != 0)
296 cpp_file << "}\n";
297 cpp_file << "\n";
298 }
299 }
300
301