/** * @RDE_HEADER@ * ISM Object Mounting Point Schedule * $Id$ * $HeadURL$ * $Author$ * Created by Iuliana Ojog, SLSE, 2016-11-26 */ #include "object_main_schedule.h" #include #include using namespace InfrastructureManagement; //---------------------------------------------------------------------------------------------------- ObjectMainSchedule::ObjectMainSchedule(MainHandler *mainHandler) : Base(mainHandler, getLogger("ObjectMainSchedule")) { } //---------------------------------------------------------------------------------------------------- ObjectMainSchedule::~ObjectMainSchedule() { } //---------------------------------------------------------------------------------------------------- bool ObjectMainSchedule::isValid() const { return m_data.id() > 0; } //---------------------------------------------------------------------------------------------------- bool ObjectMainSchedule::isUsed() const { return m_data.isUsed(); } //---------------------------------------------------------------------------------------------------- Core::FunctionReplyObject ObjectMainSchedule::createObject(const MainSchedule &data) { m_data = data; if (m_data.id() <= 0) { // This is a brand new Item to push into the Database m_data.isUsed(false); Database::IsmMountingPointSchedule dbData; dbData = toDbData(data); if (!db()->insert(dbData)) return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting IsmMainSchedule-data into database")); m_data.id(dbData.id); DEBUG_LOG(m_logger) << "New Id: " << m_data.id(); // Publish Data via DTS dts()->publish(m_data); } // If this is a replicated item from the Database, elements() must be filled with loadMountingPointPlans() // by the calling class! // Cannot be done within createObject as the SQL Janitor prevents this! // Therefore, this item is not published in this case, but within loadMountingPointPlans()! return Core::FunctionReplyObject(m_data.id()); } // Cannot be done within createObject as the SQL Janitor prevents this! bool ObjectMainSchedule::loadMountingPointPlans() { m_data.elements().clear(); // Data from DB is pushed in here, we just need to update MPPs auto cbMps = [this] (const Database::IsmMountingPointPlan &data) { MountingPointPlan ddsData = ObjectMainSchedule::toDdsData(data); m_data.elements().push_back(ddsData); m_mppMap.insert(ddsData.structureElementId(), ddsData); }; // create Mounting Point Schedule objects if (!db()->selectByMountingPointScheduleId(cbMps,m_data.id())) return false; return dts()->publish(m_data); } //---------------------------------------------------------------------------------------------------- // ---- .elements() is ignored here intentionally!!!! ---- Core::FunctionReplyObject ObjectMainSchedule::updateObject(const MainSchedule &data) { if (!isValid()) return Core::FunctionReplyObject(data.id(), tr_lts("dds", "Object not valid/blocked")); Database::IsmMountingPointSchedule dbData; dbData = toDbData(data); if (!db()->update(dbData)) return Core::FunctionReplyObject(data.id(), tr_lts("dds", "Error updating IsmMainSchedule-data into database")); // Change state if different if (m_data.statusId() != data.statusId()) setScheduleStatus(data.statusId()); // If elements are not saved, a MainSchedule with 0 elements will be published. std::vector< InfrastructureManagement::MountingPointPlan > tempElements = m_data.elements(); m_data = data; m_data.elements(tempElements); DEBUG_LOG(m_logger) << "Data changed for Id: " << m_data.id(); // Publish Data via DTS dts()->publish(m_data); return Core::FunctionReplyObject(m_data.id()); } //---------------------------------------------------------------------------------------------------- Core::FunctionReplyObject ObjectMainSchedule::copyObject(qint32 scheduleId) { int newId = db()->copySchedule(scheduleId); if (newId <= 0) return Core::FunctionReplyObject(0, tr_lts("dds", "Error on copy IsmMainSchedule")); Database::IsmMountingPointSchedule dbData; if (!db()->selectIsmMountingPointSchedule(newId, dbData)) return Core::FunctionReplyObject(newId, tr_lts("dds", "Error selecting copy id from database")); m_data = toDdsData(dbData); // // An Object initialized by this method is not used, but only getId() is called afterwards (right now) // Therefore, expensive selection of MPPs is avoided. Uncomment if needed (MD, 07.02.23) // // auto cbMps = [this] (const Database::IsmMountingPointPlan &data) // { // InfrastructureManagement::MountingPointPlan ddsData = ObjectMainSchedule::toDdsData(data); // m_data.elements().push_back(ddsData); // }; // // create Mounting Point Schedule objects // if (!db()->selectByMountingPointScheduleId(cbMps,m_data.id())) // { // return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting IsmMountingPointPlan-data into DDS Structure")); // } return Core::FunctionReplyObject(newId); } Core::FunctionReplyObject ObjectMainSchedule::updateElements(const std::vector &newElements) { std::vector insert; DBTransaction trans(db()->database()); bool retVal = true; for (const MountingPointPlan &mpp : newElements) { int seId = mpp.structureElementId(); if (m_mppMap.contains(seId)) { if (mpp.mountingPointState() == MountingPointState_def::Idle) { retVal &= db()->deleteMountingPointPlan(m_data.id(), seId); m_mppMap.remove(seId); } else { retVal &= db()->updateMountingPointPlan(m_data.id(), seId, mpp.mountingPointState()); m_mppMap[seId] = mpp; } } else { auto copy = toDbData(m_data.id(), mpp); m_mppMap[seId] = mpp; // Do this as a bulk.... insert.push_back(copy); } } retVal &= db()->insertMountingPointPlans(insert); trans.commit(); m_data.elements().clear(); m_data.elements().reserve(m_mppMap.size()); std::copy(m_mppMap.begin(), m_mppMap.end(),std::back_inserter(m_data.elements())); QTimer::singleShot(50, [this](){dts()->publish(m_data);}); if (!retVal) return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "Error on updating MountingPoint Plans.")); return Core::FunctionReplyObject(m_data.id()); } //---------------------------------------------------------------------------------------------------- Core::FunctionReplyObject ObjectMainSchedule::setUsed(bool isUsed) { if (!isValid()) return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "Trying to update an already removed IsmMainSchedule object")); m_data.isUsed(isUsed); // Publish Data via DTS //onPublishData(); return Core::FunctionReplyObject(m_data.id()); } //---------------------------------------------------------------------------------------------------- Core::FunctionReplyObject ObjectMainSchedule::removeObject() { if (isUsed()) return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "MainSchedule still in use")); if (!db()->removeIsmMountingPointSchedule(m_data.id())) return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "MainSchedule with id %1 can not be removed from DB")).arg(m_data.id()); if (!dts()->removeMainScheduleByKey(m_data.id())) return Core::FunctionReplyObject(m_data.id(), tr_lts("dds", "MainSchedule with id %1 can not be removed from DDS")).arg(m_data.id()); return Core::FunctionReplyObject(m_data.id()); } //---------------------------------------------------------------------------------------------------- bool ObjectMainSchedule::setScheduleStatus(const ScheduleStatus &status) { if (m_data.statusId() == status) return true; if (!isValid()) { WARNING_LOG(m_logger) << "Trying to update an already removed MainSchedule object"; return false; } DEBUG_LOG(m_logger) << "## old status = " << m_data.statusId(); DEBUG_LOG(m_logger) << "## new status = " << status; m_data.statusId() = status; QDateTime changed = QDateTime::currentDateTimeUtc(); if (m_data.timeCreated() <= 0) m_data.timeCreated() = changed.toMSecsSinceEpoch(); switch (m_data.statusId().underlying()) { case ScheduleStatus::Active: m_data.timeStart() = changed.toMSecsSinceEpoch(); break; case ScheduleStatus::Inactive: m_data.timeEnd() = changed.toMSecsSinceEpoch(); break; default: break; } Database::IsmMountingPointSchedule dbData; dbData = toDbData(m_data); if (!db()->update(dbData)) { ERROR_LOG(m_logger) << "Error updating MainSchedule-data in database (ScheduleStatus) for id = " << m_data.id() << " : " << db()->getLastError().text();; return false; } Database::IsmScheduleStatusChange stateChange; stateChange.id = 0; stateChange.scheduleId = m_data.id(); stateChange.changedAt = changed.currentMSecsSinceEpoch(); // record stateChange if (!db()->insert(stateChange)) WARNING_LOG(m_logger) << "Recording change of ScheduleStatusChange failed: " << db()->getLastError().text();; // Publish Data via DTS //onPublishData(); return true; } // ------------------------------------------------------------------------------------------------------- // convert methods // ------------------------------------------------------------------------------------------------------- // InfrastructureManagement::MainSchedule => Database::IsmMountingPointSchedule //---------------------------------------------------------------------------------------------------- Database::IsmMountingPointSchedule ObjectMainSchedule::toDbData(const MainSchedule &ddsData) { Database::IsmMountingPointSchedule dbData; dbData.id = ddsData.id(); dbData.name = QString::fromStdString(ddsData.name()); dbData.timeCreated = QDateTime::fromMSecsSinceEpoch(ddsData.timeCreated()); dbData.statusId = ddsData.statusId(); if (ddsData.timeStart().is_set() && ddsData.timeStart().get() > 0) dbData.timeStart = QDateTime::fromMSecsSinceEpoch(ddsData.timeStart().get()); else dbData.timeStart = QDateTime(); if (ddsData.timeEnd().is_set() && ddsData.timeEnd().get() > 0) dbData.timeEnd = QDateTime::fromMSecsSinceEpoch(ddsData.timeEnd().get()); else dbData.timeEnd = QDateTime(); if (ddsData.exerciseId().is_set() && ddsData.exerciseId().get() > 0) dbData.exerciseId = ddsData.exerciseId().get(); return dbData; } // InfrastructureManagement::MountingPointPlan => Database::IsmMountingPointPlan Database::IsmMountingPointPlan ObjectMainSchedule::toDbData(int scheduleId, const MountingPointPlan &ddsData) { Database::IsmMountingPointPlan dbData; dbData.structureElementId = ddsData.structureElementId(); dbData.mountingPointScheduleId = scheduleId; dbData.mountingPointState= ddsData.mountingPointState(); return dbData; } // ------------------------------------------------------------------------------------------------------- // Database::IsmMountingPointSchedule => InfrastructureManagement::MainSchedule //---------------------------------------------------------------------------------------------------- MainSchedule ObjectMainSchedule::toDdsData(const Database::IsmMountingPointSchedule &dbData) { MainSchedule ddsData; ddsData.id(dbData.id); ddsData.name(dbData.name.toStdString()); ddsData.statusId(dbData.statusId); if (!dbData.timeStart.isNull() && dbData.timeStart.isValid() && dbData.timeStart.toMSecsSinceEpoch() > 0) ddsData.timeStart(dbData.timeStart.toMSecsSinceEpoch()); if (!dbData.timeEnd.isNull() && dbData.timeEnd.isValid() && dbData.timeEnd.toMSecsSinceEpoch() > 0) ddsData.timeEnd(dbData.timeEnd.toMSecsSinceEpoch()); ddsData.timeCreated(dbData.timeCreated.toMSecsSinceEpoch()); if (!dbData.exerciseId.isNull() && dbData.exerciseId.canConvert()) ddsData.exerciseId(dbData.exerciseId.toInt()); // init data not in db ddsData.isDeleted(false); ddsData.isUsed(false); return ddsData; } MountingPointPlan ObjectMainSchedule::toDdsData(const Database::IsmMountingPointPlan &dbData) { MountingPointPlan ddsData; ddsData.mountingPointState(dbData.mountingPointState); ddsData.structureElementId(dbData.structureElementId); return ddsData; } // -------------------------------------------------------------------------------------------------------