0.6.0
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
Public Member Functions | 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 41 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 > 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

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

Private Attributes

bool is_root_ {false}
 
std::set< std::pair< eid_t, std::string > > added_elements_
 
std::vector< std::unique_ptr< T > > elements_
 
std::multimap< std::string, size_t > elements_by_name_
 

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 90 of file nested_trait.h.

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

◆ 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 >  p)
inline

Add element at the current nested level.

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

Definition at line 65 of file nested_trait.h.

66 {
67 if (auto id = p->id();
68 added_elements_.count(std::make_pair<eid_t, std::string>(
69 std::move(id), p->type_name()))) {
70 // Element already in element tree
71 return false;
72 }
73
74 added_elements_.emplace(p->id(), p->type_name());
75 elements_by_name_.emplace(p->name(), elements_.size());
76 elements_.emplace_back(std::move(p));
77
78 return true;
79 }

◆ 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 203 of file nested_trait.h.

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

◆ begin() [1/2]

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

Definition at line 239 of file nested_trait.h.

239{ return elements_.begin(); }

◆ begin() [2/2]

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

Definition at line 245 of file nested_trait.h.

245{ return elements_.begin(); }

◆ cbegin()

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

Definition at line 242 of file nested_trait.h.

242{ return elements_.cbegin(); }

◆ cend()

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

Definition at line 243 of file nested_trait.h.

243{ return elements_.cend(); }

◆ end() [1/2]

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

Definition at line 240 of file nested_trait.h.

240{ return elements_.end(); }

◆ end() [2/2]

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

Definition at line 246 of file nested_trait.h.

246{ return elements_.end(); }

◆ 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 126 of file nested_trait.h.

127 {
128 if (path.is_empty() || !has_element(path[0])) {
129 LOG_DBG("Nested element {} not found in element", path.to_string());
130 return optional_ref<V>{};
131 }
132
133 if (path.size() == 1) {
134 return get_element<V>(path[0], path.is_root());
135 }
136
137 auto p = get_element<T>(path[0], path.is_root());
138
139 if (!p)
140 return optional_ref<V>{};
141
142 if (dynamic_cast<nested_trait<T, Path> *>(&p.value()))
143 return dynamic_cast<nested_trait<T, Path> &>(p.value())
144 .get_element<V>(Path{path.begin() + 1, path.end()});
145
146 return optional_ref<V>{};
147 }

◆ 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 157 of file nested_trait.h.

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

◆ 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 325 of file nested_trait.h.

326 {
327 return elements_by_name_.count(name) != 0U;
328 }

◆ 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 222 of file nested_trait.h.

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

◆ is_root() [1/2]

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

Definition at line 53 of file nested_trait.h.

53{ 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 55 of file nested_trait.h.

55{ 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 255 of file nested_trait.h.

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

◆ 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 274 of file nested_trait.h.

275 {
276 // Find all elements positions to remove
277 size_t idx{0};
278 for (const auto &e : elements_) {
279 if (element_ids.count(e->id()) > 0) {
280 auto range = elements_by_name_.equal_range(e->name());
281
282 for (auto it = range.first; it != range.second; ++it) {
283 if (it->second == idx) {
284 elements_by_name_.erase(it);
285 break;
286 }
287 }
288 }
289
290 idx++;
291 }
292
293 // First remove all matching elements on this level
294 elements_.erase(std::remove_if(elements_.begin(), elements_.end(),
295 [&element_ids](auto &&e) {
296 return element_ids.count(e->id()) > 0;
297 }),
298 elements_.end());
299
300 decltype(added_elements_) to_keep_;
301
302 for (const auto &e : added_elements_) {
303 if (element_ids.count(e.first) == 0)
304 to_keep_.emplace(e);
305 }
306
307 std::swap(to_keep_, added_elements_);
308
309 // Now recurse to any packages on this level
310 for (auto &p : elements_) {
311 if (dynamic_cast<nested_trait<T, Path> *>(p.get()))
312 dynamic_cast<nested_trait<T, Path> *>(p.get())->remove(
313 element_ids);
314 }
315 }

Member Data Documentation

◆ added_elements_

template<typename T , typename Path >
std::set<std::pair<eid_t, std::string> > clanguml::common::model::nested_trait< T, Path >::added_elements_
private

Definition at line 332 of file nested_trait.h.

◆ elements_

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

Definition at line 333 of file nested_trait.h.

◆ elements_by_name_

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

Definition at line 334 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 330 of file nested_trait.h.


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