Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
@@ -0,0 +1,794 @@
|
||||
/**
|
||||
* @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 <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")] = st.underlying();
|
||||
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;
|
||||
}
|
||||
Reference in new issue
Block a user