/* **************************************************************************** * Copyright 2019 Open Systems Development BV * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the "Software"), * * to deal in the Software without restriction, including without limitation * * the rights to use, copy, modify, merge, publish, distribute, sublicense, * * and/or sell copies of the Software, and to permit persons to whom the * * Software is furnished to do so, subject to the following conditions: * * * * The above copyright notice and this permission notice shall be included in * * all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * * DEALINGS IN THE SOFTWARE. * * ***************************************************************************/ #include "ormbatchchange.h" #include "log.h" #include using namespace osdev::components; OrmBatchChange::OrmBatchChange() : m_changeTimestamp() , m_foreignId() , m_changeSet() , m_valid(false) { } OrmBatchChange::OrmBatchChange(const Timestamp& ts, const QVariant& _foreignId, const std::set& _changeSet) : m_changeTimestamp(ts) , m_foreignId(_foreignId) , m_changeSet(_changeSet) , m_valid(!_foreignId.isNull() && ts.valid()) { if (!m_valid) { LogInfo("[OrmBatchChange ctor]", QString("Change is invalid : Timestamp %1, foreignId::isNull %2").arg(m_changeTimestamp.toString()).arg(m_foreignId.isNull())); } } bool OrmBatchChange::processChange(const OrmBatchChange& change, bool exclusiveUpdate) { LogDebug("[OrmBatchChange::processChange]", QString("Check %1 against change with timestamp %2, exlusiveUpdate is %3") .arg(m_changeTimestamp.toString()) .arg(change.timestamp().toString()) .arg(exclusiveUpdate)); if (!m_valid) { LogInfo("[OrmBatchChange::processChange]", "Incoming change is invalid"); return false; // This is an invalid change and can never become valid so signal to stop processing. } if (*this < change) { if (exclusiveUpdate && (change.m_foreignId == m_foreignId)) { // this change is not necessary because it is already superseded. Invalidate it and signal to stop processing. LogInfo("[OrmBatchChange::processChange]", "Change is superseded by newer change"); m_valid = false; return false; } // Find the items that are in the incoming change but not in the already applied change that we are checking against. // These items still need to change w.r.t to this change. if (!m_changeSet.empty()) { std::set result; std::set_difference(m_changeSet.begin(), m_changeSet.end(), change.m_changeSet.begin(), change.m_changeSet.end(), std::inserter(result, result.begin())); m_changeSet.swap(result); } // If the changeset is empty and the update is not exclusive then nothing has to be done. // In case of an exclusive update an empty set means that none of the items can point to the given foreignId // and processing needs to be continued. if (!exclusiveUpdate && m_changeSet.empty()) { // Invalidate the incoming change and signal to stop processing. LogInfo("[OrmBatchChange::processChange]", "Nothing to do for non exclusive update"); m_valid = false; return false; } } return true; } // static std::set OrmBatchChange::toSet(const QList& lst) { std::set result; for (const auto& item : lst) { result.insert(item); } return result; } // static QList OrmBatchChange::toList(const std::set& s) { QList result; for (const auto& item : s) { result.push_back(item); } return result; }