1 /*=============================================================================
2
3 Library: XNAT/Core
4
5 Copyright (c) University College London,
6 Centre for Medical Image Computing
7
8 Licensed under the Apache License, Version 2.0 (the "License");
9 you may not use this file except in compliance with the License.
10 You may obtain a copy of the License at
11
12 http://www.apache.org/licenses/LICENSE-2.0
13
14 Unless required by applicable law or agreed to in writing, software
15 distributed under the License is distributed on an "AS IS" BASIS,
16 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 See the License for the specific language governing permissions and
18 limitations under the License.
19
20 =============================================================================*/
21
22 // ctkXnatAPI includes
23 #include "ctkXnatAPI_p.h"
24
25 #include "ctkXnatResourceCatalogXmlParser.h"
26
27 #include "qRestResult.h"
28
29 #include <QNetworkReply>
30 #include <QRegExp>
31 #include <QUrl>
32 #if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
33 #include <QUrlQuery>
34 #endif
35
36 // --------------------------------------------------------------------------
37 // ctkXnatAPI methods
38
39 // --------------------------------------------------------------------------
ctkXnatAPI(QObject * _parent)40 ctkXnatAPI::ctkXnatAPI(QObject* _parent)
41 : Superclass(_parent)
42 {
43 }
44
45 // --------------------------------------------------------------------------
~ctkXnatAPI()46 ctkXnatAPI::~ctkXnatAPI()
47 {
48 }
49
50 // --------------------------------------------------------------------------
get(const QString & resource,const Parameters & parameters,const qRestAPI::RawHeaders & rawHeaders)51 QUuid ctkXnatAPI::get(const QString& resource, const Parameters& parameters, const qRestAPI::RawHeaders& rawHeaders)
52 {
53 QUrl url = this->createUrl(resource, parameters);
54 #if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
55 url.addQueryItem("format", "json");
56 #else
57 QUrlQuery urlQuery(url);
58 urlQuery.addQueryItem("format", "json");
59 url.setQuery(urlQuery);
60 #endif
61 QNetworkReply* queryReply = this->sendRequest(QNetworkAccessManager::GetOperation, url, rawHeaders);
62 QUuid queryId = queryReply->property("uuid").toString();
63 return queryId;
64 }
65
66 // --------------------------------------------------------------------------
parseResponse(qRestResult * restResult,const QByteArray & response)67 void ctkXnatAPI::parseResponse(qRestResult* restResult, const QByteArray& response)
68 {
69 static QRegExp identifierPattern("[a-zA-Z][a-zA-Z0-9_]*");
70
71 QList<QVariantMap> result;
72
73 if (response.isEmpty())
74 {
75 // Some operations do not return result. E.g. creating a project.
76 }
77 else if (response.startsWith("<html>"))
78 {
79 // Some operations return an XML description of an object.
80 // E.g. GET query for a specific subject.
81 restResult->setError(QString("Bad data: ") + response, qRestAPI::ResponseParseError);
82 }
83 else if (response.startsWith("<?xml "))
84 {
85 // Some operations return an XML description of an object.
86 // E.g. GET query for a specific subject.
87 result = this->parseXmlResponse(restResult, response);
88 }
89 else if (response[0] == '{')
90 {
91 // Other operations return a json description of an object.
92 // E.g. GET query of the list of subjects
93 result = this->parseJsonResponse(restResult, response);
94 }
95 else if (identifierPattern.exactMatch(response))
96 {
97 // Some operations return the identifier of the newly created object.
98 // E.g. creating a subject.
99 QVariantMap map;
100 map["ID"] = response;
101 map["content"] = response;
102 result.push_back(map);
103 }
104 else
105 {
106 QVariantMap map;
107 map["content"] = response;
108 result.push_back(map);
109 }
110
111 restResult->setResult(result);
112 }
113
114 // --------------------------------------------------------------------------
parseXmlResponse(qRestResult *,const QByteArray & response)115 QList<QVariantMap> ctkXnatAPI::parseXmlResponse(qRestResult* /*restResult*/, const QByteArray& response)
116 {
117 QList<QVariantMap> result;
118 // In this case a resource catalog xml was requested
119 if (response.contains("<cat:Catalog"))
120 {
121 ctkXnatResourceCatalogXmlParser parser;
122 parser.setData(response);
123 parser.parseXml(result);
124 }
125 return result;
126 }
127
128 // --------------------------------------------------------------------------
parseJsonResponse(qRestResult * restResult,const QByteArray & response)129 QList<QVariantMap> ctkXnatAPI::parseJsonResponse(qRestResult* restResult, const QByteArray& response)
130 {
131 QScriptValue scriptValue = this->ScriptEngine.evaluate("(" + QString(response) + ")");
132
133 QList<QVariantMap> result;
134
135 // e.g. {"ResultSet":{"Result": [{"p1":"v1","p2":"v2",...}], "totalRecords":"13"}}
136 QScriptValue resultSet = scriptValue.property("ResultSet");
137 QScriptValue data = resultSet.property("Result");
138 if (!data.isObject())
139 {
140 if (!data.toString().isEmpty())
141 {
142 restResult->setError(QString("Bad data: ") + data.toString(), qRestAPI::ResponseParseError);
143 }
144 }
145 if (data.isArray())
146 {
147 quint32 length = data.property("length").toUInt32();
148 for(quint32 i = 0; i < length; ++i)
149 {
150 qRestAPI::appendScriptValueToVariantMapList(result, data.property(i));
151 }
152 }
153 else
154 {
155 qRestAPI::appendScriptValueToVariantMapList(result, data);
156 }
157
158 return result;
159 }
160