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

0001 // ct_lvtldr_nodestorage.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_NODESTORAGE
0021 #define INCLUDED_CT_LVTLDR_NODESTORAGE
0022 
0023 //@PURPOSE: In-Memory API for serialization / deserialization.
0024 //
0025 //@CLASSES:
0026 //  lvtldr::NodeStorage
0027 
0028 #include <ct_lvtldr_sociutils.h>
0029 #include <ct_lvtshr_uniqueid.h>
0030 #include <lvtldr_export.h>
0031 
0032 #include <QObject>
0033 
0034 #include <any>
0035 #include <memory>
0036 #include <soci/soci.h>
0037 #include <vector>
0038 
0039 #include <result/result.hpp>
0040 
0041 namespace Codethink::lvtldr {
0042 class LakosianNode;
0043 class TypeNode;
0044 
0045 // ==========================
0046 // class NodeStorage
0047 // ==========================
0048 
0049 struct ErrorRemoveEntity {
0050     enum class Kind { CannotRemoveWithProviders, CannotRemoveWithClients, CannotRemoveWithChildren };
0051 
0052     Kind kind;
0053 };
0054 
0055 struct ErrorAddPhysicalDependency {
0056     enum class Kind {
0057         InvalidType,
0058         SelfRelation,
0059         HierarchyLevelMismatch,
0060         MissingParentDependency,
0061         DependencyAlreadyExists
0062     };
0063 
0064     Kind kind;
0065 };
0066 struct ErrorRemovePhysicalDependency {
0067     enum class Kind { InexistentRelation };
0068 
0069     Kind kind;
0070 };
0071 struct ErrorAddComponent {
0072     enum class Kind { MissingParent, QualifiedNameAlreadyRegistered, CannotAddComponentToPkgGroup };
0073 
0074     Kind kind;
0075 };
0076 struct ErrorAddPackage {
0077     enum class Kind { QualifiedNameAlreadyRegistered, CannotAddPackageToStandalonePackage, CantAddChildren };
0078     Kind kind;
0079     std::string what;
0080 };
0081 
0082 struct ErrorAddUDT {
0083     enum class Kind { BadParentType };
0084 
0085     Kind kind;
0086 };
0087 struct ErrorAddLogicalRelation {
0088     enum class Kind {
0089         SelfRelation,
0090         InvalidLakosRelationType,
0091         AlreadyHaveDependency,
0092         ComponentDependencyRequired,
0093         ParentDependencyRequired,
0094         InvalidRelation
0095     };
0096 
0097     Kind kind;
0098 };
0099 struct ErrorRemoveLogicalRelation {
0100     enum class Kind { InexistentRelation, InvalidLakosRelationType };
0101 
0102     Kind kind;
0103 };
0104 struct ErrorReparentEntity {
0105     enum class Kind { InvalidEntity, InvalidParent };
0106 
0107     Kind kind;
0108 };
0109 
0110 class LVTLDR_EXPORT NodeStorage : public QObject {
0111     Q_OBJECT
0112     // Append-only store of LakosianNodes with fast lookup
0113 
0114   private:
0115     using DatabaseHandlerType = SociDatabaseHandler;
0116 
0117     // TYPES
0118     struct Private;
0119 
0120     // DATA
0121     std::unique_ptr<Private> d;
0122 
0123   public:
0124     // CREATORS
0125     NodeStorage();
0126     ~NodeStorage() noexcept;
0127     NodeStorage(const NodeStorage&) = delete;
0128     NodeStorage(NodeStorage&&) noexcept;
0129 
0130     void setDatabaseSourcePath(std::string const& path);
0131     void closeDatabase();
0132 
0133     // MODIFIERS
0134     cpp::result<LakosianNode *, ErrorAddPackage> addPackage(const std::string& name,
0135                                                             const std::string& qualifiedName,
0136                                                             LakosianNode *parent = nullptr,
0137                                                             std::any userdata = std::any());
0138 
0139     cpp::result<void, ErrorRemoveEntity> removePackage(LakosianNode *node);
0140     // removes a package.
0141 
0142     cpp::result<LakosianNode *, ErrorAddComponent>
0143     addComponent(const std::string& name, const std::string& qualifiedName, LakosianNode *parentPackage);
0144     // adds a component on a Package.
0145 
0146     cpp::result<void, ErrorRemoveEntity> removeComponent(LakosianNode *node);
0147     // removes a package.
0148 
0149     cpp::result<LakosianNode *, ErrorAddUDT> addLogicalEntity(const std::string& name,
0150                                                               const std::string& qualifiedName,
0151                                                               LakosianNode *parent,
0152                                                               lvtshr::UDTKind kind);
0153     // adds a logical entity on a given parent.
0154     // the given parent can be a component, or a logical entity.
0155 
0156     cpp::result<void, ErrorRemoveEntity> removeLogicalEntity(LakosianNode *node);
0157 
0158     [[nodiscard]] cpp::result<void, ErrorAddPhysicalDependency> addPhysicalDependency(LakosianNode *source,
0159                                                                                       LakosianNode *target);
0160 
0161     [[nodiscard]] cpp::result<void, ErrorRemovePhysicalDependency> removePhysicalDependency(LakosianNode *source,
0162                                                                                             LakosianNode *target);
0163 
0164     [[nodiscard]] cpp::result<void, ErrorAddLogicalRelation>
0165     addLogicalRelation(TypeNode *source, TypeNode *target, lvtshr::LakosRelationType type);
0166     [[nodiscard]] cpp::result<void, ErrorRemoveLogicalRelation>
0167     removeLogicalRelation(TypeNode *source, TypeNode *target, lvtshr::LakosRelationType type);
0168 
0169     [[nodiscard]] cpp::result<void, ErrorReparentEntity> reparentEntity(LakosianNode *entity, LakosianNode *newParent);
0170 
0171     LakosianNode *findById(const lvtshr::UniqueId& uid);
0172     LakosianNode *findByQualifiedName(const std::string& qualifiedName);
0173     LakosianNode *findByQualifiedName(lvtshr::DiagramType type, const std::string& qualifiedName);
0174     [[nodiscard]] std::vector<LakosianNode *> getTopLevelPackages();
0175 
0176     void clear();
0177 
0178     std::invoke_result_t<decltype(&DatabaseHandlerType::getSession), DatabaseHandlerType> getSession();
0179 
0180     // Signals
0181     Q_SIGNAL void storageCleared();
0182     Q_SIGNAL void storageChanged();
0183     Q_SIGNAL void nodeAdded(LakosianNode *, std::any);
0184     Q_SIGNAL void nodeRemoved(LakosianNode *);
0185     Q_SIGNAL void nodeNameChanged(LakosianNode *);
0186     Q_SIGNAL void physicalDependencyAdded(LakosianNode *, LakosianNode *);
0187     Q_SIGNAL void physicalDependencyRemoved(LakosianNode *, LakosianNode *);
0188     Q_SIGNAL void logicalRelationAdded(LakosianNode *, LakosianNode *, lvtshr::LakosRelationType type);
0189     Q_SIGNAL void logicalRelationRemoved(LakosianNode *, LakosianNode *, lvtshr::LakosRelationType type);
0190     Q_SIGNAL void entityReparent(LakosianNode *, LakosianNode *, LakosianNode *);
0191 
0192   private:
0193     template<typename LDR_TYPE>
0194     LakosianNode *fetchFromDBByQualifiedName(const std::string& qualifiedName);
0195 
0196     template<typename LDR_TYPE>
0197     LakosianNode *fetchFromDBById(const lvtshr::UniqueId& uid);
0198 
0199     template<typename LDR_TYPE>
0200     void updateAndNotifyNodeRename(LakosianNode *node);
0201 
0202     void preloadHighLevelComponents();
0203 };
0204 
0205 } // namespace Codethink::lvtldr
0206 #endif