##// END OF EJS Templates
Updates IDataProvider::requestDataLoading() method's signature...
Alexandre Leroux -
r375:49f712bf7e59
parent child
Show More
@@ -1,15 +1,15
1 1 #ifndef SCIQLOP_DATAPROVIDERPARAMETERS_H
2 2 #define SCIQLOP_DATAPROVIDERPARAMETERS_H
3 3
4 4 #include "SqpDateTime.h"
5 5
6 6 /**
7 7 * @brief The DataProviderParameters struct holds the information needed to retrieve data from a
8 8 * data provider
9 9 * @sa IDataProvider
10 10 */
11 11 struct DataProviderParameters {
12 SqpDateTime m_Time;
12 QVector<SqpDateTime> m_Times;
13 13 };
14 14
15 15 #endif // SCIQLOP_DATAPROVIDERPARAMETERS_H
@@ -1,60 +1,59
1 1 #ifndef SCIQLOP_IDATAPROVIDER_H
2 2 #define SCIQLOP_IDATAPROVIDER_H
3 3
4 4 #include <memory>
5 5
6 6 #include <QObject>
7 7 #include <QUuid>
8 8
9 9 #include <Common/MetaTypes.h>
10 10
11 11 #include <Data/SqpDateTime.h>
12 12
13 13 class DataProviderParameters;
14 14 class IDataSeries;
15 15 class QNetworkReply;
16 16 class QNetworkRequest;
17 17
18 18 /**
19 19 * @brief The IDataProvider interface aims to declare a data provider.
20 20 *
21 21 * A data provider is an entity that generates data and returns it according to various parameters
22 22 * (time interval, product to retrieve the data, etc.)
23 23 *
24 24 * @sa IDataSeries
25 25 */
26 26 class IDataProvider : public QObject {
27 27
28 28 Q_OBJECT
29 29 public:
30 30 virtual ~IDataProvider() noexcept = default;
31 31
32 32 /**
33 * @brief requestDataLoading provide datas for the data identified by identifier for all
34 * SqpDateTime of dateTimeList
33 * @brief requestDataLoading provide datas for the data identified by identifier and parameters
35 34 */
36 virtual void requestDataLoading(QUuid identifier, const QVector<SqpDateTime> &dateTimeList) = 0;
35 virtual void requestDataLoading(QUuid identifier, const DataProviderParameters &parameters) = 0;
37 36
38 37 signals:
39 38 /**
40 39 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
41 40 * identified by identifier
42 41 */
43 42 void dataProvided(QUuid identifier, std::shared_ptr<IDataSeries> dateSerie,
44 43 const SqpDateTime &dateTime);
45 44
46 45
47 46 /**
48 47 * @brief requestConstructed send a request for the data identified by identifier
49 48 * @callback is the methode call by the reply of the request when it is finished.
50 49 */
51 50 void requestConstructed(const QNetworkRequest &request, QUuid identifier,
52 51 std::function<void(QNetworkReply *, QUuid)> callback);
53 52 };
54 53
55 54 // Required for using shared_ptr in signals/slots
56 55 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
57 56 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
58 57 std::function<void(QNetworkReply *, QUuid)>)
59 58
60 59 #endif // SCIQLOP_IDATAPROVIDER_H
@@ -1,216 +1,216
1 1 #include <Variable/Variable.h>
2 2 #include <Variable/VariableCacheController.h>
3 3 #include <Variable/VariableController.h>
4 4 #include <Variable/VariableModel.h>
5 5
6 6 #include <Data/DataProviderParameters.h>
7 7 #include <Data/IDataProvider.h>
8 8 #include <Data/IDataSeries.h>
9 9 #include <Time/TimeController.h>
10 10
11 11 #include <QDateTime>
12 12 #include <QMutex>
13 13 #include <QThread>
14 14 #include <QUuid>
15 15 #include <QtCore/QItemSelectionModel>
16 16
17 17 #include <unordered_map>
18 18
19 19 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
20 20
21 21 struct VariableController::VariableControllerPrivate {
22 22 explicit VariableControllerPrivate(VariableController *parent)
23 23 : m_WorkingMutex{},
24 24 m_VariableModel{new VariableModel{parent}},
25 25 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
26 26 m_VariableCacheController{std::make_unique<VariableCacheController>()}
27 27 {
28 28 }
29 29
30 30 QMutex m_WorkingMutex;
31 31 /// Variable model. The VariableController has the ownership
32 32 VariableModel *m_VariableModel;
33 33 QItemSelectionModel *m_VariableSelectionModel;
34 34
35 35
36 36 TimeController *m_TimeController{nullptr};
37 37 std::unique_ptr<VariableCacheController> m_VariableCacheController;
38 38
39 39 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
40 40 m_VariableToProviderMap;
41 41 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifier;
42 42 };
43 43
44 44 VariableController::VariableController(QObject *parent)
45 45 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
46 46 {
47 47 qCDebug(LOG_VariableController()) << tr("VariableController construction")
48 48 << QThread::currentThread();
49 49 }
50 50
51 51 VariableController::~VariableController()
52 52 {
53 53 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
54 54 << QThread::currentThread();
55 55 this->waitForFinish();
56 56 }
57 57
58 58 VariableModel *VariableController::variableModel() noexcept
59 59 {
60 60 return impl->m_VariableModel;
61 61 }
62 62
63 63 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
64 64 {
65 65 return impl->m_VariableSelectionModel;
66 66 }
67 67
68 68 void VariableController::setTimeController(TimeController *timeController) noexcept
69 69 {
70 70 impl->m_TimeController = timeController;
71 71 }
72 72
73 73 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
74 74 {
75 75 if (!variable) {
76 76 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
77 77 return;
78 78 }
79 79
80 80 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
81 81 // make some treatments before the deletion
82 82 emit variableAboutToBeDeleted(variable);
83 83
84 84 // Deletes provider
85 85 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
86 86 qCDebug(LOG_VariableController())
87 87 << tr("Number of providers deleted for variable %1: %2")
88 88 .arg(variable->name(), QString::number(nbProvidersDeleted));
89 89
90 90 // Clears cache
91 91 impl->m_VariableCacheController->clear(variable);
92 92
93 93 // Deletes from model
94 94 impl->m_VariableModel->deleteVariable(variable);
95 95 }
96 96
97 97 void VariableController::deleteVariables(
98 98 const QVector<std::shared_ptr<Variable> > &variables) noexcept
99 99 {
100 100 for (auto variable : qAsConst(variables)) {
101 101 deleteVariable(variable);
102 102 }
103 103 }
104 104
105 105 void VariableController::createVariable(const QString &name,
106 106 std::shared_ptr<IDataProvider> provider) noexcept
107 107 {
108 108
109 109 if (!impl->m_TimeController) {
110 110 qCCritical(LOG_VariableController())
111 111 << tr("Impossible to create variable: The time controller is null");
112 112 return;
113 113 }
114 114
115 115
116 116 /// @todo : for the moment :
117 117 /// - the provider is only used to retrieve data from the variable for its initialization, but
118 118 /// it will be retained later
119 119 /// - default data are generated for the variable, without taking into account the timerange set
120 120 /// in sciqlop
121 121 auto dateTime = impl->m_TimeController->dateTime();
122 122 if (auto newVariable = impl->m_VariableModel->createVariable(name, dateTime)) {
123 123 auto identifier = QUuid::createUuid();
124 124
125 125 // store the provider
126 126 impl->m_VariableToProviderMap[newVariable] = provider;
127 127 impl->m_VariableToIdentifier[newVariable] = identifier;
128 128
129 129 auto addDateTimeAcquired = [ this, varW = std::weak_ptr<Variable>{newVariable} ](
130 130 QUuid identifier, auto dataSeriesAcquired, auto dateTimeToPutInCache)
131 131 {
132 132 if (auto variable = varW.lock()) {
133 133 auto varIdentifier = impl->m_VariableToIdentifier.at(variable);
134 134 if (varIdentifier == identifier) {
135 135 impl->m_VariableCacheController->addDateTime(variable, dateTimeToPutInCache);
136 136 variable->setDataSeries(dataSeriesAcquired);
137 137 }
138 138 }
139 139 };
140 140
141 141 connect(provider.get(), &IDataProvider::dataProvided, addDateTimeAcquired);
142 142 this->onRequestDataLoading(newVariable, dateTime);
143 143 }
144 144 }
145 145
146 146 void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime)
147 147 {
148 148 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
149 149 << QThread::currentThread()->objectName();
150 150 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
151 151
152 152 for (const auto &selectedRow : qAsConst(selectedRows)) {
153 153 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
154 154 selectedVariable->setDateTime(dateTime);
155 155 this->onRequestDataLoading(selectedVariable, dateTime);
156 156 }
157 157 }
158 158 }
159 159
160 160 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
161 161 {
162 162 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
163 163
164 164 auto end = impl->m_VariableToIdentifier.cend();
165 165 auto it = std::find_if(impl->m_VariableToIdentifier.cbegin(), end, findReply);
166 166 if (it != end) {
167 167 impl->m_VariableModel->setDataProgress(it->first, progress);
168 168 }
169 169 }
170 170
171 171
172 172 void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable,
173 173 const SqpDateTime &dateTime)
174 174 {
175 175 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
176 176 << QThread::currentThread()->objectName();
177 177 // we want to load data of the variable for the dateTime.
178 178 // First we check if the cache contains some of them.
179 179 // For the other, we ask the provider to give them.
180 180 if (variable) {
181 181
182 182 auto dateTimeListNotInCache
183 183 = impl->m_VariableCacheController->provideNotInCacheDateTimeList(variable, dateTime);
184 184
185 185 if (!dateTimeListNotInCache.empty()) {
186 186 // Ask the provider for each data on the dateTimeListNotInCache
187 187 auto identifier = impl->m_VariableToIdentifier.at(variable);
188 188 impl->m_VariableToProviderMap.at(variable)->requestDataLoading(
189 identifier, std::move(dateTimeListNotInCache));
189 identifier, DataProviderParameters{std::move(dateTimeListNotInCache)});
190 190 }
191 191 else {
192 192 emit variable->updated();
193 193 }
194 194 }
195 195 else {
196 196 qCCritical(LOG_VariableController()) << tr("Impossible to load data of a variable null");
197 197 }
198 198 }
199 199
200 200
201 201 void VariableController::initialize()
202 202 {
203 203 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
204 204 impl->m_WorkingMutex.lock();
205 205 qCDebug(LOG_VariableController()) << tr("VariableController init END");
206 206 }
207 207
208 208 void VariableController::finalize()
209 209 {
210 210 impl->m_WorkingMutex.unlock();
211 211 }
212 212
213 213 void VariableController::waitForFinish()
214 214 {
215 215 QMutexLocker locker{&impl->m_WorkingMutex};
216 216 }
@@ -1,38 +1,38
1 1 #ifndef SCIQLOP_AMDAPROVIDER_H
2 2 #define SCIQLOP_AMDAPROVIDER_H
3 3
4 4 #include "AmdaGlobal.h"
5 5
6 6 #include <Common/spimpl.h>
7 7
8 8 #include <Data/IDataProvider.h>
9 9
10 10 #include <QLoggingCategory>
11 11
12 12
13 13 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
14 14
15 15 class QNetworkReply;
16 16
17 17 /**
18 18 * @brief The AmdaProvider class is an example of how a data provider can generate data
19 19 */
20 20 class SCIQLOP_AMDA_EXPORT AmdaProvider : public IDataProvider {
21 21 public:
22 22 explicit AmdaProvider();
23 23
24 void requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList) override;
24 void requestDataLoading(QUuid token, const DataProviderParameters &parameters) override;
25 25
26 26 private:
27 void retrieveData(QUuid token, const DataProviderParameters &parameters);
27 void retrieveData(QUuid token, const SqpDateTime &dateTime);
28 28
29 29 class AmdaProviderPrivate;
30 30 spimpl::unique_impl_ptr<AmdaProviderPrivate> impl;
31 31
32 32 // private slots:
33 33 // void httpFinished(QNetworkReply *reply, QUuid dataId) noexcept;
34 34 // void httpDownloadFinished(QNetworkReply *reply, QUuid dataId) noexcept;
35 35 // void httpDownloadReadyRead(QNetworkReply *reply, QUuid dataId) noexcept;
36 36 };
37 37
38 38 #endif // SCIQLOP_AMDAPROVIDER_H
@@ -1,128 +1,129
1 1 #include "AmdaProvider.h"
2 2 #include "AmdaResultParser.h"
3 3
4 4 #include <Data/DataProviderParameters.h>
5 5 #include <Network/NetworkController.h>
6 6 #include <SqpApplication.h>
7 7 #include <Variable/Variable.h>
8 8
9 9 #include <QNetworkAccessManager>
10 10 #include <QNetworkReply>
11 11 #include <QTemporaryFile>
12 12 #include <QThread>
13 13
14 14 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
15 15
16 16 namespace {
17 17
18 18 /// URL format for a request on AMDA server. The parameters are as follows:
19 19 /// - %1: start date
20 20 /// - %2: end date
21 21 /// - %3: parameter id
22 22 const auto AMDA_URL_FORMAT = QStringLiteral(
23 23 "http://amda.irap.omp.eu/php/rest/"
24 24 "getParameter.php?startTime=%1&stopTime=%2&parameterID=%3&sampling=60&outputFormat=ASCII&"
25 25 "timeFormat=ISO8601&gzip=0");
26 26
27 27 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
28 28 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:ss");
29 29
30 30 /// Formats a time to a date that can be passed in URL
31 31 QString dateFormat(double sqpDateTime) noexcept
32 32 {
33 33 auto dateTime = QDateTime::fromMSecsSinceEpoch(sqpDateTime * 1000.);
34 34 return dateTime.toString(AMDA_TIME_FORMAT);
35 35 }
36 36
37 37
38 38 } // namespace
39 39
40 40 struct AmdaProvider::AmdaProviderPrivate {
41 DataProviderParameters m_Params{};
41 SqpDateTime m_DateTime{};
42 42 std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr};
43 43 QNetworkReply *m_Reply{nullptr};
44 44 // std::unique_ptr<QTemporaryFile> m_File{nullptr};
45 45 QUuid m_Token;
46 46 };
47 47
48 48 AmdaProvider::AmdaProvider() : impl{spimpl::make_unique_impl<AmdaProviderPrivate>()}
49 49 {
50 50 qCDebug(LOG_NetworkController()) << tr("AmdaProvider::AmdaProvider")
51 51 << QThread::currentThread();
52 52 if (auto app = sqpApp) {
53 53 auto &networkController = app->networkController();
54 54 connect(this, &AmdaProvider::requestConstructed, &networkController,
55 55 &NetworkController::onProcessRequested);
56 56 }
57 57 }
58 58
59 void AmdaProvider::requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList)
59 void AmdaProvider::requestDataLoading(QUuid token, const DataProviderParameters &parameters)
60 60 {
61 61 // NOTE: Try to use multithread if possible
62 for (const auto &dateTime : dateTimeList) {
63 retrieveData(token, DataProviderParameters{dateTime});
62 const auto times = parameters.m_Times;
63 for (const auto &dateTime : qAsConst(times)) {
64 retrieveData(token, dateTime);
64 65 }
65 66 }
66 67
67 void AmdaProvider::retrieveData(QUuid token, const DataProviderParameters &parameters)
68 void AmdaProvider::retrieveData(QUuid token, const SqpDateTime &dateTime)
68 69 {
69 70 // /////////// //
70 71 // Creates URL //
71 72 // /////////// //
72 73
73 auto startDate = dateFormat(parameters.m_Time.m_TStart);
74 auto endDate = dateFormat(parameters.m_Time.m_TEnd);
74 auto startDate = dateFormat(dateTime.m_TStart);
75 auto endDate = dateFormat(dateTime.m_TEnd);
75 76 auto productId = QStringLiteral("imf(0)");
76 77
77 78 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
78 79
79 80 auto tempFile = std::make_shared<QTemporaryFile>();
80 81
81 82
82 83 // LAMBDA
83 84 auto httpDownloadFinished = [this, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
84 85
85 86 if (tempFile) {
86 87 auto replyReadAll = reply->readAll();
87 88 if (!replyReadAll.isEmpty()) {
88 89 tempFile->write(replyReadAll);
89 90 }
90 91 tempFile->close();
91 92
92 93 // Parse results file
93 94 if (auto dataSeries = AmdaResultParser::readTxt(tempFile->fileName())) {
94 emit dataProvided(impl->m_Token, dataSeries, impl->m_Params.m_Time);
95 emit dataProvided(impl->m_Token, dataSeries, impl->m_DateTime);
95 96 }
96 97 else {
97 98 /// @todo ALX : debug
98 99 }
99 100 }
100 101
101 102 // Deletes reply
102 103 reply->deleteLater();
103 104 reply = nullptr;
104 105 };
105 106 auto httpFinishedLambda = [this, httpDownloadFinished, tempFile](QNetworkReply *reply,
106 107 QUuid dataId) noexcept {
107 108
108 109 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
109 110 // Deletes old reply
110 111 reply->deleteLater();
111 112
112 113 // Executes request for downloading file //
113 114
114 115 // Creates destination file
115 116 if (tempFile->open()) {
116 117 // Executes request
117 118 emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId, httpDownloadFinished);
118 119 }
119 120 };
120 121
121 122 // //////////////// //
122 123 // Executes request //
123 124 // //////////////// //
124 125
125 126 impl->m_Token = token;
126 impl->m_Params = parameters;
127 impl->m_DateTime = dateTime;
127 128 emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda);
128 129 }
@@ -1,26 +1,25
1 1 #ifndef SCIQLOP_COSINUSPROVIDER_H
2 2 #define SCIQLOP_COSINUSPROVIDER_H
3 3
4 4 #include "MockPluginGlobal.h"
5 5
6 6 #include <Data/IDataProvider.h>
7 7
8 8 #include <QLoggingCategory>
9 9
10 10 Q_DECLARE_LOGGING_CATEGORY(LOG_CosinusProvider)
11 11
12 12 /**
13 13 * @brief The CosinusProvider class is an example of how a data provider can generate data
14 14 */
15 15 class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider {
16 16 public:
17 void requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList) override;
17 void requestDataLoading(QUuid token, const DataProviderParameters &parameters) override;
18 18
19 19
20 20 private:
21 21 /// @sa IDataProvider::retrieveData()
22 std::shared_ptr<IDataSeries> retrieveData(const DataProviderParameters &parameters) const;
23 std::shared_ptr<IDataSeries> retrieveDataSeries(const SqpDateTime &dateTime);
22 std::shared_ptr<IDataSeries> retrieveData(const SqpDateTime &dateTime) const;
24 23 };
25 24
26 25 #endif // SCIQLOP_COSINUSPROVIDER_H
@@ -1,50 +1,48
1 1 #include "CosinusProvider.h"
2 2
3 3 #include <Data/DataProviderParameters.h>
4 4 #include <Data/ScalarSeries.h>
5 5
6 6 #include <cmath>
7 7
8 8 #include <QDateTime>
9 9 #include <QThread>
10 10
11 11 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
12 12
13 std::shared_ptr<IDataSeries>
14 CosinusProvider::retrieveData(const DataProviderParameters &parameters) const
13 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(const SqpDateTime &dateTime) const
15 14 {
16 auto dateTime = parameters.m_Time;
17
18 15 auto dataIndex = 0;
19 16
20 17 // Gets the timerange from the parameters
21 18 double freq = 100.0;
22 19 double start = dateTime.m_TStart * freq; // 100 htz
23 20 double end = dateTime.m_TEnd * freq; // 100 htz
24 21
25 22 // We assure that timerange is valid
26 23 if (end < start) {
27 24 std::swap(start, end);
28 25 }
29 26
30 27 // Generates scalar series containing cosinus values (one value per second)
31 28 auto scalarSeries
32 29 = std::make_shared<ScalarSeries>(end - start, Unit{QStringLiteral("t"), true}, Unit{});
33 30
34 31 for (auto time = start; time < end; ++time, ++dataIndex) {
35 32 const auto timeOnFreq = time / freq;
36 33 scalarSeries->setData(dataIndex, timeOnFreq, std::cos(timeOnFreq));
37 34 }
38 35 return scalarSeries;
39 36 }
40 37
41 void CosinusProvider::requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList)
38 void CosinusProvider::requestDataLoading(QUuid token, const DataProviderParameters &parameters)
42 39 {
43 40 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataLoading"
44 41 << QThread::currentThread()->objectName();
45 42 // NOTE: Try to use multithread if possible
46 for (const auto &dateTime : dateTimeList) {
47 auto scalarSeries = this->retrieveData(DataProviderParameters{dateTime});
43 const auto times = parameters.m_Times;
44 for (const auto &dateTime : qAsConst(times)) {
45 auto scalarSeries = this->retrieveData(dateTime);
48 46 emit dataProvided(token, scalarSeries, dateTime);
49 47 }
50 48 }
General Comments 0
You need to be logged in to leave comments. Login now