Files
qt5-legatus-legacy/Lts/Services/ParticipantManagement/PartyHandling/party_handler.cpp
T
2026-08-13 18:33:10 +02:00

385 lines
14 KiB
C++
Executable File

/**
* The PartyHandler class manages all party related function topics and holds classes for
* further party data.
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-05-12
*/
#include "PartyHandling/party_handler.h"
#include "PartyHandling/party.h"
#include <ngldb/db_service_handler.h>
#include <ppm_db.h>
#include "main_handler.h"
namespace ParticipantManagement
{
//------------------------------------------------------------------------------------------
PartyHandling::PartyHandler::PartyHandler(MainHandler *mainHandler)
: ModifyPartyDataRequestHandler(mainHandler->fts())
, RemovePartyRequestHandler(mainHandler->fts())
, SyncPartiesRequestHandler(mainHandler->exerciseId() <= 0 ? nullptr : mainHandler->fts())
, ChangePartyUsedStateRequestHandler(mainHandler->fts())
, m_mainHandler(mainHandler)
, m_logger(getLogger("PartyHandler"))
{
}
//------------------------------------------------------------------------------------------
PartyHandling::PartyHandler::~PartyHandler()
{
qDeleteAll(m_parties);
}
//------------------------------------------------------------------------------------------
PartyHandling::Party *PartyHandling::PartyHandler::partyById(int32_t partyId) const
{
return m_parties.value(partyId, nullptr);
}
//------------------------------------------------------------------------------------------
bool PartyHandling::PartyHandler::init()
{
qDeleteAll(m_parties);
m_parties.clear();
QVector<Database::PpmParty> partyVec;
// read parties from db
if (!m_mainHandler->db()->select(partyVec))
{
ERROR_LOG(m_logger) << "Error while reading party data from database";
return false;
}
// if there are no parties in db and this instance of ParticipantManagement runs not in ex_0
// parties are fetched from ex_0 PPM
if (m_mainHandler->exerciseId() > 0 && partyVec.isEmpty())
partyVec = loadDefaultParties(true);
if (partyVec.isEmpty())
{
ERROR_LOG(m_logger) << "Error while reading party data from database";
return false;
}
for ( Database::PpmParty currentParty : qAsConst(partyVec))
{
resetAdlerProperties(currentParty.properties, currentParty.id);
PartyHandling::Party *newParty = new PartyHandling::Party(currentParty);
m_parties.insert(currentParty.id, newParty);
m_mainHandler->dts()->publish(newParty->toDdsParty());
}
return true;
}
//------------------------------------------------------------------------------------------
void PartyHandling::PartyHandler::resetAdlerProperties( QString &properties, const int partyId)
{
DEBUG_LOG(m_logger) << "properties: " << properties;
QJsonObject obj = QJsonDocument::fromJson(properties.toUtf8()).object();
if (!obj.contains(QStringLiteral("Adler")))
return;
const ParticipantManagement::ConnectState connectState = m_mainHandler->ddsHandler()->dtc()->saaConnectedState(partyId);
if (connectState == ParticipantManagement::ConnectState::Undefined)
return;
DEBUG_LOG(m_logger) << "connectState: " << connectState;
if (connectState != ParticipantManagement::ConnectState::Disconnected)
{
QJsonObject propAdler = obj[QStringLiteral("Adler")].toObject();
propAdler[QStringLiteral("saaConnectedState")] = ParticipantManagement::ConnectState::Disconnected;
obj[QStringLiteral("Adler")] = propAdler;
const QByteArray propertiesStr = QJsonDocument(obj).toJson(QJsonDocument::Compact);
properties = QString::fromStdString(propertiesStr.data());
INFO_LOG(m_logger) << "isSaaConnected set to false";
}
}
//------------------------------------------------------------------------------------------
QVector<Database::PpmParty> PartyHandling::PartyHandler::loadDefaultParties(bool withInsert) const
{
QVector<Database::PpmParty> partyVec;
if (!m_mainHandler->dbEx0()->select(partyVec))
ERROR_LOG(m_logger) << "Error while reading party data from database (ex_0)";
auto cb = [](const Database::PpmParty &p1,const Database::PpmParty &p2) -> bool
{
return p1.id < p2.id;
};
std::sort(partyVec.begin(), partyVec.end(), cb);
if (withInsert)
{
for (auto it = partyVec.begin(); it != partyVec.end(); ++it)
{
// just inserting a new party, means is not in use
(*it).isUsedBy = false;
m_mainHandler->db()->insert(*it);
}
m_mainHandler->db()->fixUpSequencePpmParty();
}
return partyVec;
}
//------------------------------------------------------------------------------------------
void PartyHandling::PartyHandler::onModifyPartyDataRequest(const rti::core::SampleIdentity &cookie,
const ParticipantManagement::Party &request)
{
auto ret = modifyPartyDataRequest(request);
if (ret.error())
WARNING_LOG(m_logger) << ret();
m_mainHandler->fts()->modifyPartyDataReply(cookie, ret);
}
//------------------------------------------------------------------------------------------
Core::FunctionReplyObject PartyHandling::PartyHandler::modifyPartyDataRequest(const ParticipantManagement::Party &request)
{
DEBUG_LOG(m_logger) << "onModifyPartyDataRequest: " << request;
Party *partyToPublish = m_parties.value(request.id());
if (!partyToPublish && request.id() >= 0)
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Could not modify party with id %1, because no party with that id exists"))
.arg(request.id());
if (!partyToPublish) // create new party
{
DEBUG_LOG(m_logger) << "Creating new party";
// insert into database
Database::PpmParty newDbParty;
newDbParty.color = request.color();
newDbParty.fadingColor = request.fadingColor();
newDbParty.name = QString::fromStdString(request.name());
newDbParty.roleId = request.role();
newDbParty.isUsedBy = request.isUsedBy();
newDbParty.hlaForceIdentifier = request.hlaForceIdentifier().underlying();
newDbParty.properties = QString::fromStdString(request.properties());
if (!m_mainHandler->db()->insert(newDbParty))
{
QString errText = m_mainHandler->db()->getLastError().databaseText();
ERROR_LOG(m_logger) << "Error inserting Party into database: " << errText;
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Error inserting new party to database: %1")).arg(errText);
}
partyToPublish = new Party(newDbParty);
m_parties.insert(partyToPublish->id(), partyToPublish);
}
else // modify existing party
{
DEBUG_LOG(m_logger) << "Modifying party with id " << partyToPublish->id();
if (!partyToPublish->hasChanges(request, true))
partyToPublish = nullptr; // so it will not be published at the end of this method ...
else // update in database
{
if (!m_mainHandler->db()->update(partyToPublish->toDbParty()))
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Error updating party in database"));
}
}
if (partyToPublish)
{
auto party = partyToPublish->toDdsParty();
m_mainHandler->dts()->publish(party);
}
return Core::FunctionReplyObject(request.id());
}
//------------------------------------------------------------------------------------------
void PartyHandling::PartyHandler::onRemovePartyRequest(const rti::core::SampleIdentity &cookie,
const ParticipantManagement::RemovePartyRequest &request)
{
DEBUG_LOG(m_logger) << "onRemovePartyRequest: " << request;
auto ret = removePartyRequest(request);
if (ret.error())
WARNING_LOG(m_logger) << ret();
m_mainHandler->fts()->removePartyReply(cookie, ret);
}
//------------------------------------------------------------------------------------------
Core::FunctionReplyObject PartyHandling::PartyHandler::removePartyRequest(const ParticipantManagement::RemovePartyRequest &request)
{
DEBUG_LOG(m_logger) << "onRemovePartyRequest " << request;
if (request.partyId() < 0)
return Core::FunctionReplyObject(tr_lts("dds", "Got request to delete a party, but no valid party id to delete"));
Party *partyToDelete = m_parties.value(request.partyId());
if (!partyToDelete)
return Core::FunctionReplyObject(tr_lts("dds", "Could not delete party with id %1, because no party with that id exists"))
.arg(request.partyId());
if (partyToDelete->isUsedBy() == true)
return Core::FunctionReplyObject(tr_lts("dds", "Not possible to delete a party in use"));
DEBUG_LOG(m_logger) << "Removing party with ID " << request.partyId();
return removeParty(partyToDelete);
}
//------------------------------------------------------------------------------------------
Core::FunctionReplyObject PartyHandling::PartyHandler::removeParty(Party *partyToDelete)
{
const int partyId = partyToDelete->id();
// delete from db
if (!m_mainHandler->db()->removePpmParty(partyId))
return Core::FunctionReplyObject(tr_lts("dds", "Error removing party with id %1 from database")).arg(partyId);
// delete from dds
m_mainHandler->dts()->removePartyByKey(partyId);
// delete from map
m_parties.remove(partyId);
delete partyToDelete;
return Core::FunctionReplyObject(partyId);
}
//------------------------------------------------------------------------------------------
void PartyHandling::PartyHandler::onSyncPartiesRequest(const rti::core::SampleIdentity &cookie,
const ParticipantManagement::SyncPartiesRequest &request)
{
DEBUG_LOG(m_logger) << "onSyncPartiesRequest: " << request;
Core::FunctionReplyObject rep;
QVector<Database::PpmParty> partyVec = loadDefaultParties(false);
for (auto it = partyVec.begin(); it != partyVec.end(); ++it)
{
int partyId = (*it).id;
DEBUG_LOG(m_logger) << "Checking Party Id: " << partyId;
Database::PpmParty partyEx0 = (*it);
if (!m_parties.contains(partyId))
{
// just inserting a new party, means is not yet in use
partyEx0.isUsedBy = false;
if (!m_mainHandler->db()->insert(partyEx0))
{
QString errText = m_mainHandler->db()->getLastError().databaseText();
WARNING_LOG(m_logger) << "Error inserting new party with id " << partyId << " to database: " << errText;
continue;
}
else
{
DEBUG_LOG(m_logger) << "Inserting Party Id: " << partyId;
PartyHandling::Party *newParty = new PartyHandling::Party(partyEx0);
m_parties.insert(partyEx0.id, newParty);
m_mainHandler->dts()->publish(newParty->toDdsParty());
}
}
else
{
Party *partyEx = m_parties.value(partyId);
bool hasChanges = partyEx0.color != partyEx->toDbParty().color
|| partyEx0.fadingColor != partyEx->toDbParty().fadingColor
|| partyEx0.name != partyEx->toDbParty().name
|| partyEx0.hlaForceIdentifier != partyEx->toDbParty().hlaForceIdentifier
|| partyEx0.roleId != partyEx->toDbParty().roleId;
DEBUG_LOG(m_logger) << "Has changes = " << hasChanges;
if (hasChanges)
{
ParticipantManagement::Party req;
req.id(partyId);
// taking new properties from ex_0
req.color(partyEx0.color);
req.fadingColor(partyEx0.fadingColor);
req.name(partyEx0.name.toStdString());
req.role(partyEx0.roleId);
req.hlaForceIdentifier(static_cast<HlaForceIdentifierEnum::inner_enum>(partyEx0.hlaForceIdentifier));
// this remains as it is
req.isUsedBy(partyEx->isUsedBy());
auto ret = modifyPartyDataRequest(req);
if (ret.error())
WARNING_LOG(m_logger) << ret();
}
}
}
// now checking for non-existent parties in ex_0
const auto partiesCopy(m_parties);
for (Party *curParty : partiesCopy)
{
bool found = false;
for (auto it = partyVec.begin(); it != partyVec.end(); ++it)
{
int partyId = (*it).id;
if (partyId == curParty->id())
{
found = true;
break;
}
}
if (!found)
{
DEBUG_LOG(m_logger) << "Party id to be deleted = " << curParty->id();
if (curParty->isUsedBy())
INFO_LOG(m_logger) << "Party with id " << curParty->id() << " cannot be deleted, is in use";
else
{
auto ret = removeParty(curParty); // removed from map etc
if (ret.error())
WARNING_LOG(m_logger) << ret();
}
}
}
m_mainHandler->db()->fixUpSequencePpmParty();
m_mainHandler->fts()->syncPartiesReply(cookie, rep);
}
//------------------------------------------------------------------------------------------
void PartyHandling::PartyHandler::onChangePartyUsedStateRequest(const rti::core::SampleIdentity &cookie,
const ParticipantManagement::ChangePartyUsedStateRequest &request)
{
DEBUG_LOG(m_logger) << "onChangePartyUsedStateRequest: " << request;
auto ret = changePartyUsedStateRequest(request);
if (ret.error())
WARNING_LOG(m_logger) << ret();
m_mainHandler->fts()->changePartyUsedStateReply(cookie, ret);
}
//------------------------------------------------------------------------------------------
Core::FunctionReplyObject PartyHandling::PartyHandler::changePartyUsedStateRequest(const ParticipantManagement::ChangePartyUsedStateRequest &request)
{
Party *party = m_parties.value(request.partyId());
if (!party)
return Core::FunctionReplyObject(request.partyId(), tr_lts("dds", "Could not modify party with id %1, because no party with that id exists"))
.arg(request.partyId());
ParticipantManagement::Party ddsParty = party->toDdsParty();
ddsParty.isUsedBy(request.isUsedBy());
if (party->hasChanges(ddsParty, false))
{
if (!m_mainHandler->db()->update(party->toDbParty()))
return Core::FunctionReplyObject(request.partyId(), tr_lts("dds", "Error updating party used state in database"));
DEBUG_LOG(m_logger) << "Change used state for party " << party->id() << " to " << party->isUsedBy();
m_mainHandler->dts()->publish(party->toDdsParty());
}
return Core::FunctionReplyObject(request.partyId());
}
} // namespace ParticipantManagement