1 /***************************************************************************
2         GenClientMethod.cpp  -  generate class with client methods
3                              -------------------
4     begin                : Sun May 28 2007
5     copyright            : (C) 2002-2007 by Ewald Arnold
6     email                : ulxmlrpcpp@ewald-arnold.de
7 
8     $Id: GenClientMethod.cpp 1016 2007-07-22 15:03:44Z 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 "GenClientMethod.h"
31 
32 #include <fstream>
33 #include <iostream>
34 
35 #include <sys/stat.h>
36 
37 
GenerateClientMethods(const UlxrIdlClass & in_class)38 GenerateClientMethods::GenerateClientMethods(const UlxrIdlClass &in_class)
39   : theClass(in_class)
40 {
41   theClass.resolveOverloaded();
42 }
43 
44 
generate_H(const std::string & destdir,const std::string & name)45 void GenerateClientMethods::generate_H(const std::string &destdir, const std::string &name)
46 {
47   const std::string h_name = destdir + theClass.getBaseName() + "_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   generateHeaderClassHead(h_file, name);
53   generateHeaderMethods(h_file);
54   generateHeaderVariables(h_file);
55   generateHeaderTail(h_file, name + "UlxrClient");
56 }
57 
58 
generate_CPP(const std::string & destdir,const std::string & name)59 void GenerateClientMethods::generate_CPP(const std::string &destdir, const std::string &name)
60 {
61   const std::string h_name = theClass.getBaseName() + "_ulxr_client.h";
62   const std::string cpp_name = destdir + theClass.getBaseName() + "_ulxr_client.cpp";
63   std::ofstream cpp_file(cpp_name.c_str());
64   std::cout << "Source file will be created: " << cpp_name << std::endl;
65 
66   generateSourceHead(cpp_file, h_name);
67   generateSourceCtors(cpp_file, name);
68   generateSourceMethods(cpp_file);
69 }
70 
71 
generate_CPP_USER(const std::string & destdir,const std::string & name)72 void GenerateClientMethods::generate_CPP_USER(const std::string &destdir, const std::string &name)
73 {
74   const std::string h_name = theClass.getBaseName() + "_ulxr_client.h";
75   std::string cpp_name = destdir + theClass.getBaseName() + "_ulxr_client_user.cpp";
76 
77   struct stat statbuf;
78   if (stat(cpp_name.c_str(), &statbuf) >= 0)
79   {
80     std::cout << "User file already exists: " << cpp_name << std::endl;
81     cpp_name += ".new";
82     std::cout << "New template will be created: " << cpp_name << std::endl;
83   }
84 
85   std::ofstream cpp_file(cpp_name.c_str());
86   std::cout << "User file will be created: " << cpp_name << std::endl;
87 
88   generateUserSourceHead(cpp_file, h_name);
89 
90   cpp_file << "#include <ulxmlrpcpp/ulxr_response.h>\n";
91   cpp_file << "#include <ulxmlrpcpp/ulxr_requester.h>\n";
92   cpp_file << "#include <ulxmlrpcpp/ulxr_except.h>\n\n";
93 
94   cpp_file << "#include \"" << name + "_ulxr_names.h" << "\"\n\n";
95 
96   cpp_file << name << "Client::" << name << "Client\n"
97            << "  (ulxr::Requester &in_requester, const ulxr::CppString &realm,\n"
98               "   const ulxr::CppString &user, const ulxr::CppString &pass)\n"
99               "   : requester(in_requester)\n"
100               "   , rpc_realm(realm)\n"
101               "   , rpc_user(user)\n"
102               "   , rpc_pass(pass)\n";
103 
104   for (unsigned i = 0; i < theClass.numMethods(); ++i)
105   {
106     cpp_file << "   , ";
107 
108     Method method = theClass.getMethod(i);
109     method.extractNamespace();
110 
111     cpp_file << "callTo_" << method.getOverloadName()
112              << "(ULXR_CALLTO_" << method.getOverloadName(true, "", "_")
113              << ")  // mapped to: " << method.getCppString(0, true, "");
114 
115     if (method.getName() != method.getOverloadName())
116        cpp_file << " (there are overloaded methods)";
117 
118     cpp_file << "\n";
119   }
120 
121   cpp_file << "{\n"
122               "}\n\n\n";
123 
124   cpp_file << "ulxr::MethodResponse\n  "
125            << name << "Client::" << "sendCall(const ulxr::MethodCall &calldata) const\n"
126            << "{\n"
127            << "  ulxr::MethodResponse resp = requester.call(calldata, rpc_realm, rpc_user, rpc_pass);\n"
128            << "\n"
129            << "  if (!resp.isOK())\n"
130            << "  {\n"
131            << "    ulxr::Struct st = resp.getResult();\n"
132            << "    int ec = ulxr::Integer(st.getMember(ULXR_PCHAR(\"faultCode\"))).getInteger();\n"
133            << "    ulxr::CppString es = ulxr::RpcString(st.getMember(ULXR_PCHAR(\"faultString\"))).getString();\n"
134            << "    throw ulxr::RuntimeException(ec, es);\n"
135            << "  }\n"
136            << "\n"
137            << "  return resp;\n"
138            << "}\n\n\n";
139 
140   cpp_file<< name << "Client::~" << name << "Client()\n"
141            << "{\n"
142            << "}\n\n\n";
143 }
144 
145 
generate(const std::string & destdir,const std::string & name)146 void GenerateClientMethods::generate(const std::string &destdir, const std::string &name)
147 {
148   generate_NameDefines(destdir, theClass.getBaseName() , theClass.getAllMethods());
149   generate_H(destdir, name);
150   generate_CPP(destdir, name);
151   generate_CPP_USER(destdir, name);
152 }
153 
154 
generateHeaderMethods(std::ostream & h_file)155 void GenerateClientMethods::generateHeaderMethods(std::ostream & h_file)
156 {
157   for (unsigned i = 0; i < theClass.numMethods(); ++i)
158   {
159     Method method = theClass.getMethod(i);
160     method.extractNamespace();
161 
162     h_file << "    // mapped to " << method.getOverloadName();
163     if (method.getName() != method.getOverloadName())
164       h_file << " (there are overloaded methods)";
165 
166     h_file << "\n    " << method.getCppString(0, false, "") << "\n\n";
167   }
168 
169   h_file << "    virtual ~" << theClass.getBaseName() << "Client();\n\n";
170 
171   h_file << "    virtual ulxr::MethodResponse sendCall(const ulxr::MethodCall &calldata) const;\n\n";
172 }
173 
174 
generateSourceCtors(std::ostream & cpp_file,const std::string & name)175 void GenerateClientMethods::generateSourceCtors(std::ostream & cpp_file,
176                                                 const std::string &name)
177 {
178   cpp_file << "#include <ulxmlrpcpp/ulxr_requester.h>\n\n";
179 
180 //  cpp_file << "#include \"" << theClass.getSource() << "\"\n\n\n";
181 }
182 
183 
generateSourceMethods(std::ostream & cpp_file)184 void GenerateClientMethods::generateSourceMethods(std::ostream & cpp_file)
185 {
186   for (unsigned i = 0; i < theClass.numMethods(); ++i)
187   {
188     Method method = theClass.getMethod(i);
189     method.extractNamespace();
190 
191     cpp_file << "// mapped to " << method.getOverloadName(true);
192     if (method.getName() != method.getOverloadName())
193       cpp_file << " (there are overloaded methods)";
194 
195     cpp_file << "\n"
196              << method.getCppString(0, true, "Client") << "\n"
197              << "{\n";
198 
199     cpp_file << "  callTo_" << method.getOverloadName() << ".clear();\n";
200 
201     for (unsigned iarg = 0; iarg < method.numArgs(); ++iarg)
202     {
203       std::string adap = method.getArg(iarg).getType().getInversTypeAdapter();
204       std::string adap2;
205       if (adap.length() != 0)
206       {
207         adap += "(";
208         adap2 = ")";
209       }
210 
211       cpp_file << "  callTo_" << method.getOverloadName() << ".addParam("
212                << method.getArg(iarg).getType().getRpcName() << "(" << adap
213                << method.getArg(iarg).getType().getTypeDereference() << method.getArg(iarg).getName()
214                << adap2
215                << "));\n";
216 
217     }
218 
219     bool have_retval = false;
220     if (method.getType().getName() != "void" || method.getType().getLeft() != "" || method.getType().getRight() != "")
221       have_retval = true;
222 
223     if (have_retval)
224       cpp_file << "  ulxr::MethodResponse resp = sendCall(callTo_" << method.getOverloadName() << ");\n";
225     else
226       cpp_file << "  sendCall(callTo_" << method.getOverloadName() << ");\n";
227 
228     if (have_retval)
229     {
230       std::string adap = method.getType().getTypeAdapter();
231       std::string adap2;
232       if (adap.length() != 0)
233       {
234         adap += "(";
235         adap2 = ")";
236       }
237 
238       const bool reftype = method.getType().isReference();
239       const bool ptrtype = method.getType().isPointer();
240       if (reftype || ptrtype)
241         cpp_file << "  ulxr_refFor_"
242                 << method.getOverloadName() << " = ";
243       else
244         cpp_file  << "  return ";
245 
246       cpp_file << "(" << method.getType().getProxyType() << ") "
247                << adap + method.getType().getRpcName() << "(resp.getResult())." << method.getType().getRpcAccessor()
248                << "()" << adap2 << ";\n";
249 
250       if (reftype)
251         cpp_file << "  return ulxr_refFor_"
252                 << method.getOverloadName() << ";\n";
253 
254       else if (ptrtype)
255       {
256         std::string acc = "&";
257         std::string acc2 = method.getType().getTypeAccessor();
258         if (acc2.length() != 0)
259          acc = "";
260 
261         cpp_file << "  return "
262                  << "(" << method.getType().getCppString() << ") "
263                  << acc << "ulxr_refFor_"
264                  << method.getOverloadName() << acc2 << ";\n";
265       }
266     }
267 
268     cpp_file << "}\n\n\n";
269   }
270 }
271 
272 
generateHeaderClassHead(std::ostream & h_file,const std::string & name)273 void GenerateClientMethods::generateHeaderClassHead(std::ostream & h_file,
274                                                     const std::string &name)
275 {
276   h_file<< "#include <ulxmlrpcpp/ulxr_call.h>\n\n"
277          << "namespace ulxr\n"
278          << "{\n"
279          << "  class Requester;\n"
280          << "  class MethodResponse;\n"
281          << "  class MethodCall;\n"
282          << "}\n\n"
283          << "class " << name << "Client\n"
284          << "{\n"
285          << "  public:\n\n"
286          << "    " << name << "Client\n"
287          << "      (ulxr::Requester &requester, const ulxr::CppString &realm = ULXR_PCHAR(\"/RPC2\"),\n"
288          << "       const ulxr::CppString &user = ULXR_PCHAR(\"\"), const ulxr::CppString &pass = ULXR_PCHAR(\"\"));\n\n";
289 }
290 
291 
generateHeaderVariables(std::ostream & h_file)292 void GenerateClientMethods::generateHeaderVariables(std::ostream & h_file)
293 {
294   h_file << "  private:\n\n";
295 
296   h_file<< "    ulxr::Requester &requester;\n";
297   h_file<< "    ulxr::CppString rpc_realm;\n";
298   h_file<< "    ulxr::CppString rpc_user;\n";
299   h_file<< "    ulxr::CppString rpc_pass;\n\n";
300 
301   for (unsigned i = 0; i < theClass.numMethods(); ++i)
302   {
303     Method method = theClass.getMethod(i);
304     method.extractNamespace();
305 
306     const bool reftype = method.getType().isReference();
307     const bool ptrtype = method.getType().isPointer();
308     if (reftype || ptrtype)
309       h_file << "    mutable " << method.getType().getProxyType() << " ulxr_refFor_" << method.getOverloadName() << ";\n";
310   }
311 
312   for (unsigned i = 0; i < theClass.numMethods(); ++i)
313   {
314     if (i == 0)
315       h_file << "\n";
316 
317     Method method = theClass.getMethod(i);
318     method.extractNamespace();
319 
320     h_file << "    mutable ulxr::MethodCall callTo_" << method.getOverloadName()
321              << ";  // mapped to: " << method.getCppString(0, true, "")
322              << "\n";
323   }
324 }
325 
326 
327