1 /****************************************************************************
2 **
3 ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of a Qt Solutions component.
8 **
9 ** Commercial Usage
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Solutions Commercial License Agreement provided
12 ** with the Software or, alternatively, in accordance with the terms
13 ** contained in a written agreement between you and Nokia.
14 **
15 ** GNU Lesser General Public License Usage
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** General Public License version 2.1 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** packaging of this file. Please review the following information to
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 **
23 ** In addition, as a special exception, Nokia gives you certain
24 ** additional rights. These rights are described in the Nokia Qt LGPL
25 ** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
26 ** package.
27 **
28 ** GNU General Public License Usage
29 ** Alternatively, this file may be used under the terms of the GNU
30 ** General Public License version 3.0 as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL included in the
32 ** packaging of this file. Please review the following information to
33 ** ensure the GNU General Public License version 3.0 requirements will be
34 ** met: http://www.gnu.org/copyleft/gpl.html.
35 **
36 ** Please note Third Party Software included with Qt Solutions may impose
37 ** additional restrictions and it is the user's responsibility to ensure
38 ** that they have met the licensing requirements of the GPL, LGPL, or Qt
39 ** Solutions Commercial license and the relevant license of the Third
40 ** Party Software they are using.
41 **
42 ** If you are unsure which license is appropriate for your use, please
43 ** contact Nokia at qt-info@nokia.com.
44 **
45 ****************************************************************************/
46
47 #include "qtsoap.h"
48 #include <QtCore/QSet>
49 #include <QtNetwork/QNetworkRequest>
50 #include <QtNetwork/QNetworkReply>
51
52 /*! \page qtsoap-overview.html
53
54 \title Qt SOAP component
55
56 \tableofcontents
57
58 \target overview
59 \section1 Overview of the SOAP support in the QtSoap classes
60
61 QtSoapMessage provides an interface for creating, inspecting and
62 modifying SOAP messages. It has convenience functions for
63 generating method requests and inspecting method response
64 messages, and also functions that provide easy access to SOAP
65 Fault messages.
66
67 The QtSoapType class allows you to inspect SOAP messages with no
68 knowledge of XML or DOM. Header and body items are all derived
69 from QtSoapType, and through easy accessors and iterators, this
70 class and its derivatives make it easy to build arrays
71 (QtSoapArray), structs (QtSoapStruct) and simple types like
72 String, Integer and Boolean (QtSoapSimpleType).
73
74 Finally, QtSoapHttpTransport provides a convenient way to submit
75 SOAP messages to a host via the HTTP protocol.
76
77 \target classes
78 \section1 The SOAP classes
79
80 \table
81 \header \i Class \i Short description
82 \row \i \l QtSoapMessage
83 \i Represents a SOAP message
84 \row \i \l QtSoapQName
85 \i Represents qualified names (QNames)
86 \row \i \l QtSoapType
87 \i A superclass for all data constructs in a SOAP message.
88 \row \i \l QtSoapArray
89 \i Represents a SOAP array
90 \row \i \l QtSoapArrayIterator
91 \i Lets you iterate over all the values in a SOAP array
92 \row \i \l QtSoapStruct
93 \i Represents a SOAP struct
94 \row \i \l QtSoapStructIterator
95 \i Lets you iterate over all the values in a SOAP array
96 \row \i \l QtSoapSimpleType
97 \i Represents simple SOAP types such as String, Integer and Boolean.
98 \row \i \l QtSoapHttpTransport
99 \i Provides a method for transmitting SOAP messages to an
100 HTTP server and for getting the SOAP reply.
101 \endtable
102
103 \target partial
104 \section1 Status of the SOAP component
105
106 This is a partial implementation of the SOAP v1.1 protocol.
107
108 \list
109 \i Server side SOAP is not supported.
110 \i References to values (id and href attributes) are not supported.
111 \i Only arrays with less than 5 dimensions are supported.
112 \i Namespaces for types are not checked. Only the type names are used.
113 \i The encodingStyle attribute is ignored. The serialization and
114 encoding rules from section 5 in the SOAP v1.1 specification are
115 assumed regardless of the value of the encodingStyle attribute.
116 \i QtSoapType does not have accessors for attributes, which means
117 for example that actor, mustUnderstand and so on are not
118 accessible in headers.
119 \i The SOAP root attribute is not supported.
120 \endlist
121 */
122
123 namespace {
localName(const QString & tagName)124 QString localName(const QString &tagName)
125 {
126 int pos;
127 if ((pos = tagName.indexOf(':')))
128 return tagName.right(tagName.length() - pos - 1);
129
130 return tagName;
131 }
132
prefix(const QString & tagName)133 QString prefix(const QString &tagName)
134 {
135 int pos;
136 if ((pos = tagName.indexOf(':')))
137 return tagName.left(pos);
138
139 return tagName;
140 }
141
142 }
143
144 /*! \class QtSoapQName qtsoap.h
145
146 \brief The QtSoapQName class provides a wrapper for QNames (names with
147 namespaces).
148
149 This class is used extensively in QtSoap to define and identify
150 header and body elements, including method and argument names.
151
152 The QtSoapQName consists of a name and a URI. The URI is used as
153 the name's namespace, i.e. the name is qualified (hence 'Q'-Name)
154 by the URI. The name() and uri() functions return the QNames's
155 name and URI.
156
157 The QtSoapQName can be empty. It can also have just a name with no
158 URI. Special handling is often applied to a QtSoapQName that has
159 no URI. Typically, if a QName with no namespace is used in an
160 element in a SOAP document that already has a default namespace
161 defined, then that namespace will be applied to the QName.
162
163 \code
164 QtSoapMessage message;
165
166 message.setMethod(QtSoapQName("sendMessage", "http://messenging.example.com/"));
167 message.addMethodArgument(QtSoapSimpleType(QtSoapQName("a"), 15));
168 \endcode
169 */
170
171
172 /*!
173 Constructs a QName. Sets the QName name to \a name and the URI to
174 \a uri.
175 */
QtSoapQName(const QString & name,const QString & uri)176 QtSoapQName::QtSoapQName(const QString &name, const QString &uri)
177 : n(name), nuri(uri)
178 {
179 }
180
181 /*!
182 Destructs the QtSoapQName.
183 */
~QtSoapQName()184 QtSoapQName::~QtSoapQName()
185 {
186 }
187
188 /*!
189 Returns QName's name.
190 */
name() const191 QString QtSoapQName::name() const
192 {
193 return n;
194 }
195
196 /*!
197 Returns the QName's URI.
198 */
uri() const199 QString QtSoapQName::uri() const
200 {
201 return nuri;
202 }
203
204 /*!
205 Sets the QName's name to \a s, and sets the URI to an empty string.
206 */
operator =(const QString & s)207 QtSoapQName &QtSoapQName::operator =(const QString &s)
208 {
209 n = s;
210 nuri = "";
211
212 return *this;
213 }
214
215 /*!
216 \fn bool operator==(const QtSoapQName &s1, const QtSoapQName &s2)
217
218 \relates QtSoapQName
219
220 If \a s2 has a non-empty URI, this function returns true if the
221 merge of the URI and the name of \a s1 is equal to that of \a s2;
222 otherwise it returns false.
223
224 If \a s2 has an empty URI, this function returns true if the name
225 of \a s1 is equal to the name of \a s2; otherwise it returns false.
226
227 The comparison is case-insensitive.
228 */
operator ==(const QtSoapQName & s1,const QtSoapQName & s2)229 bool operator ==(const QtSoapQName &s1, const QtSoapQName &s2)
230 {
231 if (s2.uri() == "")
232 return s1.name().toLower() == s2.name().toLower();
233
234 return s1.name().toLower() == s2.name().toLower()
235 && s1.uri().toLower() == s2.uri().toLower();
236 }
237
238 /*!
239 \fn bool operator<(const QtSoapQName &s1, const QtSoapQName &s2)
240
241 \relates QtSoapQName
242
243 If \a s2 has a non-empty URI, this function returns true if the
244 merge of the URI and the name of \a s1 is lexically less than that
245 of \a s2; otherwise it returns false.
246
247 If \a s2 has an empty URI, this function returns true if the name
248 of \a s1 is lexically less than the name of \a s2; otherwise
249 it returns false.
250
251 The comparison is case-insensitive.
252 */
operator <(const QtSoapQName & s1,const QtSoapQName & s2)253 bool operator <(const QtSoapQName &s1, const QtSoapQName &s2)
254 {
255 if (s2.uri() == "")
256 return s1.name().toLower() < s2.name().toLower();
257
258 return (s1.uri().toLower()+s1.name().toLower()) < (s2.uri().toLower()+s2.name().toLower());
259 }
260
261 /*! \class QtSoapType qtsoap.h
262 \brief The QtSoapType class is the base class for all SOAP types
263 in QtSoap.
264
265 Although it is not used to create data types, a QtSoapType
266 reference can be conveniently used to inspect a tree of QtSoapType
267 subclasses. Accessors from this base class, such as operator[](),
268 allow safe navigation.
269
270 \code
271 const QtSoapType &root = message.returnValue();
272 if (root["fault"].isValid()) {
273 qWarning("Warning: %s", root["fault"]["faultstring"].toString().toLatin1().constData());
274 }
275 \endcode
276
277 This class holds the name(), type(), id() and href() of all its
278 derived types.
279
280 If a QtSoapType reference or pointer points to a QtSoapStruct, a
281 QtSoapArray or a QtSoapSimpleType, isValid() returns true.
282
283 \sa QtSoapStruct, QtSoapArray, QtSoapSimpleType
284 */
285
286 /*!
287 \class QtSoapStruct qtsoap.h
288 \brief The QtSoapStruct class is an implementation of the SOAP
289 struct type.
290
291 A SOAP struct is a dictionary of QtSoapTypes where entries are
292 looked up by name. Entries in a struct can be of any QtSoapType
293 type, such as QtSoapArray, QtSoapStruct or QtSoapSimpleType.
294
295 The struct can be created in several ways. parse() generates a
296 struct by analyzing a QDomNode. insert() is used to add items
297 manually.
298
299 \code
300 QtSoapStruct myStruct(QtSoapQName("myStruct"));
301
302 myStruct.insert(new QtSoapSimpleType(QtSoapQName("item1"), 5));
303 myStruct.insert(new QtSoapSimpleType(QtSoapQName("item2"), "hello"));
304 myStruct.insert(new QtSoapSimpleType(QtSoapQName("item3"), true));
305 \endcode
306
307 Use the operator[]() or at() when looking up entries in a struct
308 by name. If the names are unknown, QtSoapStructIterator lets you
309 iterate through all the items.
310
311 \code
312 QtSoapType &helloItem = myStruct["Hello"];
313 \endcode
314
315 toDomElement() converts the QtSoapStruct to a DomElement.
316
317 \sa QtSoapStructIterator, QtSoapType, QtSoapArray, QtSoapSimpleType
318 */
319
320 /*! \class QtSoapStructIterator
321 \brief The QtSoapStructIterator class provides an iterator for
322 traversing the items in a QtSoapStruct.
323
324 The iterator is created by passing a QtSoapStruct to the
325 constructor. It it not defined which item the iterator initially
326 will point to. Neither is the order in which the items are
327 processed.
328
329 key() returns the name of the current item. data() and current()
330 return a pointer to the current item, or 0 if there is none.
331 operator++() navigates to the next item in the struct.
332
333 \code
334 for (QtSoapStructIterator it(myStruct); it.current(); ++it) {
335 QtSoapType *item = it.data();
336 // process item
337 }
338 \endcode
339
340 \sa QtSoapArrayIterator
341 */
342
343 /*! \class QtSoapArray qtsoap.h
344 \brief The QtSoapArray class is an implementation of the SOAP
345 array type.
346
347 A SOAP array is a sequence of QtSoapType objects such as
348 QtSoapArrays, QtSoapStructs or QtSoapSimpleTypes, and they are
349 accessible through their ordinal position. An array can be
350 consecutive (0, 1, 2, 3, ...) or sparse (1, 5, 6, 10, ...) and
351 they can be multidimensional ((0, 0), (0, 1), ...). QtSoapArray
352 supports arrays of up to 5 dimensions. The size and dimensions of
353 the array are set in the constructor. The default constructor
354 produces a one dimensional array, with an unset size, meaning that
355 the array can grow as required.
356
357 All elements in a SOAP array must be of the same type. Inserting
358 different types will result in a run time error.
359
360 The parse() function builds the array by analyzing a QDomNode from
361 a SOAP document. count() returns the number of items in the array.
362
363 Retrieve items in the array with at() or operator[](). Note that
364 operator[]() only works with one dimensional arrays, but there are
365 at() functions for arrays of up to 5 dimensions.
366 QtSoapArrayIterator lets you iterate through all items in an
367 array.
368
369 Use insert() or append() to insert items into an array manually.
370 append() only works with one dimensional arrays.
371
372 toDomElement() returns a QDomElement representation of the SOAP
373 array.
374
375 \code
376 QtSoapArray array;
377
378 array.insert(0, new QtSoapSimpleType(QtSoapQName("Peter"), "peter"));
379 array.insert(1, new QtSoapSimpleType(QtSoapQName("Lisa"), "lisa"));
380 array.insert(2, new QtSoapSimpleType(QtSoapQName("Paul"), "paul"));
381 array.insert(3, new QtSoapSimpleType(QtSoapQName("Heather"), "heather"));
382 \endcode
383
384 \sa QtSoapType, QtSoapStruct, QtSoapSimpleType
385 */
386
387 /*! \class QtSoapArrayIterator qtsoap.h
388 \brief The QtSoapArrayIterator class provides an iterator for
389 traversing the items in a QtSoapArray.
390
391 The items are traversed in ascending order of index position,
392 depth first.
393
394 \code
395 // Construct a 2x2 array of Strings.
396 QtSoapArray array("Array of strings", String, 2, 2);
397 array.insert(0, 0, new QtSoapSimpleType(Q4SoapQName("top left"), "top left");
398 array.insert(0, 1, new QtSoapSimpleType(Q4SoapQName("top right"), "top right");
399 array.insert(1, 0, new QtSoapSimpleType(Q4SoapQName("bottom left"), "bottom left");
400 array.insert(1, 1, new QtSoapSimpleType(Q4SoapQName("bottom right"), "bottom right");
401
402 // Traverse all items.
403 QtSoapArrayIterator it(array);
404 while (!it.current()) {
405
406 // Find the position of the current element.
407 int pos1, pos2;
408 it.pos(&pos1, &pos2);
409
410 qDebug() << "Position (" << pos1 << ", " << pos2 << ") is "
411 << "the " << it.current()->toString() << " coordinate of the grid." << endl;
412
413 ++it;
414 }
415 \endcode
416 */
417
418 /*! \class QtSoapSimpleType qtsoap.h
419 \brief The QtSoapSimpleType class provides a container for all
420 simple SOAP types, such as strings, integers and booleans.
421
422
423
424 \sa QtSoapType, QtSoapStruct, QtSoapArray
425 */
426
427 /*! \enum QtSoapType::Type
428
429 SOAP supports the types described in XML Schema Part 2: Datatypes
430 listed at \l http://www.w3.org/TR/xmlschema-2/. The following
431 values are represented using QtSoapSimpleType, except where noted.
432
433 \value AnyURI
434 \value Array Represented by QtSoapArray
435 \value Base64Binary
436 \value Boolean
437 \value Byte
438 \value Date
439 \value DateTime
440 \value Decimal
441 \value Double
442 \value Duration
443 \value ENTITY
444 \value Float
445 \value GDay
446 \value GMonth
447 \value GMonthDay
448 \value GYear
449 \value GYearMonth
450 \value HexBinary
451 \value ID
452 \value IDREF
453 \value Int
454 \value Integer
455 \value Language
456 \value Long
457 \value NCName
458 \value NMTOKEN
459 \value NOTATION
460 \value Name
461 \value NegativeInteger
462 \value NonNegativeInteger
463 \value NonPositiveInteger
464 \value NormalizedString
465 \value Other
466 \value PositiveInteger
467 \value QName
468 \value Short
469 \value String
470 \value Struct Represented by QtSoapStruct
471 \value Time
472 \value Token
473 \value UnsignedByte
474 \value UnsignedInt
475 \value UnsignedLong
476 \value UnsignedShort
477 */
478
479 /*!
480 Constructs a QtSoapType.
481 */
QtSoapType()482 QtSoapType::QtSoapType()
483 {
484 t = Other;
485 errorStr = "Unknown error";
486 }
487
488 /*!
489 Constructs a QtSoapType whose name is \a name and type is \a type.
490 This contructor is usually only called by constructors in
491 subclasses.
492 */
QtSoapType(const QtSoapQName & name,Type type)493 QtSoapType::QtSoapType(const QtSoapQName &name, Type type)
494 : t(type), n(name)
495 {
496 errorStr = "Unknown error";
497 }
498
499 /*!
500 Creates a QtSoapType copy of \a copy.
501 */
QtSoapType(const QtSoapType & copy)502 QtSoapType::QtSoapType(const QtSoapType ©)
503 : t(copy.t), errorStr(copy.errorStr), i(copy.i),
504 n(copy.n), u(copy.u), h(copy.h)
505 {
506 }
507
508 /*!
509 Destructs a QtSoapType.
510 */
~QtSoapType()511 QtSoapType::~QtSoapType()
512 {
513 }
514
515 /*!
516 Clears any contents. In this base implementation, clear() does
517 nothing.
518 */
clear()519 void QtSoapType::clear()
520 {
521 }
522
523 /*!
524 Makes this QtSoapType equal to \a copy.
525 */
operator =(const QtSoapType & copy)526 QtSoapType &QtSoapType::operator =(const QtSoapType ©)
527 {
528 t = copy.t;
529 errorStr = copy.errorStr;
530 i = copy.i;
531 n = copy.n;
532 u = copy.u;
533 h = copy.h;
534 return *this;
535 }
536
537 /*!
538 Returns true if this object is of type QtSoapStruct, QtSoapArray
539 or QtSoapSimpletype; otherwise returns false.
540 */
isValid() const541 bool QtSoapType::isValid() const
542 {
543 return false;
544 }
545
546 /*!
547 Returns the QString equivalent of type \a t.
548 */
typeToName(QtSoapType::Type t)549 QString QtSoapType::typeToName(QtSoapType::Type t)
550 {
551 switch (t) {
552 case Duration: return "duration";
553 case DateTime: return "dateTime";
554 case Time: return "time";
555 case Date: return "date";
556 case GYearMonth: return "gYearMonth";
557 case GYear: return "gYear";
558 case GMonthDay: return "gMonthDay";
559 case GDay: return "gDay";
560 case GMonth: return "gMonth";
561 case Boolean: return "boolean";
562 case Base64Binary: return "base64Binary";
563 case HexBinary: return "hexBinary";
564 case Float: return "float";
565 case Double: return "double";
566 case AnyURI: return "anyURI";
567 case QName: return "QName";
568 case NOTATION: return "NOTATION";
569 case String: return "string";
570 case NormalizedString: return "normalizedString";
571 case Token: return "token";
572 case Language: return "language";
573 case Name: return "name";
574 case NMTOKEN: return "NMToken";
575 case NCName: return "NCName";
576 case ID: return "ID";
577 case IDREF: return "IDREF";
578 case ENTITY: return "ENTITY";
579 case Decimal: return "decimal";
580 case Integer: return "integer";
581 case NonPositiveInteger: return "nonPositiveInteger";
582 case NegativeInteger: return "negativeInteger";
583 case Long: return "long";
584 case Int: return "int";
585 case Short: return "short";
586 case Byte: return "byte";
587 case NonNegativeInteger: return "nonNegativeInteger";
588 case UnsignedLong: return "unsignedLong";
589 case PositiveInteger: return "positiveInteger";
590 case UnsignedInt: return "unsignedInt";
591 case UnsignedShort: return "unsignedShort";
592 case UnsignedByte: return "unsignedByte";
593 case Array: return "array";
594 case Struct: return "struct";
595 default: return "other";
596 }
597 }
598
599 /*!
600 Returns the QtSoapType::Type called \a name.
601 */
nameToType(const QString & name)602 QtSoapType::Type QtSoapType::nameToType(const QString &name)
603 {
604 const QString type = name.trimmed().toLower();
605
606 if (type == "string")
607 return String;
608 else if (type == "normalizedstring")
609 return NormalizedString;
610 else if (type == "token")
611 return Token;
612 else if (type == "language")
613 return Language;
614 else if (type == "name")
615 return Name;
616 else if (type == "ncname")
617 return NCName;
618 else if (type == "nmtoken")
619 return NMTOKEN;
620 else if (type == "id")
621 return ID;
622 else if (type == "idref")
623 return IDREF;
624 else if (type == "entity")
625 return ENTITY;
626 else if (type == "base64binary")
627 return Base64Binary;
628 else if (type == "hexBinary")
629 return HexBinary;
630 else if (type == "anyuri")
631 return AnyURI;
632 else if (type == "qname")
633 return QName;
634 else if (type == "notation")
635 return NOTATION;
636 else if (type == "duration")
637 return Duration;
638 else if (type == "datetime")
639 return DateTime;
640 else if (type == "time")
641 return Time;
642 else if (type == "date")
643 return Date;
644 else if (type == "gyearmonth")
645 return GYearMonth;
646 else if (type == "gyear")
647 return GYear;
648 else if (type == "gmonthday")
649 return GMonthDay;
650 else if (type == "gday")
651 return GDay;
652 else if (type == "gmonth")
653 return GMonth;
654 else if (type == "decimal")
655 return Decimal;
656 else if (type == "integer")
657 return Integer;
658 else if (type == "nonPositiveinteger")
659 return NonPositiveInteger;
660 else if (type == "negativeinteger")
661 return NegativeInteger;
662 else if (type == "long")
663 return Long;
664 else if (type == "int")
665 return Int;
666 else if (type == "short")
667 return Short;
668 else if (type == "byte")
669 return Byte;
670 else if (type == "nonnegativeinteger")
671 return NonNegativeInteger;
672 else if (type == "unsignedlong")
673 return UnsignedLong;
674 else if (type == "unsignedint")
675 return UnsignedInt;
676 else if (type == "unsignedshort")
677 return UnsignedShort;
678 else if (type == "unsignedbyte")
679 return UnsignedByte;
680 else if (type == "positiveinteger")
681 return PositiveInteger;
682 else if (type == "float")
683 return Float;
684 else if (type == "double")
685 return Double;
686 else if (type == "boolean")
687 return Boolean;
688 else
689 return Other;
690 }
691
692 /*!
693 Returns QString::null.
694 */
toString() const695 QString QtSoapType::toString() const
696 {
697 return QString::null;
698 }
699
700 /*!
701 Returns 0.
702 */
toInt() const703 int QtSoapType::toInt() const
704 {
705 return 0;
706 }
707
708 /*!
709 Returns false.
710 */
toBool() const711 bool QtSoapType::toBool() const
712 {
713 return false;
714 }
715
716 /*!
717 Returns the QDomElement representation of this QtSoapType
718 as a child of \a document.
719 */
toDomElement(QDomDocument document) const720 QDomElement QtSoapType::toDomElement(QDomDocument document) const
721 {
722 Q_UNUSED(document);
723 return QDomElement();
724 }
725
726 /*!
727 Returns the QString representation of this QtSoapType's type.
728 */
typeName() const729 QString QtSoapType::typeName() const
730 {
731 return QtSoapType::typeToName(type());
732 }
733
734 /*!
735 Returns the type as a QtSoapType::Type.
736 */
type() const737 QtSoapType::Type QtSoapType::type() const
738 {
739 return t;
740 }
741
742 /*!
743 Returns the QName (qualified name) of this QtSoapType.
744 */
name() const745 QtSoapQName QtSoapType::name() const
746 {
747 return n;
748 }
749
750 /*!
751 Returns the ID of this QtSoapType.
752 */
id() const753 QString QtSoapType::id() const
754 {
755 return i;
756 }
757
758 /*!
759 Returns the href attribute of this QtSoapType.
760 */
href() const761 QString QtSoapType::href() const
762 {
763 return h;
764 }
765
766 /*!
767 Sets the QName (qualified name) of this QtSoapType to \a name.
768 */
setName(const QtSoapQName & name)769 void QtSoapType::setName(const QtSoapQName &name)
770 {
771 this->n = name;
772 }
773
774 /*!
775 Sets the ID of this QtSoapType to \a i.
776 */
setId(const QString & i)777 void QtSoapType::setId(const QString &i)
778 {
779 this->i = i;
780 }
781
782 /*!
783 Sets the href attribute of this QtSoapType to \a h.
784 */
setHref(const QString & h)785 void QtSoapType::setHref(const QString &h)
786 {
787 this->h = h;
788 }
789
790 /*!
791 Returns the value of this QtSoapType. In the base implementation,
792 an invalid QVariant() is returned.
793 */
value() const794 QVariant QtSoapType::value() const
795 {
796 return QVariant();
797 }
798
799 /*!
800 Returns a human readable explanation of the most recent error.
801 */
errorString() const802 QString QtSoapType::errorString() const
803 {
804 return errorStr;
805 }
806
807 /*!
808 Returns the number of child items in this QtSoapType. In the base
809 implementation, this returns 0.
810 */
count() const811 int QtSoapType::count() const
812 {
813 return 0;
814 }
815
816 /*!
817 Returns a reference to the child item at ordinal position \a pos.
818 If no item exists at this position, returns an empty QtSoapType.
819 */
operator [](int)820 QtSoapType &QtSoapType::operator [](int /* pos */ )
821 {
822 static QtSoapType NIL;
823 return NIL;
824 }
825
826 /*!
827 \overload
828
829 Returns a reference to the child item whose QName (qualified name)
830 is \a key. If no item exists with this key an empty QtSoapType is
831 returned.
832 */
operator [](const QtSoapQName &)833 QtSoapType &QtSoapType::operator [](const QtSoapQName & /* key */)
834 {
835 static QtSoapType NIL;
836 return NIL;
837 }
838
839 /*!
840 \overload
841
842 Returns a reference to the child item whose QName (qualified name)
843 is \a key, regardless of the qualified name's URI. If no item
844 exists with this key, an empty QtSoapType is returned.
845 */
operator [](const QString &)846 QtSoapType &QtSoapType::operator [](const QString & /* key */)
847 {
848 static QtSoapType NIL;
849 return NIL;
850 }
851
852 /*!
853 \overload
854
855 Returns a reference to the child item at ordinal position \a pos.
856 If no item exists at this position, returns an empty QtSoapType.
857 */
operator [](int) const858 const QtSoapType &QtSoapType::operator [](int /* pos */) const
859 {
860 static QtSoapType NIL;
861 return NIL;
862 }
863
864 /*!
865 \overload
866
867 Returns a reference to the child item whose QName (qualified name)
868 is \a key. If no item exists with this key, returns an empty
869 QtSoapType.
870 */
operator [](const QtSoapQName &) const871 const QtSoapType &QtSoapType::operator [](const QtSoapQName & /* key */) const
872 {
873 static QtSoapType NIL;
874 return NIL;
875 }
876
877 /*!
878 \overload
879
880 Returns a reference to the child item whose QName (qualified name)
881 is \a key, regardless of the qualified name's URI. If no item
882 exists with this key, returns an empty QtSoapType.
883 */
operator [](const QString &) const884 const QtSoapType &QtSoapType::operator [](const QString & /* key */) const
885 {
886 static QtSoapType NIL;
887 return NIL;
888 }
889
890 /*!
891 Attempts to interpret \a node as a QtSoapType, and returns true if
892 successful. This base implementation always returns false.
893 */
parse(QDomNode)894 bool QtSoapType::parse(QDomNode /* node */)
895 {
896 return false;
897 }
898
899 /*!
900 \overload
901
902 Constructs an empty one dimensional QtSoapArray whose element type
903 is undefined. The first insert will decide what type of elements
904 the array can contain.
905 */
QtSoapArray()906 QtSoapArray::QtSoapArray()
907 : QtSoapType(QtSoapQName(), Array), arrayType(Other), order(1)
908 {
909 lastIndex = 0;
910 siz0 = 0;
911 siz1 = 0;
912 siz2 = 0;
913 siz3 = 0;
914 siz4 = 0;
915 }
916
917 /*!
918 Constructs an empty QtSoapArray whose QName (qualified name) is \a
919 name, that contains elements of type \a type, and whose dimensions
920 are given by \a size0, \a size1, \a size2, \a size3 and \a size4.
921
922 To construct a one dimensional array of size 5, set \a size0 = 5. To
923 create a two dimensional array of size 5x10, set \a size0 = 5 and \a
924 size1 = 10. The maximum dimension of a QtSoapArray is 5.
925 */
QtSoapArray(const QtSoapQName & name,QtSoapType::Type type,int size0,int size1,int size2,int size3,int size4)926 QtSoapArray::QtSoapArray(const QtSoapQName &name, QtSoapType::Type type, int size0,
927 int size1, int size2, int size3, int size4)
928 : QtSoapType(name, Array), lastIndex(0), arrayType(type),
929 siz0(size0), siz1(size1), siz2(size2), siz3(size3),
930 siz4(size4)
931 {
932 if (size4 != -1) order = 5;
933 else if (size3 != -1) order = 4;
934 else if (size2 != -1) order = 3;
935 else if (size1 != -1) order = 2;
936 else order = 1;
937 }
938
939 /*!
940 Create a QtSoapArray that is a copy of \a copy.
941 */
QtSoapArray(const QtSoapArray & copy)942 QtSoapArray::QtSoapArray(const QtSoapArray ©)
943 : QtSoapType(copy)
944 {
945 *this = copy;
946 }
947
948 /*!
949 Destructs the QtSoapArray.
950 */
~QtSoapArray()951 QtSoapArray::~QtSoapArray()
952 {
953 }
954
955 /*!
956 Clears the contents, and the dimensions of the QtSoapArray.
957 */
clear()958 void QtSoapArray::clear()
959 {
960 array.clear();
961 lastIndex = 0;
962 arrayType = Other;
963 siz0 = siz1 = siz2 = siz3 = siz4 = 0;
964 order = -1;
965 }
966
967 /*!
968 Makes this QtSoapArray a copy of \a copy.
969 */
operator =(const QtSoapArray & copy)970 QtSoapArray &QtSoapArray::operator = (const QtSoapArray ©)
971 {
972 if (this == ©)
973 return *this;
974 t = copy.t;
975 errorStr = copy.errorStr;
976 i = copy.i;
977 n = copy.n;
978 u = copy.u;
979 h = copy.h;
980 lastIndex = copy.lastIndex;
981 order = copy.order;
982 siz0 = copy.siz0;
983 siz1 = copy.siz1;
984 siz2 = copy.siz2;
985 siz3 = copy.siz3;
986 siz4 = copy.siz4;
987 array = copy.array;
988
989 return *this;
990 }
991
992 /*!
993 Appends the QtSoapType \a item to the end of this array, which must
994 be one dimensional.
995
996 \sa insert()
997 */
append(QtSoapType * item)998 void QtSoapArray::append(QtSoapType *item)
999 {
1000 if (order != 1) {
1001 qWarning("Attempted to insert item at position (%i) in %i-dimensional QtSoapArray.",
1002 lastIndex, order);
1003 return;
1004 }
1005
1006 if (array.count() == 0) {
1007 array.insert(0, item);
1008 } else {
1009 array.insert(lastIndex + 1, item);
1010 ++lastIndex;
1011 }
1012 }
1013
1014 /*!
1015 Inserts the QtSoapType \a item at the absolute position \a pos in
1016 the array. Note that this function can be used to insert items
1017 into arrays with any number of dimensions.
1018
1019 If the array is one dimensional, then \a pos is simply the index
1020 position in the array. But if the array is multi-dimensional then
1021 \a pos is the absolute position. For example, if we have a two
1022 dimensional array [['a', 'b'], ['c', 'd'], ['e', 'f']], the
1023 element at position 0 is 'a', at position 1 is 'b', at position 2
1024 is 'c', and so on. (There are other insert() overloads that allow
1025 for each dimension to be specified individually.)
1026 */
insert(int pos,QtSoapType * item)1027 void QtSoapArray::insert(int pos, QtSoapType *item)
1028 {
1029 if (arrayType == Other)
1030 arrayType = item->type();
1031
1032 if (item->type() != arrayType) {
1033 qWarning("Attempted to insert item of type \"%s\" in QtSoapArray of type \"%s\".",
1034 item->typeName().toLatin1().constData(), QtSoapType::typeToName(arrayType).toLatin1().constData());
1035 return;
1036 }
1037
1038 if (order == -1)
1039 order = 1;
1040 else if (order == 1 && pos > lastIndex)
1041 lastIndex = pos;
1042
1043 array.insert(pos, item);
1044 }
1045
1046 /*!
1047 \overload
1048
1049 Insert the QtoSoapType \a item at position \a pos0 x \a pos1 in a
1050 two dimensional array.
1051 */
insert(int pos0,int pos1,QtSoapType * item)1052 void QtSoapArray::insert(int pos0, int pos1, QtSoapType *item)
1053 {
1054 if (order != 2) {
1055 qWarning("Attempted to insert item at position (%i, %i)"
1056 " in %i-dimensional QtSoapArray.",
1057 pos0, pos1, order);
1058 return;
1059 }
1060
1061 if (pos0 < 0 || pos0 >= siz0 || pos1 < 0 || pos1 >= siz1) {
1062 qWarning("Attempted to insert item at position (%i, %i)"
1063 " when range of QtSoapArray is (0..%i, 0..%i)",
1064 pos0, pos1, siz0 - 1, siz1 - 1);
1065 return;
1066 }
1067
1068 insert((pos0 * siz1) + pos1, item);
1069 }
1070
1071 /*!
1072 \overload
1073
1074 Insert the QtoSoapType \a item at position \a pos0 x \a pos1 x \a
1075 pos2 in a three dimensional array.
1076 */
insert(int pos0,int pos1,int pos2,QtSoapType * item)1077 void QtSoapArray::insert(int pos0, int pos1, int pos2, QtSoapType *item)
1078 {
1079 if (order != 3) {
1080 qWarning("Attempted to insert item at position (%i, %i, %i)"
1081 " in %i-dimensional QtSoapArray.",
1082 pos0, pos1, pos2, order);
1083 return;
1084 }
1085
1086 if (pos0 < 0 || pos0 >= siz0 || pos1 < 0 || pos1 >= siz1 || pos2 < 0 || pos2 >= siz2) {
1087 qWarning("Attempted to insert item at position (%i, %i, %i)"
1088 " when range of QtSoapArray is (0..%i, 0..%i, 0..%i)",
1089 pos0, pos1, pos2, siz0 - 1, siz1 - 1, siz2 - 1);
1090 return;
1091 }
1092
1093 insert((pos0 * siz2 * siz1) + (pos1 * siz2) + pos2, item);
1094 }
1095
1096 /*!
1097 \overload
1098
1099 Insert the QtoSoapType \a item at position \a pos0 x \a pos1 x \a
1100 pos2 x \a pos3 in a four dimensional array.
1101 */
insert(int pos0,int pos1,int pos2,int pos3,QtSoapType * item)1102 void QtSoapArray::insert(int pos0, int pos1, int pos2, int pos3, QtSoapType *item)
1103 {
1104 if (order != 4) {
1105 qWarning("Attempted to insert item at position (%i, %i, %i, %i)"
1106 " in %i-dimensional QtSoapArray.",
1107 pos0, pos1, pos2, pos3, order);
1108 return;
1109 }
1110
1111 insert((pos0 * siz3 * siz2 * siz1)
1112 + (pos1 * siz3 * siz2)
1113 + (pos2 * siz3)
1114 + pos3,
1115 item);
1116 }
1117
1118 /*!
1119 \overload
1120
1121 Insert the QtoSoapType \a item at position \a pos0 x \a pos1 x \a
1122 pos2 x \a pos3 x \a pos4 in a five dimensional array.
1123 */
insert(int pos0,int pos1,int pos2,int pos3,int pos4,QtSoapType * item)1124 void QtSoapArray::insert(int pos0, int pos1, int pos2, int pos3, int pos4,
1125 QtSoapType *item)
1126 {
1127 if (order != 5) {
1128 qWarning("Attempted to insert item at position (%i, %i, %i, %i, %i)"
1129 " in %i-dimensional QtSoapArray.",
1130 pos0, pos1, pos2, pos3, pos4, order);
1131 return;
1132 }
1133
1134 insert((pos0 * siz4 * siz3 * siz2 * siz1)
1135 + (pos1 * siz4 * siz3 * siz2)
1136 + (pos2 * siz4 * siz3)
1137 + (pos3 * siz4)
1138 + pos4,
1139 item);
1140 }
1141
1142 /*! \internal
1143
1144 Given the size and dimensions of the array, generates a string
1145 used to represent the array in XML. For example, a 1-dimensional
1146 array of size 5 would get [5], a 2-dimensional array of size 5x10
1147 would get [5,10].
1148 */
arraySizeString() const1149 QString QtSoapArray::arraySizeString() const
1150 {
1151 QString arraySize = "[";
1152 if (siz0 != -1) {
1153 arraySize += QString::number(siz0);
1154 if (order > 1) arraySize += "," + QString::number(siz1);
1155 if (order > 2) arraySize += "," + QString::number(siz2);
1156 if (order > 3) arraySize += "," + QString::number(siz3);
1157 if (order > 4) arraySize += "," + QString::number(siz4);
1158 }
1159
1160 arraySize += "]";
1161 return arraySize;
1162 }
1163
1164 /*! \internal
1165
1166 Recursively inspects the items and any child arrays' items to
1167 generate the aggregate type of items in this array. It the array
1168 contains ints, returns "int[5]", but if the array is of arrays of
1169 arrays of ints, the function returns "int[][][5]".
1170 */
arrayTypeString() const1171 QString QtSoapArray::arrayTypeString() const
1172 {
1173 if (arrayType != Array)
1174 return QtSoapType::typeToName(arrayType);
1175
1176 QString atString;
1177 QtSoapArray *ar = const_cast<QtSoapArray *>(this);
1178 do {
1179 if (ar->count() == 0)
1180 break;
1181
1182 atString += ar->arraySizeString();
1183
1184 QtSoapArrayIterator it(*const_cast<QtSoapArray *>(this));
1185 if (it.data()->type() != Array)
1186 break;
1187
1188 ar = (QtSoapArray *)it.data();
1189 } while (ar);
1190
1191
1192 QtSoapArrayIterator it(*const_cast<QtSoapArray *>(this));
1193 if (ar->count() == 0)
1194 atString = QtSoapSimpleType::typeToName(Int) + atString;
1195 else
1196 atString = it.data()->typeName() + atString;
1197
1198 return atString;
1199 }
1200
1201 /*!
1202 Returns the QDomElement representation of this QtSoapArray. The
1203 returned QDomElement is created using \a doc.
1204 */
toDomElement(QDomDocument doc) const1205 QDomElement QtSoapArray::toDomElement(QDomDocument doc) const
1206 {
1207 QString prefix = QtSoapNamespaces::instance().prefixFor(n.uri());
1208 QDomElement a = n.uri() == ""
1209 ? doc.createElement( n.name())
1210 : doc.createElementNS(n.uri(), prefix + ":" + n.name());
1211
1212 QString schemaprefix = QtSoapNamespaces::instance().prefixFor(XML_SCHEMA_INSTANCE);
1213 a.setAttributeNS(XML_SCHEMA_INSTANCE, schemaprefix + ":type", "xsd:Array");
1214
1215 QString encprefix = QtSoapNamespaces::instance().prefixFor(SOAPv11_ENCODING);
1216 a.setAttributeNS(SOAPv11_ENCODING, encprefix + ":arrayType", "xsd:" + arrayTypeString());
1217
1218 for (QtSoapArrayIterator i(*const_cast<QtSoapArray *>(this)); !i.atEnd(); ++i) {
1219 QDomElement item = i.data()->toDomElement(doc);
1220 item.setTagName("item");
1221
1222 int pos0, pos1, pos2, pos3, pos4;
1223 i.pos(&pos0, &pos1, &pos2, &pos3, &pos4);
1224
1225 QString position = "[" + QString::number(pos0);
1226 if (order > 1) position += "," + QString::number(pos1);
1227 if (order > 2) position += "," + QString::number(pos2);
1228 if (order > 3) position += "," + QString::number(pos3);
1229 if (order > 4) position += "," + QString::number(pos4);
1230 position += "]";
1231
1232 QString envprefix = QtSoapNamespaces::instance().prefixFor(SOAPv11_ENVELOPE);
1233 item.setAttributeNS(SOAPv11_ENVELOPE, envprefix + ":position", position);
1234 a.appendChild(item);
1235 }
1236
1237 return a;
1238 }
1239
1240 /*! \reimp
1241
1242 For this class, always returns true.
1243 */
isValid() const1244 bool QtSoapArray::isValid() const
1245 {
1246 return true;
1247 }
1248
1249 /*!
1250 Inspects \a node and builds the content of the QtSoapArray if \a
1251 node qualifies as a SOAP array. Returns true if it does; otherwise
1252 returns false.
1253 */
parse(QDomNode node)1254 bool QtSoapArray::parse(QDomNode node)
1255 {
1256 if (node.isNull() || !node.isElement())
1257 return false;
1258
1259 QDomElement e = node.toElement();
1260 QDomAttr typeattr = e.attributeNode("type");
1261 if (!typeattr.isNull() && (localName(typeattr.value()).toLower() != "array"))
1262 return false;
1263
1264
1265 QDomNodeList children = e.childNodes();
1266 int c = children.count();
1267 array.clear();
1268 // ### array.resize(c);
1269
1270 int pos = 0;
1271 for (int i = 0; i < c; ++i) {
1272 QDomNode n = children.item(i);
1273 if (n.isComment())
1274 continue;
1275 if (!n.isElement()){
1276 // ### An error in the soap document.
1277 return false;
1278 }
1279
1280 QDomElement elem = n.toElement();
1281
1282 QtSmartPtr<QtSoapType> type = QtSoapTypeFactory::instance().soapType(elem);
1283 if (!type.ptr()) {
1284 // ### An error in the soap document.
1285 return false;
1286 }
1287
1288 // ### Check namespace
1289 QDomAttr posattr = elem.attributeNode("position");
1290 if (!posattr.isNull())
1291 pos = posattr.value().toInt();
1292
1293 array.insert(pos, type);
1294 ++pos;
1295 }
1296
1297 setName(QtSoapQName(localName(e.tagName()), e.namespaceURI()));
1298 return true;
1299 }
1300
1301 /*!
1302 Returns the number of items in the array. Note that this is not
1303 the same as the size of the array, because the array may be sparse.
1304 */
count() const1305 int QtSoapArray::count() const
1306 {
1307 return array.count();
1308 }
1309
1310 /*!
1311 Returns a reference to the item at ordinal position \a pos. If
1312 there is no item at position \a pos, returns an empty QtSoapType.
1313 */
operator [](int pos)1314 QtSoapType &QtSoapArray::operator [](int pos)
1315 {
1316 return at(pos);
1317 }
1318
1319 /*!
1320 \overload
1321
1322 Returns a reference to the child item whose local name is \a s. If
1323 there is no item with this local name, returns an empty
1324 QtSoapType.
1325 */
operator [](const QString & s)1326 QtSoapType &QtSoapArray::operator [](const QString &s)
1327 {
1328 return QtSoapType::operator[](s);
1329 }
1330
1331 /*!
1332 \overload
1333
1334 Returns a reference to the child item whose QName (qualified name)
1335 is \a s. If there is no item with this name, returns an empty
1336 QtSoapType.
1337 */
operator [](const QtSoapQName & s)1338 QtSoapType &QtSoapArray::operator [](const QtSoapQName &s)
1339 {
1340 return QtSoapType::operator[](s);
1341 }
1342
1343 /*!
1344 \overload
1345
1346 Returns a reference to the item at ordinal position \a pos. If
1347 there is no item at position \a pos, returns an empty QtSoapType.
1348 */
operator [](int pos) const1349 const QtSoapType &QtSoapArray::operator [] (int pos) const
1350 {
1351 return at(pos);
1352 }
1353
1354 /*!
1355 \overload
1356
1357 Returns a reference to the child item whose local name is \a s. If
1358 there is no item with this local name, returns an empty
1359 QtSoapType.
1360 */
operator [](const QString & s) const1361 const QtSoapType &QtSoapArray::operator [](const QString &s) const
1362 {
1363 return QtSoapType::operator[](s);
1364 }
1365
1366 /*!
1367 \overload
1368
1369 Returns a reference to the child item whose QName (qualified name)
1370 is \a s. If there is no item with this name, returns an empty
1371 QtSoapType.
1372 */
operator [](const QtSoapQName & s) const1373 const QtSoapType &QtSoapArray::operator [](const QtSoapQName &s) const
1374 {
1375 return QtSoapType::operator[](s);
1376 }
1377
1378 /*!
1379 Returns a reference to the item at ordinal position \a pos. If
1380 there is no item at position \a pos, returns an empty QtSoapType.
1381 */
at(int pos)1382 QtSoapType &QtSoapArray::at(int pos)
1383 {
1384 static QtSoapType NIL;
1385
1386 if (array.find(pos) != array.end())
1387 return *array[pos];
1388 else
1389 return NIL;
1390 }
1391
1392 /*!
1393 \overload
1394
1395 Returns a reference to the item at ordinal position \a pos0 x \a
1396 pos1 in a two dimensional array. If there is no such item, returns
1397 an empty QtSoapType.
1398 */
at(int pos0,int pos1)1399 QtSoapType &QtSoapArray::at(int pos0, int pos1)
1400 {
1401 return at(pos0 * siz1 + pos1);
1402 }
1403
1404 /*!
1405 \overload
1406
1407 Returns a reference to the item at ordinal position \a pos0 x \a
1408 pos1 x \a pos2 in a three dimensional array. If there is no such
1409 item, returns an empty QtSoapType.
1410 */
at(int pos0,int pos1,int pos2)1411 QtSoapType &QtSoapArray::at(int pos0, int pos1, int pos2)
1412 {
1413 return at((pos0 * siz2 * siz1) + (pos1 * siz2) + pos2);
1414 }
1415
1416 /*!
1417 \overload
1418
1419 Returns a reference to the item at ordinal position \a pos0 x \a
1420 pos1 x \a pos2 x \a pos3 in a four dimensional array. If there is no
1421 such item, returns an empty QtSoapType.
1422 */
at(int pos0,int pos1,int pos2,int pos3)1423 QtSoapType &QtSoapArray::at(int pos0, int pos1, int pos2, int pos3)
1424 {
1425 return at((pos0 * siz3 * siz2 * siz1)
1426 + (pos1 * siz3 * siz2)
1427 + (pos2 * siz3)
1428 + pos3);
1429 }
1430
1431 /*!
1432 \overload
1433
1434 Returns a reference to the item at ordinal position \a pos0 x \a
1435 pos1 x \a pos2 x \a pos3 x \a pos4 in a five dimensional array. If
1436 there is no such item, returns an empty QtSoapType.
1437 */
at(int pos0,int pos1,int pos2,int pos3,int pos4)1438 QtSoapType &QtSoapArray::at(int pos0, int pos1, int pos2, int pos3, int pos4)
1439 {
1440 return at((pos0 * siz4 * siz3 * siz2 * siz1)
1441 + (pos1 * siz4 * siz3 * siz2)
1442 + (pos2 * siz4 * siz3)
1443 + (pos3 * siz4)
1444 + pos4);
1445 }
1446
1447 /*!
1448 \overload
1449
1450 Returns a reference to the item at ordinal position \a pos. If
1451 there is no item at position \a pos, returns an empty QtSoapType.
1452 */
at(int pos) const1453 const QtSoapType &QtSoapArray::at(int pos) const
1454 {
1455 static QtSoapType NIL;
1456
1457 if (array.find(pos) != array.end())
1458 return *array[pos];
1459 else
1460 return NIL;
1461 }
1462
1463 /*!
1464 \overload
1465
1466 Returns a reference to the item at ordinal position \a pos0 x \a
1467 pos1 in a two dimensional array. If there is no such item, returns
1468 an empty QtSoapType.
1469 */
at(int pos0,int pos1) const1470 const QtSoapType &QtSoapArray::at(int pos0, int pos1) const
1471 {
1472 return at(pos0 * siz1 + pos1);
1473 }
1474
1475 /*!
1476 \overload
1477
1478 Returns a reference to the item at ordinal position \a pos0 x \a
1479 pos1 x \a pos2 in a three dimensional array. If there is no such
1480 item, returns an empty QtSoapType.
1481 */
at(int pos0,int pos1,int pos2) const1482 const QtSoapType &QtSoapArray::at(int pos0, int pos1, int pos2) const
1483 {
1484 return at((pos0 * siz2 * siz1) + (pos1 * siz2) + pos2);
1485 }
1486
1487 /*!
1488 \overload
1489
1490 Returns a reference to the item at ordinal position \a pos0 x \a
1491 pos1 x \a pos2 x \a pos3 in a four dimensional array. If there is no
1492 such item, returns an empty QtSoapType.
1493 */
at(int pos0,int pos1,int pos2,int pos3) const1494 const QtSoapType &QtSoapArray::at(int pos0, int pos1, int pos2, int pos3) const
1495 {
1496 return at((pos0 * siz3 * siz2 * siz1)
1497 + (pos1 * siz3 * siz2)
1498 + (pos2 * siz3)
1499 + pos3);
1500 }
1501
1502 /*!
1503 \overload
1504
1505 Returns a reference to the item at ordinal position \a pos0 x \a
1506 pos1 x \a pos2 x \a pos3 x \a pos4 in a five dimensional array. If
1507 there is no such item, returns an empty QtSoapType.
1508 */
at(int pos0,int pos1,int pos2,int pos3,int pos4) const1509 const QtSoapType &QtSoapArray::at(int pos0, int pos1, int pos2, int pos3, int pos4) const
1510 {
1511 return at((pos0 * siz4 * siz3 * siz2 * siz1)
1512 + (pos1 * siz4 * siz3 * siz2)
1513 + (pos2 * siz4 * siz3)
1514 + (pos3 * siz4)
1515 + pos4);
1516 }
1517
1518 /*!
1519 Constructs a QtSoapArrayIterator on \a array, initializing
1520 the iterator to point to the first element.
1521 */
QtSoapArrayIterator(QtSoapArray & array)1522 QtSoapArrayIterator::QtSoapArrayIterator(QtSoapArray &array)
1523 : it(array.array.begin()), arr(&array)
1524 {
1525 }
1526
1527 /*!
1528 Constructs a QtSoapArrayIterator that is a copy of \a copy.
1529 */
QtSoapArrayIterator(const QtSoapArrayIterator & copy)1530 QtSoapArrayIterator::QtSoapArrayIterator(const QtSoapArrayIterator ©)
1531 : it(copy.it), arr(copy.arr)
1532 {
1533 }
1534
1535 /*!
1536 Returns false if this iterator points to an item in the array, otherwise true.
1537 */
atEnd() const1538 bool QtSoapArrayIterator::atEnd() const
1539 {
1540 return (it == arr->array.end());
1541 }
1542
1543 /*!
1544 Assignment operator of QtSoapArrayIterator. Makes this iterator a
1545 copy of \a copy.
1546 */
operator =(const QtSoapArrayIterator & copy)1547 QtSoapArrayIterator &QtSoapArrayIterator::operator =(const QtSoapArrayIterator ©)
1548 {
1549 it = copy.it;
1550 arr = copy.arr;
1551
1552 return *this;
1553 }
1554
1555 /*!
1556 Destructs the QtSoapArrayIterator.
1557 */
~QtSoapArrayIterator()1558 QtSoapArrayIterator::~QtSoapArrayIterator()
1559 {
1560 }
1561
1562 /*!
1563 \overload
1564
1565 Returns the ordinal position of the iterator. Works for arrays of
1566 any dimension, but is only useful for one dimensional arrays.
1567 */
pos() const1568 int QtSoapArrayIterator::pos() const
1569 {
1570 return it.key();
1571 }
1572
1573 /*!
1574 Populates the arguments \a pos0, \a pos1, \a pos2, \a pos3 and \a
1575 pos4 with the coordinate of the current position of the iterator.
1576 For a one dimensional array, only \a pos0 is populated. For a two
1577 dimensional array, \a pos0 and \a pos1 are populated, and so on.
1578
1579 Any of the arguments that are 0-pointers are ignored.
1580 */
pos(int * pos0,int * pos1,int * pos2,int * pos3,int * pos4) const1581 void QtSoapArrayIterator::pos(int *pos0, int *pos1, int *pos2,
1582 int *pos3, int *pos4) const
1583 {
1584 const int key = it.key();
1585
1586 switch (arr->order) {
1587 case 1:
1588 if (pos0) *pos0 = key;
1589 break;
1590 case 2: {
1591 const int tmp = key / arr->siz1;
1592 if (pos0) *pos0 = tmp;
1593 if (pos1) *pos1 = key - (tmp * arr->siz1);
1594 }
1595 break;
1596 case 3: {
1597 const int tmp0 = key / (arr->siz2 * arr->siz1);
1598 const int tmp1 = key - (tmp0 * (arr->siz2 * arr->siz1));
1599 const int tmp2 = tmp1 / arr->siz2;
1600 if (pos0) *pos0 = tmp0;
1601 if (pos1) *pos1 = tmp2;
1602 if (pos2) *pos2 = tmp1 - (tmp2 * arr->siz2);
1603 }
1604 break;
1605 case 4: {
1606 const int tmp0 = key / (arr->siz3 * arr->siz2 * arr->siz1);
1607 const int tmp1 = key - (tmp0 * (arr->siz3 * arr->siz2 * arr->siz1));
1608 const int tmp2 = tmp1 / (arr->siz3 * arr->siz2);
1609 const int tmp3 = tmp1 - (tmp2 * (arr->siz3 * arr->siz2));
1610 const int tmp4 = tmp3 / arr->siz3;
1611 const int tmp5 = tmp3 - (tmp4 * arr->siz3);
1612 if (pos0) *pos0 = tmp0;
1613 if (pos1) *pos1 = tmp2;
1614 if (pos2) *pos2 = tmp4;
1615 if (pos3) *pos3 = tmp5;
1616 }
1617 break;
1618 case 5: {
1619 const int tmp0 = key / (arr->siz4 * arr->siz3 * arr->siz2 * arr->siz1);
1620 const int tmp1 = key - (tmp0 * (arr->siz4 * arr->siz3 * arr->siz2 * arr->siz1));
1621 const int tmp2 = tmp1 / (arr->siz4 * arr->siz3 * arr->siz2);
1622 const int tmp3 = tmp1 - (tmp2 * (arr->siz4 * arr->siz3 * arr->siz2));
1623 const int tmp4 = tmp3 / (arr->siz4 * arr->siz3);
1624 const int tmp5 = tmp3 - (tmp4 * arr->siz4 * arr->siz3);
1625 const int tmp6 = tmp5 / arr->siz3;
1626 const int tmp7 = tmp5 - (tmp6 * arr->siz3);
1627 if (pos0) *pos0 = tmp0;
1628 if (pos1) *pos1 = tmp2;
1629 if (pos2) *pos2 = tmp4;
1630 if (pos3) *pos3 = tmp6;
1631 if (pos4) *pos4 = tmp7;
1632 }
1633 break;
1634 default:
1635 break;
1636 }
1637 }
1638
1639 /*!
1640 Returns a reference to the item that the iterator is currently
1641 pointing to.
1642 */
data()1643 QtSoapType *QtSoapArrayIterator::data()
1644 {
1645 if (it == arr->array.end())
1646 return 0;
1647 return it.value().ptr();
1648 }
1649
1650 /*!
1651 Returns a reference to the item that the iterator is currently
1652 pointing to.
1653 */
current() const1654 const QtSoapType *QtSoapArrayIterator::current() const
1655 {
1656 if (it == arr->array.end())
1657 return 0;
1658 return it.value().ptr();
1659 }
1660
1661 /*!
1662 Moves the iterator position to the next item in the array.
1663 */
operator ++()1664 void QtSoapArrayIterator::operator ++()
1665 {
1666 ++it;
1667 }
1668
1669 /*!
1670 Returns true if this Iterator's position is not equal to
1671 the position of \a j; otherwise returns false.
1672 */
operator !=(const QtSoapArrayIterator & j) const1673 bool QtSoapArrayIterator::operator != (const QtSoapArrayIterator &j) const
1674 {
1675 return it != j.it;
1676 }
1677
1678 /*!
1679 Returns true if this Iterator's position is equal to the position
1680 of \a j; otherwise returns false.
1681 */
operator ==(const QtSoapArrayIterator & j) const1682 bool QtSoapArrayIterator::operator == (const QtSoapArrayIterator &j) const
1683 {
1684 return it == j.it;
1685 }
1686
1687 /*!
1688 Constructs an empty QtSoapStruct.
1689 */
QtSoapStruct()1690 QtSoapStruct::QtSoapStruct()
1691 : QtSoapType(QtSoapQName(), Struct)
1692 {
1693 }
1694
1695 /*!
1696 Constructs an empty QtSoapStruct and sets its QName (qualified
1697 name) to \a name.
1698 */
QtSoapStruct(const QtSoapQName & name)1699 QtSoapStruct::QtSoapStruct(const QtSoapQName &name)
1700 : QtSoapType(name, Struct)
1701 {
1702 }
1703
1704 /*!
1705 Constructs a QtSoapStruct that is a copy of \a copy.
1706 */
QtSoapStruct(const QtSoapStruct & copy)1707 QtSoapStruct::QtSoapStruct(const QtSoapStruct ©)
1708 : QtSoapType(copy)
1709 {
1710 *this = copy;
1711 }
1712
1713 /*!
1714 Destructs the QtSoapStruct.
1715 */
~QtSoapStruct()1716 QtSoapStruct::~QtSoapStruct()
1717 {
1718 }
1719
1720 /*!
1721 Removes all items from the struct.
1722 */
clear()1723 void QtSoapStruct::clear()
1724 {
1725 dict.clear();
1726 }
1727
1728 /*!
1729 Makes this struct a copy of \a copy.
1730 */
operator =(const QtSoapStruct & copy)1731 QtSoapStruct &QtSoapStruct::operator =(const QtSoapStruct ©)
1732 {
1733 if (this == ©)
1734 return *this;
1735 t = copy.t;
1736 errorStr = copy.errorStr;
1737 i = copy.i;
1738 n = copy.n;
1739 u = copy.u;
1740 h = copy.h;
1741 i = copy.i;
1742 dict = copy.dict;
1743
1744 return *this;
1745 }
1746
1747 /*!
1748 Inserts the QtSoapType \a item into this struct. Any existing
1749 item with the same QName (qualified name) will be erased.
1750 */
insert(QtSoapType * item)1751 void QtSoapStruct::insert(QtSoapType *item)
1752 {
1753 dict.append(item);
1754 }
1755
1756 /*!
1757 Generates the QDomElement representation of this struct. The
1758 returned QDomElement is created using \a doc.
1759 */
toDomElement(QDomDocument doc) const1760 QDomElement QtSoapStruct::toDomElement(QDomDocument doc) const
1761 {
1762 QString prefix = QtSoapNamespaces::instance().prefixFor(n.uri());
1763 QDomElement a = n.uri() == ""
1764 ? doc.createElement(n.name())
1765 : doc.createElementNS(n.uri(), prefix + ":" + n.name());
1766
1767 for (QtSoapStructIterator i(*const_cast<QtSoapStruct *>(this)); i.data(); ++i)
1768 a.appendChild(i.data()->toDomElement(doc));
1769
1770 return a;
1771 }
1772
1773 /*! \reimp
1774 */
isValid() const1775 bool QtSoapStruct::isValid() const
1776 {
1777 return true;
1778 }
1779
1780 /*!
1781 Inspects \a node and constructs the equivalent QtSoapStruct if \a
1782 node qualifies as a SOAP struct. Returns true if it does;
1783 otherwise returns false.
1784 */
parse(QDomNode node)1785 bool QtSoapStruct::parse(QDomNode node)
1786 {
1787 if (node.isNull() || !node.isElement())
1788 return false;
1789
1790 QDomElement e = node.toElement();
1791 QDomNodeList children = e.childNodes();
1792 int c = children.count();
1793 dict.clear();
1794
1795 for (int i = 0; i < c; ++i) {
1796 QDomNode n = children.item(i);
1797 if (n.isComment())
1798 continue;
1799 if (!n.isElement()){
1800 errorStr = "In the struct element " + e.tagName();
1801 errorStr += ", the " + QString::number(i) + "th child ";
1802 errorStr += "is not an element.";
1803 return false;
1804 }
1805
1806 QtSmartPtr<QtSoapType> type = QtSoapTypeFactory::instance().soapType(n.toElement());
1807 if (!type.ptr()) {
1808 errorStr = "In the struct element " + e.tagName();
1809 errorStr += ", child #" + QString::number(i) + ", ";
1810 errorStr += n.toElement().tagName() + ", was not recognized as a SOAP type.";
1811 return false;
1812 }
1813
1814 dict.append(type);
1815 }
1816
1817 setName(QtSoapQName(localName(e.tagName()), e.namespaceURI()));
1818 return true;
1819 }
1820
1821 /*!
1822 Returns the number of items in this struct.
1823 */
count() const1824 int QtSoapStruct::count() const
1825 {
1826 return dict.count();
1827 }
1828
1829 /*!
1830 Returns a reference to the item in this struct whose QName
1831 (qualified name) is \a key. If no such item exists, an empty
1832 QtSoapType is returned.
1833 */
operator [](const QtSoapQName & key)1834 QtSoapType &QtSoapStruct::operator [](const QtSoapQName &key)
1835 {
1836 return at(key);
1837 }
1838
1839 /*!
1840 \overload
1841
1842 Returns a reference to the item in this struct whose QName
1843 (qualified name) is \a key. If no such item exists, an empty
1844 QtSoapType is returned.
1845 */
operator [](const QtSoapQName & key) const1846 const QtSoapType &QtSoapStruct::operator [](const QtSoapQName &key) const
1847 {
1848 return at(key);
1849 }
1850
1851 /*!
1852 \overload
1853
1854 Returns a reference to the item in this struct whose QName
1855 (qualified name) is \a key. If no such item exists, an empty
1856 QtSoapType is returned.
1857 */
operator [](const QString & key)1858 QtSoapType &QtSoapStruct::operator [](const QString &key)
1859 {
1860 return at(QtSoapQName(key, ""));
1861 }
1862
1863 /*!
1864 \overload
1865
1866 Returns a reference to the item in this struct whose QName
1867 (qualified name) is \a key. If no such item exists, an empty
1868 QtSoapType is returned.
1869 */
operator [](const QString & key) const1870 const QtSoapType &QtSoapStruct::operator [](const QString &key) const
1871 {
1872 return at(QtSoapQName(key, ""));
1873 }
1874
1875 /*!
1876 \overload
1877
1878 Returns a reference to item number \a i in this struct. If no such
1879 item exists, an empty QtSoapType is returned.
1880
1881 The items are ordered in the sequence in which they were inserted,
1882 starting from 0.
1883 */
operator [](int i)1884 QtSoapType &QtSoapStruct::operator [](int i)
1885 {
1886 static QtSoapType NIL;
1887 if (i < 0 || i >= dict.count())
1888 return NIL;
1889
1890 return *dict[i].ptr();
1891 }
1892
1893 /*!
1894 \overload
1895
1896 Returns a reference to item number \a i in this struct. If no such
1897 item exists, an empty QtSoapType is returned.
1898
1899 The items are ordered in the sequence in which they were inserted,
1900 starting from 0.
1901 */
operator [](int i) const1902 const QtSoapType &QtSoapStruct::operator [](int i) const
1903 {
1904 static QtSoapType NIL;
1905 if (i < 0 || i >= dict.count())
1906 return NIL;
1907
1908 return *dict[i].ptr();
1909 }
1910
1911 /*!
1912 Returns a reference to the item in this struct whose QName
1913 (qualified name) is \a key. If no such item exists, an empty
1914 QtSoapType is returned.
1915 */
at(const QtSoapQName & key)1916 QtSoapType &QtSoapStruct::at(const QtSoapQName &key)
1917 {
1918 static QtSoapType NIL;
1919
1920 QListIterator<QtSmartPtr<QtSoapType> > it(dict);
1921 while (it.hasNext()) {
1922 QtSoapType *ret = it.next().ptr();
1923 if (ret->name() == key)
1924 return *ret;
1925 }
1926
1927 return NIL;
1928 }
1929
1930 /*!
1931 \overload
1932
1933 Returns a reference to the item in this struct whose QName
1934 (qualified name) is \a key. If no such item exists, an empty
1935 QtSoapType is returned.
1936 */
at(const QtSoapQName & key) const1937 const QtSoapType &QtSoapStruct::at(const QtSoapQName &key) const
1938 {
1939 static QtSoapType NIL;
1940
1941 for (QtSoapStructIterator i(*const_cast<QtSoapStruct *>(this)); i.current(); ++i)
1942 if (i.key() == key)
1943 return *i.current();
1944
1945 return NIL;
1946 }
1947
1948 /*!
1949 Constructs a QtSoapStructIterator and initializes it to point to
1950 the first element in the struct \a s.
1951 */
QtSoapStructIterator(QtSoapStruct & s)1952 QtSoapStructIterator::QtSoapStructIterator(QtSoapStruct &s) : it(s.dict.begin()), itEnd(s.dict.end())
1953 {
1954 }
1955
1956 /*!
1957 Destructs the QtSoapStructIterator.
1958 */
~QtSoapStructIterator()1959 QtSoapStructIterator::~QtSoapStructIterator()
1960 {
1961 }
1962
1963
1964 /*!
1965 Returns the QName (qualified name) of the current item.
1966 */
key() const1967 QtSoapQName QtSoapStructIterator::key() const
1968 {
1969 if (it == itEnd)
1970 return QtSoapQName();
1971 return (*it)->name();
1972 }
1973
1974 /*!
1975 Returns a pointer to the current item, or 0 if there is none.
1976 */
data()1977 QtSoapType *QtSoapStructIterator::data()
1978 {
1979 if (it == itEnd)
1980 return 0;
1981 return it->ptr();
1982 }
1983
1984 /*!
1985 Returns a pointer to the current item, or 0 if there is none.
1986 */
current() const1987 const QtSoapType *QtSoapStructIterator::current() const
1988 {
1989 if (it == itEnd)
1990 return 0;
1991 return it->ptr();
1992 }
1993
1994 /*!
1995 Moves the iterator to the next item in the struct.
1996 */
operator ++()1997 void QtSoapStructIterator::operator ++()
1998 {
1999 if (it == itEnd)
2000 return;
2001 ++it;
2002 }
2003
2004 /*!
2005 Returns true if this iterator's position is not equal to that of
2006 \a j; otherwise returns false.
2007 */
operator !=(const QtSoapStructIterator & j) const2008 bool QtSoapStructIterator::operator !=(const QtSoapStructIterator &j) const
2009 {
2010 return it != j.it;
2011 }
2012
2013 /*!
2014 Returns true if this iterator's position is equal to that of \a
2015 j; otherwise returns false.
2016 */
operator ==(const QtSoapStructIterator & j) const2017 bool QtSoapStructIterator::operator ==(const QtSoapStructIterator &j) const
2018 {
2019 return it == j.it;
2020 }
2021
2022 /*!
2023 Constructs an empty QtSoapSimpleType.
2024 */
QtSoapSimpleType()2025 QtSoapSimpleType::QtSoapSimpleType()
2026 {
2027 }
2028
2029 /*!
2030 \overload
2031
2032 Constructs an empty QtSoapSimpleType, and sets its QName
2033 (qualified name) to \a name.
2034 */
QtSoapSimpleType(const QtSoapQName & name)2035 QtSoapSimpleType::QtSoapSimpleType(const QtSoapQName &name)
2036 : QtSoapType(name)
2037 {
2038 }
2039
2040 /*!
2041 \overload
2042
2043 Constructs a QtSoapSimpleType of type Int. Sets its QName
2044 (qualified name) to \a name and its value to \a n.
2045 */
QtSoapSimpleType(const QtSoapQName & name,int n)2046 QtSoapSimpleType::QtSoapSimpleType(const QtSoapQName &name, int n)
2047 : QtSoapType(name, Int), v(QVariant(n))
2048 {
2049 }
2050
2051 /*!
2052 \overload
2053
2054 Constructs a QtSoapSimpleType of type Boolean. Sets its QName
2055 (qualified name) to \a name and its value to \a n.
2056
2057 \a dummy is an unused variable that should be set to 0; it is
2058 needed for older compilers that cannot distinguish between bool
2059 and int.
2060 */
QtSoapSimpleType(const QtSoapQName & name,bool n,int)2061 QtSoapSimpleType::QtSoapSimpleType(const QtSoapQName &name, bool n, int)
2062 : QtSoapType(name, Boolean), v(QVariant(n))
2063 {
2064 }
2065
2066 /*!
2067 \overload
2068
2069 Constructs a QtSoapSimpleType of type String. Sets its QName
2070 (qualified name) to \a name and its value to \a n.
2071 */
QtSoapSimpleType(const QtSoapQName & name,const QString & n)2072 QtSoapSimpleType::QtSoapSimpleType(const QtSoapQName &name, const QString &n)
2073 : QtSoapType(name, String), v(QVariant(n))
2074 {
2075 }
2076
2077 /*!
2078 Constructs a QtSoapSimpleType that is a copy of \a copy.
2079 */
QtSoapSimpleType(const QtSoapSimpleType & copy)2080 QtSoapSimpleType::QtSoapSimpleType(const QtSoapSimpleType ©)
2081 : QtSoapType(copy), v(copy.v)
2082 {
2083 }
2084
2085 /*!
2086 Destructs the QtSoapSimpleType.
2087 */
~QtSoapSimpleType()2088 QtSoapSimpleType::~QtSoapSimpleType()
2089 {
2090 }
2091
2092 /*!
2093 Erases the value of this QtSoapSimpleType.
2094 */
clear()2095 void QtSoapSimpleType::clear()
2096 {
2097 v.clear();
2098 }
2099
2100 /*!
2101 Returns the QDomElement representation of this QtSoapSimpleType.
2102 The returned QDomElement is created using \a doc.
2103 */
toDomElement(QDomDocument doc) const2104 QDomElement QtSoapSimpleType::toDomElement(QDomDocument doc) const
2105 {
2106 QString prefix = QtSoapNamespaces::instance().prefixFor(n.uri());
2107 QDomElement a = n.uri() == ""
2108 ? doc.createElement(n.name())
2109 : doc.createElementNS(n.uri(), prefix + ":" + n.name());
2110
2111 QString schemaprefix = QtSoapNamespaces::instance().prefixFor(XML_SCHEMA_INSTANCE);
2112 a.setAttributeNS(XML_SCHEMA_INSTANCE, schemaprefix + ":type", "xsd:" + typeName());
2113 a.appendChild(doc.createTextNode(v.toString()));
2114
2115 return a;
2116 }
2117
2118 /*! \reimp
2119 */
isValid() const2120 bool QtSoapSimpleType::isValid() const
2121 {
2122 return true;
2123 }
2124
2125 /*!
2126 Makes this QtSoapSimpleType a copy of \a copy.
2127 */
operator =(const QtSoapSimpleType & copy)2128 QtSoapSimpleType &QtSoapSimpleType::operator =(const QtSoapSimpleType ©)
2129 {
2130 t = copy.t;
2131 errorStr = copy.errorStr;
2132 i = copy.i;
2133 n = copy.n;
2134 u = copy.u;
2135 h = copy.h;
2136 v = copy.v;
2137
2138 return *this;
2139 }
2140
2141 /*!
2142 Inspects \a node and constructs the QtSoapSimpleType content if \a
2143 node qualifies as a SOAP simple type. Returns true if it does;
2144 otherwise returns false.
2145 */
parse(QDomNode node)2146 bool QtSoapSimpleType::parse(QDomNode node)
2147 {
2148 if (node.isNull() || !node.isElement())
2149 return false;
2150
2151 QDomElement e = node.toElement();
2152
2153 QDomAttr typeattr = e.attributeNode("type");
2154 QString type = typeattr.isNull() ? QString("string") : localName(typeattr.value()).toLower();
2155
2156 t = QtSoapType::nameToType(type);
2157 switch (t) {
2158 case Duration:
2159 case DateTime:
2160 case Time:
2161 case Date:
2162 case GYearMonth:
2163 case GYear:
2164 case GMonthDay:
2165 case GDay:
2166 case GMonth:
2167 case Base64Binary:
2168 case HexBinary:
2169 case AnyURI:
2170 case QName:
2171 case NOTATION:
2172 case String:
2173 case NormalizedString:
2174 case Token:
2175 case Language:
2176 case Name:
2177 case NMTOKEN:
2178 case NCName:
2179 case ID:
2180 case IDREF:
2181 case ENTITY:
2182 v = QVariant(e.text());
2183 break;
2184 case Float:
2185 v = QVariant(e.text().toFloat());
2186 break;
2187 case Double:
2188 v = QVariant(e.text().toDouble());
2189 break;
2190 case Decimal:
2191 case Integer:
2192 case NonPositiveInteger:
2193 case NegativeInteger:
2194 case Long:
2195 case Int:
2196 case Short:
2197 case Byte:
2198 case NonNegativeInteger:
2199 case UnsignedLong:
2200 case PositiveInteger:
2201 case UnsignedInt:
2202 case UnsignedShort:
2203 case UnsignedByte:
2204 if (e.text() == "" || (e.text() != "" && (e.text()[0].isNumber() || e.text()[0] == '-')))
2205 v = QVariant(e.text().toInt());
2206 else {
2207 errorStr = "Type error at element \"" + e.tagName() + "\"";
2208 return false;
2209 }
2210
2211 break;
2212 case Boolean: {
2213 QString val = e.text().trimmed().toLower();
2214 if (val == "false")
2215 v = QVariant(false);
2216 else if (val == "true")
2217 v = QVariant(true);
2218 }
2219 break;
2220 default:
2221 v = e.text();
2222 break;
2223 }
2224
2225 setName(QtSoapQName(localName(e.tagName()), e.namespaceURI()));
2226 return true;
2227 }
2228
2229 /*!
2230 Returns the value of the simple type as a QString.
2231 */
toString() const2232 QString QtSoapSimpleType::toString() const
2233 {
2234 return v.toString();
2235 }
2236
2237 /*!
2238 Returns the value of the simple type as an int.
2239 */
toInt() const2240 int QtSoapSimpleType::toInt() const
2241 {
2242 return v.toInt();
2243 }
2244
2245 /*!
2246 Returns the value of the simple type as a bool.
2247 */
toBool() const2248 bool QtSoapSimpleType::toBool() const
2249 {
2250 return v.toBool();
2251 }
2252
2253
2254 /*!
2255 Returns the QVariant value of this QtSoapSimpleType.
2256 */
value() const2257 QVariant QtSoapSimpleType::value() const
2258 {
2259 return v;
2260 }
2261
2262 /*! \class QtSoapMessage qtsoap.h
2263 \brief The QtSoapMessage class provides easy access to SOAP
2264 messages.
2265
2266 With this class, you can create and inspect any SOAP message.
2267 There are convenience functions available for generating the most
2268 common types of SOAP messages, and any other messages can be
2269 constructed manually using addBodyItem().
2270
2271 Use setMethod() and addMethodArgument() to construct a method
2272 request. The return value of a method response is available
2273 from returnValue().
2274
2275 Use setFaultCode(), setFaultString() and addFaultDetail() to
2276 construct a Fault message. To inspect a Fault message, use
2277 faultCode(), faultString() and faultDetail().
2278
2279 To add items to the body part of the SOAP message, use
2280 addBodyItem(). To add items to the header, use addHeaderItem().
2281
2282 toXmlString() returns a QString XML representation of the SOAP
2283 message. clear() resets all content in the message, creating an
2284 empty SOAP message.
2285
2286 \code
2287 QtSoapMessage message;
2288
2289 message.setMethod("getTemperature", "http://weather.example.com/temperature");
2290 message.addMethodArgument("city", "Oslo");
2291
2292 // Get the SOAP message as an XML string.
2293 QString xml = message.toXmlString();
2294 \endcode
2295
2296 QtSoap provides a partial implementation of version 1.1 of the
2297 SOAP protocol as defined in \l http://www.w3.org/TR/SOAP/.
2298
2299 \list
2300 \i Server side SOAP is not supported.
2301 \i References to values (id and href attributes) are not supported.
2302 \i Arrays support a maximum of five dimensions.
2303 \i Namespaces for types are not checked. Only the type names are used.
2304 \i The encodingStyle attribute is ignored. The serialization and
2305 encoding rules from section 5 in the SOAP v1.1 specification
2306 are assumed regardless of the value of the encodingStyle
2307 attribute.
2308 \i QtSoapType does not have accessors for attributes, which means
2309 for example that actor, mustUnderstand and so on are not
2310 accessible in headers.
2311 \i The SOAP root attribute is not supported.
2312 \endlist
2313
2314 \sa QtSoapType, QtSoapQName, QtSoapHttpTransport
2315
2316 */
2317
2318 /*! \enum QtSoapMessage::FaultCode
2319
2320 This enum describes all the supported SOAP Fault codes:
2321
2322 \value VersionMismatch
2323 The namespace for the Envelope element was unrecognized by the
2324 remote SOAP server. This usually means that the remote server does
2325 not support version 1.1 of the SOAP protocol.
2326
2327 \value MustUnderstand
2328 One of the header items in the SOAP message with a
2329 "MustUnderstand" attribute was not recognized by the remote
2330 server.
2331
2332 \value Client
2333 An error in the SOAP message or transport prevents further
2334 processing by the remote SOAP server.
2335
2336 \value Server
2337 An error in the remote SOAP server prevents it from processing the
2338 SOAP message.
2339
2340 \omitvalue Other
2341 */
2342
2343 /*! \enum QtSoapMessage::MessageType
2344
2345 \value Fault
2346 \value MethodRequest
2347 \value MethodResponse
2348 \value OtherType
2349
2350 */
2351
2352 /*!
2353 Constructs an empty QtSoapMessage. The message only contains the
2354 Envelope element, with no header and no body.
2355 */
QtSoapMessage()2356 QtSoapMessage::QtSoapMessage()
2357 : type(OtherType), envelope(QtSoapQName("Envelope", SOAPv11_ENVELOPE))
2358 {
2359 init();
2360 }
2361
2362 /*!
2363 Constructs a copy of \a copy.
2364 */
QtSoapMessage(const QtSoapMessage & copy)2365 QtSoapMessage::QtSoapMessage(const QtSoapMessage ©)
2366 : type(copy.type), envelope(copy.envelope), m(copy.m), margs(copy.margs),
2367 errorStr(copy.errorStr)
2368 {
2369 init();
2370 }
2371
2372 /*!
2373 Destructs a QtSoapMessage.
2374 */
~QtSoapMessage()2375 QtSoapMessage::~QtSoapMessage()
2376 {
2377 }
2378
2379 /*! \internal
2380
2381 Registers the standard SOAP namespaces with prefixes.
2382 */
init()2383 void QtSoapMessage::init()
2384 {
2385 QtSoapNamespaces::instance().registerNamespace("SOAP-ENV", SOAPv11_ENVELOPE);
2386 QtSoapNamespaces::instance().registerNamespace("SOAP-ENC", SOAPv11_ENCODING);
2387 QtSoapNamespaces::instance().registerNamespace("xsi", XML_SCHEMA_INSTANCE);
2388 QtSoapNamespaces::instance().registerNamespace("xsd", XML_SCHEMA);
2389 }
2390
2391 /*!
2392 Clears the content of the SOAP message.
2393 */
clear()2394 void QtSoapMessage::clear()
2395 {
2396 type = OtherType;
2397 envelope.clear();
2398 m = QtSoapQName();
2399 margs.clear();
2400 errorStr = "Unknown error";
2401 }
2402
2403 /*!
2404 Makes this message a copy of \a copy.
2405 */
operator =(const QtSoapMessage & copy)2406 QtSoapMessage &QtSoapMessage::operator =(const QtSoapMessage ©)
2407 {
2408 envelope = copy.envelope;
2409 m = copy.m;
2410 margs = copy.margs;
2411 errorStr = copy.errorStr;
2412 return *this;
2413 }
2414
2415 /*!
2416 Imports the QDomDocument \a d if it validates as a SOAP
2417 message. Any existing message content is replaced.
2418
2419 If the import fails, this message becomes a Fault message.
2420
2421 Returns true if the import succeeds, otherwise false.
2422 */
setContent(QDomDocument & d)2423 bool QtSoapMessage::setContent(QDomDocument &d)
2424 {
2425 if (isValidSoapMessage(d)) {
2426 clear();
2427 QDomNode node = d.firstChild();
2428 if (!node.isElement())
2429 node = node.nextSibling();
2430
2431 if (envelope.parse(node))
2432 return true;
2433 }
2434
2435 return false;
2436 }
2437
2438 /*!
2439 \overload
2440
2441 Parses the XML document in \a buffer. Imports the document if it
2442 validates as a SOAP message. Any existing message content is
2443 replaced.
2444
2445 If the import fails, this message becomes a Fault message.
2446
2447 Returns true if the import succeeds, otherwise false.
2448 */
setContent(const QByteArray & buffer)2449 bool QtSoapMessage::setContent(const QByteArray &buffer)
2450 {
2451 int errorLine, errorColumn;
2452 QString errorMsg;
2453
2454 QDomDocument doc;
2455 if (!doc.setContent(buffer, true, &errorMsg,
2456 &errorLine, &errorColumn)) {
2457 QString s;
2458 s.sprintf("%s at line %i, column %i", errorMsg.toLatin1().constData(),
2459 errorLine, errorColumn);
2460 setFaultCode(VersionMismatch);
2461 setFaultString("XML parse error");
2462 addFaultDetail(new QtSoapSimpleType(QtSoapQName("ParseError"), s));
2463 return false;
2464 }
2465
2466 if (!isValidSoapMessage(doc))
2467 return false;
2468
2469 QDomNode node = doc.firstChild();
2470 if (!node.isElement())
2471 node = node.nextSibling();
2472 bool res = envelope.parse(node);
2473 if (!res)
2474 qDebug("QtSoapMessage::setContent(), parsing failed: %s", envelope.errorString().toLatin1().constData());
2475 return res;
2476 }
2477
2478 /*!
2479 Validates the QDomDocument \a candidate using some simple
2480 heuristics. Returns true if the document is a valid SOAP message;
2481 otherwise returns false.
2482 */
isValidSoapMessage(const QDomDocument & candidate)2483 bool QtSoapMessage::isValidSoapMessage(const QDomDocument &candidate)
2484 {
2485 QDomNode tmp = candidate.firstChild();
2486 if (tmp.isNull())
2487 return false;
2488
2489 // Skip the initial processing instruction if there is one. Most
2490 // likely this isn't actually a processing instruction, but rather
2491 // the initial xml declaration <?xml...
2492 if (tmp.isProcessingInstruction()) {
2493 tmp = tmp.nextSibling();
2494
2495 if (tmp.isNull() || !tmp.isElement())
2496 return false;
2497 }
2498
2499 QDomElement tmpe = tmp.toElement();
2500
2501 if (localName(tmpe.tagName()).toUpper() != "ENVELOPE") {
2502 setFaultCode(VersionMismatch);
2503 setFaultString("SOAP structure invalid");
2504 addFaultDetail(new QtSoapSimpleType(QtSoapQName("extra"), "root element \"" + tmpe.localName()
2505 + "\"/\"" + tmpe.tagName() + "\" is not envelope"));
2506 return false;
2507 }
2508
2509 tmp = tmp.firstChild();
2510 if (tmp.isNull() || !tmp.isElement()) {
2511 setFaultCode(VersionMismatch);
2512 setFaultString("SOAP structure invalid");
2513 addFaultDetail(new QtSoapSimpleType(QtSoapQName("extra"), "mandatory body element missing"));
2514 return false;
2515 }
2516
2517 QDomElement tmpe2 = tmp.toElement();
2518
2519 bool foundHeader = false;
2520 if (localName(tmpe2.tagName()).toUpper() == "HEADER") {
2521 foundHeader = true;
2522 tmp = tmp.nextSibling();
2523 }
2524
2525 if (!foundHeader && (tmp.isNull() || !tmp.isElement())) {
2526 setFaultCode(VersionMismatch);
2527 setFaultString("SOAP structure invalid");
2528 addFaultDetail(new QtSoapSimpleType(QtSoapQName("extra"), "mandatory body element missing"));
2529 return false;
2530 }
2531
2532 QDomElement tmpe3 = tmp.toElement();
2533
2534 if (localName(tmpe3.tagName()).toUpper() != "BODY") {
2535 setFaultCode(VersionMismatch);
2536 setFaultString("SOAP structure invalid");
2537 addFaultDetail(new QtSoapSimpleType(QtSoapQName("extra"), "mandatory body element missing"));
2538 return false;
2539 }
2540
2541 // At this point, check that the version of the envelope is
2542 // correct.
2543 if (tmpe.namespaceURI() != SOAPv11_ENVELOPE) {
2544 setFaultCode(VersionMismatch);
2545 setFaultString("SOAP structure invalid");
2546 addFaultDetail(new QtSoapSimpleType(QtSoapQName("extra"), "Unsupported namespace for envelope element"));
2547 return false;
2548 }
2549
2550 return true;
2551 }
2552
2553 /*!
2554 Returns the XML representation of the SOAP message as a QString,
2555 optionally indenting using \a indent spaces.
2556 */
toXmlString(int indent) const2557 QString QtSoapMessage::toXmlString(int indent) const
2558 {
2559 QDomImplementation impl;
2560 QDomDocument doc = impl.createDocument(QString(), QString("placeholder"),
2561 QDomDocumentType());
2562 doc.removeChild(doc.firstChild());
2563 doc.appendChild(envelope.toDomElement(doc));
2564
2565 QDomElement env = doc.firstChild().toElement();
2566
2567 env.setAttribute(QtSoapNamespaces::instance().prefixFor(SOAPv11_ENVELOPE)
2568 + ":" + "encodingStyle",
2569 SOAPv11_ENCODING);
2570
2571 env.setAttribute("xmlns:" + QtSoapNamespaces::instance().prefixFor(XML_SCHEMA),
2572 XML_SCHEMA);
2573
2574 return doc.toString(indent);
2575 }
2576
2577 /*!
2578 Returns a human readable explanation of the most recent error that
2579 occurred in the QtSoapMessage.
2580 */
errorString() const2581 QString QtSoapMessage::errorString() const
2582 {
2583 return errorStr;
2584 }
2585
2586 /*!
2587 Adds \a item to the body in the SOAP message. The item is added
2588 after the last existing item in the body.
2589 */
addBodyItem(QtSoapType * item)2590 void QtSoapMessage::addBodyItem(QtSoapType *item)
2591 {
2592 body().insert(item);
2593 }
2594
2595 /*!
2596 Adds \a item to the header in the SOAP message. The item is added
2597 after the last existing item in the header.
2598 */
addHeaderItem(QtSoapType * item)2599 void QtSoapMessage::addHeaderItem(QtSoapType *item)
2600 {
2601 QtSoapType &headerTmp = envelope[QtSoapQName("Header", SOAPv11_ENVELOPE)];
2602 if (!headerTmp.isValid())
2603 envelope.insert(new QtSoapStruct(QtSoapQName("Header", SOAPv11_ENVELOPE)));
2604
2605 QtSoapStruct &header = (QtSoapStruct &)envelope[QtSoapQName("Header", SOAPv11_ENVELOPE)];
2606 header.insert(item);
2607 }
2608 /*!
2609 Returns the return value of a SOAP method response as a
2610 QtSoapType.
2611 */
returnValue() const2612 const QtSoapType &QtSoapMessage::returnValue() const
2613 {
2614 static QtSoapType NIL;
2615
2616 const QtSoapType &meth = method();
2617
2618 if (!meth.isValid() || meth.type() != QtSoapType::Struct)
2619 return NIL;
2620
2621 QtSoapStruct &m = (QtSoapStruct &) meth;
2622 if (m.count() == 0)
2623 return NIL;
2624
2625 QtSoapStructIterator mi(m);
2626 return *mi.data();
2627 }
2628
2629 /*!
2630 Returns the Fault detail element of a SOAP Fault message.
2631 */
faultDetail() const2632 const QtSoapType &QtSoapMessage::faultDetail() const
2633 {
2634 return body()[QtSoapQName("Fault", SOAPv11_ENVELOPE)][QtSoapQName("Detail")];
2635 }
2636
2637 /*!
2638 Returns the Fault faultstring element of a SOAP Fault message.
2639 */
faultString() const2640 const QtSoapType &QtSoapMessage::faultString() const
2641 {
2642 return body()[QtSoapQName("Fault", SOAPv11_ENVELOPE)][QtSoapQName("Faultstring")];
2643 }
2644
2645 /*!
2646 Returns true if the message is a SOAP Fault message; otherwise
2647 returns false.
2648 */
isFault() const2649 bool QtSoapMessage::isFault() const
2650 {
2651 return faultCode() != Other;
2652 }
2653
2654 /*!
2655 Returns the Fault faultcode element of a SOAP Fault message.
2656 */
faultCode() const2657 QtSoapMessage::FaultCode QtSoapMessage::faultCode() const
2658 {
2659 QtSoapType &code = body()[QtSoapQName("Fault")][QtSoapQName("Faultcode")];
2660 if (!code.isValid() || (code.type() != QtSoapType::String
2661 && code.type() != QtSoapType::QName))
2662 return Other;
2663
2664 QtSoapSimpleType &fcode = (QtSoapSimpleType &)code;
2665 QString fcodestr = fcode.value().toString();
2666
2667 // Only test string before first .
2668 int pos;
2669 if ((pos = fcodestr.indexOf('.')) != -1)
2670 fcodestr.truncate(pos);
2671
2672 if (localName(fcodestr.toLower()) == "versionmismatch")
2673 return VersionMismatch;
2674
2675 if (localName(fcodestr.toLower()) == "mustunderstand")
2676 return MustUnderstand;
2677
2678 if (localName(fcodestr.toLower()) == "client")
2679 return Client;
2680
2681 if (localName(fcodestr.toLower()) == "server")
2682 return Server;
2683
2684 return Other;
2685 }
2686
2687 /*!
2688 Returns a reference to the body of the SOAP message.
2689 */
body() const2690 QtSoapStruct &QtSoapMessage::body() const
2691 {
2692 const QtSoapQName bodyName("Body", SOAPv11_ENVELOPE);
2693
2694 QtSoapType &bodyTmp = envelope[bodyName];
2695 if (!bodyTmp.isValid())
2696 envelope.insert(new QtSoapStruct(bodyName));
2697
2698 return (QtSoapStruct &)envelope[bodyName];
2699 }
2700
2701 /*!
2702 Returns a reference to the header of the SOAP message.
2703 */
header() const2704 QtSoapStruct &QtSoapMessage::header() const
2705 {
2706 const QtSoapQName headerName("Header", SOAPv11_ENVELOPE);
2707
2708 QtSoapType &headerTmp = envelope[headerName];
2709 if (!headerTmp.isValid())
2710 envelope.insert(new QtSoapStruct(headerName));
2711
2712 return (QtSoapStruct &)envelope[headerName];
2713 }
2714
2715 /*!
2716 Sets the fault code of the SOAP Fault message to \a code.
2717 */
setFaultCode(FaultCode code)2718 void QtSoapMessage::setFaultCode(FaultCode code)
2719 {
2720 if (type != Fault && type != OtherType) {
2721 clear();
2722 type = Fault;
2723 }
2724
2725 if (!body()[QtSoapQName("Fault", SOAPv11_ENVELOPE)].isValid())
2726 addBodyItem(new QtSoapStruct(QtSoapQName("Fault", SOAPv11_ENVELOPE)));
2727
2728 QString codeStr;
2729 switch (code) {
2730 case VersionMismatch:
2731 codeStr = "SOAP-ENV:VersionMismatch";
2732 break;
2733 case MustUnderstand:
2734 codeStr = "SOAP-ENV:MustUnderstand";
2735 break;
2736 case Client:
2737 codeStr = "SOAP-ENV:Client";
2738 break;
2739 case Server:
2740 codeStr = "SOAP-ENV:Server";
2741 break;
2742 case Other:
2743 codeStr = "Other";
2744 break;
2745 }
2746
2747 QtSoapType &node = body()[QtSoapQName("Fault", SOAPv11_ENVELOPE)];
2748 QtSoapStruct &fault = reinterpret_cast<QtSoapStruct &>(node);
2749 fault.insert(new QtSoapSimpleType(QtSoapQName("Faultcode"), codeStr));
2750 }
2751
2752 /*!
2753 Sets the Fault faultstring of the SOAP Fault message to \a s.
2754 */
setFaultString(const QString & s)2755 void QtSoapMessage::setFaultString(const QString &s)
2756 {
2757 if (type != Fault && type != OtherType) {
2758 clear();
2759 type = Fault;
2760 }
2761
2762 if (!body()[QtSoapQName("Fault", SOAPv11_ENVELOPE)].isValid())
2763 addBodyItem(new QtSoapStruct(QtSoapQName("Fault", SOAPv11_ENVELOPE)));
2764
2765 QtSoapType &node = body()[QtSoapQName("Fault", SOAPv11_ENVELOPE)];
2766 QtSoapStruct &fault = reinterpret_cast<QtSoapStruct &>(node);
2767 fault.insert(new QtSoapSimpleType(QtSoapQName("Faultstring"), s));
2768 }
2769
2770 /*!
2771 Adds the QtSoapType \a detail to the end of the list of faultdetail
2772 items in a SOAP Fault message.
2773 */
addFaultDetail(QtSoapType * detail)2774 void QtSoapMessage::addFaultDetail(QtSoapType *detail)
2775 {
2776 if (type != Fault && type != OtherType) {
2777 clear();
2778 type = Fault;
2779 }
2780
2781 if (!body()[QtSoapQName("Fault", SOAPv11_ENVELOPE)].isValid())
2782 addBodyItem(new QtSoapStruct(QtSoapQName("Fault", SOAPv11_ENVELOPE)));
2783
2784 QtSoapType &node = body()[QtSoapQName("Fault", SOAPv11_ENVELOPE)];
2785 QtSoapStruct &fault = reinterpret_cast<QtSoapStruct &>(node);
2786 if (!fault[QtSoapQName("Faultdetail", SOAPv11_ENVELOPE)].isValid())
2787 fault.insert(new QtSoapStruct(QtSoapQName("Faultdetail", SOAPv11_ENVELOPE)));
2788
2789 QtSoapType &node2 = fault[QtSoapQName("Faultdetail", SOAPv11_ENVELOPE)];
2790 QtSoapStruct &fdetail = reinterpret_cast<QtSoapStruct &>(node2);
2791
2792 fdetail.insert(detail);
2793 }
2794
2795 /*!
2796 Returns the method of a SOAP method request or response
2797 as a QtSoapType.
2798 */
method() const2799 const QtSoapType &QtSoapMessage::method() const
2800 {
2801 static QtSoapType NIL;
2802
2803 if (body().count() == 0)
2804 return NIL;
2805
2806 QtSoapStructIterator it(body());
2807
2808 return *it.data();
2809 }
2810
2811 /*!
2812 Sets the QName (qualified name) of the method to call in a SOAP
2813 method request to \a meth.
2814
2815 This function \e must be called before calling
2816 addMethodArgument().
2817 */
setMethod(const QtSoapQName & meth)2818 void QtSoapMessage::setMethod(const QtSoapQName &meth)
2819 {
2820 if (type != MethodRequest && type != OtherType) {
2821 clear();
2822 type = MethodRequest;
2823 }
2824
2825 addBodyItem(new QtSoapStruct(meth));
2826 }
2827
2828 /*! \overload
2829
2830 Sets the method name to \a name and uri to \a uri.
2831 */
setMethod(const QString & name,const QString & uri)2832 void QtSoapMessage::setMethod(const QString &name, const QString &uri)
2833 {
2834 setMethod(QtSoapQName(name, uri));
2835 }
2836
2837 /*!
2838 Adds argument \a arg to the list of arguments that are passed in a
2839 SOAP method request.
2840
2841 \warning setMethod() must be called before calling this function.
2842 */
addMethodArgument(QtSoapType * arg)2843 void QtSoapMessage::addMethodArgument(QtSoapType *arg)
2844 {
2845 if (body().count() == 0) {
2846 qWarning("Attempted to add argument (%s:%s) without first setting method",
2847 arg->name().uri().toLatin1().constData(), arg->name().name().toLatin1().constData());
2848 return;
2849 }
2850
2851 QtSoapStructIterator it(body());
2852 QtSoapType &node = *it.data();
2853 QtSoapStruct &meth = static_cast<QtSoapStruct &>(node);
2854 meth.insert(arg);
2855 }
2856
2857 /*! \overload
2858
2859 Adds an argument called \a name with a uri of \a uri. The type
2860 of the argument is QtSoapType::String and its value is \a value.
2861 */
addMethodArgument(const QString & name,const QString & uri,const QString & value)2862 void QtSoapMessage::addMethodArgument(const QString &name, const QString &uri, const QString &value)
2863 {
2864 addMethodArgument(new QtSoapSimpleType(QtSoapQName(name, uri), value));
2865 }
2866
2867 /*! \overload
2868
2869 Adds an argument called \a name with a uri of \a uri. The type
2870 of the argument is QtSoapType::Boolean and its value is \a value.
2871
2872 The \a dummy argument is used to distinguish this function from
2873 the overload which takes an int.
2874 */
addMethodArgument(const QString & name,const QString & uri,bool value,int dummy)2875 void QtSoapMessage::addMethodArgument(const QString &name, const QString &uri, bool value, int dummy)
2876 {
2877 addMethodArgument(new QtSoapSimpleType(QtSoapQName(name, uri), value, dummy));
2878 }
2879
2880 /*! \overload
2881
2882 Adds an argument called \a name with a uri of \a uri. The type
2883 of the argument is QtSoapType::Integer and its value is \a value.
2884 */
addMethodArgument(const QString & name,const QString & uri,int value)2885 void QtSoapMessage::addMethodArgument(const QString &name, const QString &uri, int value)
2886 {
2887 addMethodArgument(new QtSoapSimpleType(QtSoapQName(name, uri), value));
2888 }
2889
2890 /*!
2891 Constructs a QtSoapTypeFactory and initializes it with all the
2892 known SOAP types.
2893 */
QtSoapTypeFactory()2894 QtSoapTypeFactory::QtSoapTypeFactory()
2895 {
2896 QtSoapTypeConstructor<QtSoapStruct> *structConstructor = new QtSoapTypeConstructor<QtSoapStruct>();
2897 deleteList.append(structConstructor);
2898 QtSoapTypeConstructor<QtSoapArray> *arrayConstructor = new QtSoapTypeConstructor<QtSoapArray>();
2899 deleteList.append(arrayConstructor);
2900 QtSoapTypeConstructor<QtSoapSimpleType> *basicTypeConstructor = new QtSoapTypeConstructor<QtSoapSimpleType>();
2901 deleteList.append(basicTypeConstructor);
2902
2903 registerHandler("struct", structConstructor);
2904 registerHandler("array", arrayConstructor);
2905 registerHandler("string", basicTypeConstructor);
2906 registerHandler("normalizedstring", basicTypeConstructor);
2907 registerHandler("token", basicTypeConstructor);
2908 registerHandler("language", basicTypeConstructor);
2909 registerHandler("name", basicTypeConstructor);
2910 registerHandler("ncname", basicTypeConstructor);
2911 registerHandler("id", basicTypeConstructor);
2912 registerHandler("idref", basicTypeConstructor);
2913 registerHandler("entity", basicTypeConstructor);
2914 registerHandler("nmtoken", basicTypeConstructor);
2915 registerHandler("nmtokens", basicTypeConstructor);
2916 registerHandler("boolean", basicTypeConstructor);
2917 registerHandler("decimal", basicTypeConstructor);
2918 registerHandler("integer", basicTypeConstructor);
2919 registerHandler("nonpositiveinteger", basicTypeConstructor);
2920 registerHandler("negativeinteger", basicTypeConstructor);
2921 registerHandler("int", basicTypeConstructor);
2922 registerHandler("long", basicTypeConstructor);
2923 registerHandler("short", basicTypeConstructor);
2924 registerHandler("byte", basicTypeConstructor);
2925 registerHandler("nonnegativeinteger", basicTypeConstructor);
2926 registerHandler("unsignedlong", basicTypeConstructor);
2927 registerHandler("unsignedint", basicTypeConstructor);
2928 registerHandler("unsignedshort", basicTypeConstructor);
2929 registerHandler("unsignedbyte", basicTypeConstructor);
2930 registerHandler("positiveinteger", basicTypeConstructor);
2931 registerHandler("float", basicTypeConstructor);
2932 registerHandler("double", basicTypeConstructor);
2933 registerHandler("other", structConstructor);
2934 }
2935
2936 /*!
2937 Destructs the QtSoapTypeFactory. This destructor is called when
2938 the application exits.
2939 */
~QtSoapTypeFactory()2940 QtSoapTypeFactory::~QtSoapTypeFactory()
2941 {
2942 QLinkedList<QtSoapTypeConstructorBase*>::ConstIterator it = deleteList.begin();
2943 while (it != deleteList.end()) {
2944 delete *it;
2945 ++it;
2946 }
2947 }
2948
2949 /*!
2950 Returns a reference to the QtSoapTypeFactory singleton.
2951 */
instance()2952 QtSoapTypeFactory &QtSoapTypeFactory::instance()
2953 {
2954 static QtSoapTypeFactory factory;
2955 return factory;
2956 }
2957
2958 /*!
2959 Registers a handler \a handler for a QtSoapType called \a name.
2960 */
registerHandler(const QString & name,QtSoapTypeConstructorBase * handler)2961 bool QtSoapTypeFactory::registerHandler(const QString &name, QtSoapTypeConstructorBase *handler)
2962 {
2963 if (typeHandlers.find(name) != typeHandlers.end()) {
2964 errorStr = "A handler for " + name + " is already registered.";
2965 return false;
2966 }
2967
2968 typeHandlers.insert(name, handler);
2969 return true;
2970 }
2971
2972 /*! \internal
2973 */
soapType(QDomNode node) const2974 QtSmartPtr<QtSoapType> QtSoapTypeFactory::soapType(QDomNode node) const
2975 {
2976 if (node.isNull() || !node.isElement())
2977 return QtSmartPtr<QtSoapType>();
2978
2979 QDomElement elem = node.toElement();
2980
2981 QDomAttr attr = elem.attributeNode("type");
2982 QtSoapTypeConstructorBase *constructor = 0;
2983 if (!attr.isNull()) {
2984 QHash<QString, QtSoapTypeConstructorBase *>::ConstIterator it;
2985 it = typeHandlers.find(localName(attr.value().toLower()));
2986 if (it != typeHandlers.end())
2987 constructor = *it;
2988 }
2989
2990 if (attr.isNull() || !constructor) {
2991 QHash<QString, QtSoapTypeConstructorBase *>::ConstIterator it;
2992 if (node.firstChild().isElement()) {
2993 if (localName(node.nodeName().toLower()) == "array") {
2994 it = typeHandlers.find("array");
2995 } else
2996 it = typeHandlers.find("struct");
2997 } else
2998 it = typeHandlers.find("string");
2999 if (it != typeHandlers.end())
3000 constructor = *it;
3001 }
3002
3003 if (!constructor) {
3004 return QtSmartPtr<QtSoapType>();
3005 }
3006
3007 QtSoapType *type = constructor->createObject(node);
3008
3009 if (!type)
3010 errorStr = constructor->errorString();
3011
3012 return QtSmartPtr<QtSoapType>(type);
3013 }
3014
3015 /*!
3016 Returns a human readable interpretation of the last error
3017 that occurred.
3018 */
errorString() const3019 QString QtSoapTypeFactory::errorString() const
3020 {
3021 return errorStr;
3022 }
3023
3024 /*! \class QtSoapHttpTransport
3025
3026 \brief The QtSoapHttpTransport class provides a mechanism for
3027 transporting SOAP messages to and from other hosts using the
3028 HTTP protocol.
3029
3030 Use this class to submit SOAP messages to a web service.
3031 Set the hostname of the SOAP server with setHost(). Some servers
3032 also require the SOAPAction header to be set, and you can do this
3033 with setAction(). Next, submit the request with submitRequest(),
3034 passing the message to submit together with the path that you want
3035 to submit the message to. The responseReady() signal is emitted
3036 when a response has been received. Call getResponse() to get the
3037 reponse from the service.
3038
3039 QtSoapHttpTransport usage example: If a SOAP weather service was
3040 running on the host weather.example.com, the following code might
3041 be used to find the temperature in any given city:
3042
3043 \code
3044 void WeatherFetcher::findTemperature(const QString &city)
3045 {
3046 QtSoapMessage message;
3047 message.setMethod("getTemperature", "http://weather.example.com/temperature");
3048 message.setMethodArgument("city", "", city);
3049
3050 // transport is a private member of WeatherFetcher, of type QtSoapHttpTransport
3051 transport.setHost("www.example.com");
3052 connect(&transport, SIGNAL(responseReady()), SLOT(readResponse()));
3053
3054 transport.submitRequest(message, "/weatherfetcher/fetch.asp");
3055 }
3056 \endcode
3057
3058 This is an example implementation of the readResponse() slot in
3059 the WeatherFetcher class:
3060
3061 \code
3062 void WeatherFetcher::readResponse()
3063 {
3064 const QtSoapMessage &response = transport.getResponse();
3065 if (response.isFault()) {
3066 cout << response.faultString().toString().toLatin1().constData() << endl;
3067 return;
3068 }
3069
3070 const QtSoapType &returnValue = response.returnValue();
3071 if (returnValue["temperature"].isValid()) {
3072 cout << "The current temperature is "
3073 << returnValue["temperature"].toString().toLatin1().constData()
3074 << " degrees Celcius." << endl;
3075 }
3076 \endcode
3077
3078 \sa QtSoapMessage, QtSoapType
3079 */
3080
3081 /*! \fn void QtSoapHttpTransport::responseReady()
3082
3083 This signal is emitted when a SOAP response is received from a
3084 remote peer.
3085
3086 \sa getResponse()
3087 */
3088
3089 /*! \fn void QtSoapHttpTransport::responseReady(const QtSoapMessage &response)
3090
3091 This signal is emitted when a SOAP response is received from a
3092 remote peer. The received response is available in \a
3093 response. This signal is emitted in tandem with the argument-less
3094 responseReady() signal.
3095
3096 \sa responseReady()
3097 */
3098
3099 /*!
3100 Constructs a QtSoapHttpTransport object. Passes \a parent to
3101 QObject's constructor.
3102 */
3103
QtSoapHttpTransport(QObject * parent)3104 QtSoapHttpTransport::QtSoapHttpTransport(QObject *parent)
3105 : QObject(parent), networkMgr(this)
3106 {
3107 connect(&networkMgr, SIGNAL(finished(QNetworkReply *)),
3108 SLOT(readResponse(QNetworkReply *)));
3109 }
3110
3111 /*!
3112 Destructs a QtSoapHttpTransport.
3113 */
~QtSoapHttpTransport()3114 QtSoapHttpTransport::~QtSoapHttpTransport()
3115 {
3116 }
3117
3118 /*!
3119 \obsolete
3120 */
3121
setHost(const QString & host,int port)3122 void QtSoapHttpTransport::setHost(const QString &host, int port)
3123 {
3124 setHost(host, false, port);
3125 }
3126
3127 /*!
3128 Sets the \a host this transport should connect to. The transport
3129 mode will be HTTP, unless \a useSecureHTTP is set, in which case it
3130 will be HTTPS. This transport will connect to the well-known ports
3131 by default (80 for HTTP, 443 for HTTPS), unless a different,
3132 non-zero port is specified in \a port.
3133 */
setHost(const QString & host,bool useSecureHTTP,int port)3134 void QtSoapHttpTransport::setHost(const QString &host, bool useSecureHTTP, int port)
3135 {
3136 url.setHost(host);
3137 url.setScheme(useSecureHTTP ? QLatin1String("https") : QLatin1String("http"));
3138 if (port)
3139 url.setPort(port);
3140 else
3141 url.setPort(useSecureHTTP ? 443 : 80);
3142 }
3143
3144 /*!
3145 Sets the HTTP header SOAPAction to \a action.
3146 */
setAction(const QString & action)3147 void QtSoapHttpTransport::setAction(const QString &action)
3148 {
3149 soapAction = action;
3150 }
3151
3152 /*!
3153 Submits the SOAP message \a request to the path \a path on the
3154 HTTP server set using setHost().
3155 */
submitRequest(QtSoapMessage & request,const QString & path)3156 void QtSoapHttpTransport::submitRequest(QtSoapMessage &request, const QString &path)
3157 {
3158 QNetworkRequest networkReq;
3159 networkReq.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("text/xml;charset=utf-8"));
3160 networkReq.setRawHeader("SOAPAction", soapAction.toUtf8().data());
3161 url.setPath(path);
3162 networkReq.setUrl(url);
3163
3164 soapResponse.clear();
3165 networkRep = networkMgr.post(networkReq, request.toXmlString().toUtf8().constData());
3166 }
3167
3168
3169 /*!
3170 Returns the most recently received response SOAP message. This
3171 message could be a Fault message, so it is wise to check using
3172 QtSoapMessage::isFault() before processing the response.
3173 */
getResponse() const3174 const QtSoapMessage &QtSoapHttpTransport::getResponse() const
3175 {
3176 return soapResponse;
3177 }
3178
3179
3180 /*!
3181 Returns a pointer to the QNetworkAccessManager object used by this
3182 transport. This is useful if the application needs to connect to its
3183 signals, or set or read its cookie jar, etc.
3184 */
3185
networkAccessManager()3186 QNetworkAccessManager *QtSoapHttpTransport::networkAccessManager()
3187 {
3188 return &networkMgr;
3189 }
3190
3191
3192 /*!
3193 Returns a pointer to the QNetworkReply object of the current (or last)
3194 request, or 0 if no such object is currently available.
3195
3196 This is useful if the application needs to access the raw header
3197 data etc.
3198 */
3199
networkReply()3200 QNetworkReply *QtSoapHttpTransport::networkReply()
3201 {
3202 return networkRep;
3203 }
3204
3205 /*!
3206
3207 */
3208
readResponse(QNetworkReply * reply)3209 void QtSoapHttpTransport::readResponse(QNetworkReply *reply)
3210 {
3211 networkRep = reply;
3212 switch (reply->error()) {
3213 case QNetworkReply::NoError:
3214 case QNetworkReply::ContentAccessDenied:
3215 case QNetworkReply::ContentOperationNotPermittedError:
3216 case QNetworkReply::ContentNotFoundError:
3217 case QNetworkReply::UnknownContentError:
3218 {
3219 soapResponse.setContent(reply->readAll());
3220
3221 int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
3222 if (httpStatus != 200 && httpStatus != 100) {
3223 if (soapResponse.faultCode() == QtSoapMessage::Other)
3224 soapResponse.setFaultCode(QtSoapMessage::Client);
3225 /*
3226 QString httpReason = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
3227 soapResponse.setFaultString(QString("HTTP status %2 (%3).\n%1").arg(soapResponse.faultString().toString()).arg(httpStatus).arg(httpReason));
3228 */
3229 }
3230 }
3231 break;
3232 default:
3233 {
3234 soapResponse.setFaultCode(QtSoapMessage::Client);
3235 soapResponse.setFaultString(QString("Network transport error (%1): %2").arg(reply->error()).arg(reply->errorString()));
3236 }
3237 break;
3238 }
3239
3240 emit responseReady();
3241 emit responseReady(soapResponse);
3242
3243 reply->deleteLater();
3244 }
3245
3246 /*! \class QtSoapNamespaces qtsoap.h
3247
3248 \brief The QtSoapNamespaces class provides a registry for XML
3249 namespaces and prefixes for use in QtSoap.
3250
3251 When a QtSoapMessage is converted to XML via
3252 QtSoapMessage::toXmlString(), this class is used to find
3253 appropriate XML namespace prefixes for the QNames (qualified
3254 names) in the message.
3255
3256 To register a namespace with a prefix, call register().
3257 prefixFor() will then return the prefix that is registered for the
3258 given namespace, if any.
3259
3260 To access the QtSoapNamespaces registry, call
3261 QtSoapNamespaces::instance().
3262
3263 \code
3264 QtSoapNamespaces ®istry = QtSoapNamespaces::instance();
3265
3266 registry.register("pre", "http://www.example.com/");
3267 QString prefix = registry.prefixFor("http://www.example.com/"); // returns "pre"
3268 \endcode
3269
3270 \sa QtSoapMessage
3271 */
3272
3273 /*!
3274 Returns a reference to the QtSoapNamespaces singleton.
3275 */
instance()3276 QtSoapNamespaces &QtSoapNamespaces::instance()
3277 {
3278 static QtSoapNamespaces ns;
3279 return ns;
3280 }
3281
3282 /*! \internal
3283
3284 Constructs a QtSoapNamespaces object.
3285 */
QtSoapNamespaces()3286 QtSoapNamespaces::QtSoapNamespaces()
3287 {
3288 }
3289
3290 /*!
3291 Registers the namespace \a uri with the prefix \a prefix.
3292 */
registerNamespace(const QString & prefix,const QString & uri)3293 void QtSoapNamespaces::registerNamespace(const QString &prefix, const QString &uri)
3294 {
3295 namespaces.insert(uri, prefix);
3296 }
3297
3298 /*!
3299 Returns the prefix for the namespace \a uri, or an empty string if
3300 no prefix has been registered for \a uri.
3301 */
prefixFor(const QString & uri)3302 QString QtSoapNamespaces::prefixFor(const QString &uri)
3303 {
3304 return namespaces.value(uri);
3305 }
3306