2
* libMaia - maiaObject.cpp
3
* Copyright (c) 2003 Frerich Raabe <raabe@kde.org> and
4
* Ian Reinhart Geiser <geiseri@kde.org>
5
* Copyright (c) 2007 Sebastian Wiedenroth <wiedi@frubar.net>
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
#include "maiaObject.h"
31
MaiaObject::MaiaObject(QObject* parent) : QObject(parent){
32
QDomImplementation::setInvalidDataPolicy(QDomImplementation::DropInvalidChars);
35
QDomElement MaiaObject::toXml(QVariant arg) {
39
//value element, we need this in each case
40
QDomElement tagValue = doc.createElement("value");
42
/* qDebug("type: %d (%s)", arg.type(), arg.typeName()); */
45
case QVariant::String: {
47
QDomElement tagString = doc.createElement("string");
48
QDomText textString = doc.createTextNode(arg.toString());
50
tagValue.appendChild(tagString);
51
tagString.appendChild(textString);
55
} case QVariant::Int: {
57
QDomElement tagInt = doc.createElement("int");
58
QDomText textInt = doc.createTextNode(QString::number(arg.toInt()));
60
tagValue.appendChild(tagInt);
61
tagInt.appendChild(textInt);
65
} case QVariant::Double: {
67
QDomElement tagDouble = doc.createElement("double");
68
QDomText textDouble = doc.createTextNode(QString::number(arg.toDouble()));
70
tagValue.appendChild(tagDouble);
71
tagDouble.appendChild(textDouble);
75
} case QVariant::Bool: {
77
QString textValue = arg.toBool() ? "1" : "0";
79
QDomElement tag = doc.createElement("boolean");
80
QDomText text = doc.createTextNode(textValue);
82
tagValue.appendChild(tag);
83
tag.appendChild(text);
87
} case QVariant::ByteArray: {
89
QString textValue = arg.toByteArray().toBase64();
91
QDomElement tag = doc.createElement("base64");
92
QDomText text = doc.createTextNode(textValue);
94
tagValue.appendChild(tag);
95
tag.appendChild(text);
99
} case QVariant::DateTime: {
101
QString textValue = arg.toDateTime().toString("yyyyMMddThh:mm:ss");
103
QDomElement tag = doc.createElement("datetime.iso8601");
104
QDomText text = doc.createTextNode(textValue);
106
tagValue.appendChild(tag);
107
tag.appendChild(text);
111
} case QVariant::List: {
113
QDomElement tagArray = doc.createElement("array");
114
QDomElement tagData = doc.createElement("data");
115
tagArray.appendChild(tagData);
116
tagValue.appendChild(tagArray);
118
const QList<QVariant> args = arg.toList();
119
for(int i = 0; i < args.size(); ++i) {
120
tagData.appendChild(toXml(args.at(i)));
125
} case QVariant::Map: {
127
QDomElement tagStruct = doc.createElement("struct");
131
tagValue.appendChild(tagStruct);
133
QMap<QString, QVariant> map = arg.toMap();
134
QMapIterator<QString, QVariant> i(map);
138
member = doc.createElement("member");
139
name = doc.createElement("name");
141
// (key) -> name -> member -> struct
142
tagStruct.appendChild(member);
143
member.appendChild(name);
144
name.appendChild(doc.createTextNode(i.key()));
146
// add variables by recursion
147
member.appendChild(toXml(i.value()));
153
qDebug() << "Failed to marshal unknown variant type: " << arg.type() << endl;
155
return QDomElement(); //QString::null;
158
QVariant MaiaObject::fromXml(const QDomElement &elem) {
159
if(elem.tagName().toLower() != "value") {
163
// If no type is indicated, the type is string.
164
if(!elem.firstChild().isElement()) {
165
return QVariant(elem.text());
168
const QDomElement typeElement = elem.firstChild().toElement();
169
const QString typeName = typeElement.tagName().toLower();
171
if(typeName == "string")
172
return QVariant(typeElement.text());
173
else if(typeName == "i4" || typeName == "int")
174
return QVariant(typeElement.text().toInt());
175
else if(typeName == "double")
176
return QVariant(typeElement.text().toDouble());
177
else if (typeName == "boolean") {
178
if(typeElement.text().toLower() == "true" || typeElement.text() == "1")
179
return QVariant(true);
181
return QVariant(false);
182
} else if(typeName == "base64")
183
return QVariant(QByteArray::fromBase64( typeElement.text().toLatin1()));
184
else if(typeName == "datetime" || typeName == "datetime.iso8601")
185
return QVariant(QDateTime::fromString(typeElement.text(), "yyyyMMddThh:mm:ss"));
186
else if(typeName == "nil") // Non-standard extension: http://ontosys.com/xml-rpc/extensions.php
188
else if ( typeName == "array" ) {
189
QList<QVariant> values;
190
QDomNode valueNode = typeElement.firstChild().firstChild();
191
while(!valueNode.isNull()) {
192
values << fromXml(valueNode.toElement());
193
valueNode = valueNode.nextSibling();
195
return QVariant(values);
197
else if ( typeName == "struct" ) {
198
QMap<QString, QVariant> map;
199
QDomNode memberNode = typeElement.firstChild();
200
while(!memberNode.isNull()) {
201
const QString key = memberNode.toElement().elementsByTagName("name").item(0).toElement().text();
202
const QVariant data = fromXml(memberNode.toElement().elementsByTagName("value").item(0).toElement());
204
memberNode = memberNode.nextSibling();
206
return QVariant(map);
208
qDebug() << "Cannot demarshal unknown type " << typeElement.tagName().toLower();
214
QString MaiaObject::prepareCall(QString method, QList<QVariant> args) {
219
QDomProcessingInstruction header = doc.createProcessingInstruction( "xml", QString("version=\"1.0\" encoding=\"UTF-8\"" ));
220
doc.appendChild(header);
222
QDomElement methodCall = doc.createElement("methodCall");
223
QDomElement methodName = doc.createElement("methodName");
224
QDomElement params = doc.createElement("params");
227
doc.appendChild(methodCall);
228
methodCall.appendChild(methodName);
229
methodName.appendChild(doc.createTextNode(method));
231
methodCall.appendChild(params);
233
for(int i = 0; i < args.size(); ++i) {
234
param = doc.createElement("param");
235
param.appendChild(toXml(args.at(i)));
236
params.appendChild(param);
239
return doc.toString();
242
QString MaiaObject::prepareResponse(QVariant arg) {
246
QDomProcessingInstruction header = doc.createProcessingInstruction( "xml", QString("version=\"1.0\" encoding=\"UTF-8\"" ));
247
doc.appendChild(header);
249
QDomElement methodResponse = doc.createElement("methodResponse");
250
QDomElement params = doc.createElement("params");
253
doc.appendChild(methodResponse);
255
methodResponse.appendChild(params);
258
param = doc.createElement("param");
259
param.appendChild(toXml(arg));
260
params.appendChild(param);
262
return doc.toString();
265
void MaiaObject::parseResponse(QString response, QNetworkReply* reply) {
271
if(!doc.setContent(response, &errorMsg, &errorLine, &errorColumn)) {
272
emit fault(-32700, QString("parse error: response not well formed at line %1: %2").arg(errorLine).arg(errorMsg), reply);
276
if(doc.documentElement().firstChild().toElement().tagName().toLower() == "params") {
277
QDomNode paramNode = doc.documentElement().firstChild().firstChild();
278
if(!paramNode.isNull()) {
279
arg = fromXml( paramNode.firstChild().toElement() );
281
emit aresponse(arg, reply);
282
} else if(doc.documentElement().firstChild().toElement().tagName().toLower() == "fault") {
283
const QVariant errorVariant = fromXml(doc.documentElement().firstChild().firstChild().toElement());
284
emit fault(errorVariant.toMap() [ "faultCode" ].toInt(),
285
errorVariant.toMap() [ "faultString" ].toString(),
289
"parse error: invalid xml-rpc. not conforming to spec.",
296
#include "moc_maiaObject.cpp"