1 /* $Id: wsdlstr.cpp 512472 2016-08-31 12:38:54Z ivanov $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Andrei Gourianov
27 *
28 * File Description:
29 * Type info for class generation: includes, used classes, C code etc.
30 */
31
32 #include <ncbi_pch.hpp>
33 #include "exceptions.hpp"
34 #include "type.hpp"
35 #include "blocktype.hpp"
36 #include "unitype.hpp"
37 #include "classstr.hpp"
38 #include "stdstr.hpp"
39 #include "code.hpp"
40 #include "srcutil.hpp"
41 #include "comments.hpp"
42 #include "statictype.hpp"
43 #include "value.hpp"
44
45 BEGIN_NCBI_SCOPE
46
47
CWsdlTypeStrings(const string & externalName,const string & className,const string & namespaceName,const CDataType * dataType,const CComments & comments)48 CWsdlTypeStrings::CWsdlTypeStrings(
49 const string& externalName, const string& className,
50 const string& namespaceName, const CDataType* dataType, const CComments& comments)
51 : CParent(externalName, className, namespaceName, dataType, comments)
52 {
53 }
54
~CWsdlTypeStrings(void)55 CWsdlTypeStrings::~CWsdlTypeStrings(void)
56 {
57 }
58
59 static
DeclareConstructor(CNcbiOstream & out,const string className)60 CNcbiOstream& DeclareConstructor(CNcbiOstream& out, const string className)
61 {
62 return out <<
63 " // constructor\n"
64 " "<<className<<"(void);\n";
65 }
66
67 static
DeclareDestructor(CNcbiOstream & out,const string className,bool virt)68 CNcbiOstream& DeclareDestructor(CNcbiOstream& out, const string className,
69 bool virt)
70 {
71 out <<
72 " // destructor\n"
73 " ";
74 if ( virt )
75 out << "virtual ";
76 return out << '~'<<className<<"(void);\n"
77 "\n";
78 }
79
GenerateTypeCode(CClassContext & ctx) const80 void CWsdlTypeStrings::GenerateTypeCode(CClassContext& ctx) const
81 {
82 string httpclient("CSoapHttpClient");
83 string codeClassName = GetClassNameDT();
84 bool haveUserClass = HaveUserClass();
85 if ( haveUserClass )
86 codeClassName += "_Base";
87 CClassCode code(ctx, codeClassName);
88 code.HPPIncludes().insert("serial/soap/soap_client");
89 code.SetParentClass(httpclient, CNamespace::KNCBINamespace);
90 string methodPrefix = code.GetMethodPrefix();
91
92 DeclareConstructor(code.ClassPublic(), codeClassName);
93 DeclareDestructor(code.ClassPublic(), codeClassName, haveUserClass);
94
95 BeginClassDeclaration(ctx);
96 GenerateClassCode(code,
97 code.ClassPublic(),
98 methodPrefix, haveUserClass, ctx.GetMethodPrefix());
99
100 // constructors/destructor code
101 string location("\"\"");
102 ITERATE ( TMembers, i, m_Members ) {
103 if (i->dataType->IsStdType() && i->externalName == "#location") {
104 location = i->defaultValue;
105 }
106 }
107 CNcbiOstream& methods = code.Methods();
108 methods <<
109 "// constructor\n"<<
110 methodPrefix<<codeClassName<<"(void)\n";
111 methods <<
112 " : " << httpclient << "(\n";
113 methods <<
114 " " << location << ",\n" <<
115 " \"" << GetNamespaceName() << "\")\n";
116
117 methods <<
118 "{\n";
119 code.WriteConstructionCode(methods);
120 methods <<
121 "}\n"
122 "\n";
123
124 methods <<
125 "// destructor\n"<<
126 methodPrefix<<"~"<<codeClassName<<"(void)\n"
127 "{\n";
128 code.WriteDestructionCode(methods);
129 methods <<
130 "}\n"
131 "\n";
132 }
133
134 static inline
x_WsdlDataType(const CDataType * type)135 const CWsdlDataType* x_WsdlDataType(const CDataType *type)
136 {
137 return dynamic_cast<const CWsdlDataType*>(type);
138 }
139
140 static
x_CollectMembers(list<CWsdlTypeStrings::TMembers::const_iterator> & container,const CWsdlDataType * memb_type,const CWsdlTypeStrings::TMembers & members)141 void x_CollectMembers(
142 list<CWsdlTypeStrings::TMembers::const_iterator>& container,
143 const CWsdlDataType* memb_type,
144 const CWsdlTypeStrings::TMembers& members)
145 {
146 CDataMemberContainerType::TMembers memin = memb_type->GetMembers();
147 ITERATE( CDataMemberContainerType::TMembers, mi, memin) {
148 const string& name = (*mi)->GetName();
149 ITERATE ( CWsdlTypeStrings::TMembers, ii, members ) {
150 if (!x_WsdlDataType(ii->dataType) && ii->externalName == name) {
151 container.push_back(ii);
152 }
153 }
154 }
155 }
156 static
x_IsNullDataType(CWsdlTypeStrings::TMembers::const_iterator i)157 bool x_IsNullDataType(CWsdlTypeStrings::TMembers::const_iterator i)
158 {
159 if (i->ref && i->dataType) {
160 return dynamic_cast<const CNullDataType*>(i->dataType->Resolve()) != 0;
161 }
162 return false;
163 }
164
GenerateClassCode(CClassCode & code,CNcbiOstream &,const string & methodPrefix,bool,const string &) const165 void CWsdlTypeStrings::GenerateClassCode(
166 CClassCode& code, CNcbiOstream& /*setters*/,
167 const string& methodPrefix, bool /*haveUserClass*/,
168 const string& /*classPrefix*/) const
169 {
170 string ncbiNamespace =
171 code.GetNamespace().GetNamespaceRef(CNamespace::KNCBINamespace);
172 CNcbiOstream& methods = code.Methods();
173 CNcbiOstream& header = code.ClassPublic();
174
175 // generate member methods
176 ITERATE ( TMembers, i, m_Members ) {
177 const CWsdlDataType* type = x_WsdlDataType(i->dataType);
178 if (!type && i->externalName != "#location") {
179 if ( i->ref ) {
180 i->type->GeneratePointerTypeCode(code);
181 }
182 else {
183 i->type->GenerateTypeCode(code);
184 }
185 }
186 }
187
188 set<string> regOut;
189 ITERATE ( TMembers, i, m_Members ) {
190
191 // collect operation inputs and outputs
192 const CWsdlDataType* type = x_WsdlDataType(i->dataType);
193 if (!type || type->GetWsdlType() != CWsdlDataType::eWsdlOperation) {
194 continue;
195 }
196
197 string soapaction("");
198 list<TMembers::const_iterator> headerinputs;
199 list<TMembers::const_iterator> inputs;
200 list<TMembers::const_iterator> headeroutputs;
201 list<TMembers::const_iterator> outputs;
202 // operation
203 CDataMemberContainerType::TMembers memb = type->GetMembers();
204 ITERATE( CDataMemberContainerType::TMembers, m, memb) {
205 const CWsdlDataType* memb_type = x_WsdlDataType((*m)->GetType());
206 if (!memb_type) {
207 const CDataType* st = (*m)->GetType();
208 if (st->IsStdType() && st->GetMemberName() == "#soapaction" && st->GetDataMember()) {
209 soapaction = st->GetDataMember()->GetDefault()->GetXmlString();
210 }
211 continue;
212 }
213 switch (memb_type->GetWsdlType()) {
214 case CWsdlDataType::eWsdlHeaderInput:
215 x_CollectMembers( headerinputs,memb_type, m_Members);
216 break;
217 case CWsdlDataType::eWsdlInput:
218 x_CollectMembers( inputs,memb_type, m_Members);
219 break;
220 case CWsdlDataType::eWsdlHeaderOutput:
221 x_CollectMembers( headeroutputs,memb_type, m_Members);
222 break;
223 case CWsdlDataType::eWsdlOutput:
224 x_CollectMembers( outputs,memb_type, m_Members);
225 break;
226 default:
227 break;
228 }
229 }
230
231 // generate operation code
232
233 //outputs
234 string methodRet("void");
235 list<string> methodOut;
236 int out_counter=0;
237 size_t out_total = headeroutputs.size() + outputs.size();
238
239 ITERATE( list<TMembers::const_iterator>, out, headeroutputs) {
240 ++out_counter;
241 string reg("RegisterObjectType(");
242 reg += (*out)->type->GetCType(code.GetNamespace());
243 reg += "::GetTypeInfo);";
244 regOut.insert(reg);
245 string out_param = ncbiNamespace + "CConstRef< " +
246 (*out)->type->GetCType(code.GetNamespace()) + " >";
247 if (out_total == 1) {
248 methodRet = out_param;
249 } else {
250 out_param += "& out" + NStr::IntToString(out_counter);
251 methodOut.push_back(out_param);
252 }
253 }
254 ITERATE( list<TMembers::const_iterator>, out, outputs) {
255 ++out_counter;
256 string reg("RegisterObjectType(");
257 reg += (*out)->type->GetCType(code.GetNamespace());
258 reg += "::GetTypeInfo);";
259 regOut.insert(reg);
260 string out_param = ncbiNamespace + "CConstRef< " +
261 (*out)->type->GetCType(code.GetNamespace()) + " >";
262 if (out_total == 1) {
263 methodRet = out_param;
264 } else {
265 out_param += "& out" + NStr::IntToString(out_counter);
266 methodOut.push_back(out_param);
267 }
268 }
269
270 string separator("\n ");
271 string hpp_separator("\n ");
272 string comma_separator = "," + separator;
273 string commahpp_separator = "," + hpp_separator;
274 string inout_separator = "," + separator;
275 string inouthpp_separator = "," + hpp_separator;
276 if (methodOut.empty()) {
277 inout_separator = "";
278 inouthpp_separator = "";
279 }
280
281 // inputs
282 list<string> methodIn;
283 list<string> methodInNull;
284 int in_counter=0, hin_counter=0;
285 ITERATE( list<TMembers::const_iterator>, in, headerinputs) {
286 ++in_counter;
287 string in_type((*in)->type->GetCType(code.GetNamespace()));
288 string in_name(string("in") + NStr::IntToString(in_counter));
289 if (x_IsNullDataType(*in)) {
290 methodInNull.push_back(in_type + " " + in_name + ";");
291 methodInNull.push_back(in_name + ".Set();");
292 } else {
293 methodIn.push_back(string("const ") + in_type + "& " + in_name);
294 }
295 }
296 hin_counter = in_counter;
297 ITERATE( list<TMembers::const_iterator>, in, inputs) {
298 ++in_counter;
299 string in_type((*in)->type->GetCType(code.GetNamespace()));
300 string in_name(string("in") + NStr::IntToString(in_counter));
301 if (x_IsNullDataType(*in)) {
302 methodInNull.push_back(in_type + " " + in_name + ";");
303 methodInNull.push_back(in_name + ".Set();");
304 } else {
305 methodIn.push_back(string("const ") + in_type + "& " + in_name);
306 }
307 }
308 methodIn.push_back(
309 ncbiNamespace + "CConstRef< " + ncbiNamespace + "CSoapFault" + " >* fault");
310
311 // declaration
312 header << "\n";
313 i->comments.PrintHPPMember(header);
314 header << " "
315 << methodRet << separator << i->externalName << "(";
316 header << hpp_separator
317 << NStr::Join(methodOut,commahpp_separator)
318 << inouthpp_separator
319 << NStr::Join(methodIn,commahpp_separator)
320 << " = 0) const;\n";
321
322 // definition
323 methods
324 << methodRet << "\n"
325 << methodPrefix << i->externalName << "(";
326 methods << separator
327 << NStr::Join(methodOut,comma_separator)
328 << inout_separator
329 << NStr::Join(methodIn,comma_separator)
330 << ") const\n{";
331 if (!methodInNull.empty()) {
332 methods << separator
333 << NStr::Join(methodInNull,separator);
334 }
335 methods << separator
336 << ncbiNamespace << "CSoapMessage request, response;";
337 for (int p=1; p <= in_counter; ++p) {
338 methods << separator
339 << "request.AddObject( in" << p
340 << ", "<< ncbiNamespace;
341 if (p <= hin_counter) {
342 methods << "CSoapMessage::eMsgHeader";
343 } else {
344 methods << "CSoapMessage::eMsgBody";
345 }
346 methods << ");";
347 }
348 methods << separator << "Invoke(response,request,fault";
349 if (!soapaction.empty()) {
350 methods << "," << "\"" << soapaction << "\"";
351 }
352 methods << ");";
353 out_counter=0;
354 ITERATE( list<TMembers::const_iterator>, out, headeroutputs) {
355 ++out_counter;
356 methods << separator;
357 if (out_total == 1) {
358 methods << "return ";
359 } else {
360 methods << "out" << out_counter << " = ";
361 }
362 methods
363 << ncbiNamespace << "SOAP_GetKnownObject< "
364 << (*out)->type->GetCType(code.GetNamespace())
365 << " >(response, " << ncbiNamespace << "CSoapMessage::eMsgHeader);";
366 }
367 ITERATE( list<TMembers::const_iterator>, out, outputs) {
368 ++out_counter;
369 methods << separator;
370 if (out_total == 1) {
371 methods << "return ";
372 } else {
373 methods << "out" << out_counter << " = ";
374 }
375 methods
376 << ncbiNamespace << "SOAP_GetKnownObject< "
377 << (*out)->type->GetCType(code.GetNamespace())
378 << " >(response, " << ncbiNamespace << "CSoapMessage::eMsgBody);";
379 }
380 methods << "\n}\n\n";
381 }
382 ITERATE( set<string>, reg, regOut) {
383 code.AddConstructionCode(*reg);
384 }
385 }
386
387 END_NCBI_SCOPE
388