File indexing completed on 2024-05-19 05:42:07

0001 // ct_lvtldr_lakosiannode.cpp                                         -*-C++-*-
0002 
0003 /*
0004 // Copyright 2023 Codethink Ltd <codethink@codethink.co.uk>
0005 // SPDX-License-Identifier: Apache-2.0
0006 //
0007 // Licensed under the Apache License, Version 2.0 (the "License");
0008 // you may not use this file except in compliance with the License.
0009 // You may obtain a copy of the License at
0010 //
0011 //     http://www.apache.org/licenses/LICENSE-2.0
0012 //
0013 // Unless required by applicable law or agreed to in writing, software
0014 // distributed under the License is distributed on an "AS IS" BASIS,
0015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0016 // See the License for the specific language governing permissions and
0017 // limitations under the License.
0018 */
0019 
0020 #include <ct_lvtldr_lakosiannode.h>
0021 
0022 #include <ct_lvtldr_nodestorage.h>
0023 
0024 #include <QObject>
0025 #include <QString>
0026 #include <QStringList>
0027 
0028 #include <algorithm>
0029 #include <cassert>
0030 #include <filesystem>
0031 #include <unordered_map>
0032 #include <vector>
0033 
0034 using namespace Codethink::lvtshr;
0035 
0036 namespace Codethink::lvtldr {
0037 
0038 std::vector<std::string> NamingUtils::buildQualifiedNamePrefixParts(const std::string& qname,
0039                                                                     const std::string& separator)
0040 {
0041     auto qtVector = QString::fromStdString(qname).split(QString::fromStdString(separator));
0042     auto stdVector = std::vector<std::string>{};
0043     std::transform(qtVector.begin(), qtVector.end(), std::back_inserter(stdVector), [](auto&& qtString) {
0044         return qtString.toStdString();
0045     });
0046     stdVector.pop_back();
0047     return stdVector;
0048 }
0049 
0050 std::string NamingUtils::buildQualifiedName(const std::vector<std::string>& parts,
0051                                             const std::string& name,
0052                                             const std::string& separator)
0053 {
0054     auto qname = std::string{};
0055     for (auto const& namePart : parts) {
0056         qname += namePart + separator;
0057     }
0058     qname += name;
0059     return qname;
0060 }
0061 
0062 // ==========================
0063 // class LakosianNode
0064 // ==========================
0065 
0066 LakosianNode::LakosianNode(NodeStorage& store, std::optional<std::reference_wrapper<DatabaseHandler>> dbHandler):
0067     d(std::make_unique<Private>(store, dbHandler))
0068 {
0069 }
0070 
0071 LakosianNode::~LakosianNode() noexcept = default;
0072 
0073 bool LakosianNode::isPackageGroup()
0074 {
0075     // default implementation
0076     return false;
0077 }
0078 
0079 std::string LakosianNode::notes() const
0080 {
0081     if (d->dbHandler->get().hasNotes(uid())) {
0082         return d->dbHandler->get().getNotesFromId(uid());
0083     }
0084     return "";
0085 }
0086 
0087 LakosianNode *LakosianNode::parent()
0088 {
0089     loadParent();
0090     assert(d->parentLoaded);
0091     return d->parent;
0092 }
0093 
0094 std::string LakosianNode::name() const
0095 {
0096     return d->name;
0097 }
0098 
0099 void LakosianNode::setNotes(const std::string& notes)
0100 {
0101     if (!d->dbHandler->get().hasNotes(uid())) {
0102         d->dbHandler->get().addNotes(uid(), notes);
0103     } else {
0104         d->dbHandler->get().setNotes(uid(), notes);
0105     }
0106 
0107     Q_EMIT onNotesChanged(notes);
0108 }
0109 
0110 void LakosianNode::setName(const std::string& newName)
0111 {
0112     d->name = newName;
0113     Q_EMIT onNameChanged(this);
0114 }
0115 
0116 const std::vector<LakosianNode *>& LakosianNode::children()
0117 {
0118     const auto currChildren = d->children.size();
0119     auto childrenWasLoaded = d->childrenLoaded;
0120     loadChildren();
0121 
0122     assert(d->childrenLoaded);
0123     if (currChildren != d->children.size() || !childrenWasLoaded) {
0124         Q_EMIT onChildCountChanged(d->children.size());
0125     }
0126 
0127     return d->children;
0128 }
0129 
0130 const std::vector<LakosianEdge>& LakosianNode::providers()
0131 {
0132     loadProviders();
0133     assert(d->providersLoaded);
0134     return d->providers;
0135 }
0136 
0137 void LakosianNode::invalidateProviders()
0138 {
0139     // TODO [#455]: It is possible to update providers, instead of fetching all over again from database.
0140     d->providersLoaded = false;
0141     d->providers.clear();
0142 }
0143 
0144 void LakosianNode::invalidateChildren()
0145 {
0146     d->childrenLoaded = false;
0147     d->children.clear();
0148 }
0149 
0150 void LakosianNode::invalidateParent()
0151 {
0152     d->parentLoaded = false;
0153     d->parent = nullptr;
0154 }
0155 
0156 const std::vector<LakosianEdge>& LakosianNode::clients()
0157 {
0158     loadClients();
0159     assert(d->clientsLoaded);
0160     return d->clients;
0161 }
0162 
0163 void LakosianNode::invalidateClients()
0164 {
0165     // TODO [#455]: It is possible to update clients, instead of fetching all over again from database.
0166     d->clientsLoaded = false;
0167     d->clients.clear();
0168 }
0169 
0170 bool LakosianNode::hasProvider(LakosianNode *other)
0171 {
0172     const auto& deps = providers();
0173     return std::find_if(std::cbegin(deps),
0174                         std::cend(deps),
0175                         [&](const auto& dep) {
0176                             return dep.other() == other;
0177                         })
0178         != std::cend(deps);
0179 }
0180 
0181 bool operator==(const LakosianNode& lhs, const LakosianNode& rhs)
0182 {
0183     return lhs.type() == rhs.type() && lhs.id() == rhs.id();
0184 }
0185 
0186 std::vector<LakosianNode *> LakosianNode::parentHierarchy()
0187 {
0188     // parent-hierarchy of the physical node.
0189     auto *tmp = this;
0190     std::vector<LakosianNode *> hierarchy;
0191     while (tmp) {
0192         hierarchy.push_back(tmp);
0193         tmp = tmp->parent();
0194     }
0195     std::reverse(std::begin(hierarchy), std::end(hierarchy));
0196     return hierarchy;
0197 }
0198 
0199 LakosianNode *LakosianNode::topLevelParent()
0200 {
0201     LakosianNode *parentPtr = this;
0202     while (parentPtr) {
0203         if (!parentPtr->parent()) {
0204             break;
0205         }
0206         parentPtr = parentPtr->parent();
0207     }
0208 
0209     return parentPtr;
0210 }
0211 
0212 } // namespace Codethink::lvtldr