Commit 9e211ead authored by Martin Straka's avatar Martin Straka

Merge branch 'records-management-shared-code-changes' into 'develop'

Pulled Changes in Shared Code

See merge request !135
parents 34473ed6 c27e8eef
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include "src/datovka_shared/log/log.h" #include "src/datovka_shared/log/log.h"
#include "src/datovka_shared/records_management/conversion.h" #include "src/datovka_shared/records_management/conversion.h"
QList<qint64> createIdList(const QStringList &strList, bool *ok) QList<qint64> RecMgmt::createIdList(const QStringList &strList, bool *ok)
{ {
QList<qint64> idList; QList<qint64> idList;
bool iOk = false; bool iOk = false;
......
...@@ -26,11 +26,15 @@ ...@@ -26,11 +26,15 @@
#include <QList> #include <QList>
#include <QStringList> #include <QStringList>
/*! namespace RecMgmt {
* @brief Convert list of strings into list of qint64.
* /*!
* @param[in] strList String list. * @brief Convert list of strings into list of qint64.
* @param[out] ok Set to true if all entries are successfully converted. *
* @return List if qint64. * @param[in] strList String list.
*/ * @param[out] ok Set to true if all entries are successfully converted.
QList<qint64> createIdList(const QStringList &strList, bool *ok); * @return List if qint64.
*/
QList<qint64> createIdList(const QStringList &strList, bool *ok);
}
...@@ -30,13 +30,13 @@ ...@@ -30,13 +30,13 @@
#include "src/datovka_shared/records_management/io/records_management_connection.h" #include "src/datovka_shared/records_management/io/records_management_connection.h"
/* Must be set to false for production releases. */ /* Must be set to false for production releases. */
const bool RecordsManagementConnection::ignoreSslErrorsDflt = false; const bool RecMgmt::Connection::ignoreSslErrorsDflt = false;
/*! /*!
* @brief Converts service identifier onto service name. * @brief Converts service identifier onto service name.
*/ */
static static
const QString &serviceName(enum RecordsManagementConnection::ServiceId srvcId) const QString &serviceName(enum RecMgmt::Connection::ServiceId srvcId)
{ {
static const QString SrvServiceInfo(QStringLiteral("service_info")); static const QString SrvServiceInfo(QStringLiteral("service_info"));
static const QString SrvUploadHierarchy(QStringLiteral("upload_hierarchy")); static const QString SrvUploadHierarchy(QStringLiteral("upload_hierarchy"));
...@@ -45,16 +45,16 @@ const QString &serviceName(enum RecordsManagementConnection::ServiceId srvcId) ...@@ -45,16 +45,16 @@ const QString &serviceName(enum RecordsManagementConnection::ServiceId srvcId)
static const QString InvalidService; static const QString InvalidService;
switch (srvcId) { switch (srvcId) {
case RecordsManagementConnection::SRVC_SERVICE_INFO: case RecMgmt::Connection::SRVC_SERVICE_INFO:
return SrvServiceInfo; return SrvServiceInfo;
break; break;
case RecordsManagementConnection::SRVC_UPLOAD_HIERARCHY: case RecMgmt::Connection::SRVC_UPLOAD_HIERARCHY:
return SrvUploadHierarchy; return SrvUploadHierarchy;
break; break;
case RecordsManagementConnection::SRVC_UPLOAD_FILE: case RecMgmt::Connection::SRVC_UPLOAD_FILE:
return SrvUploadFile; return SrvUploadFile;
break; break;
case RecordsManagementConnection::SRVC_STORED_FILES: case RecMgmt::Connection::SRVC_STORED_FILES:
return SrvStoredFiles; return SrvStoredFiles;
break; break;
default: default:
...@@ -68,8 +68,7 @@ const QString &serviceName(enum RecordsManagementConnection::ServiceId srvcId) ...@@ -68,8 +68,7 @@ const QString &serviceName(enum RecordsManagementConnection::ServiceId srvcId)
* @brief Create URL from base URL and from service identifier. * @brief Create URL from base URL and from service identifier.
*/ */
static static
QUrl constructUrl(QString baseUrl, QUrl constructUrl(QString baseUrl, enum RecMgmt::Connection::ServiceId srvcId)
enum RecordsManagementConnection::ServiceId srvcId)
{ {
const QString &srvcName(serviceName(srvcId)); const QString &srvcName(serviceName(srvcId));
...@@ -83,7 +82,7 @@ QUrl constructUrl(QString baseUrl, ...@@ -83,7 +82,7 @@ QUrl constructUrl(QString baseUrl,
return QUrl(baseUrl + srvcName); return QUrl(baseUrl + srvcName);
} }
RecordsManagementConnection::RecordsManagementConnection(bool ignoreSslErrors, RecMgmt::Connection::Connection(bool ignoreSslErrors,
QObject *parent) QObject *parent)
: QObject(parent), : QObject(parent),
m_baseUrlStr(), m_baseUrlStr(),
...@@ -97,14 +96,14 @@ RecordsManagementConnection::RecordsManagementConnection(bool ignoreSslErrors, ...@@ -97,14 +96,14 @@ RecordsManagementConnection::RecordsManagementConnection(bool ignoreSslErrors,
this, SLOT(handleSslErrors(QNetworkReply *, const QList<QSslError>))); this, SLOT(handleSslErrors(QNetworkReply *, const QList<QSslError>)));
} }
void RecordsManagementConnection::setConnection(const QString &baseUrl, void RecMgmt::Connection::setConnection(const QString &baseUrl,
const QString &token) const QString &token)
{ {
m_baseUrlStr = baseUrl; m_baseUrlStr = baseUrl;
m_tokenStr = token; m_tokenStr = token;
} }
bool RecordsManagementConnection::communicate(enum ServiceId srvcId, bool RecMgmt::Connection::communicate(enum ServiceId srvcId,
const QByteArray &requestData, QByteArray &replyData, QObject *cbObj) const QByteArray &requestData, QByteArray &replyData, QObject *cbObj)
{ {
debugFuncCall(); debugFuncCall();
...@@ -125,7 +124,7 @@ bool RecordsManagementConnection::communicate(enum ServiceId srvcId, ...@@ -125,7 +124,7 @@ bool RecordsManagementConnection::communicate(enum ServiceId srvcId,
cbObj, SLOT(onUploadProgress(qint64, qint64))); cbObj, SLOT(onUploadProgress(qint64, qint64)));
} }
bool retVal = waitReplyFinished(reply, m_timeOut); bool retVal = waitReplyFinished(reply, m_timeOut, cbObj);
if (cbObj != Q_NULLPTR) { if (cbObj != Q_NULLPTR) {
cbObj->disconnect(SIGNAL(callAbort()), reply, SLOT(abort())); cbObj->disconnect(SIGNAL(callAbort()), reply, SLOT(abort()));
...@@ -180,7 +179,7 @@ bool readAndAddCert(const QByteArray &certData, QSsl::EncodingFormat fmt) ...@@ -180,7 +179,7 @@ bool readAndAddCert(const QByteArray &certData, QSsl::EncodingFormat fmt)
return true; return true;
} }
bool RecordsManagementConnection::addTrustedCertificate(const QString &filePath) bool RecMgmt::Connection::addTrustedCertificate(const QString &filePath)
{ {
QByteArray certData; QByteArray certData;
...@@ -218,7 +217,7 @@ bool RecordsManagementConnection::addTrustedCertificate(const QString &filePath) ...@@ -218,7 +217,7 @@ bool RecordsManagementConnection::addTrustedCertificate(const QString &filePath)
return false; return false;
} }
void RecordsManagementConnection::handleSslErrors(QNetworkReply *reply, void RecMgmt::Connection::handleSslErrors(QNetworkReply *reply,
const QList<QSslError> &errors) const QList<QSslError> &errors)
{ {
Q_UNUSED(reply); Q_UNUSED(reply);
...@@ -246,8 +245,7 @@ void RecordsManagementConnection::handleSslErrors(QNetworkReply *reply, ...@@ -246,8 +245,7 @@ void RecordsManagementConnection::handleSslErrors(QNetworkReply *reply,
} }
} }
QNetworkRequest RecordsManagementConnection::createRequest( QNetworkRequest RecMgmt::Connection::createRequest(enum ServiceId srvcId) const
enum ServiceId srvcId) const
{ {
debugFuncCall(); debugFuncCall();
...@@ -265,8 +263,8 @@ QNetworkRequest RecordsManagementConnection::createRequest( ...@@ -265,8 +263,8 @@ QNetworkRequest RecordsManagementConnection::createRequest(
return request; return request;
} }
QNetworkReply *RecordsManagementConnection::sendRequest( QNetworkReply *RecMgmt::Connection::sendRequest(const QNetworkRequest &request,
const QNetworkRequest &request, const QByteArray &data) const QByteArray &data)
{ {
debugFuncCall(); debugFuncCall();
...@@ -297,8 +295,8 @@ QNetworkReply *RecordsManagementConnection::sendRequest( ...@@ -297,8 +295,8 @@ QNetworkReply *RecordsManagementConnection::sendRequest(
return reply; return reply;
} }
bool RecordsManagementConnection::waitReplyFinished(QNetworkReply *reply, bool RecMgmt::Connection::waitReplyFinished(QNetworkReply *reply,
unsigned int timeOut) unsigned int timeOut, QObject *cbObj)
{ {
if (Q_UNLIKELY(reply == Q_NULLPTR)) { if (Q_UNLIKELY(reply == Q_NULLPTR)) {
Q_ASSERT(0); Q_ASSERT(0);
...@@ -309,26 +307,46 @@ bool RecordsManagementConnection::waitReplyFinished(QNetworkReply *reply, ...@@ -309,26 +307,46 @@ bool RecordsManagementConnection::waitReplyFinished(QNetworkReply *reply,
QTimer timer; QTimer timer;
timer.setSingleShot(true); timer.setSingleShot(true);
QEventLoop eventLoop; QEventLoop eventLoop;
if (cbObj != Q_NULLPTR) {
connect(&timer, SIGNAL(timeout()), cbObj, SLOT(onTimeout()));
}
connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit())); connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit())); connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
timer.start(timeOut);
eventLoop.exec();
if (timer.isActive()) { do {
timer.start(timeOut);
eventLoop.exec();
/*
* Repeat if a callback object is present and while
* communication has not been stopped.
* Exit if no callback object is specified.
*/
} while ((cbObj != Q_NULLPTR) && reply->isRunning());
if (cbObj != Q_NULLPTR) {
timer.disconnect(SIGNAL(timeout()), cbObj, SLOT(onTimeout()));
}
timer.disconnect(SIGNAL(timeout()), &eventLoop, SLOT(quit()));
reply->disconnect(SIGNAL(finished()), &eventLoop, SLOT(quit()));
if (reply->isFinished()) {
timer.stop(); timer.stop();
return true;
} else { } else {
/* Timeout expired. */ /* Timeout expired. */
disconnect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
logErrorNL("%s", logErrorNL("%s",
"Connection timed out. Check your internet connection."); "Connection timed out. Check your internet connection.");
reply->abort(); reply->abort();
} }
return false; /*
* The value QNetworkReply::OperationCanceledError means cancelled via
* abort() or close().
*/
return reply->error() == QNetworkReply::NoError;
} }
bool RecordsManagementConnection::processReply(QNetworkReply *reply, bool RecMgmt::Connection::processReply(QNetworkReply *reply,
QByteArray &replyData) QByteArray &replyData)
{ {
debugFuncCall(); debugFuncCall();
......
...@@ -30,131 +30,183 @@ ...@@ -30,131 +30,183 @@
#include <QObject> #include <QObject>
#include <QString> #include <QString>
/*! namespace RecMgmt {
* @brief Encapsulates connection to records management service.
*/
class RecordsManagementConnection : public QObject {
Q_OBJECT
public:
/*!
* @brief Records management service identifiers.
*/
enum ServiceId {
SRVC_SERVICE_INFO,
SRVC_UPLOAD_HIERARCHY,
SRVC_UPLOAD_FILE,
SRVC_STORED_FILES
};
/*!
* @brief Use for controlling of global behaviour on SSL errors.
*/
static
const bool ignoreSslErrorsDflt;
/*!
* @brief Constructor.
*/
explicit RecordsManagementConnection(bool ignoreSslErrors = false,
QObject *parent = Q_NULLPTR);
/*!
* @brief Set connection data.
*
* @param[in] baseUrl Service base URL.
* @param[in] token Authentication token.
*/
void setConnection(const QString &baseUrl, const QString &token);
/*!
* @brief Send request and wait for reply.
*
* @note The callback object must be able to emit the signal
* 'callAbort()' which will abort the network communication.
* The callback object must be define the slots
* 'onDownloadProgress(qint64, qint64)' and
* 'onUploadProgress(qint64, qint64)' which should handle
* the corresponding network reply signals.
*
* @param[in] srvcId Srvice identifier.
* @param[in] requestData Data to be sent.
* @param[out] replyData Data from the reply.
* @param[in,out] cbObj Callback object to be connected to the internal
* network reply object.
*/
bool communicate(enum ServiceId srvcId, const QByteArray &requestData,
QByteArray &replyData, QObject *cbObj = Q_NULLPTR);
/*!
* @brief Add certificate to certificate store.
*
* @param[in] filePath Path to certificate file.
* @return True on success.
*/
static
bool addTrustedCertificate(const QString &filePath);
signals: #if 0
/*! /*!
* @brief Emitted when some error during communication occurs. * @brief An connection timeout handler prototype.
* *
* @param[in] message Message string containing error description. * @note There is a problem in Qt with multiple inheritance from
* QObject classes. E.g. we cannot use this class to directly derive
* dialogues from it. This class serves as an illustration how a
* progress handler (callback) object could look like. See
* https://stackoverflow.com/a/2998374 on pure virtual slots
* https://stackoverflow.com/a/8578921 on QObject multiple inheritance
*/ */
void connectionError(const QString &message); class ProgressHandler : protected QObject {
Q_OBJECT
private slots:
void handleSslErrors(QNetworkReply *reply, signals:
const QList<QSslError> &errors); /*!
* @brief When this signal is emitted then the network
private: * communication is directly aborted.
/*! */
* @brief Create network request. void callAbort(void);
*
* @param[in] srvcId Srvice identifier. public slots:
* @return Created network request. /*!
*/ * @brief This slot is connected to the network reply object and
QNetworkRequest createRequest(enum ServiceId srvcId) const; * handles the ingoing communication.
*/
/*! void onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
* @brief Send request.
* /*!
* @param[in] request Network request. * @brief This slot is connected to the network reply object and
* @param[in] data Data to be sent along with the request. * handles the outgoing communication.
* @return Null pointer on failure. */
*/ void onUploadProgress(qint64 bytesSent, qint64 bytesTotal);
QNetworkReply *sendRequest(const QNetworkRequest &request,
const QByteArray &data); /*!
* @brief This slot is connected to the internal timer object
/*! * and should watch the progress of the data transfer. It
* @brief Blocks until all data are sent and received or until timed out. * should be able to emit the callAbort() signal.
* */
* @note The reply is aborted when it times out. In this case the reply void onTimeout(void);
* is not deleted. };
* #endif
* @param[in,out] reply Communication context.
* @param[in] timeOut Communication timeout.
* @return True if all data have been received,
* false if communication timed out.
*/
static
bool waitReplyFinished(QNetworkReply *reply, unsigned int timeOut);
/*! /*!
* @brief Process reply data. * @brief Encapsulates connection to records management service.
*
* @param[in,out] reply Obtained reply.
* @param[out] replyData Obtained reply data.
* @return True on success, false on error.
*/ */
static class Connection : public QObject {
bool processReply(QNetworkReply *reply, QByteArray &replyData); Q_OBJECT
QString m_baseUrlStr; /*!< Service base URL. */ public:
QString m_tokenStr; /*!< Authentication token. */ /*!
QString m_agentName; /*!< Usually the application name. */ * @brief Records management service identifiers.
*/
enum ServiceId {
SRVC_SERVICE_INFO,
SRVC_UPLOAD_HIERARCHY,
SRVC_UPLOAD_FILE,
SRVC_STORED_FILES
};
/*!
* @brief Use for controlling of global behaviour on SSL errors.
*/
static
const bool ignoreSslErrorsDflt;
/*!
* @brief Constructor.
*/
explicit Connection(bool ignoreSslErrors = false,
QObject *parent = Q_NULLPTR);
/*!
* @brief Set connection data.
*
* @param[in] baseUrl Service base URL.
* @param[in] token Authentication token.
*/
void setConnection(const QString &baseUrl, const QString &token);
/*!
* @brief Send request and wait for reply.
*
* @note The callback object must be able to emit the signal
* 'callAbort()' which will abort the network communication.
* The callback object must be define the slots
* 'onDownloadProgress(qint64, qint64)' and
* 'onUploadProgress(qint64, qint64)' which should handle
* the corresponding network reply signals.
*
* @param[in] srvcId Srvice identifier.
* @param[in] requestData Data to be sent.
* @param[out] replyData Data from the reply.
* @param[in,out] cbObj Callback object to be connected to the
* internal network reply object.
*/
bool communicate(enum ServiceId srvcId,
const QByteArray &requestData, QByteArray &replyData,
QObject *cbObj = Q_NULLPTR);
/*!
* @brief Add certificate to certificate store.
*
* @param[in] filePath Path to certificate file.
* @return True on success.
*/
static
bool addTrustedCertificate(const QString &filePath);
signals:
/*!
* @brief Emitted when some error during communication occurs.
*
* @param[in] message Message string containing error description.
*/
void connectionError(const QString &message);
private slots:
void handleSslErrors(QNetworkReply *reply,
const QList<QSslError> &errors);
private:
/*!
* @brief Create network request.
*
* @param[in] srvcId Service identifier.
* @return Created network request.
*/
QNetworkRequest createRequest(enum ServiceId srvcId) const;
/*!
* @brief Send request.
*
* @param[in] request Network request.
* @param[in] data Data to be sent along with the request.
* @return Null pointer on failure.
*/
QNetworkReply *sendRequest(const QNetworkRequest &request,
const QByteArray &data);
/*!
* @brief Blocks until all data are sent and received or until
* timed out.
*
* @note The reply is aborted when it times out and no callback
* object is specified. In this case the reply is not deleted.
*
* @param[in,out] reply Communication context.
* @param[in] timeOut Communication timeout.
* @param[in,out] cbObj Callback object to be connected to the
* internal timer object.
* @return True if all data have been received,
* false if communication timed out.
*/
static
bool waitReplyFinished(QNetworkReply *reply,
unsigned int timeOut, QObject *cbObj);
/*!
* @brief Process reply data.
*
* @param[in,out] reply Obtained reply.
* @param[out] replyData Obtained reply data.
* @return True on success, false on error.
*/
static
bool processReply(QNetworkReply *reply, QByteArray &replyData);
QString m_baseUrlStr; /*!< Service base URL. */
QString m_tokenStr; /*!< Authentication token. */
QString m_agentName; /*!< Usually the application name. */
unsigned int m_timeOut; /*!< Communication timeout. */
bool m_ignoreSslErrors; /*!< True if SSL errors should be ignored. */
QNetworkAccessManager m_nam; /*!< Network access manager. */
};
unsigned int m_timeOut; /*!< Communication timeout. */ }
bool m_ignoreSslErrors; /*!< True if SSL errors should be ignored. */
QNetworkAccessManager m_nam; /*!< Network access manager. */
};
...@@ -41,35 +41,35 @@ static const QString strAlreadyPresent("ALREADY_PRESENT"); ...@@ -41,35 +41,35 @@ static const QString strAlreadyPresent("ALREADY_PRESENT");
static const QString strLimitExceeded("LIMIT_EXCEEDED"); static const QString strLimitExceeded("LIMIT_EXCEEDED");
static const QString strUnspecified("UNSPECIFIED"); static const QString strUnspecified("UNSPECIFIED");
ErrorEntry::ErrorEntry(void) RecMgmt::ErrorEntry::ErrorEntry(void)
: m_code(ERR_NO_ERROR), : m_code(ERR_NO_ERROR),
m_description() m_description()
{ {
} }
ErrorEntry::ErrorEntry(enum Code code, const QString &description) RecMgmt::ErrorEntry::ErrorEntry(enum Code code, const QString &description)
: m_code(code), : m_code(code),
m_description(description) m_description(description)
{ {
} }
ErrorEntry::ErrorEntry(const ErrorEntry &ee) RecMgmt::ErrorEntry::ErrorEntry(const ErrorEntry &other)
: m_code(ee.m_code), : m_code(other.m_code),
m_description(ee.m_description) m_description(other.m_description)
{ {
} }
enum ErrorEntry::Code ErrorEntry::code(void) const enum RecMgmt::ErrorEntry::Code RecMgmt::ErrorEntry::code(void) const
{ {
return m_code; return m_code;
} }
const QString &ErrorEntry::description(void) const const QString &RecMgmt::ErrorEntry::description(void) const
{ {
return m_description; return m_description;
} }
bool ErrorEntry::fromJsonVal(const QJsonValue *jsonVal) bool RecMgmt::ErrorEntry::fromJsonVal(const QJsonValue *jsonVal)
{ {
if (jsonVal == Q_NULLPTR) { if (jsonVal == Q_NULLPTR) {
Q_ASSERT(0); Q_ASSERT(0);
...@@ -107,7 +107,7 @@ bool ErrorEntry::fromJsonVal(const QJsonValue *jsonVal) ...@@ -107,7 +107,7 @@ bool ErrorEntry::fromJsonVal(const QJsonValue *jsonVal)
return true; return true;
} }
bool ErrorEntry::toJsonVal(QJsonValue *jsonVal) const bool RecMgmt::ErrorEntry::toJsonVal(QJsonValue *jsonVal) const
{ {
if (jsonVal == Q_NULLPTR) { if (jsonVal == Q_NULLPTR) {
Q_ASSERT(0); Q_ASSERT(0);
...@@ -126,7 +126,7 @@ bool ErrorEntry::toJsonVal(QJsonValue *jsonVal) const ...@@ -126,7 +126,7 @@ bool ErrorEntry::toJsonVal(QJsonValue *jsonVal) const
return true; return true;
} }
QString ErrorEntry::trVerbose(void) const QString RecMgmt::ErrorEntry::trVerbose(void) const
{ {
QString retStr(codeToString(m_code) + QLatin1String(" (")); QString retStr(codeToString(m_code) + QLatin1String(" ("));
QString explanation; QString explanation;
...@@ -166,7 +166,7 @@ QString ErrorEntry::trVerbose(void) const ...@@ -166,7 +166,7 @@ QString ErrorEntry::trVerbose(void) const
return retStr; return retStr;
} }