Pārlūkot izejas kodu

ctkXnatAPI class (former qXnatAPI from the qRestAPI project)

Miklos Espak 11 gadi atpakaļ
vecāks
revīzija
693a8a642a

+ 1 - 1
CMakeExternals/qRestAPI.cmake

@@ -23,7 +23,7 @@ if(${add_project})
 
     if(NOT DEFINED qRestAPI_DIR)
 
-      set(revision_tag "1896940bb6")
+      set(revision_tag "5830a8146b")
       if(${proj}_REVISION_TAG)
         set(revision_tag ${${proj}_REVISION_TAG})
       endif()

+ 2 - 0
Libs/XNAT/Core/CMakeLists.txt

@@ -7,6 +7,7 @@ project(CTKXNATCore)
 set(KIT_export_directive "CTK_XNAT_CORE_EXPORT")
 
 set(KIT_SRCS
+  ctkXnatAPI.cpp
   ctkXnatConnection.cpp
   ctkXnatConnectionFactory.cpp
   ctkXnatException.cpp
@@ -28,6 +29,7 @@ set(KIT_SRCS
 
 # Files which should be processed by Qts moc
 set(KIT_MOC_SRCS
+  ctkXnatAPI_p.h
 )
 
 

+ 2 - 0
Libs/XNAT/Core/Testing/ctkXnatConnectionTest.cpp

@@ -126,6 +126,8 @@ void ctkXnatConnectionTestCase::testCreateProject()
 
   exists = d->Connection->exists(project);
   QVERIFY(exists);
+
+  d->Connection->create(project);
 }
 
 // --------------------------------------------------------------------------

+ 137 - 0
Libs/XNAT/Core/ctkXnatAPI.cpp

@@ -0,0 +1,137 @@
+/*=============================================================================
+
+  Plugin: org.commontk.xnat
+
+  Copyright (c) University College London,
+    Centre for Medical Image Computing
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+// ctkXnatAPI includes
+#include "ctkXnatAPI_p.h"
+#include "qRestResult.h"
+#include <QNetworkReply>
+#include <QRegExp>
+#include <QUrl>
+
+// --------------------------------------------------------------------------
+// ctkXnatAPI methods
+
+// --------------------------------------------------------------------------
+ctkXnatAPI::ctkXnatAPI(QObject* _parent)
+  : Superclass(_parent)
+{
+}
+
+// --------------------------------------------------------------------------
+ctkXnatAPI::~ctkXnatAPI()
+{
+}
+
+// --------------------------------------------------------------------------
+QUuid ctkXnatAPI::get(const QString& resource, const Parameters& parameters, const qRestAPI::RawHeaders& rawHeaders)
+{
+  QUrl url = this->createUrl(resource, parameters);
+  url.addQueryItem("format", "json");
+  QNetworkReply* queryReply = this->sendRequest(QNetworkAccessManager::GetOperation, url, rawHeaders);
+  QUuid queryId = queryReply->property("uuid").toString();
+  return queryId;
+}
+
+// --------------------------------------------------------------------------
+void ctkXnatAPI::parseResponse(qRestResult* restResult, const QByteArray& response)
+{
+  static QRegExp identifierPattern("[a-zA-Z][a-zA-Z0-9_]*");
+
+  QList<QVariantMap> result;
+
+  if (response.isEmpty())
+    {
+    // Some operations do not return result. E.g. creating a project.
+    }
+  else if (response.startsWith("<html>"))
+    {
+    // Some operations return an XML description of an object.
+    // E.g. GET query for a specific subject.
+    restResult->setError(QString("Bad data: ") + response);
+    }
+  else if (response.startsWith("<?xml "))
+    {
+    // Some operations return an XML description of an object.
+    // E.g. GET query for a specific subject.
+    result = this->parseXmlResponse(restResult, response);
+    }
+  else if (response[0] == '{')
+    {
+    // Other operations return a json description of an object.
+    // E.g. GET query of the list of subjects
+    result = this->parseJsonResponse(restResult, response);
+    }
+  else if (identifierPattern.exactMatch(response))
+    {
+    // Some operations return the identifier of the newly created object.
+    // E.g. creating a subject.
+    QVariantMap map;
+    map["ID"] = response;
+    result.push_back(map);
+    }
+  else
+    {
+    restResult->setError(QString("Bad data: ") + response);
+    }
+
+  restResult->setResult(result);
+}
+
+// --------------------------------------------------------------------------
+QList<QVariantMap> ctkXnatAPI::parseXmlResponse(qRestResult* restResult, const QByteArray& response)
+{
+  QList<QVariantMap> result;
+  return result;
+}
+
+// --------------------------------------------------------------------------
+QList<QVariantMap> ctkXnatAPI::parseJsonResponse(qRestResult* restResult, const QByteArray& response)
+{
+  QScriptValue scriptValue = this->ScriptEngine.evaluate("(" + QString(response) + ")");
+
+  QList<QVariantMap> result;
+
+  // e.g. {"ResultSet":{"Result": [{"p1":"v1","p2":"v2",...}], "totalRecords":"13"}}
+  QScriptValue resultSet = scriptValue.property("ResultSet");
+  QScriptValue dataLength = resultSet.property("totalRecords");
+  QScriptValue data = resultSet.property("Result");
+  if (!data.isObject())
+    {
+    if (!data.toString().isEmpty())
+      {
+      restResult->setError(QString("Bad data: ") + data.toString());
+      }
+    }
+  if (data.isArray())
+    {
+    quint32 length = data.property("length").toUInt32();
+    for(quint32 i = 0; i < length; ++i)
+      {
+      qRestAPI::appendScriptValueToVariantMapList(result, data.property(i));
+      }
+    }
+  else
+    {
+    qRestAPI::appendScriptValueToVariantMapList(result, data);
+    }
+
+  return result;
+}

+ 62 - 0
Libs/XNAT/Core/ctkXnatAPI_p.h

@@ -0,0 +1,62 @@
+/*=============================================================================
+
+  Plugin: org.commontk.xnat
+
+  Copyright (c) University College London,
+    Centre for Medical Image Computing
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+#ifndef __ctkXnatAPI_h
+#define __ctkXnatAPI_h
+
+#include "qRestAPI.h"
+
+#include <QList>
+#include <QScriptEngine>
+#include <QScriptValue>
+
+/// ctkXnatAPI is a simple interface class to communicate with an XNAT
+/// server through its REST API.
+class ctkXnatAPI : public qRestAPI
+{
+  Q_OBJECT
+
+  typedef qRestAPI Superclass;
+
+public:
+  explicit ctkXnatAPI(QObject* parent = 0);
+  virtual ~ctkXnatAPI();
+
+  using Superclass::get;
+
+  virtual QUuid get(const QString& resource,
+    const Parameters& parameters = Parameters(),
+    const RawHeaders& rawHeaders = RawHeaders());
+
+protected:
+  void parseResponse(qRestResult* restResult, const QByteArray& result);
+
+private:
+  QList<QVariantMap> parseXmlResponse(qRestResult* restResult, const QByteArray& response);
+
+  QList<QVariantMap> parseJsonResponse(qRestResult* restResult, const QByteArray& response);
+
+  QScriptEngine ScriptEngine;
+
+  Q_DISABLE_COPY(ctkXnatAPI);
+};
+
+#endif

+ 5 - 5
Libs/XNAT/Core/ctkXnatConnection.cpp

@@ -40,7 +40,7 @@
 #include <QScopedPointer>
 #include <QStringBuilder>
 
-#include <qXnatAPI.h>
+#include <ctkXnatAPI_p.h>
 #include <qRestResult.h>
 
 class ctkXnatConnectionPrivate
@@ -51,8 +51,8 @@ public:
   QString userName;
   QString password;
 
-  qXnatAPI* xnat;
-  qXnatAPI::RawHeaders rawHeaders;
+  ctkXnatAPI* xnat;
+  ctkXnatAPI::RawHeaders rawHeaders;
 
   ctkXnatServer* server;
 };
@@ -63,7 +63,7 @@ ctkXnatConnection::ctkXnatConnection()
 : d_ptr(new ctkXnatConnectionPrivate())
 {
   Q_D(ctkXnatConnection);
-  d->xnat = new qXnatAPI();
+  d->xnat = new ctkXnatAPI();
 
   // TODO This is a workaround for connecting to sites with self-signed
   // certificate. Should be replaced with something more clever.  
@@ -405,7 +405,7 @@ void ctkXnatConnection::create(ctkXnatObject* object)
 
   if (!success)
   {
-    throw ctkXnatException("Error occurred while removing the data.");
+    throw ctkXnatException("Error occurred while creating the data.");
   }
 }
 

+ 2 - 1
Libs/XNAT/Core/ctkXnatObject.cpp

@@ -209,7 +209,8 @@ ctkXnatConnection* ctkXnatObject::connection() const
 {
   const ctkXnatObject* xnatObject = this;
   const ctkXnatServer* server;
-  do {
+  do
+  {
     xnatObject = xnatObject->parent();
     server = dynamic_cast<const ctkXnatServer*>(xnatObject);
   }