1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
#ifndef PACKET_H
#define PACKET_H
#include <QXmlStreamWriter>
#include <QVariant>
#include <QDomElement>
#include <QList>
/**
* Packets are serialized QVariants that map to XMLRPC types.
* @li int -> int
* @li double -> double,float
* @li string -> QString, QCString, char *, QColor, QFont
* @li datetime.iso8601 -> QDateTime, QTime, QDate
* @li array -> QList<QVariant>, QStringList
* @li struct -> QMap<QVariant>
* @li base64 -> QByteArray
*
* An example of how to use the XML Packets is as follows:
* @code
* QList<QVariant> args;
* args << m_db << m_username << m_password << dbQuery;
* RequestMessage msg( "data.query", args );
* ResponseMessage resp( SomeHttpDispatchObject( msg.xml() ) );
* if( resp.isValid() )
* {
* int rows = resp.value().toMap()["widgets"].toInt();
* }
* else
* qWarning("Error: %s", resp.error().latin1() );
* @endcode
* This example will construct invoke the data.query() method on the XMLRPC
* interface with the args. It will then check for the response to see if
* it was valid. If its valid the message contains a struct of values, one of
* which is "widgets" that is an integer. The struct is converted to a QVariant
* map and we can convert it as such from the QVariant. We can then get the
* QVariant for the "widgets" value and convert that to an integer. If there was
* an error, the packet is marked invalid and will have an error message in it. The
* error() message will return this message. The struct in the value will be a valid
* error structure so it can be dealt with accordingly.
*/
namespace XMLRPC
{
/**
* Base utility methods for working with XMLRPC messages.
@author Ian Reinhart Geiser <geiseri@kde.org>
*/
class MessageBase
{
public:
MessageBase();
virtual ~MessageBase();
/**
* Returns a human readable error that was recived from the server.
*/
QString error() const;
/**
* Sets the human readable error message.
*/
virtual void setError( const QString &message ) const;
/**
* Returns if the current message is valid.
*/
bool isValid() const;
protected:
virtual void marshall( QXmlStreamWriter *writer, const QVariant &val ) const;
virtual QVariant demarshall( const QDomElement &elem ) const;
private:
mutable QString m_message;
mutable bool m_valid;
};
/**
* Creates an XMLRPC message that will call a method with a series of
* QVariants that will be converted to XMLRPC types.
@author Ian Reinhart Geiser <geiseri@kde.org>
*/
class RequestMessage : public MessageBase
{
public:
RequestMessage( const QDomElement &element );
/**
* Creates an RequestMessage from an XML packet.
*/
RequestMessage( const QByteArray &xml );
/**
* Creates a method packet that will call method with a list of args.
*/
RequestMessage( const QByteArray &method, const QList<QVariant> &args );
/**
* Convinence ctor that creates a packet for a method with a single
* argument.
*/
RequestMessage( const QByteArray &method, const QVariant &arg );
virtual ~RequestMessage() {;}
/**
* Return the xml representation of the packet.
*/
QByteArray xml() const;
void writeXml( QXmlStreamWriter *writer ) const;
QByteArray method() const;
QList< QVariant > args() const;
private:
QByteArray m_method;
QList<QVariant> m_args;
};
/**
* Decodes an XMLRPC message from a server into a set of QVariants.
@author Ian Reinhart Geiser <geiseri@kde.org>
*/
class ResponseMessage : public MessageBase
{
public:
/**
* Create a new recive packet with an xml packet
*/
ResponseMessage( const QDomElement &element );
/**
* Create a new recive packet with an xml packet
*/
ResponseMessage( const QByteArray &xml );
/**
* Create a new response message with data.
*/
ResponseMessage( const QList< QVariant >& theValue );
/**
* Create a new response message with data. This is exactly like
* the above method save for it only takes a single QVariant.
*/
explicit ResponseMessage( const QVariant& theValue );
virtual ~ResponseMessage() {;}
/**
* Returns the number of data elements. Usually this is only
* 1 element, but some services will return mutiple messages in
* a single xmlrpc packet.
*/
int count() const;
/**
* Returns the native value for an xmlrpc message at an offset.
* Usually this method can be called with no arguments.
*/
QVariant value( int idx = 0 ) const;
/**
* Return the xml representation of the packet.
*/
virtual QByteArray xml() const;
void writeXml( QXmlStreamWriter *writer ) const;
QList< QVariant > values() const;
protected:
void setValues( const QList<QVariant> va2ls);
private:
QList<QVariant> m_values;
};
class FaultMessage : public ResponseMessage
{
public:
FaultMessage( int code, const QString &message );
QByteArray xml() const;
void writeXml( QXmlStreamWriter *writer ) const;
};
}
#endif
|