590 lines
19 KiB
C++
Executable File
590 lines
19 KiB
C++
Executable File
/**
|
|
* CnrTvcProfileHandler - reads TetraChannel and TvcConfig data from the database and publishes the data to dds,
|
|
* reacts to TvcConfig related Function topics
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by Gerlinde Rudolphus, SLSE, 2017-10-20
|
|
*/
|
|
|
|
#include "cnr_tvc_profile_handler.h"
|
|
#include "cnr_handler.h"
|
|
#include "tvc_handler.h"
|
|
#include <AudioVideoManagement/avm_dts.h>
|
|
#include <ngldb/dbtransaction.h>
|
|
#include <QtGlobal>
|
|
#include <algorithm>
|
|
|
|
|
|
namespace AudioVideoManagement
|
|
{
|
|
|
|
namespace
|
|
{
|
|
|
|
CnrTvcProfileData toDds(const Database::AvmCnrTvcProfileData &circuitDb)
|
|
{
|
|
// either cnrConfigId or tvcConfigId must be set
|
|
|
|
if (!circuitDb.cnrConfigId.isNull())
|
|
{
|
|
Q_ASSERT(circuitDb.tvcConfigId.isNull());
|
|
return CnrTvcProfileData(circuitDb.cnrConfigId.toInt(), RadioSystem::Cnr);
|
|
}
|
|
|
|
Q_ASSERT(!circuitDb.tvcConfigId.isNull());
|
|
return CnrTvcProfileData(circuitDb.tvcConfigId.toInt(), RadioSystem::Tvc);
|
|
}
|
|
|
|
|
|
template<typename T>
|
|
CnrTvcProfile toDds(const Database::AvmCnrTvcProfile &circuitContainerDb, T circuitsDb)
|
|
{
|
|
auto lessRadioCircuitsContent = [](const Database::AvmCnrTvcProfileData &lhs, const Database::AvmCnrTvcProfileData &rhs)
|
|
{
|
|
return lhs.sortIndex < rhs.sortIndex;
|
|
};
|
|
// Bring the elements in the correct order as indicated by 'sort_index' column.
|
|
std::sort(circuitsDb.begin(), circuitsDb.end(), lessRadioCircuitsContent);
|
|
|
|
CnrTvcProfile circuitContainerDds(circuitContainerDb.id, circuitContainerDb.operatorId, circuitContainerDb.exerciseId, {});
|
|
circuitContainerDds.data().reserve(circuitsDb.size());
|
|
for (const auto ¤tCircuitDb : qAsConst(circuitsDb))
|
|
circuitContainerDds.data().push_back(toDds(currentCircuitDb));
|
|
return circuitContainerDds;
|
|
}
|
|
|
|
Database::AvmCnrTvcProfile toDb(const CnrTvcProfile &profileDds)
|
|
{
|
|
Database::AvmCnrTvcProfile profileDb;
|
|
profileDb.id = profileDds.id();
|
|
profileDb.operatorId = profileDds.operatorId();
|
|
profileDb.exerciseId = profileDds.exerciseId();
|
|
return profileDb;
|
|
}
|
|
|
|
Database::AvmCnrTvcProfileData toDb(const CnrTvcProfileData &circuitDds, int32_t containerId, int32_t sortIndex)
|
|
{
|
|
Database::AvmCnrTvcProfileData circuitDb;
|
|
circuitDb.containerId = containerId;
|
|
circuitDb.sortIndex = sortIndex;
|
|
|
|
switch (circuitDds.radioSystemId().underlying())
|
|
{
|
|
case RadioSystem::Cnr:
|
|
circuitDb.cnrConfigId = circuitDds.radioCircuitId();
|
|
return circuitDb;
|
|
|
|
case RadioSystem::Tvc:
|
|
circuitDb.tvcConfigId = circuitDds.radioCircuitId();
|
|
return circuitDb;
|
|
}
|
|
Q_ASSERT(false);
|
|
return circuitDb;
|
|
}
|
|
|
|
/**
|
|
* Helper function for CnrTvcProfileHandler::isValidCnr() and CnrTvcProfileHandler::isValidTvc().
|
|
* Handler is either CnrHandler or TvcHandler.
|
|
*/
|
|
template<class Handler>
|
|
Core::FunctionReplyObject isValid(int configId, int64_t exerciseId, Handler *handler, int requestId, const QString &configTypeAsString)
|
|
{
|
|
Q_ASSERT(handler);
|
|
|
|
Core::FunctionReplyObject reply;
|
|
if (requestId > 0)
|
|
reply.setId(requestId);
|
|
|
|
if (!handler->hasConfig(configId))
|
|
return reply.setStr(tr_lts("dds", "%1 config %2 does not exist")).arg(configTypeAsString).arg(configId);
|
|
|
|
const auto &config = handler->config(configId);
|
|
if (config.exerciseId().is_set() && config.exerciseId().get() != exerciseId)
|
|
return reply.setStr(tr_lts("dds", "%1 config %2 cannot be used in exercise %3")).arg(configTypeAsString).arg(configId).arg(exerciseId);
|
|
|
|
return reply;
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
CnrTvcProfileHandler::CnrTvcProfileHandler(DatabaseInterface *db, Interface::Dts *dts, Interface::Fts *fts, CnrHandler *cnrHandler, TvcHandler *tvcHandler)
|
|
: ModifyCnrTvcProfileRequestHandler(nullptr)
|
|
, RemoveCnrTvcProfileRequestHandler(nullptr)
|
|
, m_db(db)
|
|
, m_dts(dts)
|
|
, m_fts(fts)
|
|
, m_cnrHandler(cnrHandler)
|
|
, m_tvcHandler(tvcHandler)
|
|
, m_logger(getLogger("CnrTvcProfileHandler"))
|
|
{
|
|
Q_ASSERT(db);
|
|
Q_ASSERT(dts);
|
|
Q_ASSERT(fts);
|
|
Q_ASSERT(cnrHandler);
|
|
Q_ASSERT(tvcHandler);
|
|
m_fts->setModifyCnrTvcProfileRequestHandler(this);
|
|
m_fts->setRemoveCnrTvcProfileRequestHandler(this);
|
|
|
|
connect(m_cnrHandler, &CnrHandler::cnrConfigChanged, this, &CnrTvcProfileHandler::onCnrConfigChanged);
|
|
connect(m_tvcHandler, &TvcHandler::tvcConfigChanged, this, &CnrTvcProfileHandler::onTvcConfigChanged);
|
|
connect(db, &DatabaseInterface::notifyDeleteCnrTvcProfile, this, &CnrTvcProfileHandler::onDbDeletedCnrTvcProfile);
|
|
connect(db, &DatabaseInterface::notifyDeleteCnrTvcProfileData, this, &CnrTvcProfileHandler::onDbDeletedCnrTvcProfileData);
|
|
}
|
|
|
|
CnrTvcProfileHandler::~CnrTvcProfileHandler()
|
|
{
|
|
m_fts->setModifyCnrTvcProfileRequestHandler(nullptr);
|
|
m_fts->setRemoveCnrTvcProfileRequestHandler(nullptr);
|
|
}
|
|
|
|
bool CnrTvcProfileHandler::init()
|
|
{
|
|
QVector<Database::AvmCnrTvcProfile> circuitContainersDb;
|
|
bool status = m_db->select(circuitContainersDb);
|
|
if (!status)
|
|
{
|
|
ERROR_LOG(m_logger) << "Error reading data from database 'avm.avm_cnr_tvc_profile'";
|
|
return false;
|
|
}
|
|
|
|
for (const auto ¤tCircuitContainer: qAsConst(circuitContainersDb))
|
|
status &= collectAndPublish(currentCircuitContainer);
|
|
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* Fetch the entries from avm_cnr_tvc_profile_data for the given container,
|
|
* build the corresponding CnrTvcProfile-Topic and publish.
|
|
*
|
|
* This method can be called in two cases:
|
|
* 1. due to init() (isReload == false)
|
|
* 2. as a consequence of the delete notification or a modification of a Cnr-/TvcConfig (isReload == true)
|
|
*/
|
|
bool CnrTvcProfileHandler::collectAndPublish(const Database::AvmCnrTvcProfile &circuitContainerDb, bool isReload)
|
|
{
|
|
if (isReload)
|
|
{
|
|
Q_ASSERT(m_cache.contains(circuitContainerDb.id));
|
|
Q_ASSERT(OperatorExerciseKey(m_cache.value(circuitContainerDb.id)) == OperatorExerciseKey(circuitContainerDb));
|
|
}
|
|
|
|
QVector<Database::AvmCnrTvcProfileData> circuitsContentDb;
|
|
bool status = m_db->selectByContainerId(circuitsContentDb, circuitContainerDb.id);
|
|
if (!status)
|
|
{
|
|
ERROR_LOG(m_logger) << "Error reading data from database 'avm.avm_cnr_tvc_profile_data'";
|
|
return false;
|
|
}
|
|
|
|
|
|
// Check for invalid entries (where the exercise does not match) and remove those.
|
|
const QVector<Database::AvmCnrTvcProfileData> invalidEntries = determineInvalidEntries(circuitsContentDb, circuitContainerDb.exerciseId);
|
|
for (const auto &invalid : invalidEntries)
|
|
{
|
|
status = m_db->removeAvmCnrTvcProfileData(invalid.id);
|
|
if (!status)
|
|
ERROR_LOG(m_logger) << "Failed to remove from 'avm.avm_cnr_tvc_profile_data' with id " << invalid.id;
|
|
auto newEnd = std::remove_if(circuitsContentDb.begin(), circuitsContentDb.end(), [&invalid] (const Database::AvmCnrTvcProfileData &circuit) { return circuit.id == invalid.id; });
|
|
circuitsContentDb.erase(newEnd, circuitsContentDb.end());
|
|
}
|
|
|
|
|
|
// Check for possibly empty containers in the DB.
|
|
// Those are deleted and not published. In case of a reload, the removal is published.
|
|
if (circuitsContentDb.empty())
|
|
{
|
|
status = m_db->removeAvmCnrTvcProfile(circuitContainerDb.id);
|
|
if (!status)
|
|
{
|
|
ERROR_LOG(m_logger) << "Failed to remove from 'avm.avm_cnr_tvc_profile' with id " << circuitContainerDb.id;
|
|
return false;
|
|
}
|
|
|
|
if (isReload)
|
|
removeProfile(circuitContainerDb.id);
|
|
|
|
return true;
|
|
}
|
|
|
|
CnrTvcProfile profileDds = toDds(circuitContainerDb, circuitsContentDb);
|
|
if (isReload)
|
|
updateProfile(profileDds);
|
|
else
|
|
addProfile(profileDds);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Modify is used for both: to create and modify a data set.
|
|
* A request with request.id <= 0 is a create-request.
|
|
*/
|
|
void CnrTvcProfileHandler::onModifyCnrTvcProfileRequest(const rti::core::SampleIdentity &cookie,
|
|
const CnrTvcProfile &request)
|
|
{
|
|
Core::FunctionReplyObject rep;
|
|
if (request.id() <= 0)
|
|
rep = createProfile(request);
|
|
else
|
|
rep = modifyProfile(request);
|
|
|
|
if (rep.error())
|
|
WARNING_LOG(m_logger) << rep.str();
|
|
|
|
m_fts->modifyCnrTvcProfileReply(cookie, rep);
|
|
}
|
|
|
|
void CnrTvcProfileHandler::onRemoveCnrTvcProfileRequest(const rti::core::SampleIdentity &cookie,
|
|
const Core::RemoveElementRequest &request)
|
|
{
|
|
Core::FunctionReplyObject rep = removeProfile(request);
|
|
|
|
if (rep.error())
|
|
WARNING_LOG(m_logger) << rep.str();
|
|
|
|
m_fts->removeCnrTvcProfileReply(cookie, rep);
|
|
}
|
|
|
|
Core::FunctionReplyObject CnrTvcProfileHandler::createProfile(const CnrTvcProfile &createRequest)
|
|
{
|
|
Q_ASSERT(createRequest.id() <= 0);
|
|
|
|
Core::FunctionReplyObject reply = validateRequest(createRequest);
|
|
if (reply.error())
|
|
return reply;
|
|
|
|
Database::AvmCnrTvcProfile dbEntry = toDb(createRequest);
|
|
|
|
DBTransaction dbTransaction(m_db->database());
|
|
bool status = m_db->insert(dbEntry);
|
|
if (!status)
|
|
return reply.setStr(tr_lts("dds", "Failed to insert into 'avm.avm_cnr_tvc_profile'"));
|
|
reply.setId(dbEntry.id);
|
|
|
|
const auto circuitDataDb = insert(createRequest.data(), dbEntry.id, status);
|
|
if (!status)
|
|
return reply.setStr(tr_lts("dds", "Failed to insert into 'avm.avm_cnr_tvc_profile_data'"));
|
|
|
|
dbTransaction.commit();
|
|
|
|
CnrTvcProfile toPublish = toDds(dbEntry, circuitDataDb);
|
|
addProfile(toPublish);
|
|
|
|
return reply;
|
|
}
|
|
|
|
Core::FunctionReplyObject CnrTvcProfileHandler::modifyProfile(const CnrTvcProfile &modifyRequest)
|
|
{
|
|
Q_ASSERT(modifyRequest.id() > 0);
|
|
|
|
Core::FunctionReplyObject reply = validateRequest(modifyRequest);
|
|
if (reply.error())
|
|
return reply;
|
|
|
|
DBTransaction dbTransaction(m_db->database());
|
|
Database::AvmCnrTvcProfile dbEntry = toDb(modifyRequest);
|
|
|
|
bool status = m_db->update(dbEntry);
|
|
if (!status)
|
|
return reply.setStr(tr_lts("dds", "Failed to update 'avm.avm_cnr_tvc_profile' data with id %1")).arg(modifyRequest.id());
|
|
|
|
status = m_db->removeAvmCnrTvcProfileDataByContainerId(modifyRequest.id());
|
|
if (!status)
|
|
return reply.setStr(tr_lts("dds", "Failed to remove from 'avm.avm_cnr_tvc_profile_data' with container_id %1")).arg(modifyRequest.id());
|
|
|
|
insert(modifyRequest.data(), modifyRequest.id(), status);
|
|
if (!status)
|
|
return reply.setStr(tr_lts("dds", "Failed to insert into 'avm.avm_cnr_tvc_profile_data'"));
|
|
|
|
dbTransaction.commit();
|
|
updateProfile(modifyRequest);
|
|
|
|
return reply;
|
|
}
|
|
|
|
Core::FunctionReplyObject CnrTvcProfileHandler::removeProfile(const Core::RemoveElementRequest &request)
|
|
{
|
|
Core::FunctionReplyObject reply = validateRequest(request);
|
|
if (reply.error())
|
|
return reply;
|
|
|
|
DBTransaction dbTransaction(m_db->database());
|
|
|
|
bool status = m_db->removeAvmCnrTvcProfileDataByContainerId(request.id());
|
|
if (!status)
|
|
return reply.setStr(tr_lts("dds", "Failed to remove from 'avm.avm_cnr_tvc_profile_data' with container_id %1")).arg(request.id());
|
|
|
|
status = m_db->removeAvmCnrTvcProfile(request.id());
|
|
if (!status)
|
|
return reply.setStr(tr_lts("dds", "Failed to remove from 'avm.avm_cnr_tvc_profile' with id %1")).arg(request.id());
|
|
|
|
dbTransaction.commit();
|
|
removeProfile(request.id());
|
|
|
|
return reply;
|
|
}
|
|
|
|
/**
|
|
* In case the bulk-insert into the DB fails, the returned vector is empty
|
|
* and status is set to false.
|
|
*/
|
|
std::vector<Database::AvmCnrTvcProfileData> CnrTvcProfileHandler::insert(const std::vector<CnrTvcProfileData> &circuitsDds, qint64 containerId, bool &status)
|
|
{
|
|
status = false;
|
|
std::vector<Database::AvmCnrTvcProfileData> circuitsDb;
|
|
circuitsDb.reserve(circuitsDds.size());
|
|
|
|
// The order of circuits in the vector also indicates the user's requested sort order.
|
|
int sortIndex = 0;
|
|
for (const auto &circuitData: circuitsDds)
|
|
circuitsDb.push_back(toDb(circuitData, containerId, sortIndex++));
|
|
|
|
status = m_db->insert(circuitsDb);
|
|
if (!status)
|
|
return {};
|
|
|
|
return circuitsDb;
|
|
}
|
|
|
|
void CnrTvcProfileHandler::addProfile(const CnrTvcProfile &profile)
|
|
{
|
|
Q_ASSERT(profile.id() > 0);
|
|
Q_ASSERT(!m_cache.contains(profile.id()));
|
|
|
|
OperatorExerciseKey key(profile);
|
|
Q_ASSERT(!m_uniqueKeys.contains(key));
|
|
|
|
m_cache[profile.id()] = profile;
|
|
m_uniqueKeys.append(key);
|
|
|
|
bool status = m_dts->publish(profile);
|
|
if (!status)
|
|
ERROR_LOG(m_logger) << QStringLiteral("Failed to publish 'CnrTvcProfile' data with id %1 (create)").arg(profile.id());
|
|
}
|
|
|
|
void CnrTvcProfileHandler::removeProfile(int64_t id)
|
|
{
|
|
Q_ASSERT(m_cache.contains(id));
|
|
CnrTvcProfile profile = m_cache.value(id);
|
|
OperatorExerciseKey key(profile);
|
|
m_cache.remove(id);
|
|
int count = m_uniqueKeys.removeAll(key);
|
|
Q_ASSERT(count == 1);
|
|
|
|
bool status = m_dts->removeCnrTvcProfileByKey(id);
|
|
if (!status)
|
|
ERROR_LOG(m_logger) << QStringLiteral("Failed to publish 'CnrTvcProfile' with id %1 (remove)").arg(id);
|
|
}
|
|
|
|
void CnrTvcProfileHandler::updateProfile(const CnrTvcProfile &profile)
|
|
{
|
|
Q_ASSERT(profile.id() > 0);
|
|
Q_ASSERT(m_cache.contains(profile.id()));
|
|
|
|
OperatorExerciseKey key(profile);
|
|
Q_ASSERT(m_uniqueKeys.contains(key));
|
|
|
|
if (m_cache[profile.id()] == profile)
|
|
return;
|
|
|
|
m_cache[profile.id()] = profile;
|
|
|
|
bool status = m_dts->publish(profile);
|
|
if (!status)
|
|
ERROR_LOG(m_logger) << QStringLiteral("Failed to publish 'CnrTvcProfile' data with id %1 (modify)").arg(profile.id());
|
|
}
|
|
|
|
void CnrTvcProfileHandler::onCnrConfigChanged(const CnrConfig &cnrConfig)
|
|
{
|
|
onConfigChanged(cnrConfig.id(), RadioSystem::Cnr);
|
|
}
|
|
|
|
void CnrTvcProfileHandler::onTvcConfigChanged(const TvcConfig &tvcConfig)
|
|
{
|
|
onConfigChanged(tvcConfig.id(), RadioSystem::Tvc);
|
|
}
|
|
|
|
/**
|
|
* Will be called whenever a row from avm_cnr_tvc_profile is removed.
|
|
* The remove-operation itself can be a result of the following:
|
|
* 1. we ourselves are about to remove a row as a result of a RemoveRadioCircuitsRequest
|
|
* 2. one of our foreign key dependencies was removed (exercise or operator) and our row
|
|
* was removed as a result of a cascading delete
|
|
* 3. someone removed the row by hand.
|
|
*/
|
|
void CnrTvcProfileHandler::onDbDeletedCnrTvcProfile(const QVariant &id)
|
|
{
|
|
bool couldConvert = false;
|
|
qint64 dbId = id.toLongLong(&couldConvert);
|
|
Q_ASSERT(couldConvert);
|
|
|
|
if (!m_cache.contains(dbId))
|
|
return; // We don't have the id in our cache. We probably just removed the Row ourselves. => nothing to do.
|
|
|
|
// We still have the id in our cache. Someone else must have deleted this row.
|
|
// We remove the entry from our cache and publish the removal.
|
|
removeProfile(dbId);
|
|
}
|
|
|
|
/**
|
|
* Will be called whenever a row from avm_cnr_tvc_profile_data is removed.
|
|
* Besides the causes already mentioned above (onDbDeletedCnrTvcProfile())
|
|
* this method can also be called as a result of a ModifyRadioCircuitRequest.
|
|
* This is because the modify is implemented via deletion of all previous entries
|
|
* and insertion of all new entries.
|
|
*
|
|
* @param containerId The id of the row in avm_cnr_tvc_profile where the deleted row
|
|
* belongs to, not the primary key of the deleted row itself.
|
|
*/
|
|
void CnrTvcProfileHandler::onDbDeletedCnrTvcProfileData(const QVariant &containerId)
|
|
{
|
|
bool couldConvert = false;
|
|
qint64 dbId = containerId.toLongLong(&couldConvert);
|
|
Q_ASSERT(couldConvert);
|
|
|
|
if (!m_cache.contains(dbId))
|
|
return; // We don't have the id in our cache. We probably just removed the Row ourselves. => nothing to do.
|
|
|
|
|
|
// We still have the id in our cache. Someone else must have deleted this row.
|
|
// We need to reload the whole container and publish the modification.
|
|
// In case the container is now empty, we need to delete the container and publish the removal.
|
|
|
|
Database::AvmCnrTvcProfile profileDb = toDb(m_cache.value(dbId));
|
|
const bool isReload = true;
|
|
(void) collectAndPublish(profileDb, isReload);
|
|
}
|
|
|
|
Core::FunctionReplyObject CnrTvcProfileHandler::validateRequest(const CnrTvcProfile &request) const
|
|
{
|
|
Core::FunctionReplyObject reply;
|
|
|
|
if (request.id() > 0)
|
|
{
|
|
// modify
|
|
reply.setId(request.id());
|
|
|
|
if (!m_cache.contains(request.id()))
|
|
return reply.setStr(tr_lts("dds", "CnrTvcProfile for operator %1 in exercise %2 does not exist")).arg(request.operatorId()).arg(request.exerciseId());
|
|
|
|
if (OperatorExerciseKey(m_cache.value(request.id())) != OperatorExerciseKey(request))
|
|
return reply.setStr(tr_lts("dds", "operator or exercise may not be changed"));
|
|
}
|
|
else
|
|
{
|
|
// create
|
|
if (m_uniqueKeys.contains(OperatorExerciseKey(request)))
|
|
return reply.setStr(tr_lts("dds", "CnrTvcProfile for operator %1 already exists in exercise %2")).arg(request.operatorId()).arg(request.exerciseId());
|
|
}
|
|
|
|
if (request.data().size() == 0)
|
|
return reply.setStr(tr_lts("dds", "CnrTvcProfile must not be empty"));
|
|
|
|
for (const auto &entry : request.data())
|
|
{
|
|
if (entry.radioSystemId() == RadioSystem::Tvc)
|
|
{
|
|
auto reply2 = isValidTvc(entry.radioCircuitId(), request.exerciseId(), request.id());
|
|
if (reply2.error())
|
|
return reply2;
|
|
}
|
|
else if (entry.radioSystemId() == RadioSystem::Cnr)
|
|
{
|
|
auto reply2 = isValidCnr(entry.radioCircuitId(), request.exerciseId(), request.id());
|
|
if (reply2.error())
|
|
return reply2;
|
|
}
|
|
}
|
|
|
|
return reply;
|
|
}
|
|
|
|
Core::FunctionReplyObject CnrTvcProfileHandler::validateRequest(const Core::RemoveElementRequest &request) const
|
|
{
|
|
Q_ASSERT(request.id() > 0);
|
|
Core::FunctionReplyObject reply(request.id());
|
|
|
|
if (!m_cache.contains(request.id()))
|
|
return reply.setStr(tr_lts("dds", "CnrTvcProfile %1 does not exist")).arg(request.id());
|
|
|
|
return reply;
|
|
}
|
|
|
|
/**
|
|
* Check whether all entries are valid in the context of the given exercise.
|
|
* Return all invalid entries.
|
|
*/
|
|
QVector<Database::AvmCnrTvcProfileData> CnrTvcProfileHandler::determineInvalidEntries(const QVector<Database::AvmCnrTvcProfileData> &entries, int64_t exerciseId) const
|
|
{
|
|
QVector<Database::AvmCnrTvcProfileData> invalid;
|
|
invalid.reserve(entries.size());
|
|
|
|
for (const auto &circuit : entries)
|
|
{
|
|
Q_ASSERT(circuit.cnrConfigId.isNull() ^ circuit.tvcConfigId.isNull());
|
|
|
|
if (!circuit.tvcConfigId.isNull())
|
|
{
|
|
if (!isValidTvc(circuit.tvcConfigId.toInt(), exerciseId))
|
|
invalid.append(circuit);
|
|
}
|
|
else
|
|
{
|
|
if (!isValidCnr(circuit.cnrConfigId.toInt(), exerciseId))
|
|
invalid.append(circuit);
|
|
}
|
|
}
|
|
|
|
return invalid;
|
|
}
|
|
|
|
bool CnrTvcProfileHandler::isValidCnr(int32_t cnrConfigId, int64_t exerciseId) const
|
|
{
|
|
int dummyRequestId = 0;
|
|
return !isValidCnr(cnrConfigId, exerciseId, dummyRequestId).error();
|
|
}
|
|
|
|
bool CnrTvcProfileHandler::isValidTvc(int32_t tvcConfigId, int64_t exerciseId) const
|
|
{
|
|
int dummyRequestId = 0;
|
|
return !isValidTvc(tvcConfigId, exerciseId, dummyRequestId).error();
|
|
}
|
|
|
|
Core::FunctionReplyObject CnrTvcProfileHandler::isValidCnr(int32_t cnrConfigId, int64_t exerciseId, int requestId) const
|
|
{
|
|
static const QString configType = QStringLiteral("CNR");
|
|
return isValid(cnrConfigId, exerciseId, m_cnrHandler, requestId, configType);
|
|
}
|
|
|
|
Core::FunctionReplyObject CnrTvcProfileHandler::isValidTvc(int32_t tvcConfigId, int64_t exerciseId, int requestId) const
|
|
{
|
|
static const QString configType = QStringLiteral("TVC");
|
|
return isValid(tvcConfigId, exerciseId, m_tvcHandler, requestId, configType);
|
|
}
|
|
|
|
void CnrTvcProfileHandler::onConfigChanged(int32_t configId, RadioSystem type)
|
|
{
|
|
QVector<CnrTvcProfile> toBeReloaded;
|
|
|
|
// Find all CnrTvcProfiles where this config is referenced and reload those.
|
|
// Hint: reloading might modify m_cache. Thus the reloading is done in a separate loop.
|
|
for (const auto &profile : qAsConst(m_cache))
|
|
for (const auto &data : profile.data())
|
|
if (data.radioSystemId() == type && data.radioCircuitId() == configId)
|
|
{
|
|
toBeReloaded.append(profile);
|
|
break;
|
|
}
|
|
|
|
for (const auto &profile : qAsConst(toBeReloaded))
|
|
{
|
|
Database::AvmCnrTvcProfile profileDb = toDb(profile);
|
|
const bool isReload = true;
|
|
(void) collectAndPublish(profileDb, isReload);
|
|
}
|
|
}
|
|
|
|
} // namespace AudioVideoManagement
|