795 lines
29 KiB
C++
Executable File
795 lines
29 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* ISM Object Main Structure Element
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by Iuliana Ojog, SLSE, 2016-11-26
|
|
*/
|
|
|
|
#include "object_main_structure_element.h"
|
|
#include "handler_main_structure_element.h"
|
|
#include "object_structure_element.h"
|
|
#include "main_handler.h"
|
|
#include "handler_mounting_point_asset.h"
|
|
#include "convert_db_to_dds.h"
|
|
#include <ngldb/dbtransaction.h>
|
|
#include <LtsUtilsCore/dds_vector.h>
|
|
#include <LtsUtilsCore/json_object.h>
|
|
#include <LtsCoordTrans/lts_coord_trans.h>
|
|
|
|
#include <QJsonObject>
|
|
#include <QtCore/QTimer>
|
|
|
|
namespace
|
|
{
|
|
|
|
inline bool isValidJsonObject(const std::string &json)
|
|
{
|
|
return LtsUtils::JsonObject::fromJson(json).isValid();
|
|
}
|
|
|
|
inline int parentFromPath(const std::vector<int32_t> &path)
|
|
{
|
|
if (path.size() < 2)
|
|
return -1;
|
|
return path.at(path.size() - 2);
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
using namespace InfrastructureManagement;
|
|
//----------------------------------------------------------------------------------------------------
|
|
ObjectMainStructureElement::ObjectMainStructureElement(MainHandler *mainHandler)
|
|
: Base(mainHandler, getLogger("ObjectMainStructureElement"))
|
|
{
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------------------------
|
|
ObjectMainStructureElement::ObjectMainStructureElement(const Database::IsmMainStructureElement &dbData,
|
|
MainHandler *mainHandler)
|
|
: Base(mainHandler, getLogger("ObjectMainStructureElement"))
|
|
, m_data(Database::convert(dbData))
|
|
{
|
|
m_data.elements.reserve(100); // sadly dds::vector has neither squeeze() nor is using over-provisioning... :(
|
|
m_footprint.id = m_data.id;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
ObjectMainStructureElement::~ObjectMainStructureElement()
|
|
{
|
|
qDeleteAll(m_objectStructureElements);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
bool ObjectMainStructureElement::isValid() const
|
|
{
|
|
return m_data.id > 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
Core::FunctionReplyObject ObjectMainStructureElement::updatePosition(const Core::GeoPosition &position)
|
|
{
|
|
MainStructureElement data(m_data);
|
|
data.geoPosition = position;
|
|
|
|
if (!db()->update(toDbData(data)))
|
|
return Core::FunctionReplyObject(data.id, tr_lts("dds", "Error updating IsmMainStructureElement-data into database"));
|
|
|
|
m_data = data;
|
|
|
|
DEBUG_LOG(m_logger) << "Data changed for Id: " << m_data.id;
|
|
|
|
return Core::FunctionReplyObject(m_data.id);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
Core::FunctionReplyObject ObjectMainStructureElement::setBridgeStatus(const BridgeStatus &st)
|
|
{
|
|
MainStructureElement data(m_data);
|
|
|
|
QJsonObject jsonObj;
|
|
jsonObj[QStringLiteral("bridgeStatus")] = static_cast<int>(st);
|
|
QJsonDocument doc(jsonObj);
|
|
data.properties = doc.toJson().toStdString();
|
|
|
|
if (!db()->update(toDbData(data)))
|
|
return Core::FunctionReplyObject(data.id, tr_lts("dds", "Error updating IsmMainStructureElement-properties into database"));
|
|
|
|
m_data = data;
|
|
|
|
DEBUG_LOG(m_logger) << "Properties changed for Id: " << m_data.id;
|
|
|
|
return Core::FunctionReplyObject(m_data.id);
|
|
}
|
|
/*!
|
|
* \brief ObjectMainStructureElement::deleteEGCUOverrides
|
|
* \param data
|
|
* \param oldExerciseId
|
|
* \param newExerciseId
|
|
* \param modifiedStructureElements
|
|
* \author Niklas Schmidt
|
|
* \details If a building with egcu's change/lose their exercise, the relay information in database will be deleted,
|
|
* so the buttons in ECGU Info dialog got there initial state
|
|
* \return
|
|
*/
|
|
std::vector<StructureElement> ObjectMainStructureElement::deleteEGCUOverrides(const MainStructureElement &data, int oldExerciseId, int newExerciseId, QSet<int> &modifiedStructureElements)
|
|
{
|
|
|
|
if(oldExerciseId == newExerciseId)
|
|
return data.elements;
|
|
|
|
|
|
std::vector<InfrastructureManagement::StructureElement> resElements;
|
|
for(auto element : data.elements)
|
|
{
|
|
if (element.mountingPointTypeId == MountingPointType::EffectGenerationControlUnit)
|
|
{
|
|
QJsonObject structureEleProps = QJsonDocument::fromJson(QByteArray::fromStdString(element.properties)).object();
|
|
if(structureEleProps.contains(QStringLiteral("Overrides")))
|
|
{
|
|
|
|
QJsonObject overrides = structureEleProps.value(QStringLiteral("Overrides")).toObject();
|
|
|
|
if(overrides.contains(QStringLiteral("relays")))
|
|
{
|
|
QJsonArray relays = overrides.value(QStringLiteral("relays")).toArray();
|
|
|
|
if(relays.size() > 0)
|
|
{
|
|
QJsonObject relaysResult;
|
|
//QJsonArray resultList;
|
|
for(int i = 0; i < relays.size(); ++i)
|
|
{
|
|
//QJsonObject resultObj = relays[i].toObject();
|
|
//resultObj.insert(resultObj.keys().at(0), 0);
|
|
//resultList.append(resultObj);
|
|
}
|
|
//relaysResult[QStringLiteral("relays")] = resultList;
|
|
|
|
structureEleProps[QStringLiteral("Overrides")] = relaysResult;
|
|
element.properties = QString::fromUtf8(QJsonDocument(structureEleProps).toJson()).toStdString();
|
|
modifiedStructureElements.insert(element.id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
resElements.push_back(element);
|
|
}
|
|
|
|
return resElements;
|
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
void ObjectMainStructureElement::noticeNewProperties(bool remove)
|
|
{
|
|
if (!m_mainHandler->getHandlerMountingPointAsset().get())
|
|
{
|
|
QTimer::singleShot(3000, this, [this, remove]()
|
|
{
|
|
noticeNewProperties(remove);
|
|
});
|
|
return;
|
|
}
|
|
|
|
std::vector<int32_t> exercises;
|
|
|
|
if (!remove)
|
|
exercises = getAvailableInExercise();
|
|
|
|
for (const auto &ele : m_data.elements)
|
|
{
|
|
if (ele.structureElementTypeId == StructureElementType::MountingPoint)
|
|
m_mainHandler->getHandlerMountingPointAsset()->setAvailableInExerciseForAssetOnMountingPoint(ele.id, exercises);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
Core::FunctionReplyObject ObjectMainStructureElement::createObject(const MainStructureElementModifyRequest &request)
|
|
{
|
|
if (!isValidJsonObject(request.properties))
|
|
return Core::FunctionReplyObject(0, tr_lts("dds", "MainStructureElement with invalid JSON properties"));
|
|
|
|
m_data = MainStructureElement();
|
|
m_footprint = MainFootprint();
|
|
|
|
m_data.name = request.name;
|
|
m_data.description = request.description;
|
|
m_data.geoPosition = request.geoPosition;
|
|
m_data.angle = request.angle;
|
|
m_data.modelId = request.modelId;
|
|
m_data.externalWlsId = request.externalWlsId;
|
|
m_data.groupId = request.groupId;
|
|
m_data.elements = request.elements;
|
|
m_data.properties = request.properties;
|
|
m_data.structureElementTypeId = request.structureElementTypeId;
|
|
|
|
DBTransaction trans(db()->database());
|
|
m_data.isUsed = false;
|
|
|
|
// Insert MainStructure Element
|
|
Database::IsmMainStructureElement dbData(toDbData(m_data));
|
|
if (!db()->insert(dbData))
|
|
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting IsmMainStructureElement-data into database"));
|
|
m_data.id = dbData.id;
|
|
|
|
// Insert Structure Elements
|
|
QVector<ObjectStructureElement *> objSeVec;
|
|
objSeVec.reserve(m_data.elements.size());
|
|
auto fro = createStructureElements(m_data, objSeVec);
|
|
if (fro.error())
|
|
return fro;
|
|
ObjectStructureElement *objStructureElementBuilding = objSeVec.first();
|
|
|
|
// Insert Footprint Elements
|
|
m_footprint.id = m_data.id; // = buildingId, important for remove etc.
|
|
m_footprint.structureElementId = objStructureElementBuilding->getId();
|
|
m_footprint.name = m_data.name; // footprint name = building name
|
|
if (request.footprint.is_set())
|
|
{
|
|
const auto &fp = request.footprint.get();
|
|
for (size_t i = 0; i < fp.size(); ++i)
|
|
{
|
|
FootprintElement fpElem = fp.at(i);
|
|
const Core::RelativePosition &relPos = fpElem.relPosition;
|
|
Database::IsmStructureElementFootprint footprint;
|
|
footprint.indexNo = i;
|
|
footprint.relPosition = LtsUtils::QPoint3D(relPos.offsetX, relPos.offsetY, relPos.offsetZ);
|
|
footprint.structureElementId = objStructureElementBuilding->getId();
|
|
if (!db()->insert(footprint))
|
|
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting IsmStructureElementFootprint-data into database"));
|
|
fpElem.id = footprint.id;
|
|
m_footprint.elements.resize(m_footprint.elements.size()+1, fpElem);
|
|
}
|
|
}
|
|
DEBUG_LOG(m_logger) << "m_footprint.elements.size() = " << m_footprint.elements.size();
|
|
|
|
if (!db()->update(toDbData(m_data)))
|
|
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Error updating IsmMainStructureElement-data into database"));
|
|
|
|
fro = updatePaths(m_data, objSeVec, request.childParentRelations);
|
|
if (fro.error())
|
|
return fro;
|
|
|
|
DEBUG_LOG(m_logger) << "New Id: " << m_data.id;
|
|
trans.commit();
|
|
|
|
if (m_data.properties.size())
|
|
noticeNewProperties();
|
|
|
|
m_mainHandler->getHandlerMainStructureElement()->addedStructureElements(m_objectStructureElements);
|
|
return Core::FunctionReplyObject(m_data.id);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
Core::FunctionReplyObject ObjectMainStructureElement::updateObject(const MainStructureElementModifyRequest &request)
|
|
{
|
|
if (!isValidJsonObject(request.properties))
|
|
return Core::FunctionReplyObject(0, tr_lts("dds", "MainStructureElement with invalid JSON properties"));
|
|
|
|
if (!isValid())
|
|
return Core::FunctionReplyObject(request.id, tr_lts("dds", "Object not valid/blocked"));
|
|
|
|
bool hasNewProps = m_data.properties != request.properties;
|
|
|
|
MainStructureElement data(m_data);
|
|
|
|
|
|
QJsonObject objRequest = QJsonDocument::fromJson(QByteArray::fromStdString(request.properties)).object();
|
|
QJsonObject objCurrent = QJsonDocument::fromJson(QByteArray::fromStdString(data.properties)).object();
|
|
|
|
int newExerciseId = objRequest.value(QStringLiteral("available_in_exercise")).toArray().at(0).toInt();
|
|
int currentExerciseId = objCurrent.value(QStringLiteral("available_in_exercise")).toArray().at(0).toInt();
|
|
|
|
|
|
data.name = request.name;
|
|
data.description = request.description;
|
|
data.geoPosition = request.geoPosition;
|
|
data.angle = request.angle;
|
|
data.modelId = request.modelId;
|
|
data.externalWlsId = request.externalWlsId;
|
|
data.groupId = request.groupId;
|
|
data.properties = request.properties;
|
|
data.structureElementId = request.structureElementId;
|
|
data.structureElementTypeId = request.structureElementTypeId;
|
|
|
|
// when we want to allow insert / update / remove for SE:
|
|
// data.elements(request.elements);
|
|
QSet<int> modifiedStructureElements;
|
|
bool bStructureElementCountChanged = false;
|
|
std::vector<int> childParentMapping;
|
|
|
|
const auto oldStructureElements = m_objectStructureElements;
|
|
if (request.elements.size() != 0)
|
|
{
|
|
if (request.elements.size() != data.elements.size())
|
|
{
|
|
bStructureElementCountChanged = true;
|
|
QHash<int, size_t> parentId2Index;
|
|
childParentMapping.resize(request.elements.size());
|
|
data.elements = request.elements;
|
|
for (size_t i = 0; i < request.elements.size(); ++i)
|
|
{
|
|
StructureElement &newElem = data.elements.at(i);
|
|
if (!isValidJsonObject(newElem.properties))
|
|
return Core::FunctionReplyObject(0, tr_lts("dds", "StructureElement with invalid JSON properties"));
|
|
parentId2Index[newElem.id] = i;
|
|
childParentMapping[i] = parentId2Index.value(parentFromPath(newElem.path));
|
|
// Do *not* modify the those
|
|
if (!isStructureElementDeletable(newElem))
|
|
continue;
|
|
newElem.id = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (size_t i = 0; i < request.elements.size(); ++i)
|
|
{
|
|
const StructureElement &newElem = request.elements.at(i);
|
|
|
|
if (!isValidJsonObject(newElem.properties))
|
|
return Core::FunctionReplyObject(0, tr_lts("dds", "StructureElement with invalid JSON properties"));
|
|
|
|
StructureElement &oldElem = data.elements[i];
|
|
if (oldElem.id != newElem.id && newElem.id != 0)
|
|
return Core::FunctionReplyObject(data.id, tr_lts("dds", "Adding / Removing Structure elements not (yet) supported"));
|
|
if (oldElem == newElem)
|
|
continue;
|
|
modifiedStructureElements += oldElem.id;
|
|
|
|
|
|
// currently we only support modifing these values:
|
|
oldElem.displayName = newElem.displayName;
|
|
oldElem.barcode = newElem.barcode;
|
|
oldElem.mountingPointId = newElem.mountingPointId;
|
|
oldElem.mountingPointTypeId = newElem.mountingPointTypeId;
|
|
oldElem.relPosition = newElem.relPosition;
|
|
oldElem.structureElementTypeId = newElem.structureElementTypeId;
|
|
oldElem.properties = newElem.properties;
|
|
|
|
DEBUG_LOG(m_logger) << "add " << oldElem.id << " to modifiedStructureElements" << oldElem;
|
|
}
|
|
}
|
|
}
|
|
|
|
MainFootprint mfData(m_footprint);
|
|
bool bUpdateFootprintNeeded = false;
|
|
if (request.footprint.is_set())
|
|
{
|
|
const auto &fpReq = request.footprint.get();
|
|
bUpdateFootprintNeeded = fpReq.size() != mfData.elements.size();
|
|
if (!bUpdateFootprintNeeded)
|
|
{
|
|
for (size_t i = 0; i < fpReq.size(); ++i)
|
|
{
|
|
if (fpReq.at(i) != mfData.elements.at(i))
|
|
{
|
|
bUpdateFootprintNeeded = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//The modifiedStructureElements need to be filled
|
|
data.elements = deleteEGCUOverrides(data, currentExerciseId, newExerciseId, modifiedStructureElements);
|
|
|
|
DBTransaction trans(db()->database());
|
|
|
|
if (bStructureElementCountChanged)
|
|
{
|
|
DEBUG_LOG(m_logger) << "Re-creating structure elements for " << data.id;
|
|
QVector<ObjectStructureElement *> objSeVec;
|
|
objSeVec.reserve(data.elements.size());
|
|
auto fro = createStructureElements(data, objSeVec);
|
|
if (fro.error())
|
|
return fro;
|
|
fro = updatePaths(data, objSeVec, childParentMapping);
|
|
if (fro.error())
|
|
return fro;
|
|
}
|
|
else
|
|
{
|
|
for (const auto &dataSe : data.elements)
|
|
{
|
|
if (!modifiedStructureElements.contains(dataSe.id))
|
|
continue;
|
|
InfrastructureManagement::ObjectStructureElement *objSe = m_objectStructureElements.value(dataSe.id);
|
|
if (!objSe)
|
|
WARNING_LOG(m_logger) << "Internal Error: can not find structure element with id " << dataSe.id;
|
|
else
|
|
objSe->updateObject(dataSe);
|
|
}
|
|
}
|
|
if (!db()->update(toDbData(data)))
|
|
return Core::FunctionReplyObject(data.id, tr_lts("dds", "Error updating IsmMainStructureElement-data into database"));
|
|
|
|
DEBUG_LOG(m_logger) << "bUpdateFootprintNeeded = " << bUpdateFootprintNeeded;
|
|
if (bUpdateFootprintNeeded)
|
|
{
|
|
// remove old footprint data
|
|
for (const FootprintElement &elem : m_footprint.elements)
|
|
db()->removeIsmStructureElementFootprint(elem.id);
|
|
// add new footprint data
|
|
Database::IsmStructureElementFootprint sef;
|
|
sef.structureElementId = getStructureElementId();
|
|
for (size_t i = 0; i < mfData.elements.size(); ++i)
|
|
{
|
|
FootprintElement &elem = mfData.elements[i];
|
|
const Core::RelativePosition &relPos = elem.relPosition;
|
|
sef.indexNo = i;
|
|
sef.relPosition = LtsUtils::QPoint3D(relPos.offsetX,
|
|
relPos.offsetY,
|
|
relPos.offsetZ);
|
|
if (!db()->insert(sef))
|
|
return Core::FunctionReplyObject(data.id, tr_lts("dds", "Error updating IsmStructureElementFootprint-data into database"));
|
|
elem.id = sef.id;
|
|
m_footprint.elements.resize(m_footprint.elements.size()+1, elem);
|
|
}
|
|
}
|
|
DEBUG_LOG(m_logger) << "mfData.elements.size() = " << mfData.elements.size();
|
|
|
|
trans.commit();
|
|
|
|
if (bStructureElementCountChanged)
|
|
{
|
|
m_mainHandler->getHandlerMainStructureElement()->removedStructureElements(oldStructureElements);
|
|
m_mainHandler->getHandlerMainStructureElement()->addedStructureElements(m_objectStructureElements);
|
|
QMap<int, ObjectStructureElement*> newObjectStructureElements;
|
|
for (ObjectStructureElement *ose : qAsConst(m_objectStructureElements))
|
|
{
|
|
// only delete the old ones
|
|
// and also not the one for the mse and bcu
|
|
if (!oldStructureElements.contains(ose->getId()) ||
|
|
!isStructureElementDeletable(ose->getData()))
|
|
{
|
|
newObjectStructureElements[ose->getId()] = ose;
|
|
continue;
|
|
}
|
|
ose->removeObject();
|
|
delete ose;
|
|
}
|
|
m_objectStructureElements = newObjectStructureElements;
|
|
}
|
|
|
|
|
|
|
|
m_data = data;
|
|
m_footprintNeedsUpdate = (m_footprint != mfData);
|
|
m_footprint = mfData;
|
|
|
|
DEBUG_LOG(m_logger) << "Data changed for Id: " << m_data.id;
|
|
|
|
if (hasNewProps)
|
|
noticeNewProperties();
|
|
|
|
|
|
|
|
|
|
return Core::FunctionReplyObject(m_data.id);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
Core::FunctionReplyObject ObjectMainStructureElement::removeObject()
|
|
{
|
|
/* done in Handler MSE
|
|
for (auto dataSe : m_data.elements)
|
|
{
|
|
if (!db()->removeIsmStructureElement(dataSe.id))
|
|
return Core::FunctionReplyObject(dataSe.id, tr_lts("dds", "StructureElement %1 can not be removed from DB")).arg(dataSe.id);
|
|
}
|
|
*/
|
|
if (!db()->removeIsmMainStructureElement(m_data.id))
|
|
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "MainStructureElement with id %1 can not be removed from DB")).arg(m_data.id);
|
|
|
|
dts()->removeMainStructureElementByKey(m_data.id);
|
|
dts()->removeMainFootprintByKey(m_footprint.id);
|
|
|
|
for (ObjectStructureElement *ose : qAsConst(m_objectStructureElements))
|
|
{
|
|
ose->removeObject();
|
|
delete ose;
|
|
}
|
|
m_objectStructureElements.clear();
|
|
|
|
m_data = MainStructureElement();
|
|
m_footprint = MainFootprint();
|
|
|
|
return Core::FunctionReplyObject(m_data.id);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
void ObjectMainStructureElement::onPublishData()
|
|
{
|
|
INFO_LOG(m_logger) << "Publish IsmMainStructureElement-data to dds (" << m_data.id << ") ...";
|
|
|
|
dts()->publish(m_data);
|
|
|
|
DEBUG_LOG(m_logger) << "m_footprint.elements.size() = " << m_footprint.elements.size();
|
|
|
|
if (m_footprint.elements.size() == 0)
|
|
{
|
|
if (m_footprint.id != 0)
|
|
dts()->removeMainFootprintByKey(m_footprint.id);
|
|
}
|
|
else if (m_footprintNeedsUpdate)
|
|
dts()->publish(m_footprint);
|
|
|
|
|
|
m_footprintNeedsUpdate = false;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
ObjectStructureElement *ObjectMainStructureElement::createStructureElementObject(const Database::IsmStructureElement &dbData)
|
|
{
|
|
ObjectStructureElement *ifs(new ObjectStructureElement(m_mainHandler, this));
|
|
Core::FunctionReplyObject ret = ifs->createObject(dbData);
|
|
if (ret.error())
|
|
{
|
|
delete ifs;
|
|
ERROR_LOG(m_logger) << ret();
|
|
return nullptr;
|
|
}
|
|
|
|
// top level types: Building, ApproachingPoint, Announcement, MeteoDataUnit, RadioStation, Bridge
|
|
if (isTopLevel(dbData.structureElementTypeId))
|
|
{
|
|
m_data.structureElementId = ifs->getId();
|
|
m_data.structureElementTypeId = dbData.structureElementTypeId;
|
|
if (dbData.structureElementTypeId == StructureElementType::Building)
|
|
{
|
|
m_footprintNeedsUpdate |= (m_footprint.structureElementId != ifs->getId());
|
|
m_footprint.structureElementId = ifs->getId();
|
|
auto name = dbData.name.toStdString();
|
|
m_footprintNeedsUpdate |= (m_footprint.name != name);
|
|
m_footprint.name = name;
|
|
}
|
|
}
|
|
|
|
ifs->updateGeoPosition();
|
|
|
|
int last = m_data.elements.size();
|
|
// ifs->getData() to retrieve the correct geo position
|
|
m_data.elements.resize(last + 1, ifs->getData());
|
|
|
|
m_objectStructureElements.insert(ifs->getId(), ifs);
|
|
|
|
return ifs;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
const ObjectStructureElement *ObjectMainStructureElement::getMainStructureElementMountingPoint() const
|
|
{
|
|
// search for mounting point for building (direct below building)
|
|
for (const ObjectStructureElement *ose : m_objectStructureElements)
|
|
{
|
|
const auto &data = ose->getData();
|
|
if (data.structureElementTypeId == InfrastructureManagement::StructureElementType::MountingPoint &&
|
|
data.mountingPointTypeId == InfrastructureManagement::MountingPointType::BuildingControlUnit)
|
|
return ose;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
void ObjectMainStructureElement::setFootprintData(const std::vector<FootprintElement> &elements)
|
|
{
|
|
m_footprintNeedsUpdate |= (m_footprint.elements != elements);
|
|
m_footprint.elements = elements;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
QJsonArray ObjectMainStructureElement::getAvailableInExerciseJsonArray() const
|
|
{
|
|
return LtsUtils::JsonObject::fromJson(m_data.properties).object().value(QLatin1String("available_in_exercise")).toArray();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
int ObjectMainStructureElement::getBridgeStatus() const
|
|
{
|
|
return LtsUtils::JsonObject::fromJson(m_data.properties).object().value(QLatin1String("bridgeStatus")).toInt();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
std::vector<int32_t> ObjectMainStructureElement::getAvailableInExercise() const
|
|
{
|
|
const QJsonArray jsonArray = getAvailableInExerciseJsonArray();
|
|
|
|
std::vector<int32_t> result;
|
|
result.reserve(jsonArray.size());
|
|
|
|
for (const auto &ele : jsonArray)
|
|
result.push_back(ele.toInt());
|
|
|
|
return result;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
Core::FunctionReplyObject ObjectMainStructureElement::createStructureElements(MainStructureElement &mse,
|
|
QVector<ObjectStructureElement *> &objSeVec)
|
|
{
|
|
if (mse.elements.size() == 0)
|
|
return Core::FunctionReplyObject(0, tr_lts("dds", "MainStructureElement without StructureElements"));
|
|
|
|
ObjectStructureElement *objStructureElementBuilding = nullptr;
|
|
int rootStructureElementId = -1;
|
|
|
|
const Core::GeoPosition &geoPositionBase = m_data.geoPosition;
|
|
const auto mseBaseCoord(LtsCoordTrans::UtmCoordinate::fromGeographic(geoPositionBase.lon, geoPositionBase.lat));
|
|
|
|
for (size_t i = 0; i < mse.elements.size(); ++i)
|
|
{
|
|
StructureElement &dataSe = mse.elements[i];
|
|
|
|
if (!isValidJsonObject(dataSe.properties))
|
|
return Core::FunctionReplyObject(0, tr_lts("dds", "StructureElement with invalid JSON properties"));
|
|
|
|
DEBUG_LOG(m_logger) << "#CreateStructureElement: " << dataSe.displayName;
|
|
|
|
Database::IsmStructureElement dbDataSe(InfrastructureManagement::ObjectStructureElement::toDbData(dataSe));
|
|
dbDataSe.mainStructureElementId = mse.id;
|
|
// id + 1 to make sure the path does not exist when we update the paths with the correct values
|
|
const int seDummyParentId = rootStructureElementId < 0 ? mse.id : rootStructureElementId + 1;
|
|
dbDataSe.path = LtsUtils::IntArray(std::vector<int>({seDummyParentId, static_cast<int>(i)})); // dummy path for unique constraint
|
|
// DEBUG_LOG(m_logger) << "dbDataSe.path: " << mse.id << ", " << i;
|
|
|
|
if (dataSe.id == 0)
|
|
{
|
|
if (!db()->insert(dbDataSe))
|
|
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting IsmStructureElement-data into database"));
|
|
}
|
|
else
|
|
{
|
|
if (!db()->update(dbDataSe))
|
|
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting IsmStructureElement-data into database"));
|
|
}
|
|
|
|
// filled with the first inserted structure element (== building structure element)
|
|
if (rootStructureElementId < 0)
|
|
rootStructureElementId = dbDataSe.id;
|
|
|
|
ObjectStructureElement *objSe = nullptr;
|
|
if (dataSe.id == 0)
|
|
objSe = m_objectStructureElements.value(dataSe.id);
|
|
if (!objSe)
|
|
objSe = new ObjectStructureElement(Database::convert(dbDataSe), m_mainHandler, this);
|
|
|
|
// first one is buildingSE per definition (checked outside)
|
|
if (objStructureElementBuilding == nullptr)
|
|
{
|
|
objStructureElementBuilding = objSe;
|
|
// make sure to be consistent (will be updated later when se.path is updated)
|
|
objStructureElementBuilding->getData().mountingPointTypeId = InfrastructureManagement::MountingPointType::Unknown;
|
|
}
|
|
|
|
// in two containers - need a sorted one for path updates
|
|
objSeVec += objSe;
|
|
m_objectStructureElements.insert(objSe->getId(), objSe);
|
|
// update GeoPos
|
|
objSe->updateGeoPosition(mseBaseCoord, geoPositionBase.z, m_data.angle);
|
|
dataSe.geoPosition = objSe->getGeoPosition();
|
|
}
|
|
if (!objStructureElementBuilding)
|
|
return Core::FunctionReplyObject(0, tr_lts("dds", "MainStructureElement without valid StructureElements"));
|
|
mse.structureElementId = objStructureElementBuilding->getId();
|
|
mse.structureElementTypeId = objStructureElementBuilding->getStructureElementTypeId();
|
|
|
|
DEBUG_LOG(m_logger) << "(Re)Created " << mse.elements.size() << " structure elements";
|
|
|
|
return Core::FunctionReplyObject();
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
Core::FunctionReplyObject ObjectMainStructureElement::updatePaths(MainStructureElement &mse,
|
|
const QVector<ObjectStructureElement *> &objSeVec,
|
|
const std::vector<int> &childParentMapping)
|
|
{
|
|
// now update parent - child relations
|
|
const int buildingId = mse.id;
|
|
// update first element (building SE)
|
|
{
|
|
ObjectStructureElement *objSe = objSeVec.at(0);
|
|
StructureElement seData = objSe->getData();
|
|
|
|
seData.path.clear();
|
|
seData.path.resize(1, seData.id);
|
|
seData.mainStructureElementId = buildingId;
|
|
|
|
objSe->updateObject(seData);
|
|
|
|
DEBUG_LOG(m_logger) << "UpdatePaths Building = " << seData.displayName;
|
|
// update mse.elements
|
|
mse.elements[0] = objSe->getData();
|
|
}
|
|
|
|
for (int i = 1; i < objSeVec.size(); ++i)
|
|
{
|
|
const int parentIdx = childParentMapping.at(i);
|
|
ObjectStructureElement *objSe = objSeVec.at(i);
|
|
|
|
// sanity check
|
|
if (parentIdx < 0 || parentIdx >= i)
|
|
return Core::FunctionReplyObject(objSe->getId(), tr_lts("dds", "Error updating path information for structure element"));
|
|
|
|
DEBUG_LOG(m_logger) << "UpdatePath for element " << objSe->getName();
|
|
|
|
// create our path
|
|
std::vector<int> path = objSeVec.at(parentIdx)->getPath();
|
|
|
|
QString p;
|
|
for (int ii : path)
|
|
p += QString::number(ii) + QStringLiteral(",");
|
|
DEBUG_LOG(m_logger) << "## Parent path = " << p ;
|
|
|
|
path.resize(path.size() + 1, objSe->getId());
|
|
p += QString::number(objSe->getId());
|
|
|
|
// update db
|
|
StructureElement seData = objSe->getData();
|
|
DEBUG_LOG(m_logger) << "Updated path for element: " << seData.displayName << ", path = " << p;
|
|
|
|
seData.path = path;
|
|
seData.mainStructureElementId = buildingId;
|
|
const Core::FunctionReplyObject fro = objSe->updateObject(seData);
|
|
if (fro.error())
|
|
return fro;
|
|
// update mse.elements
|
|
mse.elements[i] = objSe->getData();
|
|
}
|
|
DEBUG_LOG(m_logger) << "Updated paths for " << objSeVec.size() << " structure elements";
|
|
return Core::FunctionReplyObject();
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
bool ObjectMainStructureElement::isStructureElementDeletable(const StructureElement &se)
|
|
{
|
|
if (se.structureElementTypeId == InfrastructureManagement::StructureElementType::Building)
|
|
return false;
|
|
if (se.structureElementTypeId == InfrastructureManagement::StructureElementType::MountingPoint &&
|
|
se.mountingPointTypeId == InfrastructureManagement::MountingPointType::BuildingControlUnit)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------
|
|
// convert methods
|
|
// -------------------------------------------------------------------------------------------------------
|
|
|
|
// InfrastructureManagement::MainStructureElement => Database::IsmMainStructureElement
|
|
Database::IsmMainStructureElement ObjectMainStructureElement::toDbData(const MainStructureElement &ddsData)
|
|
{
|
|
Database::IsmMainStructureElement dbData;
|
|
|
|
dbData.id = ddsData.id;
|
|
dbData.name = QString::fromStdString(ddsData.name);
|
|
dbData.description = QString::fromStdString(ddsData.description);
|
|
dbData.geoPosition = LtsUtils::QPoint3D(ddsData.geoPosition.lon, ddsData.geoPosition.lat, ddsData.geoPosition.z);
|
|
dbData.angle = ddsData.angle;
|
|
dbData.modelId = ddsData.modelId;
|
|
dbData.externalWlsId = ddsData.externalWlsId;
|
|
dbData.groupId = ddsData.groupId;
|
|
dbData.properties = QString::fromStdString(ddsData.properties);
|
|
|
|
return dbData;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------------------
|
|
bool ObjectMainStructureElement::isTopLevel(InfrastructureManagement::StructureElementType structureElementTypeId)
|
|
{
|
|
if (structureElementTypeId == StructureElementType::Building ||
|
|
structureElementTypeId == StructureElementType::ApproachingPoint ||
|
|
structureElementTypeId == StructureElementType::Announcement ||
|
|
structureElementTypeId == StructureElementType::MeteoDataUnit ||
|
|
structureElementTypeId == StructureElementType::RadioStation ||
|
|
structureElementTypeId == StructureElementType::Bridge)
|
|
return true;
|
|
return false;
|
|
}
|