1 /***************************************************************************
2         GenServerMethod.cpp  -  generate class with server methods
3                              -------------------
4     begin                : Sun May 28 2007
5     copyright            : (C) 2002-2007 by Ewald Arnold
6     email                : Ulxr@ewald-arnold.de
7 
8     $Id: GenServerMethod.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 "GenServerMethod.h"
31 
32 #include <fstream>
33 #include <iostream>
34 
35 #include <sys/stat.h>
36 
37 
38 GenerateServerMethods::GenerateServerMethods(const UlxrIdlClass &in_class)
39   : theClass(in_class)
40 {
41   theClass.resolveOverloaded();
42 }
43 
44 
45 void GenerateServerMethods::generate_H(const std::string &destdir, const std::string &name)
46 {
47   const std::string h_name = destdir + theClass.getBaseName() + "_ulxr_server.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 + "UlxrServer");
52   generateHeaderClassHead(h_file, name);
53   generateHeaderMethods(h_file);
54   generateHeaderVariables(h_file);
55   generateHeaderTail(h_file, name + "UlxrServer");
56 }
57 
58 
59 void GenerateServerMethods::generate_CPP(const std::string &destdir, const std::string &name)
60 {
61   const std::string h_name = theClass.getBaseName() + "_ulxr_server.h";
62   const std::string cpp_name = destdir + theClass.getBaseName() + "_ulxr_server.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 
72 void GenerateServerMethods::generate_CPP_USER(const std::string &destdir, const std::string &name)
73 {
74   const std::string h_name = theClass.getBaseName() + "_ulxr_server.h";
75   std::string cpp_name = destdir + theClass.getBaseName() + "_ulxr_server_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_method_adder.h>\n";
92   cpp_file << "#include <ulxmlrpcpp/ulxr_signature.h>\n\n";
93 
94   cpp_file << "#include \"" << theClass.getSource() << "\"\n";
95   cpp_file << "#include \"" << name + "_ulxr_names.h" << "\"\n\n";
96 
97   cpp_file <<
98     "\nvoid " << name << "Server::setupServerMethods()\n"
99     "{\n";
100 
101   for (unsigned i = 0; i < theClass.numMethods(); ++i)
102   {
103     if (i != 0)
104       cpp_file << "\n";
105 
106     Method method = theClass.getMethod(i);
107     method.extractNamespace();
108 
109     cpp_file << "  // mapped to: " << method.getCppString(0, false, "");
110 
111     if (method.getName() != method.getOverloadName())
112        cpp_file << "   (there are overloaded methods)";
113 
114     cpp_file <<
115       "\n"
116       "  method_adder.addMethod(ulxr::make_method(*this, &" << method.getOverloadName(true, "Server") << "),\n"
117       "                         " << method.getType().getRpcName() << "::getValueName(),\n"
118       "                         ULXR_CALLTO_" << method.getOverloadName(true, "", "_") << ",\n"
119       "                         ulxr::Signature()";
120 
121     for (unsigned p = 0; p < method.numArgs(); ++p)
122       cpp_file << "\n                           << " << method.getArg(p).getType().getRpcName() << "::getValueName()";
123 
124     cpp_file <<
125       ",\n"
126       "                         ulxr_i18n(ULXR_PCHAR(\"Some descriptive comment about '" << method.getCppString(0, true, "") << "'.\"))); // TODO adjust comment\n";
127   }
128 
129   cpp_file <<
130     "}\n\n";
131 }
132 
133 
134 void GenerateServerMethods::generate(const std::string &destdir, const std::string &name)
135 {
136   generate_NameDefines(destdir, theClass.getBaseName(), theClass.getAllMethods());
137   generate_H(destdir, name);
138   generate_CPP(destdir, name);
139   generate_CPP_USER(destdir, name);
140 }
141 
142 
143 void GenerateServerMethods::generateHeaderMethods(std::ostream & h_file)
144 {
145   for (unsigned i = 0; i < theClass.numMethods(); ++i)
146   {
147     Method method = theClass.getMethod(i);
148     method.extractNamespace();
149 
150     h_file << "    // mapped to: " << method.getCppString(0, false, "");
151 
152     if (method.getName() != method.getOverloadName())
153        h_file << "   (there are overloaded methods)";
154 
155     h_file << "\n"
156            << "    ulxr::MethodResponse " << method.getOverloadName() << " (const ulxr::MethodCall &calldata);\n\n";
157   }
158 
159   h_file << " private:\n\n";
160   h_file << "    void setupServerMethods();\n";
161   h_file << "    void removeServerMethods();\n\n";
162 }
163 
164 
165 void GenerateServerMethods::generateSourceCtors(std::ostream & cpp_file,
166                                                 const std::string &name)
167 {
168   cpp_file << "#include <ulxmlrpcpp/ulxr_response.h>\n";
169   cpp_file << "#include <ulxmlrpcpp/ulxr_call.h>\n";
170   cpp_file << "#include <ulxmlrpcpp/ulxr_dispatcher.h>\n";
171   cpp_file << "#include <ulxmlrpcpp/ulxr_value.h>\n\n";
172 
173   cpp_file << "#include \"" << theClass.getSource() << "\"\n\n\n";
174   cpp_file << "#include \"" << name + "_ulxr_names.h" << "\"\n\n";
175 
176   cpp_file << name << "Server::" << name << "Server"
177            << "(ulxr::MethodAdder &in_method_adder, " << theClass.getName() << " &in_server)\n"
178            << "   : server(in_server)\n"
179               "   , method_adder(in_method_adder)\n";
180 
181   cpp_file << "{\n"
182               "  setupServerMethods();\n"
183               "}\n\n\n";
184 
185   cpp_file << name << "Server::~" << name << "Server()\n"
186            << "{\n"
187               "  removeServerMethods();\n"
188               "}\n\n\n";
189 }
190 
191 
192 void GenerateServerMethods::generateSourceMethods(std::ostream & cpp_file)
193 {
194   for (unsigned i = 0; i < theClass.numMethods(); ++i)
195   {
196     Method method = theClass.getMethod(i);
197     method.extractNamespace();
198 
199     cpp_file << "// mapped to: " << method.getCppString(0, false, "");
200 
201     if (method.getName() != method.getOverloadName())
202        cpp_file << "   (there are overloaded methods)";
203 
204     cpp_file << "\nulxr::MethodResponse\n  "
205              << method.getOverloadName(true, "Server") << " (const ulxr::MethodCall &calldata)\n"
206              << "{\n"
207              << "  try\n"
208              << "  {\n";
209 
210     for (unsigned iarg = 0; iarg < method.numArgs(); ++iarg)
211     {
212       std::string adap = method.getArg(iarg).getType().getTypeAdapter();
213       std::string adap2;
214       if (adap.length() != 0)
215       {
216         adap += "(";
217         adap2 = ")";
218       }
219 
220       cpp_file << "    " << method.getArg(iarg).getType().getName() << " p" << iarg << " = "
221                << "(" << method.getArg(iarg).getType().getName() << ") "
222                << adap + method.getArg(iarg).getType().getRpcName() << "(calldata.getParam(" << iarg << "))." << method.getArg(iarg).getType().getRpcAccessor()
223                << "()" << adap2 << ";\n";
224     }
225 
226     bool have_retval = false;
227     if (method.getType().getName() != "void" || method.getType().getLeft() != "" || method.getType().getRight() != "")
228       have_retval = true;
229 
230     if (have_retval)
231     {
232       cpp_file << "    " << method.getType().getProxyType() << " retval = "
233                << method.getType().getTypeDereference();
234     }
235     else
236       cpp_file << "    ";
237 
238     cpp_file << "server." << method.getName() << "(";
239 
240     for (unsigned iarg = 0; iarg < method.numArgs(); ++iarg)
241     {
242       if (iarg != 0)
243         cpp_file << ", ";
244 
245 //      cpp_file << "(" << method.getArg(iarg).getType().getCppString() << ")";
246 
247       if(method.getArg(iarg).getType().isPointer())
248         cpp_file << "&";
249 
250       cpp_file  << "p" << iarg;
251     }
252 
253     cpp_file << ");\n";
254 
255     std::string adap = method.getType().getInversTypeAdapter();
256     std::string adap2;
257     if (adap.length() != 0)
258     {
259       adap += "(";
260       adap2 = ")";
261     }
262 
263     if (have_retval)
264       cpp_file << "    return ulxr::MethodResponse ("<< method.getType().getRpcName() << " (" <<  adap << "retval" << adap2 << "));\n";
265     else
266       cpp_file << "    return ulxr::MethodResponse (ulxr::Void());\n";
267 
268     cpp_file << "  }\n"
269              << "  catch(std::exception &ex)\n"
270              << "  {\n"
271              << "    ulxr::CppString s = ULXR_PCHAR(\"C++ exception caught when invoking '" << method.getCppString(0, false, "") << "'\\n  \");\n"
272              << "    s += ULXR_GET_STRING(ex.what());\n"
273              << "    return ulxr::MethodResponse(ulxr::ApplicationError, s);\n"
274              << "  }\n"
275              << "  catch(...)\n"
276              << "  {\n"
277              << "    ulxr::CppString s = ULXR_PCHAR(\"Unknown exception caught when invoking '" << method.getCppString(0, false, "") << "'\");\n"
278              << "    return ulxr::MethodResponse(ulxr::ApplicationError, s);\n"
279              << "  }\n";
280 
281     cpp_file << "}\n\n\n";
282   }
283 
284   // ------------------------------------
285 
286   cpp_file <<
287     "\nvoid " << theClass.getBaseName() << "Server::removeServerMethods()\n"
288     "{\n";
289 
290   for (unsigned i = 0; i < theClass.numMethods(); ++i)
291   {
292     Method method = theClass.getMethod(i);
293     method.extractNamespace();
294 
295     cpp_file <<
296       "  method_adder.removeMethod(ULXR_CALLTO_" << method.getOverloadName(true, "", "_") << ");";
297 
298     cpp_file << "  // mapped to: " << method.getCppString(0, false, "");
299 
300     if (method.getName() != method.getOverloadName())
301        cpp_file << "   (there are overloaded methods)";
302 
303     cpp_file << "\n";
304   }
305 
306   cpp_file << "\n}\n\n\n";
307 }
308 
309 
310 void GenerateServerMethods::generateHeaderClassHead(std::ostream & h_file,
311                                                     const std::string &name)
312 {
313   std::string ns = theClass.getNamespace();
314   if (ns.length() == 0)
315     h_file << "\n"
316            << "class " << name << ";\n\n";
317   else
318     h_file << "namespace " << ns << "\n{\n"
319            << "  class " << theClass.getBaseName() << ";\n"
320            << "}\n\n";
321 
322   h_file << "\nnamespace ulxr\n"
323          << "{\n"
324          << "  class MethodAdder;\n"
325          << "  class MethodCall;\n"
326          << "  class MethodResponse;\n"
327          << "}\n\n"
328          << "class " << name << "Server\n"
329          << "{\n"
330          << "  public:\n\n"
331          << "    " << name << "Server(ulxr::MethodAdder &method_adder, " << theClass.getName() << " &server);\n\n"
332          << "    ~" << name << "Server();\n\n";
333 }
334 
335 
336 void GenerateServerMethods::generateHeaderVariables(std::ostream & h_file)
337 {
338   h_file << "  private:\n\n";
339   for (unsigned i = 0; i < theClass.numMethods(); ++i)
340   {
341     Method method = theClass.getMethod(i);
342     method.extractNamespace();
343 
344     const bool reftype = method.getType().isReference();
345     if (reftype)
346       h_file << "    mutable " << method.getType().getName() << " ulxr_refFor_" << method.getOverloadName() << ";\n";
347   }
348 
349   h_file << "    " << theClass.getName() << " &server;\n"
350          << "    ulxr::MethodAdder &method_adder;\n";
351 }
352 
353 
354