#include "application_connector.h" #include "model_manager.h" #include "repository_manager.h" #include "schema_metadata.h" #include ApplicationConnector::ApplicationConnector(QObject *rootObject) : modelManager_(ModelManager::instance()), repositoryManager_(RepositoryManager::instance()), rootObject_(rootObject) {} bool ApplicationConnector::connect() { if (!connectSelfReferenceTableLinks()) { return false; } if (!connectTablePairLinks()) { return false; } if (!connectUpdateDeleteRFLinks()) { return false; } if (!connectDeleteRFLinks()) { return false; } return true; } ApplicationConnector::RMLinkList ApplicationConnector::initializeSelfReferenceTableLinks() { return {linkRepositoryToModel("genres", "genres"), linkRepositoryToModel("halls", "halls"), linkRepositoryToModel("movies", "movies"), linkRepositoryToModel("sessions", "sessions"), linkRepositoryToModel("refunds", "refunds"), linkRepositoryToModel("tickets", "tickets")}; } ApplicationConnector::RMLinkList ApplicationConnector::initializeTablePairLinks() { return {linkRepositoryToModel("genres", "movies"), linkRepositoryToModel("genres", "sessions"), linkRepositoryToModel("genres", "tickets"), linkRepositoryToModel("genres", "refunds"), linkRepositoryToModel("halls", "sessions"), linkRepositoryToModel("halls", "tickets"), linkRepositoryToModel("halls", "refunds"), linkRepositoryToModel("movies", "sessions"), linkRepositoryToModel("movies", "tickets"), linkRepositoryToModel("movies", "refunds"), linkRepositoryToModel("sessions", "refunds"), linkRepositoryToModel("tickets", "refunds")}; } ApplicationConnector::RFLinkList ApplicationConnector::flattenLinkList(const QVector &linkLists) { RFLinkList result; for (const RFLinkList ¤tList : linkLists) { std::move(currentList.cbegin(), currentList.cend(), std::back_inserter(result)); } return result; } ApplicationConnector::RFLinkList ApplicationConnector::initializeUpdateDeleteCandidates() { const QVector updateDeleteCandidates = { linkRepositoryToFinder("genres", "genreFinder"), linkRepositoryToFinder("genres", "movieFinder"), linkRepositoryToFinder("genres", "sessionFinder"), linkRepositoryToFinder("genres", "ticketFinder"), linkRepositoryToFinder("genres", "entityFinder"), linkRepositoryToFinder("halls", "hallFinder"), linkRepositoryToFinder("halls", "movieFinder"), linkRepositoryToFinder("halls", "sessionFinder"), linkRepositoryToFinder("halls", "ticketFinder"), linkRepositoryToFinder("halls", "entityFinder"), linkRepositoryToFinder("movies", "movieFinder"), linkRepositoryToFinder("movies", "sessionFinder"), linkRepositoryToFinder("movies", "ticketFinder"), linkRepositoryToFinder("movies", "entityFinder"), linkRepositoryToFinder("sessions", "sessionFinder"), linkRepositoryToFinder("sessions", "ticketFinder"), linkRepositoryToFinder("sessions", "entityFinder"), linkRepositoryToFinder("tickets", "ticketFinder"), linkRepositoryToFinder("tickets", "entityFinder"), linkRepositoryToFinder("refunds", "entityFinder")}; return flattenLinkList(updateDeleteCandidates); } ApplicationConnector::RFLinkList ApplicationConnector::initializeDeleteCandidates() { // foreignKeyFinder will reset to default on signal primaryKeyFinder const QVector deleteCandidates = { linkRepositoryToFinder("genres", "primaryKeyFinder"), linkRepositoryToFinder("halls", "primaryKeyFinder"), linkRepositoryToFinder("movies", "primaryKeyFinder"), linkRepositoryToFinder("sessions", "primaryKeyFinder"), linkRepositoryToFinder("tickets", "primaryKeyFinder"), linkRepositoryToFinder("refunds", "primaryKeyFinder")}; return flattenLinkList(deleteCandidates); } bool ApplicationConnector::connectSelfReferenceTableLinks() { const QList selfReferenceTableLinks = initializeSelfReferenceTableLinks(); qInfo() << "Connecting self-reference tables..."; if (!connect(selfReferenceTableLinks, singleTableConnections())) { qWarning() << "Failed to connect self-reference tables"; return false; } return true; } bool ApplicationConnector::connectTablePairLinks() { const RMLinkList tablePairLinks = initializeTablePairLinks(); qInfo() << "Connecting pair tables..."; if (!connect(tablePairLinks, pairTableConnections())) { qWarning() << "Failed to connect pair tables"; return false; } return true; } bool ApplicationConnector::connectUpdateDeleteRFLinks() { const RFLinkList repositoryToFinderLinks = initializeUpdateDeleteCandidates(); qInfo() << "Connecting repository to finder..."; if (!connect(repositoryToFinderLinks, repositoryToFinderConnections())) { qWarning() << "Failed to connect repository to finder"; return false; } return true; } bool ApplicationConnector::connectDeleteRFLinks() { const RFLinkList repositoryToFinderLinks = initializeDeleteCandidates(); qInfo() << "Connecting repository to finder..."; using Signal = void (Repository::*)(); using Slot = void (Finder::*)(); RFConnectionList connections; connections.append(Connection(&Repository::dataDeleted, &Finder::resetToDefault)); if (!connect(repositoryToFinderLinks, connections)) { qWarning() << "Failed to connect repository to finder"; return false; } return true; } ApplicationConnector::RMConnectionList ApplicationConnector::pairTableConnections() { using Signal = void (Repository::*)(); using Slot = bool (Model::*)(); RMConnectionList result; std::initializer_list> initList = { {&Repository::dataUpdated, &Model::refreshAll}, {&Repository::dataDeleted, &Model::refreshAll}}; for (const auto &connection : initList) { result.append(connection); } return result; } ApplicationConnector::RMConnectionList ApplicationConnector::singleTableConnections() { using Signal = void (Repository::*)(); using Slot = bool (Model::*)(); RMConnectionList result; std::initializer_list> initList = { {&Repository::dataCreated, &Model::refreshAll}, {&Repository::dataUpdated, &Model::refreshAll}, {&Repository::dataDeleted, &Model::refreshAll}}; for (const auto &connection : initList) { result.append(connection); } return result; } ApplicationConnector::RMLink ApplicationConnector::linkRepositoryToModel( const QString &senderDatabaseTableName, const QString &receiverDatabaseTableName) { SchemaMetadata metadata = SchemaMetadata::defaultSchema(); Repository *sender = repositoryManager_.getRepositoryAs( metadata.repositoryTableName(senderDatabaseTableName)); if (!sender) { qWarning() << "Sender with type" << typeid(sender).name() << "is null"; } Model *receiver = modelManager_.getModelAs( metadata.modelTableName(receiverDatabaseTableName)); if (!receiver) { qWarning() << "Receiver with type" << typeid(receiver).name() << "is null"; } if (!sender || !receiver) { return qMakePair(nullptr, nullptr); } return qMakePair(sender, receiver); } ApplicationConnector::RFLinkList ApplicationConnector::linkRepositoryToFinder( const QString &senderDatabaseTableName, const QString &receiverEntityFinderName) { SchemaMetadata metadata = SchemaMetadata::defaultSchema(); Repository *sender = repositoryManager_.getRepositoryAs( metadata.repositoryTableName(senderDatabaseTableName)); if (!sender) { qWarning() << "Sender with type" << typeid(sender).name() << "is null"; } QList receiver = rootObject_->findChildren(receiverEntityFinderName); if (receiver.isEmpty()) { qWarning() << "Receivers with type" << typeid(receiver).name() << "there is not"; } if (!sender || receiver.isEmpty()) { return QList(); } RFLinkList result; for (Finder *currentReceiver : receiver) { result.append(qMakePair(sender, currentReceiver)); } return result; } ApplicationConnector::RFConnectionList ApplicationConnector::repositoryToFinderConnections() { using Signal = void (Repository::*)(); using Slot = void (Finder::*)(); RFConnectionList result; std::initializer_list> initList = { {&Repository::dataDeleted, &Finder::resetToDefault}, {&Repository::dataUpdated, &Finder::resetToDefault}}; for (const auto &connection : initList) { result.append(connection); } return result; } QString ApplicationConnector::getAddress(const QObject *object) { quintptr address = reinterpret_cast(object); return object ? QString::number(address, 16) : "null"; }; QString ApplicationConnector::getMetaClassName(const QMetaObject *meta) { return meta ? meta->className() : "Unknown"; }; QString ApplicationConnector::getMethodSignature(const QMetaObject *meta, const char *methodType, bool isSignal) { if (!meta) { return "Unknown"; } QByteArray normalizedSignature = QMetaObject::normalizedSignature(methodType); int methodIndex = isSignal ? meta->indexOfSignal(normalizedSignature) : meta->indexOfSlot(normalizedSignature); if (methodIndex < 0) { return normalizedSignature; } QString result = meta->method(methodIndex).methodSignature(); return result; };