0.5.4
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
Public Member Functions | Private Member Functions | List of all members
clanguml::class_diagram::model::diagram Class Reference

Class representing a class diagram. More...

Detailed Description

Class representing a class diagram.

Definition at line 51 of file diagram.h.

#include <diagram.h>

Public Member Functions

 diagram ()=default
 
 diagram (const diagram &)=delete
 
 diagram (diagram &&)=default
 
diagramoperator= (const diagram &)=delete
 
diagramoperator= (diagram &&)=default
 
diagram_t type () const override
 Get the diagram model type - in this case class.
 
bool should_include (const class_member &m) const
 Whether a class_member should be included in the diagram.
 
bool should_include (const class_method &m) const
 Whether a class_method should be included in the diagram.
 
opt_ref< diagram_elementget (const std::string &full_name) const override
 Search for element in the diagram by fully qualified name.
 
opt_ref< diagram_elementget (eid_t id) const override
 Search for element in the diagram by id.
 
const common::reference_vector< class_ > & classes () const
 Get list of references to classes in the diagram model.
 
const common::reference_vector< enum_ > & enums () const
 Get list of references to enums in the diagram model.
 
const common::reference_vector< concept_ > & concepts () const
 Get list of references to concepts in the diagram model.
 
template<typename ElementT >
bool contains (const ElementT &e)
 Check, if diagram contains a specific element.
 
template<typename ElementT >
opt_ref< ElementT > find (const std::string &name) const
 Find an element in the diagram by name.
 
template<typename ElementT >
std::vector< opt_ref< ElementT > > find (const clanguml::common::string_or_regex &pattern) const
 Find elements in the diagram by regex pattern.
 
template<typename ElementT >
opt_ref< ElementT > find (eid_t id) const
 Find an element in the diagram by id.
 
template<typename ElementT >
const common::reference_vector< ElementT > & elements () const
 Get reference to vector of elements of specific type.
 
template<typename ElementT >
bool add (const path &parent_path, std::unique_ptr< ElementT > &&e)
 Add element to the diagram at a specified nested path.
 
std::string to_alias (eid_t id) const
 Convert element id to PlantUML alias.
 
void get_parents (clanguml::common::reference_set< class_ > &parents) const
 Given an initial set of classes, add all their parents to the argument.
 
bool has_element (eid_t id) const override
 Check if diagram contains element by id.
 
void remove_redundant_dependencies ()
 Remove redundant dependency relationships.
 
inja::json context () const override
 Return the elements JSON context for inja templates.
 
bool is_empty () const override
 Check whether the diagram is empty.
 
void apply_filter () override
 
- Public Member Functions inherited from clanguml::common::model::diagram
 diagram ()
 
 diagram (const diagram &)=delete
 
 diagram (diagram &&) noexcept
 
diagramoperator= (const diagram &)=delete
 
diagramoperator= (diagram &&) noexcept
 
virtual ~diagram ()
 
virtual diagram_t type () const =0
 Return type of the diagram.
 
virtual opt_ref< clanguml::common::model::diagram_elementget (const std::string &full_name) const =0
 
virtual common::optional_ref< clanguml::common::model::diagram_elementget (eid_t id) const =0
 
virtual common::optional_ref< clanguml::common::model::diagram_elementget_with_namespace (const std::string &name, const namespace_ &ns) const
 
void set_name (const std::string &name)
 
std::string name () const
 
void set_filter (std::unique_ptr< diagram_filter > filter)
 
const diagram_filterfilter () const
 
void set_complete (bool complete)
 Set diagram in a complete state.
 
bool complete () const
 Whether the diagram is complete.
 
virtual void finalize ()
 Once the diagram is complete, run any final processing.
 
bool should_include (const element &e) const
 
bool should_include (const namespace_ &ns) const
 
bool should_include (const source_file &path) const
 
bool should_include (relationship r) const
 
bool should_include (relationship_t r) const
 
bool should_include (access_t s) const
 
bool should_include (const std::string &s) const =delete
 
virtual bool has_element (const eid_t) const
 
virtual bool should_include (const namespace_ &ns, const std::string &name) const
 
virtual inja::json context () const =0
 
virtual bool is_empty () const =0
 Check whether the diagram is empty.
 
virtual void apply_filter ()
 
- Public Member Functions inherited from clanguml::common::model::element_view< T >
void add (std::reference_wrapper< T > element)
 Add reference to diagram element.
 
const reference_vector< T > & view () const
 Get collection of reference to diagram elements.
 
reference_vector< T > & view ()
 Get collection of reference to diagram elements.
 
common::optional_ref< T > get (eid_t id) const
 Get typed diagram element by id.
 
bool is_empty () const
 Check whether the element view is empty.
 
void remove (const std::set< eid_t > &element_ids)
 
- Public Member Functions inherited from clanguml::common::model::nested_trait< T, Path >
 nested_trait ()=default
 
 nested_trait (const nested_trait &)=delete
 
 nested_trait (nested_trait &&) noexcept=default
 
nested_traitoperator= (const nested_trait &)=delete
 
nested_traitoperator= (nested_trait &&) noexcept=default
 
virtual ~nested_trait ()=default
 
template<typename V = T>
bool add_element (std::unique_ptr< V > p)
 
template<typename V = T>
bool add_element (const Path &path, std::unique_ptr< V > p)
 
template<typename V = T>
auto get_element (const Path &path) const
 
template<typename V = T>
auto get_element (const std::string &name) const
 
bool has_element (const std::string &name) const
 
template<typename F >
bool all_of (F &&f) const
 
bool is_empty () const
 
auto begin ()
 
auto end ()
 
auto cbegin () const
 
auto cend () const
 
auto begin () const
 
auto end () const
 
void print_tree (const int level)
 
void remove (const std::set< eid_t > &element_ids)
 

Private Member Functions

template<typename ElementT >
bool add_with_namespace_path (std::unique_ptr< ElementT > &&e)
 
template<typename ElementT >
bool add_with_module_path (const common::model::path &parent_path, std::unique_ptr< ElementT > &&e)
 
template<typename ElementT >
bool add_with_filesystem_path (const common::model::path &parent_path, std::unique_ptr< ElementT > &&e)
 

Constructor & Destructor Documentation

◆ diagram() [1/3]

clanguml::class_diagram::model::diagram::diagram ( )
default

◆ diagram() [2/3]

clanguml::class_diagram::model::diagram::diagram ( const diagram )
delete

◆ diagram() [3/3]

clanguml::class_diagram::model::diagram::diagram ( diagram &&  )
default

Member Function Documentation

◆ add()

template<typename ElementT >
bool clanguml::class_diagram::model::diagram::add ( const path parent_path,
std::unique_ptr< ElementT > &&  e 
)
inline

Add element to the diagram at a specified nested path.

Adds an element to a diagram, at a specific package (if any exist). The package is specified by the parent_path, which can be either a namespace or a directory path.

Template Parameters
ElementTType of diagram element.
Parameters
parent_pathPath to the parent package of the new diagram element.
eDiagram element to be added.
Returns
True, if the element was added to the diagram.

Definition at line 199 of file diagram.h.

200 {
201 if (parent_path.type() == common::model::path_type::kNamespace) {
202 return add_with_namespace_path(std::move(e));
203 }
204
205 if (parent_path.type() == common::model::path_type::kModule) {
206 return add_with_module_path(parent_path, std::move(e));
207 }
208
209 return add_with_filesystem_path(parent_path, std::move(e));
210 }

◆ add_with_filesystem_path()

template<typename ElementT >
bool clanguml::class_diagram::model::diagram::add_with_filesystem_path ( const common::model::path parent_path,
std::unique_ptr< ElementT > &&  e 
)
private

Definition at line 368 of file diagram.h.

370{
371 const auto element_type = e->type_name();
372
373 // Make sure all parent modules are already packages in the
374 // model
375 for (auto it = parent_path.begin(); it != parent_path.end(); it++) {
376 auto pkg = std::make_unique<common::model::package>(
377 e->using_namespace(), parent_path.type());
378 pkg->set_name(*it);
379 auto ns =
380 common::model::path(parent_path.begin(), it, parent_path.type());
381 // ns.pop_back();
382 pkg->set_namespace(ns);
383 pkg->set_id(common::to_id(pkg->full_name(false)));
384
385 add(ns, std::move(pkg));
386 }
387
388 const auto base_name = e->name();
389 const auto full_name = e->full_name(false);
390 auto &e_ref = *e;
391
392 if (add_element(parent_path, std::move(e))) {
393 element_view<ElementT>::add(std::ref(e_ref));
394 return true;
395 }
396
397 return false;
398}

◆ add_with_module_path()

template<typename ElementT >
bool clanguml::class_diagram::model::diagram::add_with_module_path ( const common::model::path parent_path,
std::unique_ptr< ElementT > &&  e 
)
private

Definition at line 335 of file diagram.h.

337{
338 const auto element_type = e->type_name();
339
340 // Make sure all parent modules are already packages in the
341 // model
342 for (auto it = parent_path.begin(); it != parent_path.end(); it++) {
343 auto pkg = std::make_unique<common::model::package>(
344 e->using_namespace(), parent_path.type());
345 pkg->set_name(*it);
346 auto ns =
347 common::model::path(parent_path.begin(), it, parent_path.type());
348 // ns.pop_back();
349 pkg->set_namespace(ns);
350 pkg->set_id(common::to_id(pkg->full_name(false)));
351
352 add(ns, std::move(pkg));
353 }
354
355 const auto base_name = e->name();
356 const auto full_name = e->full_name(false);
357 auto &e_ref = *e;
358
359 if (add_element(parent_path, std::move(e))) {
360 element_view<ElementT>::add(std::ref(e_ref));
361 return true;
362 }
363
364 return false;
365}

◆ add_with_namespace_path()

template<typename ElementT >
bool clanguml::class_diagram::model::diagram::add_with_namespace_path ( std::unique_ptr< ElementT > &&  e)
private

Definition at line 283 of file diagram.h.

284{
285 const auto base_name = e->name();
286 const auto full_name = e->full_name(false);
287 const auto element_type = e->type_name();
288
289 LOG_DBG("Adding {}: {}::{}, {}", element_type,
290 e->get_namespace().to_string(), base_name, full_name);
291
292 if (util::contains(base_name, "::"))
293 throw std::runtime_error("Name cannot contain namespace: " + base_name);
294
295 if (util::contains(base_name, "*"))
296 throw std::runtime_error("Name cannot contain *: " + base_name);
297
298 const auto ns = e->get_relative_namespace();
299 auto name = base_name;
300 auto name_with_ns = e->name_and_ns();
301 auto name_and_ns = ns | name;
302 auto &e_ref = *e;
303 auto id = e_ref.id();
304
305 try {
306 if (!contains(e_ref)) {
307 if (add_element(ns, std::move(e)))
308 element_view<ElementT>::add(std::ref(e_ref));
309
310 const auto &el = get_element<ElementT>(name_and_ns).value();
311
312 if ((el.name() != name) || !(el.get_relative_namespace() == ns))
313 throw std::runtime_error(
314 "Invalid element stored in the diagram tree");
315
316 LOG_DBG("Added {} {} ({} - [{}])", element_type, base_name,
317 full_name, id);
318
319 return true;
320 }
321 }
322 catch (const std::runtime_error &e) {
323 LOG_WARN("Cannot add {} {} with id {} due to: {}", element_type, name,
324 id, e.what());
325 return false;
326 }
327
328 LOG_DBG("{} {} ({} - [{}]) already in the model", element_type, base_name,
329 full_name, id);
330
331 return false;
332}

◆ apply_filter()

void clanguml::class_diagram::model::diagram::apply_filter ( )
overridevirtual

Reimplemented from clanguml::common::model::diagram.

Definition at line 259 of file diagram.cc.

260{
261 // First find all element ids which should be removed
262 std::set<eid_t> to_remove;
263
264 for (const auto &c : element_view<class_>::view())
265 if (!filter().should_include(c.get()))
266 to_remove.emplace(c.get().id());
267
268 for (const auto &e : element_view<enum_>::view())
269 if (!filter().should_include(e.get()))
270 to_remove.emplace(e.get().id());
271
272 for (const auto &c : element_view<concept_>::view())
273 if (!filter().should_include(c.get()))
274 to_remove.emplace(c.get().id());
275
279
280 nested_trait_ns::remove(to_remove);
281
282 for (auto &c : element_view<class_>::view())
283 c.get().apply_filter(filter(), to_remove);
284
285 for (auto &e : element_view<enum_>::view())
286 e.get().apply_filter(filter(), to_remove);
287
288 for (auto &c : element_view<concept_>::view())
289 c.get().apply_filter(filter(), to_remove);
290}

◆ classes()

const common::reference_vector< class_ > & clanguml::class_diagram::model::diagram::classes ( ) const

Get list of references to classes in the diagram model.

Returns
List of references to classes in the diagram model.

Definition at line 37 of file diagram.cc.

38{
40}

◆ concepts()

const common::reference_vector< concept_ > & clanguml::class_diagram::model::diagram::concepts ( ) const

Get list of references to concepts in the diagram model.

Returns
List of references to concepts in the diagram model.

Definition at line 47 of file diagram.cc.

48{
50}

◆ contains()

template<typename ElementT >
bool clanguml::class_diagram::model::diagram::contains ( const ElementT &  e)

Check, if diagram contains a specific element.

Template Parameters
ElementTType of diagram element (e.g. class_)
Parameters
eElement to check
Returns
True, if element already exists in the diagram

Definition at line 274 of file diagram.h.

275{
276 return std::any_of(element_view<ElementT>::view().cbegin(),
278 [&element](
279 const auto &element_opt) { return element_opt.get() == element; });
280}

◆ context()

inja::json clanguml::class_diagram::model::diagram::context ( ) const
overridevirtual

Return the elements JSON context for inja templates.

Returns
JSON node with elements context.

Implements clanguml::common::model::diagram.

Definition at line 197 of file diagram.cc.

198{
199 inja::json ctx;
200 ctx["name"] = name();
201 ctx["type"] = "class";
202
203 inja::json::array_t elements{};
204
205 // Add classes
206 for (const auto &c : classes()) {
207 elements.emplace_back(c.get().context());
208 }
209
210 // Add enums
211 for (const auto &e : enums()) {
212 elements.emplace_back(e.get().context());
213 }
214
215 // Add enums
216 for (const auto &c : concepts()) {
217 elements.emplace_back(c.get().context());
218 }
219
220 ctx["elements"] = elements;
221
222 return ctx;
223}

◆ elements()

template<typename ElementT >
const common::reference_vector< ElementT > & clanguml::class_diagram::model::diagram::elements

Get reference to vector of elements of specific type.

Template Parameters
ElementTType of elements view
Returns
Reference to elements vector

Definition at line 448 of file diagram.h.

449{
451}

◆ enums()

const common::reference_vector< enum_ > & clanguml::class_diagram::model::diagram::enums ( ) const

Get list of references to enums in the diagram model.

Returns
List of references to enums in the diagram model.

Definition at line 42 of file diagram.cc.

43{
45}

◆ find() [1/3]

template<typename ElementT >
std::vector< opt_ref< ElementT > > clanguml::class_diagram::model::diagram::find ( const clanguml::common::string_or_regex pattern) const

Find elements in the diagram by regex pattern.

This method allows for typed search, where the type of searched for element is determined from template specialization.

Template Parameters
ElementTType of element (e.g. class_)
Parameters
nameString or regex pattern
Returns
List of optional references to matched elements.

Definition at line 418 of file diagram.h.

420{
421 std::vector<opt_ref<ElementT>> result;
422
423 for (const auto &element : element_view<ElementT>::view()) {
424 const auto full_name = element.get().full_name(false);
425 auto full_name_escaped = full_name;
426 util::replace_all(full_name_escaped, "##", "::");
427
428 if (pattern == full_name || pattern == full_name_escaped) {
429 result.emplace_back(element);
430 }
431 }
432
433 return result;
434}

◆ find() [2/3]

template<typename ElementT >
opt_ref< ElementT > clanguml::class_diagram::model::diagram::find ( const std::string &  name) const

Find an element in the diagram by name.

This method allows for typed search, where the type of searched for element is determined from template specialization.

Template Parameters
ElementTType of element (e.g. class_)
Parameters
nameFully qualified name of the element
Returns
Optional reference to a diagram element

Definition at line 401 of file diagram.h.

402{
403 for (const auto &element : element_view<ElementT>::view()) {
404 const auto full_name = element.get().full_name(false);
405
406 auto full_name_escaped = full_name;
407 util::replace_all(full_name_escaped, "##", "::");
408
409 if (name == full_name || name == full_name_escaped) {
410 return {element};
411 }
412 }
413
414 return {};
415}

◆ find() [3/3]

template<typename ElementT >
opt_ref< ElementT > clanguml::class_diagram::model::diagram::find ( eid_t  id) const

Find an element in the diagram by id.

This method allows for typed search, where the type of searched for element is determined from template specialization.

Template Parameters
ElementTType of element (e.g. class_)
Parameters
idId of the element
Returns
Optional reference to a diagram element

Definition at line 436 of file diagram.h.

437{
438 for (const auto &element : element_view<ElementT>::view()) {
439 if (element.get().id() == id) {
440 return {element};
441 }
442 }
443
444 return {};
445}

◆ get() [1/2]

common::optional_ref< clanguml::common::model::diagram_element > clanguml::class_diagram::model::diagram::get ( const std::string &  full_name) const
overridevirtual

Search for element in the diagram by fully qualified name.

Parameters
full_nameFully qualified element name.
Returns
Optional reference to a diagram element.

Implements clanguml::common::model::diagram.

Definition at line 57 of file diagram.cc.

59{
60 common::optional_ref<clanguml::common::model::diagram_element> res =
61 find<class_>(full_name);
62
63 if (res.has_value())
64 return res;
65
66 res = find<enum_>(full_name);
67
68 if (res.has_value())
69 return res;
70
71 res = find<concept_>(full_name);
72
73 return res;
74}

◆ get() [2/2]

common::optional_ref< clanguml::common::model::diagram_element > clanguml::class_diagram::model::diagram::get ( eid_t  id) const
overridevirtual

Search for element in the diagram by id.

Parameters
idElement id.
Returns
Optional reference to a diagram element.

Implements clanguml::common::model::diagram.

Definition at line 76 of file diagram.cc.

78{
79 common::optional_ref<clanguml::common::model::diagram_element> res;
80
81 res = find<class_>(id);
82
83 if (res.has_value())
84 return res;
85
86 res = find<enum_>(id);
87
88 if (res.has_value())
89 return res;
90
91 res = find<concept_>(id);
92
93 return res;
94}

◆ get_parents()

void clanguml::class_diagram::model::diagram::get_parents ( clanguml::common::reference_set< class_ > &  parents) const

Given an initial set of classes, add all their parents to the argument.

Parameters
parentsIn and out parameter with the parent classes.

Definition at line 131 of file diagram.cc.

133{
134 bool found_new{false};
135 for (const auto &parent : parents) {
136 for (const auto &pp : parent.get().parents()) {
137 auto p = find<class_>(pp.id());
138
139 if (p.has_value()) {
140 auto [it, found] = parents.emplace(std::ref(p.value()));
141 if (found)
142 found_new = true;
143 }
144 else {
145 LOG_WARN("Couldn't find class representing base class: {} [{}]",
146 pp.name(), pp.id());
147 }
148 }
149 }
150
151 if (found_new) {
152 get_parents(parents);
153 }
154}

◆ has_element()

bool clanguml::class_diagram::model::diagram::has_element ( eid_t  id) const
overridevirtual

Check if diagram contains element by id.

Todo:
Remove in favour of 'contains'
Parameters
idId of the element.
Returns
True, if diagram contains an element with a specific id.

Reimplemented from clanguml::common::model::diagram.

Definition at line 156 of file diagram.cc.

157{
158 const auto has_class = std::any_of(classes().begin(), classes().end(),
159 [id](const auto &c) { return c.get().id() == id; });
160
161 if (has_class)
162 return true;
163
164 const auto has_concept = std::any_of(classes().begin(), classes().end(),
165 [id](const auto &c) { return c.get().id() == id; });
166
167 if (has_concept)
168 return true;
169
170 return std::any_of(enums().begin(), enums().end(),
171 [id](const auto &c) { return c.get().id() == id; });
172}

◆ is_empty()

bool clanguml::class_diagram::model::diagram::is_empty ( ) const
overridevirtual

Check whether the diagram is empty.

Returns
True, if diagram is empty

Implements clanguml::common::model::diagram.

Definition at line 292 of file diagram.cc.

◆ operator=() [1/2]

diagram & clanguml::class_diagram::model::diagram::operator= ( const diagram )
delete

◆ operator=() [2/2]

diagram & clanguml::class_diagram::model::diagram::operator= ( diagram &&  )
default

◆ remove_redundant_dependencies()

void clanguml::class_diagram::model::diagram::remove_redundant_dependencies ( )

Remove redundant dependency relationships.

Definition at line 225 of file diagram.cc.

226{
227 using common::eid_t;
228 using common::model::relationship;
230
231 for (auto &c : element_view<class_>::view()) {
232 std::set<eid_t> dependency_relationships_to_remove;
233
234 for (auto &r : c.get().relationships()) {
235 if (r.type() != relationship_t::kDependency)
236 dependency_relationships_to_remove.emplace(r.destination());
237 }
238
239 for (const auto &base : c.get().parents()) {
240 dependency_relationships_to_remove.emplace(base.id());
241 }
242
243 util::erase_if(c.get().relationships(),
244 [&dependency_relationships_to_remove, &c](const auto &r) {
245 if (r.type() != relationship_t::kDependency)
246 return false;
247
248 auto has_another_relationship_to_destination =
249 dependency_relationships_to_remove.count(r.destination()) >
250 0;
251 auto is_self_dependency = r.destination() == c.get().id();
252
253 return has_another_relationship_to_destination ||
254 is_self_dependency;
255 });
256 }
257}

◆ should_include() [1/2]

bool clanguml::class_diagram::model::diagram::should_include ( const class_member m) const

Whether a class_member should be included in the diagram.

Parameters
mClass member
Returns
True, if class member should be included in the diagram.

Definition at line 27 of file diagram.cc.

28{
29 return filter().should_include(m);
30}

◆ should_include() [2/2]

bool clanguml::class_diagram::model::diagram::should_include ( const class_method m) const

Whether a class_method should be included in the diagram.

Parameters
mClass method
Returns
True, if class method should be included in the diagram.

Definition at line 32 of file diagram.cc.

33{
34 return filter().should_include(m);
35}

◆ to_alias()

std::string clanguml::class_diagram::model::diagram::to_alias ( eid_t  id) const

Convert element id to PlantUML alias.

Todo:
This method does not belong here - refactor to PlantUML specific code.
Parameters
idId of the diagram element.
Returns
PlantUML alias.

Definition at line 174 of file diagram.cc.

175{
176 LOG_DBG("Looking for alias for {}", id);
177
178 for (const auto &c : classes()) {
179 if (c.get().id() == id) {
180 return c.get().alias();
181 }
182 }
183
184 for (const auto &e : enums()) {
185 if (e.get().id() == id)
186 return e.get().alias();
187 }
188
189 for (const auto &c : concepts()) {
190 if (c.get().id() == id)
191 return c.get().alias();
192 }
193
194 throw error::uml_alias_missing(fmt::format("Missing alias for {}", id));
195}

◆ type()

common::model::diagram_t clanguml::class_diagram::model::diagram::type ( ) const
overridevirtual

Get the diagram model type - in this case class.

Returns
Type of class diagram.

Implements clanguml::common::model::diagram.

Definition at line 52 of file diagram.cc.


The documentation for this class was generated from the following files: