Heart 1.3.842.34c2ab5
Heart is base back end library for your c++ Qt projects.
apiversionparser.cpp
Go to the documentation of this file.
1//#
2//# Copyright (C) 2022-2024 QuasarApp.
3//# Distributed under the lgplv3 software license, see the accompanying
4//# Everyone is permitted to copy and distribute verbatim copies
5//# of this license document, but changing it is not allowed.
6//#
7
8#include "apiversionparser.h"
9#include "abstractnodeinfo.h"
10#include "distversion.h"
11
12#include <apiversion.h>
13#include <versionisreceived.h>
14#include <quasarapp.h>
15#include <versionisreceived.h>
16#include <abstractnode.h>
17#include <qaglobalutils.h>
18#include <apiversion.h>
19
20namespace QH {
21
25
26ParserResult APIVersionParser::parsePackage(const QSharedPointer<PKG::AbstractData> &pkg,
27 const Header &pkgHeader,
28 AbstractNodeInfo *sender) {
29
30 // here node must be receive version of connected application.
31 // if not use the default version (0)APIVersion
32 auto parentResult = commandHandler<PKG::APIVersion>(this, &APIVersionParser::processAppVersion,
35 return parentResult;
36 }
37
38 // here node must be receive responce that version is delivered.
39 // when node receive this message then node status are confirmed
40 parentResult = commandHandler<PKG::VersionIsReceived>(this, &APIVersionParser::versionDeliveredSuccessful,
43 return parentResult;
44 }
45
46 const auto parser = selectParser(pkg->cmd(), sender);
47
48 if (!parser) {
49 QuasarAppUtils::Params::log(QString("Can't found requeried parser for versions"),
50 QuasarAppUtils::Warning);
52 }
53
54 auto perserResult = parser->parsePackage(pkg, pkgHeader, sender);
56 return perserResult;
57 }
58
60}
61
63 return 0;
64}
65
67 return "APIVersionParser";
68}
69
71 QString message = " supports parsers:\n";
73
74 for (const auto& parser: _apiParsers) {
75 for (auto it = parser.begin(); it != parser.end(); ++it) {
76 message += "ver: " + QString::number(it.key()) + " " + it.value()->toString();
77 }
78 }
79
80 return message;
81}
82
83QSharedPointer<PKG::AbstractData>
85 AbstractNodeInfo *sender) const {
86 if (!sender)
87 return nullptr;
88
89 if (cmd == PKG::APIVersion::command()) {
90 return QSharedPointer<PKG::APIVersion>::create();
91 } else if (cmd == PKG::VersionIsReceived::command()) {
92 return QSharedPointer<PKG::VersionIsReceived>::create();
93 }
94
95 auto distVersion = sender->version();
96 const auto parsers = selectParser(distVersion);
97
98 if (parsers.isEmpty()) {
99 return nullptr;
100 }
101
102 for (const auto& parser: parsers) {
103 if (!parser) {
104 QuasarAppUtils::Params::log(QString("Internal Error with selection parasers."),
105 QuasarAppUtils::Error);
106 continue;
107 }
108
109 if (auto package = parser->genPackage(cmd))
110 return package;
111 }
112
113 return nullptr;
114}
115
116QSharedPointer<iParser>
118 AbstractNodeInfo *node) const {
119 return selectParser(node->version()).value(apiKey, nullptr);
120}
121
122bool QH::APIVersionParser::commandsValidation(const QSharedPointer<iParser> &parserObject) {
123#ifdef QT_DEBUG
124 auto types = QSet<unsigned short>{parserObject->registeredTypes().keyBegin(),
125 parserObject->registeredTypes().keyEnd()};
126 int typesSize = types.size();
127
128 for (const auto &parsersMap : std::as_const(_apiParsers)) {
129 for (const auto &parser: parsersMap) {
130 if (parser->parserId() == parserObject->parserId()) {
131 continue;
132 }
133
134 auto localTypes = QSet<unsigned short>{parser->registeredTypes().keyBegin(),
135 parser->registeredTypes().keyEnd()};
136 types -= localTypes;
137
138 if (types.size() != typesSize) {
139 auto err = QString("Parser object can't be added. "
140 "Because commands of the %0_v%1 parser "
141 "already registered in the %2_v%3 parser. "
142 "Use the iParser::initSupportedCommands method to "
143 "fix this issue. "
144 "See our documentation for get more inforamtion. "
145 "https://quasarapp.ddns.net:3031/docs/QuasarApp/Heart/latest/classQH_1_1iParser.html").
146 arg(parserObject->parserId()).
147 arg(parserObject->version()).
148 arg(parser->parserId()).
149 arg(parser->version());
150
151 QuasarAppUtils::Params::log(err, QuasarAppUtils::Error);
152
153 return false;
154 }
155 }
156 }
157#endif
158
159 return true;
160}
161
162const QSharedPointer<QH::iParser>& APIVersionParser::addApiParser(const QSharedPointer<iParser> &parserObject) {
163 debug_assert(parserObject, "Parser object should not be nullptr");
164
165 parserObject->initSupportedCommands();
166
167 if (!commandsValidation(parserObject)) {
168 debug_assert(false, "Parser object can't be added. "
169 "Because its commands already registered "
170 "in the another parsers.");
171 }
172
173 _apiParsers[parserObject->parserId()][parserObject->version()] = parserObject;
174 return _apiParsers[parserObject->parserId()][parserObject->version()];
175}
176
177QHash<QString, QSharedPointer<iParser>>
180
181 for (auto it = distVersion.begin(); it != distVersion.end(); ++it) {
182 for (int version = it->max(); version >= it->min(); --version) {
183 auto parser = _apiParsers[it.key()].value(version, nullptr);
184 if (parser) {
185 result[it.key()] = parser;
186 break;
187 }
188 }
189 }
190
191 return result;
192}
193
195 return _apiParsers.size();
196}
197
198QSharedPointer<iParser> APIVersionParser::selectParser(unsigned short cmd,
199 AbstractNodeInfo *sender) const{
200 auto parser = sender->getParser(cmd);
201 if (!parser) {
202 parser = selectParserImpl(cmd, sender);
203 }
204
205 return parser;
206}
207
208QSharedPointer<iParser> APIVersionParser::selectParser(const QString &parserKey,
209 AbstractNodeInfo *sender) const {
210 if (!sender)
211 return nullptr;
212
213 auto parser = sender->getParser(parserKey);
214 if (!parser) {
215 parser = selectParserImpl(parserKey, sender);
216 }
217
218 return parser;
219}
220
221QSharedPointer<iParser> APIVersionParser::selectParser(const QString &parserKey,
222 unsigned short version) const {
223
226 versionData.setMax(version);
227
230
231 return selectParser(versions).value(parserKey);
232}
233
234QSharedPointer<iParser> APIVersionParser::selectParserImpl(unsigned short cmd,
235 AbstractNodeInfo *sender) const {
236 auto version = sender->version();
238 for (const auto& parser: availableParser) {
239 if (parser->checkCommand(cmd)) {
240 sender->addParser(cmd, parser);
241 return parser;
242 }
243 }
244
245 return nullptr;
246}
247
248QSharedPointer<iParser> APIVersionParser::selectParserImpl(const QString &key,
249 AbstractNodeInfo *sender) const{
250 auto version = sender->version();
251 auto parser = selectParser(version).value(key);
252 sender->addParser(parser);
253
254 return parser;
255}
256
257unsigned short APIVersionParser::maximumApiVersion(const QString &apiKey) const {
258
259 auto availableVersion = _apiParsers.value(apiKey, {});
260 if (availableVersion.size()) {
261 return availableVersion.lastKey();
262 }
263
264 return 0;
265}
266
267unsigned short APIVersionParser::minimumApiVersion(const QString &apiKey) const {
268 auto availableVersion = _apiParsers.value(apiKey, {});
269 if (availableVersion.size()) {
270 return availableVersion.firstKey();
271 }
272
273 return 0;
274}
275
279
280 for (auto it = _apiParsers.begin(); it != _apiParsers.end(); ++it) {
282
283 for (auto api = it->begin(); api != it->end(); ++api) {
284 const auto packages = api.value()->multiVersionPackages();
285 for (auto pkg = packages.begin(); pkg != packages.end(); ++pkg) {
286 multiVersionPackages[pkg.key()] = pkg.value();
287 }
288 }
289
290 supportVersions.setMax(it->lastKey());
291 supportVersions.setMin(it->firstKey());
292
293 supportedAPIs.insert(it.key(), supportVersions);
294
295 }
296
297 if (supportedAPIs.isEmpty())
298 return false;
299
302 versionInformationPkg.setPackagesVersions(multiVersionPackages);
303
305}
306
307bool APIVersionParser::processAppVersion(const QSharedPointer<PKG::APIVersion> &message,
308 QH::AbstractNodeInfo *sender,
309 const QH::Header &) {
310
311 auto distVersion = message->apisVersions();
312 sender->setVersion(distVersion);
313 sender->setMultiVersionPackages(message->packagesVersions());
314
316
317 for (auto parserKey = distVersion.keyBegin(); parserKey != distVersion.keyEnd(); ++parserKey) {
318 if (!parser.contains(*parserKey)) {
319 auto requiredApi = distVersion.value(*parserKey);
320
321 QuasarAppUtils::Params::log(QString("Can't found %0 parser for versions: %1-%2").
322 arg(*parserKey).
323 arg(requiredApi.min()).
324 arg(requiredApi.max()),
325 QuasarAppUtils::Error);
326
327 unsigned short distMinVersion = sender->version().value(*parserKey).min();
328
331 }
332
333 return false;
334 }
335 }
336
337 sender->setFVersionReceived(true);
338
339 PKG::VersionIsReceived result;
340 return node()->sendData(&result, sender);
341}
342
343bool APIVersionParser::versionDeliveredSuccessful(const QSharedPointer<PKG::VersionIsReceived> &,
344 AbstractNodeInfo *sender,
345 const QH::Header &) {
346 sender->setFVersionDelivered(true);
347 return true;
348}
349
350}
int version() const override
version This method return version of parser object
QSharedPointer< PKG::AbstractData > searchPackage(unsigned short cmd, AbstractNodeInfo *sender) const
searchPackage This method search package recursive in all registered pararsers. Searching will be in ...
unsigned short minimumApiVersion(const QString &apiKey) const
minimumApiVersion This method return minimum supported api version of this node.
QHash< QString, QSharedPointer< QH::iParser > > selectParser(const VersionData &distVersion) const
selectParser This method select api parser betwin nodes.
unsigned short maximumApiVersion(const QString &apiKey) const
maximumApiVersion This method return maximum supported api version of this node.
const QSharedPointer< QH::iParser > & addApiParser(const QSharedPointer< QH::iParser > &parserObject)
addApiParser This method add new Api parser for this node.
ParserResult parsePackage(const QSharedPointer< PKG::AbstractData > &pkg, const Header &pkgHeader, AbstractNodeInfo *sender) override
parsePackage This is main method of all childs classes of an AbstractNode class. This method work on ...
APIVersionParser(AbstractNode *node)
void sigNoLongerSupport(const QString &ApiKey, unsigned short version)
sigNoLongerSupport This signal will be emit when node receive incomplite versions.
QSharedPointer< iParser > getSelectedApiParser(const QString &apiKey, QH::AbstractNodeInfo *node) const
getSelectedApiParser This method return apiParser for selected node
unsigned int parsersTypedCount() const
parsersTypedCount This method return count of the parsers types.
QString toString() const override
toString This method show all supported commands and them names.
QString parserId() const override
parserId This is id of the parsers. All parser will be synced betwin nodes by ids.
bool sendSupportedAPI(AbstractNodeInfo *dist) const
sendSupportedAPI This method sents all ainformation about suppported api.
The AbstractNodeInfo class contains information about client or server connection and tcp socket of n...
The AbstractNode class - Abstract implementation of node. this implementation have a methods for send...
virtual unsigned int sendData(const PKG::AbstractData *resp, const HostAddress &address, const Header *req=nullptr)
sendData This method send data object another to node
The DistVersion class This is information of supported versions of the destinations api.
Definition distversion.h:21
void setMax(unsigned short newMax)
void setMin(unsigned short newMin)
The APIVersion class This is base pacakge class that send information about supported api version on ...
Definition apiversion.h:24
static unsigned short command()
Definition apiversion.h:29
void setApisVersions(const VersionData &newApisVersions)
static unsigned short command()
The iParser class This class provide functions for parsing income packages. For yousing just override...
Definition iparser.h:51
QString toString() const override
Definition iparser.cpp:68
virtual unsigned int sendData(const PKG::AbstractData *resp, const HostAddress &address, const Header *req=nullptr) const
sendData This method send data object another to node
Definition iparser.cpp:50
void registerPackageType()
registerPackageType This method register package type T. This is need to prepare pacakge for parsing ...
Definition iparser.h:62
const PackagesVersionData & multiVersionPackages() const
multiVersionPackages return list of the supported multiversions packages.
Definition iparser.cpp:62
AbstractNode * node() const
Definition iparser.cpp:46
The QH namespace - QuasarApp Heart namespace. This namespace contains all classes of the Heart librar...
Definition heart.cpp:13
ParserResult
The ParserResult enum. Error - parser detect a errorob package. NotProcessed - the parser does not kn...
Definition iparser.h:35
@ NotProcessed
the parser does not know what to do with the package or has not finished processing it.
QHash< QString, DistVersion > VersionData
VersionData This is array of all available apis and supported its versions.
Definition distversion.h:73
QHash< unsigned short, DistVersion > PackagesVersionData
PackagesVersionData This is some as VersionData but for int commands.
Definition distversion.h:78
The Header struct 32 bytes.
Definition header.h:19