0.6.0
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
diagram_element.h
Go to the documentation of this file.
1/**
2 * src/common/model/diagram_element.h
3 *
4 * Copyright (c) 2021-2025 Bartek Kryza <bkryza@gmail.com>
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18#pragma once
19
20#include "decorated_element.h"
21#include "relationship.h"
22#include "source_location.h"
23#include "util/memoized.h"
24#include "util/util.h"
25
26#include <inja/inja.hpp>
27
28#include <atomic>
29#include <exception>
30#include <set>
31#include <string>
32#include <vector>
33
35
36class diagram_filter;
37
38struct full_name_tag_t { };
39struct name_and_ns_tag { };
40
41/**
42 * @brief Base class for standalone diagram elements.
43 *
44 * This is a base cass of any standalone elements such as classes, structs,
45 * concepts, packages and so on participants and so on.
46 */
48 : public decorated_element,
49 public source_location,
50 public util::memoized<full_name_tag_t, std::string, bool>,
51 public util::memoized<name_and_ns_tag, std::string> {
52public:
54
55 ~diagram_element() override = default;
56
57 /**
58 * @brief Returns diagram element id.
59 *
60 * Each element in the diagram is uniquely identified by id. The id
61 * is currently calculated from the full string representation of the
62 * element, in order to be uniquely identifiable among multiple translation
63 * units.
64 *
65 * @return Elements id.
66 */
67 const eid_t &id() const;
68
69 /**
70 * Set elements id.
71 *
72 * @param id Elements id.
73 */
74 void set_id(eid_t id);
75
76 /**
77 * Get elements parent package id.
78 *
79 * @return Parent package id if element is nested.
80 */
81 std::optional<eid_t> parent_element_id() const;
82
83 /**
84 * Set elements parent package id.
85 *
86 * @param id Id of parent package.
87 */
89
90 /**
91 * @brief Return elements' diagram alias.
92 *
93 * @todo This is a PlantUML specific method - it shouldn't be here.
94 *
95 * @return PlantUML's diagram element alias.
96 */
97 virtual std::string alias() const;
98
99 /**
100 * Set diagram elements name.
101 *
102 * @param name Elements name.
103 */
104 void set_name(const std::string &name)
105 {
107 name_ = name;
108 }
109
110 /**
111 * Set diagram elements name for nested elements.
112 *
113 * @param parent Parents name.
114 * @param name Elements name.
115 */
116 void set_name(const std::string &parent, const std::string &name)
117 {
118 set_name(fmt::format("{}##{}", parent, name));
119 }
120
121 /**
122 * Return diagram element name.
123 *
124 * @return Diagram element name.
125 */
126 std::string name() const { return name_; }
127
128 /**
129 * Return the type name of the diagram element.
130 *
131 * @return Diagrams element type name.
132 */
133 virtual std::string type_name() const { return "__undefined__"; };
134
135 /**
136 * @brief Return the elements fully qualified name.
137 *
138 * This method should be implemented in each subclass, and ensure that
139 * for instance it includes fully qualified namespace, template params, etc.
140 *
141 * @return Full elements name.
142 */
143 std::string full_name(bool relative) const
144 {
146 complete(),
147 [this](bool relative) { return full_name_impl(relative); },
148 relative);
149 }
150
151 /**
152 * Return all relationships outgoing from this element.
153 *
154 * @return List of relationships.
155 */
156 std::vector<relationship> &relationships();
157
158 /**
159 * Return all relationships outgoing from this element.
160 *
161 * @return List of relationships.
162 */
163 const std::vector<relationship> &relationships() const;
164
165 /**
166 * Add relationships, whose source is this element.
167 *
168 * @param cr Relationship to another diagram element.
169 */
171
172 /**
173 * Add element to the diagram.
174 *
175 * @param e Diagram element.
176 */
177 void append(const decorated_element &e);
178
179 friend bool operator==(const diagram_element &l, const diagram_element &r);
180
181 friend std::ostream &operator<<(
182 std::ostream &out, const diagram_element &rhs);
183
184 /**
185 * Whether this element is nested in another element.
186 *
187 * @return
188 */
189 bool is_nested() const;
190
191 /**
192 * Set element's nested status.
193 *
194 * @param nested
195 */
196 void nested(bool nested);
197
198 /**
199 * Returns the diagrams completion status.
200 *
201 * @return Whether the diagram is complete.
202 */
203 bool complete() const;
204
205 /**
206 * Set the diagrams completion status.
207 *
208 * @param completed
209 */
210 void complete(bool completed);
211
212 /**
213 * Due to the fact that a relationship to the same element can be added
214 * once with local TU id and other time with global id, the relationship
215 * set can contain duplicates.
216 */
218
219 virtual void apply_filter(
220 const diagram_filter &filter, const std::set<eid_t> &removed);
221
222protected:
223 virtual std::string full_name_impl(bool /*relative*/) const
224 {
225 return name();
226 }
227
228private:
230 std::optional<eid_t> parent_element_id_{};
231 std::string name_;
232 std::vector<relationship> relationships_;
233 bool nested_{false};
234 bool complete_{false};
235};
236} // namespace clanguml::common::model
237
238template <typename T>
239struct fmt::formatter<T,
240 std::enable_if_t<
241 std::is_base_of_v<clanguml::common::model::diagram_element, T>, char>>
242 : fmt::formatter<std::string> {
244 format_context &ctx) const
245 {
246 return formatter<std::string>::format(a.full_name(false), ctx);
247 }
248};