/** * @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::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) { 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.has_value() && ddsData.timeStart.get() > 0) dbData.timeStart = QDateTime::fromMSecsSinceEpoch(ddsData.timeStart.get()); else dbData.timeStart = QDateTime(); if (ddsData.timeEnd.has_value() && ddsData.timeEnd.get() > 0) dbData.timeEnd = QDateTime::fromMSecsSinceEpoch(ddsData.timeEnd.get()); else dbData.timeEnd = QDateTime(); if (ddsData.exerciseId.has_value() && 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; } // -------------------------------------------------------------------------------------------------------