Heart 1.3.848.aa44c26
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-2025 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 qWarning () << "Can't found requeried parser for versions";
51 }
52
53 auto perserResult = parser->parsePackage(pkg, pkgHeader, sender);
55 return perserResult;
56 }
57
59}
60
62 return 0;
63}
64
66 return "APIVersionParser";
67}
68
70 QString message = " supports parsers:\n";
72
73 for (const auto& parser: _apiParsers) {
74 for (auto it = parser.begin(); it != parser.end(); ++it) {
75 message += "ver: " + QString::number(it.key()) + " " + it.value()->toString();
76 }
77 }
78
79 return message;
80}
81
82QSharedPointer<PKG::AbstractData>
84 AbstractNodeInfo *sender) const {
85 if (!sender)
86 return nullptr;
87
88 if (cmd == PKG::APIVersion::command()) {
89 return QSharedPointer<PKG::APIVersion>::create();
90 } else if (cmd == PKG::VersionIsReceived::command()) {
91 return QSharedPointer<PKG::VersionIsReceived>::create();
92 }
93
94 auto distVersion = sender->version();
95 const auto parsers = selectParser(distVersion);
96
97 if (parsers.isEmpty()) {
98 return nullptr;
99 }
100
101 for (const auto& parser: parsers) {
102 if (!parser) {
103 qCritical() << "Internal Error with selection parasers.";
104 continue;
105 }
106
107 if (auto package = parser->genPackage(cmd))
108 return package;
109 }
110
111 return nullptr;
112}
113
114QSharedPointer<iParser>
116 AbstractNodeInfo *node) const {
117 return selectParser(node->version()).value(apiKey, nullptr);
118}
119
120bool QH::APIVersionParser::commandsValidation(const QSharedPointer<iParser> &parserObject) {
121#ifdef QT_DEBUG
122 auto types = QSet<unsigned short>{parserObject->registeredTypes().keyBegin(),
123 parserObject->registeredTypes().keyEnd()};
124 int typesSize = types.size();
125
126 for (const auto &parsersMap : std::as_const(_apiParsers)) {
127 for (const auto &parser: parsersMap) {
128 if (parser->parserId() == parserObject->parserId()) {
129 continue;
130 }
131
132 auto localTypes = QSet<unsigned short>{parser->registeredTypes().keyBegin(),
133 parser->registeredTypes().keyEnd()};
134 types -= localTypes;
135
136 if (types.size() != typesSize) {
137 auto err = QString("Parser object can't be added. "
138 "Because commands of the %0_v%1 parser "
139 "already registered in the %2_v%3 parser. "
140 "Use the iParser::initSupportedCommands method to "
141 "fix this issue. "
142 "See our documentation for get more inforamtion. "
143 "https://quasarapp.ddns.net:3031/docs/QuasarApp/Heart/latest/classQH_1_1iParser.html").
144 arg(parserObject->parserId()).
145 arg(parserObject->version()).
146 arg(parser->parserId()).
147 arg(parser->version());
148
149 qCritical() << err;
150
151 return false;
152 }
153 }
154 }
155#endif
156
157 return true;
158}
159
160const QSharedPointer<QH::iParser>& APIVersionParser::addApiParser(const QSharedPointer<iParser> &parserObject) {
161 debug_assert(parserObject, "Parser object should not be nullptr");
162
163 parserObject->initSupportedCommands();
164
165 if (!commandsValidation(parserObject)) {
166 debug_assert(false, "Parser object can't be added. "
167 "Because its commands already registered "
168 "in the another parsers.");
169 }
170
171 _apiParsers[parserObject->parserId()][parserObject->version()] = parserObject;
172 return _apiParsers[parserObject->parserId()][parserObject->version()];
173}
174
175QHash<QString, QSharedPointer<iParser>>
178
179 for (auto it = distVersion.begin(); it != distVersion.end(); ++it) {
180 for (int version = it->max(); version >= it->min(); --version) {
181 auto parser = _apiParsers[it.key()].value(version, nullptr);
182 if (parser) {
183 result[it.key()] = parser;
184 break;
185 }
186 }
187 }
188
189 return result;
190}
191
193 return _apiParsers.size();
194}
195
196QSharedPointer<iParser> APIVersionParser::selectParser(unsigned short cmd,
197 AbstractNodeInfo *sender) const{
198 auto parser = sender->getParser(cmd);
199 if (!parser) {
200 parser = selectParserImpl(cmd, sender);
201 }
202
203 return parser;
204}
205
206QSharedPointer<iParser> APIVersionParser::selectParser(const QString &parserKey,
207 AbstractNodeInfo *sender) const {
208 if (!sender)
209 return nullptr;
210
211 auto parser = sender->getParser(parserKey);
212 if (!parser) {
213 parser = selectParserImpl(parserKey, sender);
214 }
215
216 return parser;
217}
218
219QSharedPointer<iParser> APIVersionParser::selectParser(const QString &parserKey,
220 unsigned short version) const {
221
224 versionData.setMax(version);
225
228
229 return selectParser(versions).value(parserKey);
230}
231
232QSharedPointer<iParser> APIVersionParser::selectParserImpl(unsigned short cmd,
233 AbstractNodeInfo *sender) const {
234 auto version = sender->version();
236 for (const auto& parser: availableParser) {
237 if (parser->checkCommand(cmd)) {
238 sender->addParser(cmd, parser);
239 return parser;
240 }
241 }
242
243 return nullptr;
244}
245
246QSharedPointer<iParser> APIVersionParser::selectParserImpl(const QString &key,
247 AbstractNodeInfo *sender) const{
248 auto version = sender->version();
249 auto parser = selectParser(version).value(key);
250 sender->addParser(parser);
251
252 return parser;
253}
254
255unsigned short APIVersionParser::maximumApiVersion(const QString &apiKey) const {
256
257 auto availableVersion = _apiParsers.value(apiKey, {});
258 if (availableVersion.size()) {
259 return availableVersion.lastKey();
260 }
261
262 return 0;
263}
264
265unsigned short APIVersionParser::minimumApiVersion(const QString &apiKey) const {
266 auto availableVersion = _apiParsers.value(apiKey, {});
267 if (availableVersion.size()) {
268 return availableVersion.firstKey();
269 }
270
271 return 0;
272}
273
277
278 for (auto it = _apiParsers.begin(); it != _apiParsers.end(); ++it) {
280
281 for (auto api = it->begin(); api != it->end(); ++api) {
282 const auto packages = api.value()->multiVersionPackages();
283 for (auto pkg = packages.begin(); pkg != packages.end(); ++pkg) {
284 multiVersionPackages[pkg.key()] = pkg.value();
285 }
286 }
287
288 supportVersions.setMax(it->lastKey());
289 supportVersions.setMin(it->firstKey());
290
291 supportedAPIs.insert(it.key(), supportVersions);
292
293 }
294
295 if (supportedAPIs.isEmpty())
296 return false;
297
300 versionInformationPkg.setPackagesVersions(multiVersionPackages);
301
303}
304
305bool APIVersionParser::processAppVersion(const QSharedPointer<PKG::APIVersion> &message,
306 QH::AbstractNodeInfo *sender,
307 const QH::Header &) {
308
309 auto distVersion = message->apisVersions();
310 sender->setVersion(distVersion);
311 sender->setMultiVersionPackages(message->packagesVersions());
312
314
315 for (auto parserKey = distVersion.keyBegin(); parserKey != distVersion.keyEnd(); ++parserKey) {
316 if (!parser.contains(*parserKey)) {
317 auto requiredApi = distVersion.value(*parserKey);
318
319 qCritical() << "Can't found required parser for versions: " << *parserKey << requiredApi.min() << requiredApi.max();
320
321 unsigned short distMinVersion = sender->version().value(*parserKey).min();
322
325 }
326
327 return false;
328 }
329 }
330
331 sender->setFVersionReceived(true);
332
333 PKG::VersionIsReceived result;
334 return node()->sendData(&result, sender);
335}
336
337bool APIVersionParser::versionDeliveredSuccessful(const QSharedPointer<PKG::VersionIsReceived> &,
338 AbstractNodeInfo *sender,
339 const QH::Header &) {
340 sender->setFVersionDelivered(true);
341 return true;
342}
343
344}
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