File indexing completed on 2024-05-19 05:41:57
0001 // ct_lvtcgn_app_adapter.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_lvtcgn_app_adapter.h> 0021 #include <ct_lvtcgn_codegendialog.h> 0022 #include <ct_lvtcgn_generatecode.h> 0023 0024 #include <ct_lvtldr_lakosiannode.h> 0025 #include <ct_lvtldr_nodestorage.h> 0026 0027 #include <preferences.h> 0028 0029 using namespace Codethink::lvtcgn::mdl; 0030 using namespace Codethink::lvtcgn::gui; 0031 using namespace Codethink::lvtldr; 0032 using namespace Codethink::lvtshr; 0033 0034 namespace { 0035 bool shouldDefaultSelectForCodegen(LakosianNode& node) 0036 { 0037 // External dependencies (Within non-lakosian group) are disabled by default 0038 if (node.name() == "non-lakosian group") { 0039 return false; 0040 } 0041 auto *parentNode = &node; 0042 while (parentNode->parent()) { 0043 parentNode = parentNode->parent(); 0044 if (parentNode->name() == "non-lakosian group") { 0045 return false; 0046 } 0047 } 0048 0049 return true; 0050 } 0051 } // namespace 0052 0053 namespace Codethink::lvtcgn::app { 0054 0055 WrappedLakosianNode::WrappedLakosianNode(NodeStorageDataProvider& dataProvider, 0056 LakosianNode *node, 0057 bool isSelectedForCodegen): 0058 dataProvider(dataProvider), node(node), isSelectedForCodegen(isSelectedForCodegen) 0059 { 0060 } 0061 0062 WrappedLakosianNode::~WrappedLakosianNode() = default; 0063 0064 std::string WrappedLakosianNode::name() const 0065 { 0066 return node->name(); 0067 } 0068 0069 std::string WrappedLakosianNode::type() const 0070 { 0071 std::string type = "Unknown"; 0072 if (node->type() == DiagramType::ComponentType) { 0073 type = "Component"; 0074 } 0075 if (node->type() == DiagramType::PackageType && node->parent() != nullptr) { 0076 type = "Package"; 0077 } 0078 if (node->type() == DiagramType::PackageType && node->parent() == nullptr) { 0079 // If there's no parent, the node may be a package or a package group: 0080 auto const& children = node->children(); 0081 if (children.empty()) { 0082 // (1) If there are no children, assume package. 0083 type = "Package"; 0084 } else if (children.at(0)->type() == DiagramType::PackageType) { 0085 // (2) If any child is a package, assume package groups 0086 type = "PackageGroup"; 0087 } else if (children.at(0)->type() == DiagramType::ComponentType) { 0088 // (3) If any child is a component, assume package 0089 type = "Package"; 0090 } 0091 } 0092 return type; 0093 } 0094 0095 std::optional<std::reference_wrapper<IPhysicalEntityInfo>> WrappedLakosianNode::parent() const 0096 { 0097 if (!node->parent()) { 0098 return std::nullopt; 0099 } 0100 return dataProvider.getWrappedNode(node->parent()); 0101 } 0102 0103 std::vector<std::reference_wrapper<IPhysicalEntityInfo>> WrappedLakosianNode::children() const 0104 { 0105 auto wrappedVec = std::vector<std::reference_wrapper<IPhysicalEntityInfo>>{}; 0106 for (auto *e : node->children()) { 0107 if (e->type() == DiagramType::ComponentType || e->type() == DiagramType::PackageType) { 0108 wrappedVec.push_back(dataProvider.getWrappedNode(e)); 0109 } 0110 } 0111 return wrappedVec; 0112 } 0113 0114 std::vector<std::reference_wrapper<IPhysicalEntityInfo>> WrappedLakosianNode::fwdDependencies() const 0115 { 0116 auto wrappedVec = std::vector<std::reference_wrapper<IPhysicalEntityInfo>>{}; 0117 for (auto const& edge : node->providers()) { 0118 auto *e = edge.other(); 0119 if (e->type() == DiagramType::ComponentType || e->type() == DiagramType::PackageType) { 0120 wrappedVec.push_back(dataProvider.getWrappedNode(e)); 0121 } 0122 } 0123 return wrappedVec; 0124 } 0125 0126 bool WrappedLakosianNode::selectedForCodeGeneration() const 0127 { 0128 return isSelectedForCodegen; 0129 } 0130 0131 void WrappedLakosianNode::setSelectedForCodeGeneration(bool value) 0132 { 0133 isSelectedForCodegen = value; 0134 } 0135 0136 NodeStorageDataProvider::NodeStorageDataProvider(Codethink::lvtldr::NodeStorage& sharedNodeStorage): 0137 ns(sharedNodeStorage) 0138 { 0139 } 0140 0141 NodeStorageDataProvider::~NodeStorageDataProvider() = default; 0142 0143 std::reference_wrapper<IPhysicalEntityInfo> NodeStorageDataProvider::getWrappedNode(LakosianNode *node) 0144 { 0145 if (nodeToInfo.find(node) == nodeToInfo.end()) { 0146 nodeToInfo.insert( 0147 {node, std::make_unique<WrappedLakosianNode>(*this, node, shouldDefaultSelectForCodegen(*node))}); 0148 } 0149 return *nodeToInfo.at(node); 0150 } 0151 0152 std::vector<std::reference_wrapper<IPhysicalEntityInfo>> NodeStorageDataProvider::topLevelEntities() 0153 { 0154 std::vector<std::reference_wrapper<IPhysicalEntityInfo>> refVec; 0155 for (auto *topLevelNode : ns.getTopLevelPackages()) { 0156 refVec.emplace_back(getWrappedNode(topLevelNode).get()); 0157 } 0158 return refVec; 0159 } 0160 0161 int NodeStorageDataProvider::numberOfPhysicalEntities() const 0162 { 0163 // Count package groups 0164 auto topLvlPkgs = ns.getTopLevelPackages(); 0165 auto counter = topLvlPkgs.size(); 0166 for (auto *pkgGrp : topLvlPkgs) { 0167 // Count packages 0168 counter += pkgGrp->children().size(); 0169 for (auto *pkg : pkgGrp->children()) { 0170 // Count components 0171 counter += pkg->children().size(); 0172 } 0173 } 0174 return int(counter); 0175 } 0176 0177 void CodegenAppAdapter::run(QWidget *parent, Codethink::lvtldr::NodeStorage& sharedNodeStorage) 0178 { 0179 auto dataProvider = NodeStorageDataProvider{sharedNodeStorage}; 0180 auto dialog = CodeGenerationDialog{dataProvider, nullptr, parent}; 0181 0182 dialog.setOutputDir(Preferences::lastOutputDir()); 0183 0184 dialog.exec(); 0185 0186 Preferences::setLastOutputDir(dialog.outputDir()); 0187 } 0188 0189 } // namespace Codethink::lvtcgn::app