0.6.0
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
Public Member Functions | Protected Member Functions | Protected Attributes | Private Member Functions | Private Attributes | List of all members
clanguml::common::generators::graphml::generator< ConfigType, DiagramType > Class Template Referenceabstract

Base class for diagram generators. More...

Detailed Description

template<typename ConfigType, typename DiagramType>
class clanguml::common::generators::graphml::generator< ConfigType, DiagramType >

Base class for diagram generators.

Template Parameters
ConfigTypeConfiguration type
DiagramTypeDiagram model type

Definition at line 113 of file generator.h.

#include <generator.h>

Public Member Functions

 ~generator () override=default
 
virtual std::vector< std::pair< std::string, property_type > > graph_property_names () const
 
virtual std::vector< std::pair< std::string, property_type > > node_property_names () const
 
virtual std::vector< std::pair< std::string, property_type > > edge_property_names () const
 
void generate (std::ostream &ostr) const override
 Generate diagram.
 
void generate_diagram (graphml_node_t &parent) const
 Generate diagram model.
 
virtual void generate_top_level_elements (graphml_node_t &parent) const =0
 In a nested diagram, generate the top level elements.
 
template<typename T >
void generate_notes (const T &e, graphml_node_t &parent) const
 Generate any notes to be attached to diagram elements.
 
void generate_metadata (graphml_t &parent) const
 Generate metadata element with diagram metadata.
 
virtual void generate (const model::package &p, graphml_node_t &parent) const
 Generate diagram package.
 
virtual void generate_relationships (graphml_node_t &parent) const
 Generate all relationships in the diagram.
 
virtual void generate_relationships (const model::diagram_element &c, graphml_node_t &parent) const
 Generate all relationships originating at a diagram element.
 
template<typename T >
void generate_link (pugi::xml_node &node, const T &c) const
 
const property_keymap_tgraph_properties () const
 
const property_keymap_tnode_properties () const
 
const property_keymap_tedge_properties () const
 
pugi::xml_node make_node (graphml_node_t &parent, const std::string &id) const
 
pugi::xml_node make_graph (graphml_node_t &parent, const std::string &id) const
 
pugi::xml_node make_subgraph (graphml_node_t &parent, const std::string &id, const std::string &name="", const std::string &type="") const
 
void add_data (pugi::xml_node &node, const std::string &key, const std::string &value, bool cdata=false) const
 
void add_cdata (pugi::xml_node &node, const std::string &key, const std::string &value) const
 
- Public Member Functions inherited from clanguml::common::generators::generator< ConfigType, DiagramType >
 generator (ConfigType &config, DiagramType &model)
 Constructor.
 
virtual ~generator ()=default
 
virtual void generate (std::ostream &ostr) const =0
 Generate diagram.
 
const ConfigType & config () const
 Get reference to diagram config.
 
const DiagramType & model () const
 Get reference to diagram model.
 
std::optional< std::pair< std::string, std::string > > get_link_pattern (const common::model::source_location &sl) const
 
std::optional< std::pair< std::string, std::string > > get_tooltip_pattern (const common::model::source_location &sl) const
 
std::optional< std::string > render_link (const common::model::diagram_element &e) const
 
std::optional< std::string > render_link (const common::model::relationship &e) const
 
std::optional< std::string > render_tooltip (const common::model::diagram_element &e) const
 
std::optional< std::string > render_tooltip (const common::model::relationship &e) const
 
void init_context ()
 Initialize diagram Jinja context.
 
void update_context () const
 Update diagram Jinja context.
 
void init_env ()
 
const inja::json & context () const
 
inja::Environment & env () const
 

Protected Member Functions

void generate_key (pugi::xml_node &parent, const std::string &attr_name, const std::string &for_value, const std::string &id_value, const std::string &attr_type="string") const
 
property_keymap_tgraph_properties ()
 
property_keymap_tnode_properties ()
 
property_keymap_tedge_properties ()
 

Protected Attributes

graphml_node_map_t graph_ids_ {"g"}
 
graphml_node_map_t node_ids_ {"n"}
 
graphml_node_map_t edge_ids_ {"e"}
 
- Protected Attributes inherited from clanguml::common::generators::generator< ConfigType, DiagramType >
inja::json m_context
 
inja::Environment m_env
 

Private Member Functions

void generate_keys (graphml_node_t &parent) const
 

Private Attributes

property_keymap_t graph_properties_ {"gd"}
 
property_keymap_t node_properties_ {"nd"}
 
property_keymap_t edge_properties_ {"ed"}
 
uint64_t edge_id_ {0}
 
uint64_t note_id_ {0}
 

Constructor & Destructor Documentation

◆ ~generator()

template<typename ConfigType , typename DiagramType >
clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::~generator ( )
overridevirtualdefault

Member Function Documentation

◆ add_cdata()

template<typename C , typename D >
void clanguml::common::generators::graphml::generator< C, D >::add_cdata ( pugi::xml_node &  node,
const std::string &  key,
const std::string &  value 
) const

Definition at line 544 of file generator.h.

546{
547 return add_data(node, key_name, value, true);
548}

◆ add_data()

template<typename C , typename D >
void clanguml::common::generators::graphml::generator< C, D >::add_data ( pugi::xml_node &  node,
const std::string &  key,
const std::string &  value,
bool  cdata = false 
) const

Definition at line 520 of file generator.h.

522{
523 using namespace std::string_literals;
524
525 std::optional<std::pair<std::string, property_type>> key_id;
526 if (node.name() == "node"s)
527 key_id = node_properties().get(key_name);
528 else if (node.name() == "graph"s)
529 key_id = graph_properties().get(key_name);
530 else if (node.name() == "edge"s)
531 key_id = edge_properties().get(key_name);
532
533 if (key_id.has_value()) {
534 auto data = node.append_child("data");
535 data.append_attribute("key") = key_id->first;
536 if (cdata)
537 data.append_child(pugi::node_cdata).set_value(value);
538 else
539 data.text().set(value);
540 }
541}

◆ edge_properties() [1/2]

template<typename ConfigType , typename DiagramType >
property_keymap_t & clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::edge_properties ( )
inlineprotected

Definition at line 279 of file generator.h.

279{ return edge_properties_; }

◆ edge_properties() [2/2]

template<typename ConfigType , typename DiagramType >
const property_keymap_t & clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::edge_properties ( ) const
inline

Definition at line 252 of file generator.h.

253 {
254 return edge_properties_;
255 }

◆ edge_property_names()

template<typename ConfigType , typename DiagramType >
virtual std::vector< std::pair< std::string, property_type > > clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::edge_property_names ( ) const
inlinevirtual

Definition at line 145 of file generator.h.

146 {
147 using namespace std::string_literals;
148 return {{"type"s, property_type::kString},
149 {"access"s, property_type::kString},
150 {"label"s, property_type::kString},
151 {"url"s, property_type::kString}};
152 }

◆ generate() [1/2]

template<typename ConfigType , typename DiagramType >
virtual void clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::generate ( const model::package p,
graphml_node_t parent 
) const
inlinevirtual

Generate diagram package.

Parameters
pDiagram package element
parentParent JSON node

Definition at line 218 of file generator.h.

219 {
220 }

◆ generate() [2/2]

template<typename C , typename D >
void clanguml::common::generators::graphml::generator< C, D >::generate ( std::ostream &  ostr) const
overridevirtual

Generate diagram.

This is the main diagram generation entrypoint. It is responsible for calling other methods in appropriate order to generate the diagram into the output stream. It generates diagram elements, that are common to all types of diagrams in a given generator.

Parameters
ostrOutput stream

Implements clanguml::common::generators::generator< ConfigType, DiagramType >.

Definition at line 305 of file generator.h.

306{
308
309 graphml_t graph;
310
311 auto node_decl = graph.append_child(pugi::node_declaration);
312 node_decl.append_attribute("version") = "1.0";
313 node_decl.append_attribute("encoding") = "UTF-8";
314
315 generate_metadata(graph);
316
317 auto graphml = graph.append_child("graphml");
318 graphml.append_attribute("xmlns") = "http://graphml.graphdrawing.org/xmlns";
319 graphml.append_attribute("xmlns:xsi") =
320 "http://www.w3.org/2001/XMLSchema-instance";
321 graphml.append_attribute("xsi:schemaLocation") =
322 "http://graphml.graphdrawing.org/xmlns "
323 "http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd";
324
325 if (config.title) {
326 graphml.append_child("desc")
327 .append_child(pugi::node_cdata)
328 .set_value(config.title());
329 }
330
331 generate_keys(graphml);
332
333 auto graph_node = make_graph(graphml, "G");
334
335 if (config.using_namespace) {
336 add_data(graph_node, "using_namespace",
337 config.using_namespace().to_string());
338 }
339
340 generate_diagram(graph_node);
341
342 graph.save(ostr, " ");
343}

◆ generate_diagram()

template<typename ConfigType , typename DiagramType >
void clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::generate_diagram ( graphml_node_t parent) const
inline

Generate diagram model.

This method must be implemented in subclasses for specific diagram types.

Parameters
ostrOutput stream

Definition at line 174 of file generator.h.

175 {
177
179 DiagramType>::model(),
180 parent);
181
183 }

◆ generate_key()

template<typename ConfigType , typename DiagramType >
void clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::generate_key ( pugi::xml_node &  parent,
const std::string &  attr_name,
const std::string &  for_value,
const std::string &  id_value,
const std::string &  attr_type = "string" 
) const
protected

◆ generate_keys()

template<typename C , typename D >
void clanguml::common::generators::graphml::generator< C, D >::generate_keys ( graphml_node_t parent) const
private

Definition at line 579 of file generator.h.

580{
581 for (const auto &[name, type] : graph_property_names()) {
582 const auto [id, t] = graph_properties_.add(name);
583 generate_key(parent, name, "graph", id, to_string(type));
584 }
585
586 for (const auto &[name, type] : node_property_names()) {
587 const auto [id, t] = node_properties_.add(name);
588 generate_key(parent, name, "node", id, to_string(type));
589 }
590
591 for (const auto &[name, type] : edge_property_names()) {
592 const auto [id, t] = edge_properties_.add(name);
593 generate_key(parent, name, "edge", id, to_string(type));
594 }
595}

◆ generate_link()

template<typename C , typename D >
template<typename T >
void clanguml::common::generators::graphml::generator< C, D >::generate_link ( pugi::xml_node &  node,
const T &  c 
) const

Definition at line 552 of file generator.h.

553{
554 const auto maybe_link = generator<C, D>::render_link(c);
555 const auto maybe_tooltip = generator<C, D>::render_tooltip(c);
556
557 if (maybe_link) {
558 add_data(node, "url", *maybe_link);
559 }
560
561 if (maybe_tooltip) {
562 add_data(node, "tooltip", *maybe_tooltip);
563 }
564}

◆ generate_metadata()

template<typename C , typename D >
void clanguml::common::generators::graphml::generator< C, D >::generate_metadata ( graphml_t parent) const

Generate metadata element with diagram metadata.

Parameters
parentRoot JSON object

Definition at line 467 of file generator.h.

468{
470 auto comment = parent.append_child(pugi::node_comment);
471 comment.set_value(fmt::format(
472 " Generated with clang-uml {} ", clanguml::version::version()));
473
474 comment = parent.append_child(pugi::node_comment);
475 comment.set_value(
476 fmt::format(" LLVM version {} ", clang::getClangFullVersion()));
477 }
478}

◆ generate_notes()

template<typename C , typename D >
template<typename T >
void clanguml::common::generators::graphml::generator< C, D >::generate_notes ( const T &  e,
graphml_node_t parent 
) const

Generate any notes to be attached to diagram elements.

Parameters
eDiagram element
parentParent GraphML package node to attach the note to

Definition at line 401 of file generator.h.

402{
404
405 std::vector<std::pair</* element node id */ std::string,
406 /* note node id */ std::string>>
407 note_id_map;
408
409 // First generate the note XML nodes
410 auto note_index{0U};
411 for (const auto &e : p) {
412 // First try to extract notes from comment decorators (i.e. \uml
413 // directives in code comments)
414 for (const auto &decorator : e->decorators()) {
415 auto note = std::dynamic_pointer_cast<decorators::note>(decorator);
416 if (note && note->applies_to_diagram(config.name)) {
417 auto note_id = node_ids_.add(
418 fmt::format("{}-N_{}", e->alias(), note_index));
419 auto maybe_element_node_id = node_ids_.get(e->alias());
420 if (maybe_element_node_id) {
421 auto note_node = make_node(parent, note_id);
422 add_data(note_node, "type", "note");
423 add_data(note_node, "name", note->text, true);
424 note_id_map.emplace_back(*maybe_element_node_id, note_id);
425 note_index++;
426 }
427 }
428 }
429
430 // Now try to extract notes from `graphml` configuration file section
431 if (config.graphml &&
432 config.graphml().notes.count(e->full_name(false))) {
433 for (const auto &note :
434 config.graphml().notes.at(e->full_name(false))) {
435 auto note_id = node_ids_.add(
436 fmt::format("{}-N_{}", e->alias(), note_index));
437 auto maybe_element_node_id = node_ids_.get(e->alias());
438 if (maybe_element_node_id) {
439 auto rendered_note = common::jinja::render_template(
440 generator<C, D>::env(), note);
441 if (rendered_note) {
442 auto note_node = make_node(parent, note_id);
443 add_data(note_node, "type", "note");
444 add_data(note_node, "name", *rendered_note, true);
445 note_id_map.emplace_back(
446 *maybe_element_node_id, note_id);
447 note_index++;
448 }
449 }
450 }
451 }
452 }
453
454 // Now generate the edges connecting note nodes to element notes
455 for (const auto &[element_node_id, note_node_id] : note_id_map) {
456 auto edge_node = parent.append_child("edge");
457
458 edge_node.append_attribute("id") = fmt::format("e{}", edge_id_++);
459 edge_node.append_attribute("source") = note_node_id;
460 edge_node.append_attribute("target") = element_node_id;
461
462 add_data(edge_node, "type", "none");
463 }
464}

◆ generate_relationships() [1/2]

template<typename C , typename D >
void clanguml::common::generators::graphml::generator< C, D >::generate_relationships ( const model::diagram_element c,
graphml_node_t parent 
) const
virtual

Generate all relationships originating at a diagram element.

Template Parameters
TType of diagram element
Parameters
cDiagram diagram element
parentJSON node

Definition at line 356 of file generator.h.

358{
359 const auto &model = generator<C, D>::model();
360
361 for (const auto &r : c.relationships()) {
362 auto target_element = model.get(r.destination());
363 if (!target_element.has_value()) {
364 LOG_DBG("Skipping {} relation from '{}' to '{}' due "
365 "to unresolved destination id",
366 to_string(r.type()), c.full_name(true),
367 r.destination().value());
368 continue;
369 }
370
371 const auto maybe_target_id =
372 node_ids_.get(target_element.value().alias());
373 const auto maybe_src_id = node_ids_.get(c.alias());
374
375 if (!maybe_src_id || !maybe_target_id)
376 continue;
377
378 auto edge_node = parent.append_child("edge");
379
380 edge_node.append_attribute("id") = fmt::format("e{}", edge_id_++);
381 edge_node.append_attribute("source") = *maybe_src_id;
382 edge_node.append_attribute("target") = *maybe_target_id;
383
384 const auto maybe_link = generator<C, D>::render_link(r);
385
386 if (maybe_link) {
387 add_data(edge_node, "url", *maybe_link);
388 }
389
390 add_data(edge_node, "type", to_string(r.type()));
391 if (!r.label().empty())
392 add_data(edge_node, "label", r.label());
393
394 if (r.access() != access_t::kNone)
395 add_data(edge_node, "access", to_string(r.access()));
396 }
397}

◆ generate_relationships() [2/2]

template<typename ConfigType , typename DiagramType >
virtual void clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::generate_relationships ( graphml_node_t parent) const
virtual

Generate all relationships in the diagram.

Parameters
parentGraphML node

◆ generate_top_level_elements()

template<typename ConfigType , typename DiagramType >
virtual void clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::generate_top_level_elements ( graphml_node_t parent) const
pure virtual

In a nested diagram, generate the top level elements.

This method iterates over the top level elements. In case the diagram is nested (i.e. includes packages), for each package it recursively call generation of elements contained in each package.

Parameters
parentGraphML node

◆ graph_properties() [1/2]

template<typename ConfigType , typename DiagramType >
property_keymap_t & clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::graph_properties ( )
inlineprotected

Definition at line 277 of file generator.h.

277{ return graph_properties_; }

◆ graph_properties() [2/2]

template<typename ConfigType , typename DiagramType >
const property_keymap_t & clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::graph_properties ( ) const
inline

Definition at line 242 of file generator.h.

243 {
244 return graph_properties_;
245 }

◆ graph_property_names()

template<typename ConfigType , typename DiagramType >
virtual std::vector< std::pair< std::string, property_type > > clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::graph_property_names ( ) const
inlinevirtual

Definition at line 121 of file generator.h.

122 {
123 using namespace std::string_literals;
124 return {
125 {"id"s, property_type::kString},
126 {"diagram_type"s, property_type::kString},
127 {"name"s, property_type::kString},
128 {"using_namespace"s, property_type::kString},
129 };
130 }

◆ make_graph()

template<typename C , typename D >
pugi::xml_node clanguml::common::generators::graphml::generator< C, D >::make_graph ( graphml_node_t parent,
const std::string &  id 
) const

Definition at line 490 of file generator.h.

492{
493 auto result = parent.append_child("graph");
494 result.append_attribute("id") = graph_ids_.add(id);
495 result.append_attribute("edgedefault").set_value("directed");
496 result.append_attribute("parse.nodeids").set_value("canonical");
497 result.append_attribute("parse.edgeids").set_value("canonical");
498 result.append_attribute("parse.order").set_value("nodesfirst");
499 return result;
500}

◆ make_node()

template<typename C , typename D >
pugi::xml_node clanguml::common::generators::graphml::generator< C, D >::make_node ( graphml_node_t parent,
const std::string &  id 
) const

Definition at line 481 of file generator.h.

483{
484 auto result = parent.append_child("node");
485 result.append_attribute("id") = id;
486 return result;
487}

◆ make_subgraph()

template<typename C , typename D >
pugi::xml_node clanguml::common::generators::graphml::generator< C, D >::make_subgraph ( graphml_node_t parent,
const std::string &  id,
const std::string &  name = "",
const std::string &  type = "" 
) const

Definition at line 503 of file generator.h.

506{
507 auto graph_node = parent.append_child("node");
508 graph_node.append_attribute("id") = node_ids_.add(id);
509
510 if (!name.empty())
511 add_data(graph_node, "name", name);
512
513 if (!type.empty())
514 add_data(graph_node, "type", type);
515
516 return graph_node;
517}

◆ node_properties() [1/2]

template<typename ConfigType , typename DiagramType >
property_keymap_t & clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::node_properties ( )
inlineprotected

Definition at line 278 of file generator.h.

278{ return node_properties_; }

◆ node_properties() [2/2]

template<typename ConfigType , typename DiagramType >
const property_keymap_t & clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::node_properties ( ) const
inline

Definition at line 247 of file generator.h.

248 {
249 return node_properties_;
250 }

◆ node_property_names()

template<typename ConfigType , typename DiagramType >
virtual std::vector< std::pair< std::string, property_type > > clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::node_property_names ( ) const
inlinevirtual

Reimplemented in clanguml::class_diagram::generators::graphml::generator, and clanguml::include_diagram::generators::graphml::generator.

Definition at line 133 of file generator.h.

134 {
135 using namespace std::string_literals;
136 return {{"id"s, property_type::kString},
137 {"type"s, property_type::kString},
138 {"name"s, property_type::kString},
139 {"stereotype"s, property_type::kString},
140 {"url"s, property_type::kString},
141 {"tooltip"s, property_type::kString}};
142 }

Member Data Documentation

◆ edge_id_

template<typename ConfigType , typename DiagramType >
uint64_t clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::edge_id_ {0}
mutableprivate

Definition at line 292 of file generator.h.

◆ edge_ids_

template<typename ConfigType , typename DiagramType >
graphml_node_map_t clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::edge_ids_ {"e"}
mutableprotected

Definition at line 283 of file generator.h.

◆ edge_properties_

template<typename ConfigType , typename DiagramType >
property_keymap_t clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::edge_properties_ {"ed"}
mutableprivate

Definition at line 290 of file generator.h.

◆ graph_ids_

template<typename ConfigType , typename DiagramType >
graphml_node_map_t clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::graph_ids_ {"g"}
mutableprotected

Definition at line 281 of file generator.h.

◆ graph_properties_

template<typename ConfigType , typename DiagramType >
property_keymap_t clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::graph_properties_ {"gd"}
mutableprivate

Definition at line 288 of file generator.h.

◆ node_ids_

template<typename ConfigType , typename DiagramType >
graphml_node_map_t clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::node_ids_ {"n"}
mutableprotected

Definition at line 282 of file generator.h.

◆ node_properties_

template<typename ConfigType , typename DiagramType >
property_keymap_t clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::node_properties_ {"nd"}
mutableprivate

Definition at line 289 of file generator.h.

◆ note_id_

template<typename ConfigType , typename DiagramType >
uint64_t clanguml::common::generators::graphml::generator< ConfigType, DiagramType >::note_id_ {0}
mutableprivate

Definition at line 293 of file generator.h.


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