~ifolder-dev/simias/trunk-packaging

« back to all changes in this revision

Viewing changes to tools/gsoap/macosx-2.7/wsdl/.svn/text-base/service.cpp.svn-base

  • Committer: Jorge O. Castro
  • Date: 2007-12-03 06:56:46 UTC
  • Revision ID: jorge@ubuntu.com-20071203065646-mupcnjcwgm5mnhyt
* Remove a bunch of .svn directories we no longer need.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 
3
 
service.cpp
4
 
 
5
 
Service structures.
6
 
 
7
 
--------------------------------------------------------------------------------
8
 
gSOAP XML Web services tools
9
 
Copyright (C) 2001-2004, Robert van Engelen, Genivia, Inc. All Rights Reserved.
10
 
This software is released under one of the following two licenses:
11
 
GPL or Genivia's license for commercial use.
12
 
--------------------------------------------------------------------------------
13
 
GPL license.
14
 
 
15
 
This program is free software; you can redistribute it and/or modify it under
16
 
the terms of the GNU General Public License as published by the Free Software
17
 
Foundation; either version 2 of the License, or (at your option) any later
18
 
version.
19
 
 
20
 
This program is distributed in the hope that it will be useful, but WITHOUT ANY
21
 
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
22
 
PARTICULAR PURPOSE. See the GNU General Public License for more details.
23
 
 
24
 
You should have received a copy of the GNU General Public License along with
25
 
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
26
 
Place, Suite 330, Boston, MA 02111-1307 USA
27
 
 
28
 
Author contact information:
29
 
engelen@genivia.com / engelen@acm.org
30
 
--------------------------------------------------------------------------------
31
 
A commercial use license is available from Genivia, Inc., contact@genivia.com
32
 
--------------------------------------------------------------------------------
33
 
 
34
 
TODO:   add support for HTTP operations (non-SOAP access)
35
 
        add headerfault output definitions
36
 
 
37
 
*/
38
 
 
39
 
#include "types.h"
40
 
#include "service.h"
41
 
 
42
 
static void comment(const char *start, const char *middle, const char *end, const char *text);
43
 
 
44
 
////////////////////////////////////////////////////////////////////////////////
45
 
//
46
 
//      Definitions methods
47
 
//
48
 
////////////////////////////////////////////////////////////////////////////////
49
 
 
50
 
Definitions::Definitions()
51
 
{ }
52
 
 
53
 
void Definitions::collect(const wsdl__definitions &definitions)
54
 
{ // Collect information: analyze WSDL definitions and imported definitions
55
 
  if (definitions.service.empty())
56
 
    fprintf(stderr, "Warning: no wsdl:definitions/service in definitions %s targetNamespace %s\n", definitions.name?definitions.name:"", definitions.targetNamespace);
57
 
  analyze(definitions);
58
 
  for (vector<wsdl__import>::const_iterator import = definitions.import.begin(); import != definitions.import.end(); ++import)
59
 
    if ((*import).definitionsPtr())
60
 
      analyze(*(*import).definitionsPtr());
61
 
}
62
 
 
63
 
void Definitions::analyze(const wsdl__definitions &definitions)
64
 
{ // Analyze WSDL and build Service information
65
 
  for (vector<wsdl__binding>::const_iterator binding = definitions.binding.begin(); binding != definitions.binding.end(); ++binding)
66
 
  { // /definitions/binding/documentation
67
 
    const char *binding_documentation = (*binding).documentation;
68
 
    // /definitions/binding/soap:binding
69
 
    soap__binding *soap__binding_ = (*binding).soap__binding_;
70
 
    // /definitions/binding/soap:binding/@transport
71
 
    const char *soap__binding_transport = NULL;
72
 
    if (soap__binding_)
73
 
      soap__binding_transport = soap__binding_->transport;
74
 
    // /definitions/binding/soap:binding/@style
75
 
    soap__styleChoice soap__binding_style = rpc;
76
 
    if (soap__binding_ && soap__binding_->style)
77
 
      soap__binding_style = *soap__binding_->style;
78
 
    // /definitions/binding/http:binding
79
 
    http__binding *http__binding_ = (*binding).http__binding_;
80
 
    const char *http__binding_verb = NULL;
81
 
    if (http__binding_)
82
 
       http__binding_verb = http__binding_->verb;
83
 
    // /definitions/binding/operation*
84
 
    for (vector<wsdl__binding_operation>::const_iterator operation = (*binding).operation.begin(); operation != (*binding).operation.end(); ++operation)
85
 
    { // /definitions/portType/operation/ associated with /definitions/binding/operation
86
 
      wsdl__operation *wsdl__operation_ = (*operation).operationPtr();
87
 
      // /definitions/binding/operation/soap:operation
88
 
      soap__operation *soap__operation_ = (*operation).soap__operation_;
89
 
      // /definitions/binding/operation/soap:operation/@style
90
 
      soap__styleChoice soap__operation_style = soap__binding_style;
91
 
      if (soap__operation_ && soap__operation_->style)
92
 
        soap__operation_style = *soap__operation_->style;
93
 
      // /definitions/binding/operation/http:operation
94
 
      http__operation *http__operation_ = (*operation).http__operation_;
95
 
      // /definitions/binding/operation/http:operation/@location
96
 
      const char *http__operation_location = NULL;
97
 
      if (http__operation_)
98
 
        http__operation_location = http__operation_->location;
99
 
      // /definitions/binding/operation/input
100
 
      wsdl__ext_input *ext_input = (*operation).input;
101
 
      // /definitions/binding/operation/output
102
 
      wsdl__ext_output *ext_output = (*operation).output;
103
 
      // /definitions/portType/operation
104
 
      if (wsdl__operation_)
105
 
      { wsdl__input *input = wsdl__operation_->input;
106
 
        wsdl__output *output = wsdl__operation_->output;
107
 
        if (http__operation_)
108
 
        { // TODO: HTTP operation
109
 
        }
110
 
        else if (input && ext_input)
111
 
        { soap__body *input_body = ext_input->soap__body_;
112
 
          if (ext_input->mime__multipartRelated_)
113
 
          { for (vector<mime__part>::const_iterator part = ext_input->mime__multipartRelated_->part.begin(); part != ext_input->mime__multipartRelated_->part.end(); ++part)
114
 
              if ((*part).soap__body_)
115
 
              { input_body = (*part).soap__body_;
116
 
                break;
117
 
              }
118
 
          }
119
 
          // MUST have an input, otherwise can't generate a service operation
120
 
          if (input_body)
121
 
          { const char *URI;
122
 
            if (soap__operation_style == rpc)
123
 
              URI = input_body->namespace_;
124
 
            else
125
 
              URI = definitions.targetNamespace;
126
 
            if (URI)
127
 
            { const char *prefix = types.nsprefix(NULL, URI);
128
 
              const char *name = types.aname(NULL, NULL, (*binding).name); // name of service is binding name
129
 
              Service *s = services[prefix];
130
 
              if (!s)
131
 
              { s = services[prefix] = new Service();
132
 
                s->prefix = prefix;
133
 
                s->URI = URI;
134
 
                s->name = name;
135
 
                if ((*binding).portTypePtr())
136
 
                  s->type = types.aname(NULL, NULL, (*binding).portTypePtr()->name);
137
 
                else
138
 
                  s->type = NULL;
139
 
              }
140
 
              for (vector<wsdl__service>::const_iterator service = definitions.service.begin(); service != definitions.service.end(); ++service)
141
 
              { for (vector<wsdl__port>::const_iterator port = (*service).port.begin(); port != (*service).port.end(); ++port)
142
 
                { if ((*port).bindingPtr() == &(*binding))
143
 
                  { if ((*port).soap__address_)
144
 
                      s->location.insert((*port).soap__address_->location);
145
 
                    // TODO: HTTP address for HTTP operations
146
 
                    // if ((*port).http__address_)
147
 
                      // http__address_location = http__address_->location;
148
 
                    if ((*service).documentation)
149
 
                      s->service_documentation[(*service).name] = (*service).documentation;
150
 
                    if ((*port).documentation && (*port).name)
151
 
                      s->port_documentation[(*port).name] = (*port).documentation;
152
 
                    if (binding_documentation)
153
 
                      s->binding_documentation[(*binding).name] = binding_documentation;
154
 
                  }
155
 
                }
156
 
              }
157
 
              Operation *o = new Operation();
158
 
              o->name = types.aname(NULL, NULL, wsdl__operation_->name);
159
 
              o->prefix = prefix;
160
 
              o->URI = URI;
161
 
              o->style = soap__operation_style;
162
 
              o->documentation = wsdl__operation_->documentation;
163
 
              o->operation_documentation = (*operation).documentation;
164
 
              o->parameterOrder = wsdl__operation_->parameterOrder;
165
 
              if ((*operation).soap__operation_)
166
 
                o->soapAction = (*operation).soap__operation_->soapAction;
167
 
              else
168
 
              { o->soapAction = "";
169
 
                // determine if we use SOAP 1.2 in which case soapAction is absent, this is a bit of a hack due to the lack of WSDL1.1/SOAP1.2 support and better alternatives
170
 
                for (Namespace *p = definitions.soap->local_namespaces; p && p->id; p++)
171
 
                { if (p->out && !strcmp(p->id, "soap") && !strcmp(p->out, "http://schemas.xmlsoap.org/wsdl/soap12/"))
172
 
                  { o->soapAction = NULL;
173
 
                    break;
174
 
                  }
175
 
                }
176
 
              }
177
 
              o->input = new Message();
178
 
              o->input->name = (*operation).name; // RPC uses operation/@name
179
 
              if (soap__operation_style == rpc && !input_body->namespace_)
180
 
              { o->input->URI = "";
181
 
                fprintf(stderr, "Error: no soap:body namespace attribute\n");
182
 
              }
183
 
              else
184
 
                o->input->URI = input_body->namespace_;
185
 
              o->input->use = input_body->use;
186
 
              o->input->encodingStyle = input_body->encodingStyle;
187
 
              o->input->message = input->messagePtr();
188
 
              o->input->body_parts = input_body->parts;
189
 
              o->input->part = NULL;
190
 
              o->input->header = ext_input->soap__header_;
191
 
              o->input->multipartRelated = ext_input->mime__multipartRelated_;
192
 
              if (ext_input->dime__message_)
193
 
                o->input->layout = ext_input->dime__message_->layout;
194
 
              else
195
 
                o->input->layout = NULL;
196
 
              o->input->documentation = input->documentation;
197
 
              o->input->ext_documentation = ext_input->documentation;
198
 
              if (soap__operation_style == document)
199
 
                o->input_name = types.oname("__", o->URI, o->input->name);
200
 
              else
201
 
                o->input_name = types.oname(NULL, o->input->URI, o->input->name);
202
 
              if (output && ext_output)
203
 
              { soap__body *output_body = ext_output->soap__body_;
204
 
                if (ext_output->mime__multipartRelated_)
205
 
                { for (vector<mime__part>::const_iterator part = ext_output->mime__multipartRelated_->part.begin(); part != ext_output->mime__multipartRelated_->part.end(); ++part)
206
 
                    if ((*part).soap__body_)
207
 
                    { output_body = (*part).soap__body_;
208
 
                      break;
209
 
                    }
210
 
                }
211
 
                o->output = new Message();
212
 
                o->output->name = (*operation).name; // RPC uses operation/@name with suffix 'Response' as set below
213
 
                o->output->use = output_body->use;
214
 
                // the code below is a hack around the RPC encoded response message element tag mismatch with Axis:
215
 
                if (!output_body->namespace_ || o->output->use == encoded)
216
 
                  o->output->URI = o->input->URI; // encoded seems (?) to require the request's namespace
217
 
                else
218
 
                  o->output->URI = output_body->namespace_;
219
 
                o->output->encodingStyle = output_body->encodingStyle;
220
 
                o->output->message = output->messagePtr();
221
 
                o->output->body_parts = output_body->parts;
222
 
                o->output->part = NULL;
223
 
                o->output->header = ext_output->soap__header_;
224
 
                o->output->multipartRelated = ext_output->mime__multipartRelated_;
225
 
                if (ext_output->dime__message_)
226
 
                  o->output->layout = ext_output->dime__message_->layout;
227
 
                else
228
 
                  o->output->layout = NULL;
229
 
                o->output->documentation = output->documentation;
230
 
                o->output->ext_documentation = ext_output->documentation;
231
 
                char *s = (char*)soap_malloc(definitions.soap, strlen(o->output->name) + 9);
232
 
                strcpy(s, o->output->name);
233
 
                strcat(s, "Response");
234
 
                if (soap__operation_style == document)
235
 
                  o->output_name = types.oname("__", o->URI, s);
236
 
                else
237
 
                  o->output_name = types.oname(NULL, o->output->URI, s);
238
 
              }
239
 
              else
240
 
              { o->output_name = NULL;
241
 
                o->output = NULL;
242
 
              }
243
 
              // collect input headers and headerfaults
244
 
              if (ext_input)
245
 
              { for (vector<soap__header>::const_iterator header = ext_input->soap__header_.begin(); header != ext_input->soap__header_.end(); ++header)
246
 
                { Message *h = new Message();
247
 
                  h->message = (*header).messagePtr();
248
 
                  h->body_parts = NULL;
249
 
                  h->part = (*header).partPtr();
250
 
                  h->URI = (*header).namespace_;
251
 
                  if (h->part && h->part->element)
252
 
                    h->name = types.aname(NULL, NULL, h->part->element);
253
 
                  else if (h->URI && h->part && h->part->name && h->part->type)
254
 
                    h->name = types.aname(NULL, h->URI, h->part->name);
255
 
                  else
256
 
                  { fprintf(stderr, "Error in SOAP Header part definition\n");
257
 
                    h->name = "";
258
 
                  }
259
 
                  h->encodingStyle = (*header).encodingStyle;
260
 
                  h->use = (*header).use;
261
 
                  h->multipartRelated = NULL;
262
 
                  h->layout = NULL;
263
 
                  h->ext_documentation = NULL;  // TODO: add document content
264
 
                  h->documentation = NULL;              // TODO: add document content
265
 
                  s->header[h->name] = h;
266
 
                  for (vector<soap__headerfault>::const_iterator headerfault = (*header).headerfault.begin(); headerfault != (*header).headerfault.end(); ++headerfault)
267
 
                  { // TODO: complete headerfault processing
268
 
                  }
269
 
                }
270
 
              }
271
 
              // collect output headers and headerfaults
272
 
              if (ext_output)
273
 
              { for (vector<soap__header>::const_iterator header = ext_output->soap__header_.begin(); header != ext_output->soap__header_.end(); ++header)
274
 
                { Message *h = new Message();
275
 
                  h->message = (*header).messagePtr();
276
 
                  h->body_parts = NULL;
277
 
                  h->part = (*header).partPtr();
278
 
                  h->URI = (*header).namespace_;
279
 
                  if (h->part && h->part->element)
280
 
                    h->name = types.aname(NULL, NULL, h->part->element);
281
 
                  else if (h->URI && h->part && h->part->name && h->part->type)
282
 
                    h->name = types.aname(NULL, h->URI, h->part->name);
283
 
                  else
284
 
                  { fprintf(stderr, "Error in SOAP Header part definition\n");
285
 
                    h->name = "";
286
 
                  }
287
 
                  h->encodingStyle = (*header).encodingStyle;
288
 
                  h->use = (*header).use;
289
 
                  h->multipartRelated = NULL;
290
 
                  h->layout = NULL;
291
 
                  h->ext_documentation = NULL;  // TODO: add document content
292
 
                  h->documentation = NULL;              // TODO: add document content
293
 
                  s->header[h->name] = h;
294
 
                  for (vector<soap__headerfault>::const_iterator headerfault = (*header).headerfault.begin(); headerfault != (*header).headerfault.end(); ++headerfault)
295
 
                  { // TODO: complete headerfault processing
296
 
                  }
297
 
                }
298
 
              }
299
 
              // collect faults
300
 
              for (vector<wsdl__ext_fault>::const_iterator ext_fault = (*operation).fault.begin(); ext_fault != (*operation).fault.end(); ++ext_fault)
301
 
              { if ((*ext_fault).soap__fault_ && (*ext_fault).messagePtr())
302
 
                { Message *f = new Message();
303
 
                  f->message = (*ext_fault).messagePtr();
304
 
                  f->body_parts = NULL;
305
 
                  f->part = NULL;
306
 
                  f->encodingStyle = (*ext_fault).soap__fault_->encodingStyle;
307
 
                  f->URI = (*ext_fault).soap__fault_->namespace_;
308
 
                  f->use = (*ext_fault).soap__fault_->use;
309
 
                  f->multipartRelated = NULL;
310
 
                  f->layout = NULL;
311
 
                  f->ext_documentation = (*ext_fault).documentation;
312
 
                  f->name = types.aname("_", f->URI, f->message->name);
313
 
                  f->documentation = f->message->documentation;
314
 
                  o->fault.push_back(f);
315
 
                  s->fault[f->name] = f;
316
 
                }
317
 
                else
318
 
                  fprintf(stderr, "Error: no wsdl:definitions/binding/operation/fault/soap:fault\n");
319
 
              }
320
 
              s->operation.push_back(o);
321
 
            }
322
 
            else
323
 
              fprintf(stderr, "Warning: no SOAP RPC operation namespace, operations will be ignored\n");
324
 
          }
325
 
          else
326
 
            fprintf(stderr, "Error: no wsdl:definitions/binding/operation/input/soap:body\n");
327
 
        }
328
 
        else
329
 
          fprintf(stderr, "Error: no wsdl:definitions/portType/operation/input\n");
330
 
      }
331
 
      else
332
 
        fprintf(stderr, "Error: no wsdl:definitions/portType/operation\n");
333
 
    }
334
 
  }
335
 
}
336
 
 
337
 
void Definitions::compile(const wsdl__definitions& definitions)
338
 
{ // compile the definitions and generate gSOAP header file
339
 
  collect(definitions);
340
 
  fprintf(stream, "/** @mainpage %s Definitions\n\n", definitions.name?definitions.name:outfile?outfile:"Web Service");
341
 
  // copy documentation from WSDL definitions
342
 
  if (definitions.documentation)
343
 
    fprintf(stream, "@section Service Documentation\n\n%s\n\n", definitions.documentation);
344
 
  for (MapOfStringToService::const_iterator service = services.begin(); service != services.end(); ++service)
345
 
  { Service *sv = (*service).second;
346
 
    if (sv && (*sv).name)
347
 
    { fprintf(stream, "@section %s Service Binding \"%s\"\n\n", (*sv).name, (*sv).name);
348
 
      for (MapOfStringToString::const_iterator service_doc = (*sv).service_documentation.begin(); service_doc != (*sv).service_documentation.end(); ++service_doc)
349
 
        fprintf(stream, "@subsection %s \"%s\" Documentation\n\n%s\n\n", (*service_doc).first, (*service_doc).first, (*service_doc).second);
350
 
      for (MapOfStringToString::const_iterator port_doc = (*sv).port_documentation.begin(); port_doc != (*sv).port_documentation.end(); ++port_doc)
351
 
        fprintf(stream, "@subsection %s Port \"%s\" Documentation\n\n%s\n\n", (*port_doc).first, (*port_doc).first, (*port_doc).second);
352
 
      for (MapOfStringToString::const_iterator binding_doc = (*sv).binding_documentation.begin(); binding_doc != (*sv).binding_documentation.end(); ++binding_doc)
353
 
        fprintf(stream, "@subsection %s Binding \"%s\" Documentation\n\n%s\n\n", (*binding_doc).first, (*binding_doc).first, (*binding_doc).second);
354
 
      fprintf(stream, "@subsection %s_operations Operations\n\n", (*sv).name);
355
 
      for (vector<Operation*>::const_iterator op = (*sv).operation.begin(); op != (*sv).operation.end(); ++op)
356
 
      { if (*op && (*op)->input_name)
357
 
          fprintf(stream, "  - @ref %s\n", (*op)->input_name);
358
 
      }
359
 
      fprintf(stream, "\n@subsection %s_ports Endpoint Ports\n\n", (*sv).name);
360
 
      for (SetOfString::const_iterator port = (*sv).location.begin(); port != (*sv).location.end(); ++port)
361
 
        fprintf(stream, "  - %s\n", *port);
362
 
    }
363
 
  }
364
 
  fprintf(stream, "\n*/\n\n//  Note: modify this file to customize the generated data type declarations\n\n");
365
 
  if (lflag)
366
 
    fprintf(stream, "/*\n%s*/\n\n", licensenotice);
367
 
  // gsoap compiler options: 'w' disables WSDL/schema output to avoid file collisions
368
 
  if (cflag)
369
 
    fprintf(stream, "//gsoapopt cw\n");
370
 
  else
371
 
    fprintf(stream, "//gsoapopt w\n");
372
 
  // determine if we must use SOAP 1.2, this is a bit of a hack due to the lack of WSDL1.1/SOAP1.2 support and better alternatives
373
 
  for (Namespace *p = definitions.soap->local_namespaces; p && p->id; p++)
374
 
  { // p->out is set to the actual namespace name that matches the p->in pattern
375
 
    if (p->out && !strcmp(p->id, "soap") && !strcmp(p->out, "http://schemas.xmlsoap.org/wsdl/soap12/"))
376
 
    { fprintf(stream, "// This service uses SOAP 1.2 namespaces:\n");
377
 
      fprintf(stream, schemaformat, "SOAP-ENV", "namespace", "http://www.w3.org/2003/05/soap-envelope");
378
 
      fprintf(stream, schemaformat, "SOAP-ENC", "namespace", "http://www.w3.org/2003/05/soap-encoding");
379
 
      break;
380
 
    }
381
 
  }
382
 
  if (!cflag && !sflag)
383
 
    fprintf(stream, "#import \"stl.h\"\n");
384
 
  if (mflag)
385
 
    fprintf(stream, "#import \"base.h\"\n");
386
 
  // generate the prototypes first: these should allow use before def, e.g. class names then generate the defs
387
 
  // check if xsd:anyType is used
388
 
  if (!cflag && !pflag)
389
 
  { for (SetOfString::const_iterator i = definitions.builtinTypes().begin(); i != definitions.builtinTypes().end(); ++i)
390
 
    { if (!cflag && !strcmp(*i, "xs:anyType"))
391
 
      { pflag = 1;
392
 
        break;
393
 
      }
394
 
    }
395
 
  }
396
 
  // define xsd:anyType first, if used
397
 
  if (!cflag && pflag)
398
 
  { const char *s, *t;
399
 
    t = types.cname(NULL, NULL, "xs:anyType");
400
 
    s = types.deftypemap[t];
401
 
    if (s)
402
 
    { if (*s)
403
 
      { if (!mflag)
404
 
          fprintf(stream, "%s\n", s);
405
 
      }
406
 
      s = types.usetypemap[t];
407
 
      if (s)
408
 
      { if (mflag)
409
 
          fprintf(stream, "// base.h must define type: %s\n", s);
410
 
        types.knames.insert(s);
411
 
      }
412
 
    }
413
 
    else
414
 
    { fprintf(stderr, "Error: no xsd__anyType defined in type map\n");
415
 
      pflag = 0;
416
 
    }
417
 
  }
418
 
  // produce built-in primitive types, limited to the ones that are used only
419
 
  for (SetOfString::const_iterator i = definitions.builtinTypes().begin(); i != definitions.builtinTypes().end(); ++i)
420
 
  { const char *s, *t;
421
 
    if (!cflag && pflag && !strcmp(*i, "xs:anyType"))
422
 
      continue;
423
 
    t = types.cname(NULL, NULL, *i);
424
 
    s = types.deftypemap[t];
425
 
    if (s)
426
 
    { if (*s)
427
 
      { if (!mflag)
428
 
        { if (**i == '"')
429
 
            fprintf(stream, "/// Imported type %s\n", *i);
430
 
          else
431
 
            fprintf(stream, "/// Built-in type \"%s\"\n", *i);
432
 
          fprintf(stream, "%s\n", s);
433
 
        }
434
 
      }
435
 
      s = types.usetypemap[t];
436
 
      if (s)
437
 
      { if (mflag && **i != '"')
438
 
          fprintf(stream, "// base.h must define type: %s\n", s);
439
 
        if (types.knames.find(s) == types.knames.end())
440
 
          types.knames.insert(s);
441
 
      }
442
 
    }
443
 
    else
444
 
    { if (!mflag)
445
 
      { if (**i == '"')
446
 
          fprintf(stream, "// Imported type %s defined by %s\n", *i, t);
447
 
        else
448
 
        { fprintf(stream, "/// Primitive built-in type \"%s\"\n", *i);
449
 
          fprintf(stream, "typedef char *%s;\n", t);
450
 
        }
451
 
      }
452
 
      else if (**i == '"')
453
 
        fprintf(stream, "// Imported type %s defined by %s\n", *i, t);
454
 
      else
455
 
        fprintf(stream, "// base.h must define type: %s\n", t);
456
 
      types.ptrtypemap[t] = types.deftname(TYPEDEF, NULL, NULL, NULL, *i);      // already pointer
457
 
    }
458
 
    if (pflag && !strncmp(*i, "xs:", 3))                // only xsi types are polymorph
459
 
    { s = types.aname(NULL, NULL, *i);
460
 
      if (!mflag)
461
 
      { fprintf(stream, "/// Class wrapper for built-in type \"%s\" derived from xsd__anyType\n", *i);
462
 
        fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", s);
463
 
        fprintf(stream, elementformat, types.tname(NULL, NULL, *i), "__item;");
464
 
        fprintf(stream, "\n};\n");
465
 
      }
466
 
      types.knames.insert(s);
467
 
    }
468
 
  }
469
 
  // produce built-in primitive elements, limited to the ones that are used only
470
 
  for (SetOfString::const_iterator j = definitions.builtinElements().begin(); j != definitions.builtinElements().end(); ++j)
471
 
  { const char *s, *t = types.cname("_", NULL, *j);
472
 
    s = types.deftypemap[t];
473
 
    if (s && *s)
474
 
    { if (mflag)
475
 
      { if (**j == '"')
476
 
          fprintf(stream, "/// Imported element %s\n", *j);
477
 
        else
478
 
          fprintf(stream, "/// Built-in element \"%s\"\n", *j);
479
 
      }
480
 
      else
481
 
        fprintf(stream, "// base.h must define element: ");
482
 
      fprintf(stream, "%s\n", s);
483
 
      s = types.usetypemap[t];
484
 
      if (s && *s && types.knames.find(s) == types.knames.end())
485
 
        types.knames.insert(s);
486
 
    }
487
 
    else
488
 
    { if (!mflag)
489
 
      { if (**j == '"')
490
 
          fprintf(stream, "// Imported element %s defined by %s\n", *j, t);
491
 
        else
492
 
        { fprintf(stream, "/// Built-in element \"%s\"\n", *j);
493
 
          fprintf(stream, "typedef _XML %s;\n", t);
494
 
        }
495
 
      }
496
 
      else if (**j == '"')
497
 
        fprintf(stream, "// Imported element %s defined by %s\n", *j, t);
498
 
      else
499
 
        fprintf(stream, "// base.h must define element: %s\n", t);
500
 
      types.ptrtypemap[t] = types.deftname(TYPEDEF, NULL, NULL, NULL, *j);      // already pointer
501
 
      types.knames.insert(t);
502
 
    }
503
 
  }
504
 
  // produce built-in primitive attributes, limited to the ones that are used only
505
 
  for (SetOfString::const_iterator k = definitions.builtinAttributes().begin(); k != definitions.builtinAttributes().end(); ++k)
506
 
  { const char *s, *t = types.cname(NULL, NULL, *k);
507
 
    s = types.deftypemap[t];
508
 
    if (s && *s)
509
 
    { if (mflag)
510
 
      { if (**k == '"')
511
 
          fprintf(stream, "/// Imported attribute %s\n", *k);
512
 
        else
513
 
          fprintf(stream, "/// Built-in attribute \"%s\"\n", *k);
514
 
      }
515
 
      else
516
 
        fprintf(stream, "// base.h must define attribute: ");
517
 
      fprintf(stream, "%s\n", s);
518
 
      s = types.usetypemap[t];
519
 
      if (s && *s && types.knames.find(s) == types.knames.end())
520
 
        types.knames.insert(s);
521
 
    }
522
 
    else
523
 
    { if (!mflag)
524
 
      { if (**k == '"')
525
 
          fprintf(stream, "// Imported attribute %s defined by %s\n", *k, t);
526
 
        else
527
 
        { fprintf(stream, "/// Built-in attribute \"%s\"\n", *k);
528
 
          fprintf(stream, "typedef char *%s;\n", t);
529
 
        }
530
 
      }
531
 
      else if (**k == '"')
532
 
        fprintf(stream, "// Imported attribute %s defined by %s\n", *k, t);
533
 
      else
534
 
        fprintf(stream, "// base.h must define attribute: %s\n", t);
535
 
      types.ptrtypemap[t] = types.deftname(TYPEDEF, NULL, NULL, NULL, *k);      // already pointer
536
 
      types.knames.insert(t);
537
 
    }
538
 
  }
539
 
  // produce types
540
 
  if (definitions.types)
541
 
  { fprintf(stream, "\n/*\nTo customize the names of the namespace prefixes generated by wsdl2h, modify\nthe prefix names below and add the modified lines to typemap.dat to run wsdl2h:\n\n");
542
 
    for (vector<xs__schema*>::const_iterator schema1 = definitions.types->xs__schema_.begin(); schema1 != definitions.types->xs__schema_.end(); ++schema1)
543
 
      fprintf(stream, "%s = %s\n", types.nsprefix(NULL, (*schema1)->targetNamespace), (*schema1)->targetNamespace);
544
 
    fprintf(stream, "*/\n\n");
545
 
    comment("Definitions", definitions.name?definitions.name:"", "types", definitions.types->documentation);
546
 
    for (vector<xs__schema*>::const_iterator schema2 = definitions.types->xs__schema_.begin(); schema2 != definitions.types->xs__schema_.end(); ++schema2)
547
 
      fprintf(stream, schemaformat, types.nsprefix(NULL, (*schema2)->targetNamespace), "namespace", (*schema2)->targetNamespace);
548
 
    for (vector<xs__schema*>::const_iterator schema3 = definitions.types->xs__schema_.begin(); schema3 != definitions.types->xs__schema_.end(); ++schema3)
549
 
    { if ((*schema3)->elementFormDefault == (*schema3)->attributeFormDefault)
550
 
        fprintf(stream, schemaformat, types.nsprefix(NULL, (*schema3)->targetNamespace), "form", (*schema3)->elementFormDefault == qualified ? "qualified" : "unqualified");
551
 
      else
552
 
      { fprintf(stream, schemaformat, types.nsprefix(NULL, (*schema3)->targetNamespace), "elementForm", (*schema3)->elementFormDefault == qualified ? "qualified" : "unqualified");
553
 
        fprintf(stream, schemaformat, types.nsprefix(NULL, (*schema3)->targetNamespace), "attributeForm", (*schema3)->attributeFormDefault == qualified ? "qualified" : "unqualified");
554
 
      }
555
 
    }
556
 
    // define class/struct types first
557
 
    fprintf(stream, "\n// Forward declarations\n");
558
 
    for (vector<xs__schema*>::const_iterator schema4 = definitions.types->xs__schema_.begin(); schema4 != definitions.types->xs__schema_.end(); ++schema4)
559
 
    { for (vector<xs__complexType>::const_iterator complexType = (*schema4)->complexType.begin(); complexType != (*schema4)->complexType.end(); ++complexType)
560
 
        types.define((*schema4)->targetNamespace, NULL, *complexType);
561
 
      for (vector<xs__element>::const_iterator element = (*schema4)->element.begin(); element != (*schema4)->element.end(); ++element)
562
 
        if (!(*element).type && (*element).complexTypePtr())
563
 
          types.define((*schema4)->targetNamespace, (*element).name, *(*element).complexTypePtr());
564
 
    }  
565
 
    fprintf(stream, "\n// End of forward declarations\n\n");
566
 
    // visit types with lowest base level first
567
 
    int baseLevel = 1;
568
 
    bool found;
569
 
    do
570
 
    { found = (baseLevel == 1);
571
 
      for (vector<xs__schema*>::iterator schema = definitions.types->xs__schema_.begin(); schema != definitions.types->xs__schema_.end(); ++schema)
572
 
      { for (vector<xs__simpleType>::iterator simpleType = (*schema)->simpleType.begin(); simpleType != (*schema)->simpleType.end(); ++simpleType)
573
 
        { if ((*simpleType).baseLevel() == baseLevel)
574
 
          { found = true;
575
 
            types.gen((*schema)->targetNamespace, NULL, *simpleType);
576
 
          }
577
 
        }
578
 
        for (vector<xs__element>::iterator element = (*schema)->element.begin(); element != (*schema)->element.end(); ++element)
579
 
        { if (!(*element).type && (*element).simpleTypePtr() && (*element).simpleTypePtr()->baseLevel() == baseLevel)
580
 
          { found = true;
581
 
            types.gen((*schema)->targetNamespace, (*element).name, *(*element).simpleTypePtr());
582
 
          }
583
 
          if (!(*element).type && (*element).complexTypePtr() && (*element).complexTypePtr()->baseLevel() == baseLevel)
584
 
            found = true;
585
 
        }
586
 
        for (vector<xs__attribute>::const_iterator attribute = (*schema)->attribute.begin(); attribute != (*schema)->attribute.end(); ++attribute)
587
 
        { if (!(*attribute).type && (*attribute).simpleTypePtr() && (*attribute).simpleTypePtr()->baseLevel() == baseLevel)
588
 
          { found = true;
589
 
            types.gen((*schema)->targetNamespace, (*attribute).name, *(*attribute).simpleTypePtr()); // URI = NULL won't generate type in schema (type without namespace qualifier)
590
 
          }
591
 
        }
592
 
        for (vector<xs__complexType>::iterator complexType = (*schema)->complexType.begin(); complexType != (*schema)->complexType.end(); ++complexType)
593
 
        { if ((*complexType).baseLevel() == baseLevel)
594
 
            found = true;
595
 
        }
596
 
      }
597
 
      ++baseLevel;
598
 
    } while (found);
599
 
    // generate complex type defs. Problem: what if a simpleType restriction/extension depends on a complexType simpleContent restriction/extension?
600
 
    int maxLevel = baseLevel;
601
 
    for (baseLevel = 1; baseLevel < maxLevel; ++baseLevel)
602
 
    { for (vector<xs__schema*>::iterator schema = definitions.types->xs__schema_.begin(); schema != definitions.types->xs__schema_.end(); ++schema)
603
 
      { for (vector<xs__complexType>::iterator complexType = (*schema)->complexType.begin(); complexType != (*schema)->complexType.end(); ++complexType)
604
 
        { if ((*complexType).baseLevel() == baseLevel)
605
 
            types.gen((*schema)->targetNamespace, NULL, *complexType);
606
 
        }
607
 
        for (vector<xs__element>::iterator element = (*schema)->element.begin(); element != (*schema)->element.end(); ++element)
608
 
        { if (!(*element).type && (*element).complexTypePtr() && (*element).complexTypePtr()->baseLevel() == baseLevel)
609
 
            types.gen((*schema)->targetNamespace, (*element).name, *(*element).complexTypePtr());
610
 
        }
611
 
      }
612
 
    }
613
 
    // option to consider: generate local complexTypes iteratively
614
 
    /*
615
 
    for (MapOfStringToType::const_iterator local = types.locals.begin(); local != types.locals.end(); ++local)
616
 
    { types.gen(NULL, (*local).first, *(*local).second);
617
 
    }
618
 
    */
619
 
  }
620
 
  generate();
621
 
  fprintf(stream, "\n/*  End of %s Definitions */\n", definitions.name?definitions.name:outfile?outfile:"Web Service");
622
 
}
623
 
 
624
 
void Definitions::generate()
625
 
{ MapOfStringToMessage headers;
626
 
  MapOfStringToMessage faults;
627
 
  for (MapOfStringToService::const_iterator service1 = services.begin(); service1 != services.end(); ++service1)
628
 
  { if ((*service1).second)
629
 
    { for (MapOfStringToMessage::const_iterator header = (*service1).second->header.begin(); header != (*service1).second->header.end(); ++header)
630
 
        headers[(*header).first] = (*header).second;
631
 
      for (MapOfStringToMessage::const_iterator fault = (*service1).second->fault.begin(); fault != (*service1).second->fault.end(); ++fault)
632
 
        faults[(*fault).first] = (*fault).second;
633
 
    }
634
 
  }
635
 
  // Generate SOAP Header definition
636
 
  if (!headers.empty())
637
 
  { fprintf(stream, "// SOAP Header\n");
638
 
    //if (cflag) always use structs to avoid compilation warnings
639
 
      fprintf(stream, "struct SOAP_ENV__Header\n{\n");
640
 
    //else
641
 
      //fprintf(stream, "class SOAP_ENV__Header\n{ public:\n");
642
 
    for (MapOfStringToMessage::const_iterator header = headers.begin(); header != headers.end(); ++header)
643
 
    { if ((*header).second->URI && !types.uris[(*header).second->URI])
644
 
        fprintf(stream, schemaformat, types.nsprefix(NULL, (*header).second->URI), "namespace", (*header).second->URI);
645
 
      comment("Header", (*header).first, "WSDL", (*header).second->ext_documentation);
646
 
      comment("Header", (*header).first, "SOAP", (*header).second->documentation);
647
 
      if ((*header).second->part && (*header).second->part->elementPtr())
648
 
      { fprintf(stream, "/// \"%s\" SOAP Header part element\n", (*header).second->part->name);
649
 
        types.gen((*header).second->part->elementPtr()->schemaPtr()->targetNamespace, *(*header).second->part->elementPtr());
650
 
      }
651
 
      else if ((*header).second->part && (*header).second->part->name && (*header).second->part->type)
652
 
      { fprintf(stream, elementformat, types.pname(true, NULL, NULL, (*header).second->part->type), (*header).first);
653
 
        fprintf(stream, ";\n");
654
 
      }
655
 
      else
656
 
        fprintf(stderr, "Error in SOAP Header part\n");
657
 
    }
658
 
    fprintf(stream, "\n};\n");
659
 
  }
660
 
  // Generate Fault detail element definitions
661
 
  for (MapOfStringToMessage::const_iterator fault = faults.begin(); fault != faults.end(); ++fault)
662
 
  { fprintf(stream, "/// SOAP Fault Detail element\n\n");
663
 
    fprintf(stream, "/// The SOAP Fault Detail element contains one of the following types serialized\n// in the __type and fault fields of the SOAP_ENV__Detail struct (see docs)\n");
664
 
    if ((*fault).second->URI && !types.uris[(*fault).second->URI])
665
 
      fprintf(stream, schemaformat, types.nsprefix(NULL, (*fault).second->URI), "namespace", (*fault).second->URI);
666
 
    comment("Fault", (*fault).first, "WSDL", (*fault).second->ext_documentation);
667
 
    comment("Fault", (*fault).first, "SOAP", (*fault).second->documentation);
668
 
    if (cflag)
669
 
      fprintf(stream, "struct %s\n{\n", (*fault).first);
670
 
    else
671
 
      fprintf(stream, "class %s\n{ public:", (*fault).first);
672
 
    (*fault).second->generate(types, ";", false, true);
673
 
    if (!cflag)
674
 
    { fprintf(stream, "\n");
675
 
      fprintf(stream, pointerformat, "struct soap", "soap");
676
 
      fprintf(stream, ";");
677
 
    }
678
 
    fprintf(stream, "\n};\n");
679
 
  }
680
 
  /* The SOAP Fault struct below is autogenerated by soapcpp2 (kept here for future mods)
681
 
  if (!mflag && !faults.empty())
682
 
  { fprintf(stream, "struct SOAP_ENV__Code\n{\n"); 
683
 
    fprintf(stream, elementformat, "_QName", "SOAP_ENV__Value");
684
 
    fprintf(stream, ";\n");
685
 
    fprintf(stream, pointerformat, "char", "SOAP_ENV__Node");
686
 
    fprintf(stream, ";\n");
687
 
    fprintf(stream, pointerformat, "char", "SOAP_ENV__Role");
688
 
    fprintf(stream, ";\n};\n");
689
 
    fprintf(stream, "struct SOAP_ENV__Detail\n{\n"); 
690
 
    fprintf(stream, elementformat, "int", "__type");
691
 
    fprintf(stream, ";\n");
692
 
    fprintf(stream, pointerformat, "void", "fault");
693
 
    fprintf(stream, ";\n");
694
 
    fprintf(stream, elementformat, "_XML", "__any");
695
 
    fprintf(stream, ";\n};\n");
696
 
    fprintf(stream, "struct SOAP_ENV__Fault\n{\n"); 
697
 
    fprintf(stream, elementformat, "_QName", "faultcode");
698
 
    fprintf(stream, ";\n");
699
 
    fprintf(stream, pointerformat, "char", "faultstring");
700
 
    fprintf(stream, ";\n");
701
 
    fprintf(stream, pointerformat, "char", "faultactor");
702
 
    fprintf(stream, ";\n");
703
 
    fprintf(stream, pointerformat, "struct SOAP_ENV__Detail", "detail");
704
 
    fprintf(stream, ";\n");
705
 
    fprintf(stream, pointerformat, "struct SOAP_ENV__Code", "SOAP_ENV__Code");
706
 
    fprintf(stream, ";\n");
707
 
    fprintf(stream, pointerformat, "char", "SOAP_ENV__Reason");
708
 
    fprintf(stream, ";\n");
709
 
    fprintf(stream, pointerformat, "struct SOAP_ENV__Detail", "SOAP_ENV__Detail");
710
 
    fprintf(stream, ";\n};\n");
711
 
  }
712
 
  */
713
 
  for (MapOfStringToService::const_iterator service2 = services.begin(); service2 != services.end(); ++service2)
714
 
    if ((*service2).second)
715
 
      (*service2).second->generate(types);
716
 
717
 
 
718
 
////////////////////////////////////////////////////////////////////////////////
719
 
//
720
 
//      Service methods
721
 
//
722
 
////////////////////////////////////////////////////////////////////////////////
723
 
 
724
 
Service::Service()
725
 
{ prefix = NULL;
726
 
  URI = NULL;
727
 
  name = NULL;
728
 
}
729
 
 
730
 
void Service::generate(Types& types)
731
 
{ fprintf(stream, "\n");
732
 
  fprintf(stream, serviceformat, prefix, "name", name, "");
733
 
  fprintf(stream, serviceformat, prefix, "type", type, "");
734
 
  for (SetOfString::const_iterator port = location.begin(); port != location.end(); ++port)
735
 
    fprintf(stream, serviceformat, prefix, "port", (*port), "");
736
 
  fprintf(stream, serviceformat, prefix, "namespace", URI, "");
737
 
  for (vector<Operation*>::const_iterator op2 = operation.begin(); op2 != operation.end(); ++op2)
738
 
  { if (*op2 && (*op2)->input)
739
 
    { bool flag = false, anonymous = (*op2)->parameterOrder != NULL;
740
 
      if ((*op2)->output && (*op2)->output_name)
741
 
      { flag = ((*op2)->style == document && (*op2)->output->message && (*op2)->output->message->part.size() == 1);
742
 
        if (flag && (*op2)->input->message && (*(*op2)->output->message->part.begin()).element)
743
 
          for (vector<wsdl__part>::const_iterator part = (*op2)->input->message->part.begin(); part != (*op2)->input->message->part.end(); ++part)
744
 
            if ((*part).element && !strcmp((*part).element, (*(*op2)->output->message->part.begin()).element))
745
 
              flag = false;
746
 
        if (!flag)
747
 
        { fprintf(stream, "\n/// Operation response struct \"%s\" of service binding \"%s\" operation \"%s\"\n", (*op2)->output_name, name, (*op2)->input_name);
748
 
          fprintf(stream, "struct %s\n{", (*op2)->output_name);
749
 
          (*op2)->output->generate(types, ";", anonymous, true);
750
 
          fprintf(stream, "\n};\n");
751
 
        }
752
 
      }
753
 
      fprintf(stream, "\n/// Operation \"%s\" of service binding \"%s\"\n\n/**\n\nOperation details:\n\n", (*op2)->input_name, name);
754
 
      if ((*op2)->documentation)
755
 
        fprintf(stream, "%s\n\n", (*op2)->documentation);
756
 
      if ((*op2)->operation_documentation)
757
 
        fprintf(stream, "%s\n\n", (*op2)->operation_documentation);
758
 
      if ((*op2)->input->documentation)
759
 
        fprintf(stream, "Input:\n%s\n\n", (*op2)->input->documentation);
760
 
      if ((*op2)->input->ext_documentation)
761
 
        fprintf(stream, "Input:\n%s\n\n", (*op2)->input->ext_documentation);
762
 
      if ((*op2)->output)
763
 
      { if ((*op2)->output->documentation)
764
 
          fprintf(stream, "Output:\n%s\n\n", (*op2)->output->documentation);
765
 
        if ((*op2)->output->ext_documentation)
766
 
          fprintf(stream, "Output:\n%s\n\n", (*op2)->output->ext_documentation);
767
 
      }
768
 
      if ((*op2)->style == document)
769
 
        fprintf(stream, "  - SOAP document/literal style\n");
770
 
      else
771
 
      { if ((*op2)->input->use == literal)
772
 
          fprintf(stream, "  - SOAP RPC literal style\n");
773
 
        else if ((*op2)->input->encodingStyle)
774
 
          fprintf(stream, "  - SOAP RPC encodingStyle=\"%s\"\n", (*op2)->input->encodingStyle);
775
 
        else
776
 
          fprintf(stream, "  - SOAP RPC encoded\n");
777
 
      }
778
 
      if ((*op2)->output)
779
 
      { if ((*op2)->input->use != (*op2)->output->use)
780
 
        { if ((*op2)->output->use == literal)
781
 
            fprintf(stream, "  - SOAP RPC literal response\n");
782
 
          else if ((*op2)->output->encodingStyle)
783
 
            fprintf(stream, "  - SOAP RPC response encodingStyle=\"%s\"\n", (*op2)->output->encodingStyle);
784
 
          else
785
 
            fprintf(stream, "  - SOAP RPC encoded response\n");
786
 
        }
787
 
      }
788
 
      if ((*op2)->soapAction)
789
 
        if (*(*op2)->soapAction)
790
 
          fprintf(stream, "  - SOAP action=\"%s\"\n", (*op2)->soapAction);
791
 
      for (vector<Message*>::const_iterator message = (*op2)->fault.begin(); message != (*op2)->fault.end(); ++message)
792
 
        if ((*message)->message && (*message)->message->name)
793
 
          fprintf(stream, "  - SOAP Fault: %s\n", (*message)->name);
794
 
      for (vector<soap__header>::const_iterator inputheader = (*op2)->input->header.begin(); inputheader != (*op2)->input->header.end(); ++inputheader)
795
 
        if ((*inputheader).part)
796
 
          fprintf(stream, "  - Request message has mandatory header part: %s\n", types.aname(NULL, (*inputheader).namespace_, (*inputheader).part));
797
 
      if ((*op2)->input->multipartRelated)
798
 
        fprintf(stream, "  - Request message has MIME multipart/related attachments\n");
799
 
      if ((*op2)->input->layout)
800
 
        fprintf(stream, "  - Request message has DIME attachments in compliance with %s\n", (*op2)->input->layout);
801
 
      if ((*op2)->output)
802
 
        for (vector<soap__header>::const_iterator outputheader = (*op2)->output->header.begin(); outputheader != (*op2)->output->header.end(); ++outputheader)
803
 
          if ((*outputheader).part)
804
 
            fprintf(stream, "  - Response message has mandatory header part: %s\n", types.aname(NULL, (*outputheader).namespace_, (*outputheader).part));
805
 
      if ((*op2)->output && (*op2)->output_name && (*op2)->output->multipartRelated)
806
 
        fprintf(stream, "  - Response message has MIME multipart/related attachments\n");
807
 
      if ((*op2)->output && (*op2)->output_name && (*op2)->output->layout)
808
 
        fprintf(stream, "  - Response message has DIME attachments in compliance with %s\n", (*op2)->output->layout);
809
 
      fprintf(stream, "\nC stub function (defined in soapClient.c[pp]):\n@code\n  int soap_call_%s(struct soap *soap,\n    NULL, // char *endpoint = NULL selects default endpoint for this operation\n    NULL, // char *action = NULL selects default action for this operation", (*op2)->input_name);
810
 
      (*op2)->input->generate(types, ",", false, false);
811
 
      if ((*op2)->output && (*op2)->output_name)
812
 
      { if (flag)
813
 
        { // Shortcut: do not generate wrapper struct
814
 
          (*op2)->output->generate(types, "", false, false);
815
 
        }
816
 
        else
817
 
          fprintf(stream, "\n    struct %s%s", (*op2)->output_name, cflag ? "*" : "&");
818
 
      }
819
 
      fprintf(stream, "\n  );\n@endcode\n\n");
820
 
      if (!cflag)
821
 
      { fprintf(stream, "C++ proxy class (defined in soap%sProxy.h):\n", name);
822
 
        fprintf(stream, "  class %s;\n\n", name);
823
 
      }
824
 
      fprintf(stream, "*/\n\n");
825
 
      (*op2)->generate(types);
826
 
    }
827
 
  }
828
 
}
829
 
 
830
 
////////////////////////////////////////////////////////////////////////////////
831
 
//
832
 
//      Operation methods
833
 
//
834
 
////////////////////////////////////////////////////////////////////////////////
835
 
 
836
 
void Operation::generate(Types &types)
837
 
{ bool flag = false, anonymous = parameterOrder != NULL;
838
 
  const char *method_name = strstr(input_name + 1, "__") + 2;
839
 
  if (!method_name)
840
 
    method_name = input_name;
841
 
  if (style == document)
842
 
    fprintf(stream, serviceformat, prefix, "method-style", method_name, "document");
843
 
  else
844
 
    fprintf(stream, serviceformat, prefix, "method-style", method_name, "rpc");
845
 
  if (input->use == literal)
846
 
    fprintf(stream, serviceformat, prefix, "method-encoding", method_name, "literal");
847
 
  else if (input->encodingStyle)
848
 
    fprintf(stream, serviceformat, prefix, "method-encoding", method_name, input->encodingStyle);
849
 
  else
850
 
    fprintf(stream, serviceformat, prefix, "method-encoding", method_name, "encoded");
851
 
  if (output)
852
 
  { if (input->use != output->use)
853
 
    { if (output->use == literal)
854
 
        fprintf(stream, serviceformat, prefix, "method-response-encoding", method_name, "literal");
855
 
      else if (output->encodingStyle)
856
 
        fprintf(stream, serviceformat, prefix, "method-response-encoding", method_name, output->encodingStyle);
857
 
      else
858
 
        fprintf(stream, serviceformat, prefix, "method-response-encoding", method_name, "encoded");
859
 
    }
860
 
    if (style == rpc && input->URI && output->URI && strcmp(input->URI, output->URI))
861
 
      fprintf(stream, schemaformat, types.nsprefix(NULL, output->URI), "namespace", output->URI);
862
 
  }
863
 
  if (soapAction)
864
 
    if (*soapAction)
865
 
      fprintf(stream, serviceformat, prefix, "method-action", method_name, soapAction);
866
 
    else
867
 
      fprintf(stream, serviceformat, prefix, "method-action", method_name, "\"\"");
868
 
  for (vector<Message*>::const_iterator message = fault.begin(); message != fault.end(); ++message)
869
 
    if ((*message)->message && (*message)->message->name)
870
 
      fprintf(stream, serviceformat, prefix, "method-fault", method_name, (*message)->name);
871
 
  // TODO: add headerfault directives
872
 
  for (vector<soap__header>::const_iterator inputheader = input->header.begin(); inputheader != input->header.end(); ++inputheader)
873
 
    if ((*inputheader).part)
874
 
      fprintf(stream, serviceformat, prefix, "method-input-header-part", method_name, types.aname(NULL, (*inputheader).namespace_, (*inputheader).part));
875
 
  if (output)
876
 
    for (vector<soap__header>::const_iterator outputheader = output->header.begin(); outputheader != output->header.end(); ++outputheader)
877
 
      if ((*outputheader).part)
878
 
        fprintf(stream, serviceformat, prefix, "method-output-header-part", method_name, types.aname(NULL, (*outputheader).namespace_, (*outputheader).part));
879
 
  if (output_name)
880
 
  { flag = (style == document && output->message && output->message->part.size() == 1);
881
 
    if (flag && input->message && (*output->message->part.begin()).element)
882
 
      for (vector<wsdl__part>::const_iterator part = input->message->part.begin(); part != input->message->part.end(); ++part)
883
 
        if ((*part).element && !strcmp((*part).element, (*output->message->part.begin()).element))
884
 
          flag = false;
885
 
  }
886
 
  fprintf(stream, "int %s(", input_name);
887
 
  input->generate(types, ",", anonymous, true);
888
 
  if (output_name)
889
 
  { if (flag)
890
 
    { // Shortcut: do not generate wrapper struct
891
 
      output->generate(types, "", anonymous, true);
892
 
      fprintf(stream, " );\n");
893
 
    }
894
 
    else
895
 
    { fprintf(stream, "\n    struct %s%s );\n", output_name, cflag ? "*" : "&");
896
 
    }
897
 
  }
898
 
  else
899
 
    fprintf(stream, " void );\n");
900
 
}
901
 
 
902
 
////////////////////////////////////////////////////////////////////////////////
903
 
//
904
 
//      Message methods
905
 
//
906
 
////////////////////////////////////////////////////////////////////////////////
907
 
 
908
 
void Message::generate(Types &types, const char *sep, bool anonymous, bool remark)
909
 
{ if (message)
910
 
  { for (vector<wsdl__part>::const_iterator part = message->part.begin(); part != message->part.end(); ++part)
911
 
    { if ((*part).name)
912
 
      { if (remark && (*part).documentation)
913
 
          comment("", (*part).name, "parameter", (*part).documentation);
914
 
        else
915
 
          fprintf(stream, "\n");
916
 
        if ((*part).elementPtr())
917
 
        { const char *name, *type, *URI;
918
 
          name = (*part).elementPtr()->name;
919
 
          /* comment out to use a type that refers to an element defined with typedef */
920
 
          if ((*part).elementPtr()->type)
921
 
            type = (*part).elementPtr()->type;
922
 
          else
923
 
          /* */
924
 
            type = name;
925
 
          if ((*part).elementPtr()->schemaPtr())
926
 
            URI = (*part).elementPtr()->schemaPtr()->targetNamespace;
927
 
          else
928
 
            URI = NULL;
929
 
          fprintf(stream, anonymous ? anonformat : paraformat, types.tname(NULL, URI, type), types.aname(NULL, URI, name), sep);
930
 
        }
931
 
        else if ((*part).type)
932
 
        { if (use == literal)
933
 
            fprintf(stderr, "Warning: part '%s' uses literal style and must refer to an element rather than a type\n", (*part).name);
934
 
          fprintf(stream, anonymous ? anonformat : paraformat, types.tname(NULL, NULL, (*part).type), types.aname(NULL, NULL, (*part).name), sep);
935
 
        }
936
 
        else
937
 
          fprintf(stderr, "Error: no wsdl:definitions/message/part/@type in part '%s'\n", (*part).name);
938
 
      }
939
 
      else
940
 
        fprintf(stderr, "Error: no part name in message '%s'\n", message->name?message->name:"");
941
 
    }
942
 
  }
943
 
  else
944
 
    fprintf(stderr, "Error: no wsdl:definitions/message\n");
945
 
}
946
 
 
947
 
////////////////////////////////////////////////////////////////////////////////
948
 
//
949
 
//      Miscellaneous
950
 
//
951
 
////////////////////////////////////////////////////////////////////////////////
952
 
 
953
 
static void comment(const char *start, const char *middle, const char *end, const char *text)
954
 
{ if (text)
955
 
  { if (strchr(text, '\r') || strchr(text, '\n'))
956
 
      fprintf(stream, "\n/** %s %s %s documentation:\n%s\n*/\n\n", start, middle, end, text);
957
 
    else
958
 
      fprintf(stream, "\n/// %s %s %s: %s\n", start, middle, end, text);
959
 
  }
960
 
}
961