0.6.0
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 54 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 objc_member &m) const
 
bool should_include (const class_method &m) const
 Whether a class_method should be included in the diagram.
 
bool should_include (const objc_method &m) const
 
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.
 
const common::reference_vector< objc_interface > & objc_interfaces () const
 
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.
 
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 bool is_empty () const =0
 Check whether the diagram is empty.
 
virtual void apply_filter ()
 
- Public Member Functions inherited from clanguml::common::model::element_views< Ts >
template<typename F >
void for_all_elements (F &&f)
 
template<typename F >
void for_all_elements (F &&f) const
 
template<typename T >
const element_view< T > & view () const
 
template<typename T , typename F >
void dynamic_apply (T *e, F &&f) const
 Calls f function on e if it can be dynamically casted to any type in the element_views.
 
- Public Member Functions inherited from clanguml::common::model::element_view< Ts >
void add (std::reference_wrapper< Ts > element)
 Add reference to diagram element.
 
const reference_vector< Ts > & view () const
 Get collection of reference to diagram elements.
 
reference_vector< Ts > & view ()
 Get collection of reference to diagram elements.
 
common::optional_ref< Ts > 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)
 
void for_each (F &&f) const
 
- 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
 
bool is_root () const
 
void is_root (bool a)
 
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, bool is_root=false) const
 
template<typename F >
bool all_of (F &&f) const
 
bool is_empty (bool include_inner_packages=false) const
 
auto begin ()
 
auto end ()
 
auto cbegin () const
 
auto cend () const
 
auto begin () const
 
auto end () const
 
void print_tree (const int level) const
 
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 204 of file diagram.h.

205 {
206 if (parent_path.type() == common::model::path_type::kNamespace) {
207 return add_with_namespace_path(std::move(e));
208 }
209
210 if (parent_path.type() == common::model::path_type::kModule) {
211 return add_with_module_path(parent_path, std::move(e));
212 }
213
214 return add_with_filesystem_path(parent_path, std::move(e));
215 }

◆ 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 365 of file diagram.h.

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

◆ 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 332 of file diagram.h.

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

◆ 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 281 of file diagram.h.

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

◆ apply_filter()

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

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

Definition at line 270 of file diagram.cc.

271{
272 // First find all element ids which should be removed
273 std::set<eid_t> to_remove;
274
275 for_all_elements([&](auto &&elements_view) mutable {
276 for (const auto &el : elements_view)
277 if (!filter().should_include(el.get()))
278 to_remove.emplace(el.get().id());
279 });
280
285
286 nested_trait_ns::remove(to_remove);
287
288 for_all_elements([&](auto &&elements_view) mutable {
289 for (const auto &el : elements_view)
290 el.get().apply_filter(filter(), to_remove);
291 });
292}

◆ 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 47 of file diagram.cc.

48{
50}

◆ 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 57 of file diagram.cc.

58{
60}

◆ 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 272 of file diagram.h.

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

◆ 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 445 of file diagram.h.

446{
448}

◆ 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 52 of file diagram.cc.

53{
55}

◆ 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 415 of file diagram.h.

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

◆ 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 398 of file diagram.h.

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

◆ 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 433 of file diagram.h.

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

◆ 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 72 of file diagram.cc.

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

◆ get() [2/2]

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

Search for element in the diagram by id.

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

Definition at line 96 of file diagram.cc.

98{
99 common::optional_ref<clanguml::common::model::diagram_element> res;
100
101 res = find<class_>(id);
102
103 if (res.has_value())
104 return res;
105
106 res = find<enum_>(id);
107
108 if (res.has_value())
109 return res;
110
111 res = find<concept_>(id);
112
113 if (res.has_value())
114 return res;
115
116 res = find<objc_interface>(id);
117
118 return res;
119}

◆ 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 158 of file diagram.cc.

160{
161 bool found_new{false};
162 for (const auto &parent : parents) {
163 for (const auto &rel : parent.get().relationships()) {
165 continue;
166
167 auto p = find<class_>(rel.destination());
168
169 if (p.has_value()) {
170 auto [it, found] = parents.emplace(std::ref(p.value()));
171 if (found)
172 found_new = true;
173 }
174 else {
175 LOG_WARN("Couldn't find class representing base class: {}",
176 rel.destination().value());
177 }
178 }
179 }
180
181 if (found_new) {
182 get_parents(parents);
183 }
184}

◆ has_element()

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

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.

Definition at line 186 of file diagram.cc.

187{
188 const auto has_class = std::any_of(classes().begin(), classes().end(),
189 [id](const auto &c) { return c.get().id() == id; });
190
191 if (has_class)
192 return true;
193
194 const auto has_concept = std::any_of(classes().begin(), classes().end(),
195 [id](const auto &c) { return c.get().id() == id; });
196
197 if (has_concept)
198 return true;
199
200 const auto has_enum = std::any_of(enums().begin(), enums().end(),
201 [id](const auto &c) { return c.get().id() == id; });
202
203 if (has_enum)
204 return true;
205
206 return std::any_of(objc_interfaces().begin(), objc_interfaces().end(),
207 [id](const auto &c) { return c.get().id() == id; });
208}

◆ 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 294 of file diagram.cc.

◆ objc_interfaces()

const common::reference_vector< objc_interface > & clanguml::class_diagram::model::diagram::objc_interfaces ( ) const

Definition at line 62 of file diagram.cc.

63{
65}

◆ 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 238 of file diagram.cc.

239{
240 using common::eid_t;
241 using common::model::relationship;
243
244 for_all_elements([&](auto &&elements_view) mutable {
245 for (const auto &el : elements_view) {
246 std::set<eid_t> dependency_relationships_to_remove;
247
248 for (auto &r : el.get().relationships()) {
249 if (r.type() != relationship_t::kDependency)
250 dependency_relationships_to_remove.emplace(r.destination());
251 }
252
253 util::erase_if(el.get().relationships(),
254 [&dependency_relationships_to_remove, &el](const auto &r) {
255 if (r.type() != relationship_t::kDependency)
256 return false;
257
258 auto has_another_relationship_to_destination =
259 dependency_relationships_to_remove.count(
260 r.destination()) > 0;
261 auto is_self_dependency = r.destination() == el.get().id();
262
263 return has_another_relationship_to_destination ||
264 is_self_dependency;
265 });
266 }
267 });
268}

◆ should_include() [1/4]

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/4]

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}

◆ should_include() [3/4]

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

Definition at line 37 of file diagram.cc.

38{
39 return filter().should_include(m);
40}

◆ should_include() [4/4]

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

Definition at line 42 of file diagram.cc.

43{
44 return filter().should_include(m);
45}

◆ 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 210 of file diagram.cc.

211{
212 LOG_DBG("Looking for alias for {}", id);
213
214 for (const auto &c : classes()) {
215 if (c.get().id() == id) {
216 return c.get().alias();
217 }
218 }
219
220 for (const auto &e : enums()) {
221 if (e.get().id() == id)
222 return e.get().alias();
223 }
224
225 for (const auto &c : concepts()) {
226 if (c.get().id() == id)
227 return c.get().alias();
228 }
229
230 for (const auto &c : objc_interfaces()) {
231 if (c.get().id() == id)
232 return c.get().alias();
233 }
234
235 throw error::uml_alias_missing(fmt::format("Missing alias for {}", id));
236}

◆ 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 67 of file diagram.cc.


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