0.6.1
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
Public Member Functions | Private Types | Private Member Functions | Private Attributes | List of all members
clanguml::common::model::nested_trait< T, Path > Class Template Reference

Base class for elements nested in the diagram. More...

Detailed Description

template<typename T, typename Path>
class clanguml::common::model::nested_trait< T, Path >

Base class for elements nested in the diagram.

This class provides a common trait for diagram elements which can contain other nested elements, e.g. packages.

Template Parameters
TType of element
PathType of nested path (e.g. namespace or directory path)

Definition at line 43 of file nested_trait.h.

#include <nested_trait.h>

Public Member Functions

 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 > element)
 
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 cbegin () const
 
auto cend () const
 
auto begin () const
 
auto end () const
 
void print_tree (const int level) const
 
template<typename V = T>
std::unique_ptr< V > get_and_remove (eid_t id)
 
void remove (const std::set< eid_t > &element_ids)
 

Private Types

using element_iterator_t = typename std::list< std::unique_ptr< T > >::iterator
 

Private Member Functions

bool has_element (const std::string &name) const
 

Private Attributes

bool is_root_ {false}
 
std::list< std::unique_ptr< T > > elements_
 
std::map< eid_t, element_iterator_telements_by_id_
 
std::multimap< std::string, element_iterator_telements_by_name_
 

Member Typedef Documentation

◆ element_iterator_t

template<typename T , typename Path >
using clanguml::common::model::nested_trait< T, Path >::element_iterator_t = typename std::list<std::unique_ptr<T> >::iterator
private

Definition at line 344 of file nested_trait.h.

Constructor & Destructor Documentation

◆ nested_trait() [1/3]

template<typename T , typename Path >
clanguml::common::model::nested_trait< T, Path >::nested_trait ( )
default

◆ nested_trait() [2/3]

template<typename T , typename Path >
clanguml::common::model::nested_trait< T, Path >::nested_trait ( const nested_trait< T, Path > &  )
delete

◆ nested_trait() [3/3]

template<typename T , typename Path >
clanguml::common::model::nested_trait< T, Path >::nested_trait ( nested_trait< T, Path > &&  )
defaultnoexcept

◆ ~nested_trait()

template<typename T , typename Path >
virtual clanguml::common::model::nested_trait< T, Path >::~nested_trait ( )
virtualdefault

Member Function Documentation

◆ add_element() [1/2]

template<typename T , typename Path >
template<typename V = T>
bool clanguml::common::model::nested_trait< T, Path >::add_element ( const Path &  path,
std::unique_ptr< V >  p 
)
inline

Add element at a nested path.

Template Parameters
VType of element
Parameters
pathNested path (e.g. list of namespaces)
pElement
Returns
True, if element was added.

Definition at line 99 of file nested_trait.h.

100 {
101 assert(p);
102
103 LOG_TRACE("Adding nested element {} at path '{}{}'", p->name(),
104 path.is_root() ? "::" : "", path.to_string());
105
106 if (path.is_empty()) {
107 return add_element(std::move(p));
108 }
109
110 auto parent = get_element(path);
111
112 if (parent) {
113 auto *nested_trait_ptr =
114 dynamic_cast<nested_trait<T, Path> *>(&parent.value());
115 if (nested_trait_ptr != nullptr) {
116 p->set_parent_element_id(parent.value().id());
117 return (*nested_trait_ptr)
118 .template add_element<V>(std::move(p));
119 }
120 }
121
122 LOG_INFO("No parent element found at: {}", path.to_string());
123
124 throw std::runtime_error(
125 "No parent element found for " + path.to_string());
126 }

◆ add_element() [2/2]

template<typename T , typename Path >
template<typename V = T>
bool clanguml::common::model::nested_trait< T, Path >::add_element ( std::unique_ptr< V >  element)
inline

Add element at the current nested level.

Template Parameters
VType of element
Parameters
pElement
Returns
True, if element was added.

Definition at line 67 of file nested_trait.h.

68 {
69 const auto element_id = element->id();
70 const auto element_name = element->name();
71
72 if (elements_by_id_.count(element_id) > 0) {
73 // Element already in element tree
74 return false;
75 }
76
77 elements_.push_back(std::move(element));
78
79 auto element_it = std::prev(elements_.end());
80
81 elements_by_id_.emplace(element_id, element_it);
82 elements_by_name_.emplace(element_name, element_it);
83
84 assert(elements_.size() == elements_by_id_.size());
85 assert(elements_.size() == elements_by_name_.size());
86
87 return true;
88 }

◆ all_of()

template<typename T , typename Path >
template<typename F >
bool clanguml::common::model::nested_trait< T, Path >::all_of ( F &&  f) const
inline

Return result of functor f applied to all_of elements.

Template Parameters
FFunctor type
Parameters
fFunctor value
Returns
True, if functor return true for elements, including nested ones.

Definition at line 207 of file nested_trait.h.

208 {
209 return std::all_of(
210 elements_.cbegin(), elements_.cend(), [f](const auto &e) {
211 const auto *package_ptr =
212 dynamic_cast<nested_trait<T, Path> *>(e.get());
213
214 if (package_ptr != nullptr)
215 return package_ptr->all_of(f);
216
217 return f(*e);
218 });
219 }

◆ begin()

template<typename T , typename Path >
auto clanguml::common::model::nested_trait< T, Path >::begin ( ) const
inline

Definition at line 246 of file nested_trait.h.

246{ return elements_.begin(); }

◆ cbegin()

template<typename T , typename Path >
auto clanguml::common::model::nested_trait< T, Path >::cbegin ( ) const
inline

Definition at line 243 of file nested_trait.h.

243{ return elements_.cbegin(); }

◆ cend()

template<typename T , typename Path >
auto clanguml::common::model::nested_trait< T, Path >::cend ( ) const
inline

Definition at line 244 of file nested_trait.h.

244{ return elements_.cend(); }

◆ end()

template<typename T , typename Path >
auto clanguml::common::model::nested_trait< T, Path >::end ( ) const
inline

Definition at line 247 of file nested_trait.h.

247{ return elements_.end(); }

◆ get_and_remove()

template<typename T , typename Path >
template<typename V = T>
std::unique_ptr< V > clanguml::common::model::nested_trait< T, Path >::get_and_remove ( eid_t  id)
inline

Definition at line 277 of file nested_trait.h.

278 {
279 std::unique_ptr<V> result;
280
281 auto id_it = elements_by_id_.find(id);
282 if (id_it == elements_by_id_.end()) {
283 for (auto &p : elements_) {
284 if (dynamic_cast<nested_trait<T, Path> *>(p.get())) {
285 result = dynamic_cast<nested_trait<T, Path> *>(p.get())
286 ->get_and_remove<V>(id);
287 if (result)
288 break;
289 }
290 }
291 return result;
292 }
293
294 // Get the iterator into the elements_ storage.
295 auto element_it = id_it->second;
296
297 // Remove from the name index.
298 auto name = (*element_it)->name();
299 auto name_range = elements_by_name_.equal_range(name);
300 for (auto it = name_range.first; it != name_range.second; ++it) {
301 if (it->second == element_it) {
302 elements_by_name_.erase(it);
303 break;
304 }
305 }
306
307 elements_by_id_.erase(id);
308
309 result = util::unique_pointer_cast<V>(std::move(*element_it));
310
311 elements_.erase(element_it);
312
313 assert(result);
314
315 assert(elements_.size() == elements_by_id_.size());
316 assert(elements_.size() == elements_by_name_.size());
317
318 return result;
319 }

◆ get_element() [1/2]

template<typename T , typename Path >
template<typename V = T>
auto clanguml::common::model::nested_trait< T, Path >::get_element ( const Path &  path) const
inline

Get element at path, if exists.

Template Parameters
VElement type.
Parameters
pathPath to the element.
Returns
Optional reference to the element.

Definition at line 135 of file nested_trait.h.

136 {
137 if (path.is_empty() || !has_element(path[0])) {
138 LOG_DBG("Nested element {} not found in element", path.to_string());
139 return optional_ref<V>{};
140 }
141
142 if (path.size() == 1) {
143 return get_element<V>(path[0], path.is_root());
144 }
145
146 auto p = get_element<T>(path[0], path.is_root());
147
148 if (!p)
149 return optional_ref<V>{};
150
151 if (dynamic_cast<nested_trait<T, Path> *>(&p.value()))
152 return dynamic_cast<nested_trait<T, Path> &>(p.value())
153 .get_element<V>(Path{path.begin() + 1, path.end()});
154
155 return optional_ref<V>{};
156 }

◆ get_element() [2/2]

template<typename T , typename Path >
template<typename V = T>
auto clanguml::common::model::nested_trait< T, Path >::get_element ( const std::string &  name,
bool  is_root = false 
) const
inline

Get element by name at the current nested level.

Template Parameters
VType of element.
Parameters
nameName of the element (cannot contain namespace or path)
Returns
Optional reference to the element.

Definition at line 166 of file nested_trait.h.

167 {
168 assert(!util::contains(name, "::"));
169
170 // Try to find an element by name and assuming it is a specific type
171 // For some reason it is legal to have a C/C++ struct with the same
172 // name as some ObjC protocol/interface, so the name is not
173 // necessarily unique
174
175 auto [it, matches_end] = elements_by_name_.equal_range(name);
176
177 while (true) {
178 if (it == matches_end)
179 break;
180
181 auto element_it = it->second;
182 it++;
183
184 if (auto element_ptr = dynamic_cast<V *>(element_it->get());
185 element_ptr != nullptr) {
186 if (auto nt_ptr = dynamic_cast<nested_trait<T, Path> *>(
187 element_it->get());
188 nt_ptr != nullptr) {
189 if (nt_ptr->is_root_ == is_root)
190 return optional_ref<V>{std::ref<V>(*element_ptr)};
191 }
192 else
193 return optional_ref<V>{std::ref<V>(*element_ptr)};
194 }
195 }
196
197 return optional_ref<V>{};
198 }

◆ has_element()

template<typename T , typename Path >
bool clanguml::common::model::nested_trait< T, Path >::has_element ( const std::string &  name) const
inlineprivate

Returns true of this nested level contains an element with specified name.

Parameters
nameName of the element.
Returns
True if element exists.

Definition at line 336 of file nested_trait.h.

337 {
338 return elements_by_name_.count(name) != 0U;
339 }

◆ is_empty()

template<typename T , typename Path >
bool clanguml::common::model::nested_trait< T, Path >::is_empty ( bool  include_inner_packages = false) const
inline

Check if nested element is empty.

Returns
True if this nested element is empty.

Definition at line 226 of file nested_trait.h.

227 {
228 // If we're interested whether the tree contains any elements including
229 // packages (even if their empty) just check elements_
230 if (include_inner_packages)
231 return elements_.empty();
232
233 // If we're interested only in non-package elements, that we have to
234 // traverse the nested chain
235 return elements_.empty() ||
236 std::all_of(elements_.cbegin(), elements_.cend(), [](auto &e) {
237 const auto *package_ptr =
238 dynamic_cast<nested_trait<T, Path> *>(e.get());
239 return package_ptr != nullptr && package_ptr->is_empty();
240 });
241 }

◆ is_root() [1/2]

template<typename T , typename Path >
bool clanguml::common::model::nested_trait< T, Path >::is_root ( ) const
inline

Definition at line 55 of file nested_trait.h.

55{ return is_root_; }

◆ is_root() [2/2]

template<typename T , typename Path >
void clanguml::common::model::nested_trait< T, Path >::is_root ( bool  a)
inline

Definition at line 57 of file nested_trait.h.

57{ is_root_ = a; }

◆ operator=() [1/2]

template<typename T , typename Path >
nested_trait & clanguml::common::model::nested_trait< T, Path >::operator= ( const nested_trait< T, Path > &  )
delete

◆ operator=() [2/2]

template<typename T , typename Path >
nested_trait & clanguml::common::model::nested_trait< T, Path >::operator= ( nested_trait< T, Path > &&  )
defaultnoexcept

◆ print_tree()

template<typename T , typename Path >
void clanguml::common::model::nested_trait< T, Path >::print_tree ( const int  level) const
inline

Print the nested trait in the form of a tree.

This method is used for debugging only.

Parameters
levelTree level

Definition at line 256 of file nested_trait.h.

257 {
258 if (level == 0) {
259 std::cout << "--- Printing tree:\n";
260 }
261
262 for (auto it = elements_.cbegin(); it != elements_.cend(); it++) {
263 const auto &e = *it;
264 if (dynamic_cast<nested_trait<T, Path> *>(e.get())) {
265 std::cout << std::string(level, ' ');
266 std::cout << "[" << *e << "]\n";
267 dynamic_cast<nested_trait<T, Path> *>(e.get())->print_tree(
268 level + 2);
269 }
270 else {
271 std::cout << std::string(level, ' ');
272 std::cout << "- " << *e << "]\n";
273 }
274 }
275 }

◆ remove()

template<typename T , typename Path >
void clanguml::common::model::nested_trait< T, Path >::remove ( const std::set< eid_t > &  element_ids)
inline

Definition at line 321 of file nested_trait.h.

322 {
323 for (const auto id : element_ids) {
324 get_and_remove(id);
325 }
326 }

Member Data Documentation

◆ elements_

template<typename T , typename Path >
std::list<std::unique_ptr<T> > clanguml::common::model::nested_trait< T, Path >::elements_
private

Definition at line 343 of file nested_trait.h.

◆ elements_by_id_

template<typename T , typename Path >
std::map<eid_t, element_iterator_t> clanguml::common::model::nested_trait< T, Path >::elements_by_id_
private

Definition at line 346 of file nested_trait.h.

◆ elements_by_name_

template<typename T , typename Path >
std::multimap<std::string, element_iterator_t> clanguml::common::model::nested_trait< T, Path >::elements_by_name_
private

Definition at line 347 of file nested_trait.h.

◆ is_root_

template<typename T , typename Path >
bool clanguml::common::model::nested_trait< T, Path >::is_root_ {false}
private

Definition at line 341 of file nested_trait.h.


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