File indexing completed on 2024-05-19 05:42:07
0001 // ct_lvtldr_lakosiannode.h -*-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 #ifndef INCLUDED_CT_LVTLDR_LAKOSIANNODE 0021 #define INCLUDED_CT_LVTLDR_LAKOSIANNODE 0022 0023 //@PURPOSE: Types *internal to lvtldr* used to cache loaded graphs in memory 0024 // 0025 //@CLASSES: 0026 // lvtldr::NodeStorage: Append-only store of LakosianNodes with fast lookup 0027 // lvtldr::LakosianEdge: Models a relation between LakosianNodes 0028 // lvtldr::LakosianNode: Representation of one node in the graph we loaded from 0029 // the database 0030 // lvtldr::TypeNode: Implementation of LakosianNode for UDTs 0031 // lvtldr::ComponentNode: Implementation of LakosianNode for components 0032 // lvtldr::PackageNode: Implementation of LakosianNode for packages 0033 0034 #include <lvtldr_export.h> 0035 0036 #include <ct_lvtldr_lakosianedge.h> 0037 0038 #include <ct_lvtldr_databasehandler.h> 0039 #include <ct_lvtshr_graphenums.h> 0040 #include <ct_lvtshr_uniqueid.h> 0041 0042 #include <QObject> 0043 0044 #include <functional> 0045 #include <memory> 0046 #include <string> 0047 #include <vector> 0048 0049 #include <result/result.hpp> 0050 0051 namespace Codethink::lvtldr { 0052 0053 // FORWARD DECLARATIONS 0054 class LakosianNode; 0055 0056 // TODO: Remove NodeStorage from this class. there should be no reason that a Node needs to know *how* it's stored. 0057 class NodeStorage; 0058 0059 struct LVTLDR_EXPORT AddChildError { 0060 std::string what; 0061 }; 0062 0063 struct LVTLDR_EXPORT NamingUtils { 0064 static std::vector<std::string> buildQualifiedNamePrefixParts(const std::string& qname, 0065 const std::string& separator); 0066 static std::string 0067 buildQualifiedName(const std::vector<std::string>& parts, const std::string& name, const std::string& separator); 0068 }; 0069 0070 // ========================== 0071 // class LakosianNode 0072 // ========================== 0073 0074 class LVTLDR_EXPORT LakosianNode : public QObject { 0075 Q_OBJECT 0076 // A node in a physical graph. This could be a package group, package, 0077 // component or type. 0078 // Should not be used outside of lvtldr. 0079 0080 protected: 0081 // TYPES 0082 struct Private { 0083 NodeStorage& store; 0084 std::optional<std::reference_wrapper<DatabaseHandler>> dbHandler = std::nullopt; 0085 0086 std::string name; 0087 0088 bool parentLoaded = false; 0089 bool childrenLoaded = false; 0090 bool providersLoaded = false; 0091 bool clientsLoaded = false; 0092 bool fieldsLoaded = false; 0093 0094 LakosianNode *parent = nullptr; 0095 std::vector<LakosianNode *> children; 0096 std::vector<LakosianNode *> innerPackages; 0097 std::vector<LakosianEdge> providers; 0098 std::vector<LakosianEdge> clients; 0099 std::vector<std::string> fieldNames; 0100 0101 explicit Private(NodeStorage& store, std::optional<std::reference_wrapper<DatabaseHandler>> dbHandler): 0102 store(store), dbHandler(dbHandler) 0103 { 0104 } 0105 }; 0106 0107 // DATA 0108 std::unique_ptr<Private> d; // NOLINT 0109 0110 // MODIFIERS 0111 virtual void loadParent() = 0; 0112 // Load the parent (if any) of this node 0113 0114 virtual void loadChildren() = 0; 0115 // Load the children (if any) of this node 0116 0117 virtual void loadProviders() = 0; 0118 // Load the forward dependencies (if any) of this node 0119 0120 virtual void loadClients() = 0; 0121 // Load the reverse dependencies (if any) of this node 0122 0123 public: 0124 enum class IsLakosianResult { 0125 IsLakosian, 0126 ComponentHasNoPackage, 0127 ComponentDoesntStartWithParentName, 0128 PackageParentIsNotGroup, 0129 PackagePrefixDiffersFromGroup, 0130 PackageNameInvalidNumberOfChars, 0131 PackageGroupNameInvalidNumberOfChars 0132 }; 0133 0134 // CREATORS 0135 explicit LakosianNode(NodeStorage& store, std::optional<std::reference_wrapper<DatabaseHandler>> dbHandler); 0136 // Stores the database session as a reference, so the SessionPtr 0137 // must outlive this LakosianNode 0138 0139 virtual ~LakosianNode() noexcept; 0140 0141 // ACCESSORS 0142 [[nodiscard]] virtual lvtshr::DiagramType type() const = 0; 0143 [[nodiscard]] virtual bool isPackageGroup(); 0144 // Unfortunately lvtshr::DiagramType doesn't distinguish between packages 0145 // and package groups 0146 0147 // For adding to IGraphLoader 0148 [[nodiscard]] virtual std::string qualifiedName() const = 0; 0149 [[nodiscard]] virtual std::string parentName() = 0; 0150 [[nodiscard]] virtual long long id() const = 0; 0151 0152 [[nodiscard]] virtual lvtshr::UniqueId uid() const = 0; 0153 0154 [[nodiscard]] virtual IsLakosianResult isLakosian() = 0; 0155 0156 virtual cpp::result<void, AddChildError> addChild(LakosianNode *child) = 0; 0157 // Add a child to this node NodeStorage. 0158 // Useful when creating a Node manually. 0159 0160 [[nodiscard]] virtual std::string name() const; 0161 virtual void setName(std::string const& newName); 0162 0163 // these aren't const because they are lazy-loaded 0164 0165 LakosianNode *parent(); 0166 // Returns the parent of this LakosianNode, 0167 // or nullptr if there is no parent. 0168 0169 LakosianNode *topLevelParent(); 0170 // Returns the parent of this LakosianNode, 0171 // or itself, if it's the toplevel entity. 0172 0173 std::vector<LakosianNode *> parentHierarchy(); 0174 // first element is the topmost parent, last element is this node. 0175 0176 const std::vector<LakosianNode *>& children(); 0177 0178 const std::vector<LakosianEdge>& providers(); 0179 const std::vector<LakosianEdge>& clients(); 0180 0181 const std::vector<std::string>& fields(); 0182 0183 std::string notes() const; 0184 void setNotes(const std::string& setNotes); 0185 0186 void invalidateProviders(); 0187 void invalidateClients(); 0188 virtual void invalidateChildren(); 0189 void invalidateParent(); 0190 0191 bool hasProvider(LakosianNode *other); 0192 0193 // signals 0194 Q_SIGNAL void onNameChanged(LakosianNode *); 0195 Q_SIGNAL void onChildCountChanged(size_t); 0196 Q_SIGNAL void onNotesChanged(std::string); 0197 }; 0198 0199 LVTLDR_EXPORT bool operator==(const LakosianNode& lhs, const LakosianNode& rhs); 0200 0201 template<typename T> 0202 struct LakosianNodeType { 0203 }; 0204 0205 } // namespace Codethink::lvtldr 0206 0207 #endif // INCLUDED_CT_LVTLDR_LAKOSIANNODE