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::sequence_diagram::generators::json::generator Class Reference

Sequence diagram JSON generator. More...

Detailed Description

Sequence diagram JSON generator.

Definition at line 46 of file sequence_diagram_generator.h.

#include <sequence_diagram_generator.h>

Public Member Functions

 generator (diagram_config &config, diagram_model &model)
 
void generate_diagram (nlohmann::json &parent) const override
 Main generator method.
 
void generate_call (const sequence_diagram::model::message &m, nlohmann::json &parent) const
 Generate sequence diagram message.
 
std::optional< eid_tgenerate_participant (nlohmann::json &parent, eid_t id, bool force=false) const
 Generate sequence diagram participant.
 
void generate_participant (nlohmann::json &parent, const std::string &name) const
 Generate sequence diagram participant by name.
 
void generate_activity (const sequence_diagram::model::activity &a, std::vector< eid_t > &visited) const
 Generate sequence diagram activity.
 
nlohmann::json & current_block_statement () const
 Get reference to the current block statement.
 
std::string make_display_name (const std::string &full_name) const
 
- Public Member Functions inherited from clanguml::common::generators::json::generator< ConfigType, DiagramType >
 ~generator () override=default
 
void generate (std::ostream &ostr) const override
 Generate diagram.
 
virtual void generate_diagram (nlohmann::json &parent) const =0
 Generate diagram model.
 
void generate_metadata (nlohmann::json &parent) const
 Generate metadata element with diagram metadata.
 
- 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
 

Private Member Functions

bool is_participant_generated (eid_t id) const
 Check if specified participant has already been generated.
 
void process_call_message (const model::message &m, std::vector< eid_t > &visited) const
 Process call message.
 
void process_if_message (const model::message &m) const
 Process if statement message.
 
void process_else_if_message () const
 Process else if statement message.
 
void process_end_if_message () const
 Process end if statement message.
 
void process_conditional_message (const model::message &m) const
 Process :? statement message.
 
void process_end_conditional_message () const
 Process end of conditional statement message.
 
void process_conditional_else_message (const model::message &m) const
 Process conditional else statement message.
 
void process_switch_message (const model::message &m) const
 Process switch statement message.
 
void process_end_switch_message () const
 Process switch end statement message.
 
void process_case_message (const model::message &m) const
 Process switch case statement message.
 
void process_try_message (const model::message &m) const
 Process try statement message.
 
void process_end_try_message () const
 Process try end statement message.
 
void process_catch_message () const
 Process catch statement message.
 
void process_do_message (const model::message &m) const
 Process do loop statement message.
 
void process_end_do_message () const
 Process do end statement message.
 
void process_for_message (const model::message &m) const
 Process for loop statement message.
 
void process_end_for_message () const
 Process for end statement message.
 
void process_while_message (const model::message &m) const
 Process while loop message.
 
void process_end_while_message () const
 Process while end loop message.
 
void generate_from_to_sequences (nlohmann::json &parent) const
 
void generate_to_sequences (nlohmann::json &parent) const
 
void generate_from_sequences (nlohmann::json &parent) const
 
std::vector< eid_tfind_from_activities () const
 

Private Attributes

std::set< eid_tgenerated_participants_
 
nlohmann::json json_
 
std::vector< std::reference_wrapper< nlohmann::json > > block_statements_stack_
 
std::vector< model::messagealready_generated_in_static_context_
 

Additional Inherited Members

- Protected Attributes inherited from clanguml::common::generators::generator< ConfigType, DiagramType >
inja::json m_context
 
inja::Environment m_env
 

Constructor & Destructor Documentation

◆ generator()

clanguml::sequence_diagram::generators::json::generator::generator ( diagram_config config,
diagram_model model 
)

Definition at line 69 of file sequence_diagram_generator.cc.

71 : common_generator<diagram_config, diagram_model>{config, model}
72{
73}

Member Function Documentation

◆ current_block_statement()

nlohmann::json & clanguml::sequence_diagram::generators::json::generator::current_block_statement ( ) const

Get reference to the current block statement.

This method returns a reference to the last block statement (e.g if statement or for loop) in the call stack.

Returns
Reference to the current block statement.

Definition at line 277 of file sequence_diagram_generator.cc.

278{
279 assert(!block_statements_stack_.empty());
280
281 return block_statements_stack_.back().get();
282}

◆ find_from_activities()

std::vector< eid_t > clanguml::sequence_diagram::generators::json::generator::find_from_activities ( ) const
private

Definition at line 959 of file sequence_diagram_generator.cc.

960{
961 std::vector<eid_t> start_from;
962 for (const auto &sf : config().from()) {
963 if (sf.location_type == location_t::function) {
964 bool found{false};
965 for (const auto &[k, v] : model().sequences()) {
966 if (model().participants().count(v.from()) == 0)
967 continue;
968
969 const auto &caller = *model().participants().at(v.from());
970 std::string vfrom = caller.full_name(false);
971 if (sf.location == vfrom) {
972 LOG_DBG("Found sequence diagram start point: {}", k);
973 start_from.push_back(k);
974 found = true;
975 }
976 }
977
978 if (!found)
979 throw error::invalid_sequence_from_condition(model().type(),
980 model().name(),
981 fmt::format("Failed to find participant matching '{}' for "
982 "'from' condition: ",
983 sf.location.to_string()));
984 }
985 }
986
987 return start_from;
988}

◆ generate_activity()

void clanguml::sequence_diagram::generators::json::generator::generate_activity ( const sequence_diagram::model::activity a,
std::vector< eid_t > &  visited 
) const

Generate sequence diagram activity.

Parameters
aActivity model
visitedList of already visited participants, this is necessary for breaking infinite recursion on recursive calls

Definition at line 207 of file sequence_diagram_generator.cc.

209{
210 // Generate calls from this activity to other activities
211 for (const auto &m : a.messages()) {
212 switch (m.type()) {
213 case message_t::kCall:
214 process_call_message(m, visited);
215 break;
216 case message_t::kIf:
218 break;
219 case message_t::kElseIf:
220 case message_t::kElse:
222 break;
223 case message_t::kIfEnd:
225 break;
226 case message_t::kWhile:
228 break;
229 case message_t::kWhileEnd:
231 break;
232 case message_t::kFor:
234 break;
235 case message_t::kForEnd:
237 break;
238 case message_t::kDo:
240 break;
241 case message_t::kDoEnd:
243 break;
244 case message_t::kTry:
246 break;
247 case message_t::kCatch:
249 break;
250 case message_t::kTryEnd:
252 break;
253 case message_t::kSwitch:
255 break;
256 case message_t::kCase:
258 break;
259 case message_t::kSwitchEnd:
261 break;
262 case message_t::kConditional:
264 break;
265 case message_t::kConditionalElse:
267 break;
268 case message_t::kConditionalEnd:
270 break;
271 case message_t::kNone:
272 case message_t::kReturn:; // noop
273 }
274 }
275}

◆ generate_call()

void clanguml::sequence_diagram::generators::json::generator::generate_call ( const sequence_diagram::model::message m,
nlohmann::json &  parent 
) const

Generate sequence diagram message.

Parameters
mMessage model
parentJSON node

Definition at line 75 of file sequence_diagram_generator.cc.

76{
77 const auto &from = model().get_participant<model::participant>(m.from());
78 const auto &to = model().get_participant<model::participant>(m.to());
79
80 if (!from || !to) {
81 LOG_DBG("Skipping empty call from '{}' to '{}'", m.from(), m.to());
82 return;
83 }
84
85 generate_participant(json_, m.from());
87
88 std::string message;
89
92
93 if (to.value().type_name() == "method") {
94 message = dynamic_cast<const model::method &>(to.value())
95 .message_name(render_mode);
96 }
97 else if (to.value().type_name() == "objc_method") {
98 message = dynamic_cast<const model::objc_method &>(to.value())
99 .message_name(render_mode);
100 }
101 else if (config().combine_free_functions_into_file_participants()) {
102 if (to.value().type_name() == "function") {
103 message = dynamic_cast<const model::function &>(to.value())
104 .message_name(render_mode);
105 }
106 else if (to.value().type_name() == "function_template") {
107 message = dynamic_cast<const model::function_template &>(to.value())
108 .message_name(render_mode);
109 }
110 }
111
112 message = config().simplify_template_type(message);
113
114 nlohmann::json msg;
115
116 msg["name"] = message;
117 msg["type"] = "message";
118 msg["from"]["activity_id"] = std::to_string(from.value().id().value());
119 msg["to"]["activity_id"] = std::to_string(to.value().id().value());
120 if (const auto &cmt = m.comment(); cmt.has_value())
121 msg["comment"] = cmt.value().at("comment");
122
123 if (from.value().type_name() == "method") {
124 const auto &class_participant =
125 model().get_participant<model::method>(from.value().id()).value();
126
127 msg["from"]["participant_id"] =
128 std::to_string(class_participant.class_id().value());
129 }
130 else if (from.value().type_name() == "objc_method") {
131 const auto &class_participant =
132 model()
133 .get_participant<model::objc_method>(from.value().id())
134 .value();
135
136 msg["from"]["participant_id"] =
137 std::to_string(class_participant.class_id().value());
138 }
139 else if (from.value().type_name() == "function" ||
140 from.value().type_name() == "function_template") {
141 if (config().combine_free_functions_into_file_participants()) {
142 const auto &file_participant =
143 model()
144 .get_participant<model::function>(from.value().id())
145 .value();
146 msg["from"]["participant_id"] = std::to_string(
147 common::to_id(file_participant.file_relative()).value());
148 }
149 else {
150 msg["from"]["participant_id"] =
151 std::to_string(from.value().id().value());
152 }
153 }
154 else if (from.value().type_name() == "lambda") {
155 msg["from"]["participant_id"] =
156 std::to_string(from.value().id().value());
157 }
158
159 if (to.value().type_name() == "method") {
160 const auto &class_participant =
161 model().get_participant<model::method>(to.value().id()).value();
162
163 msg["to"]["participant_id"] =
164 std::to_string(class_participant.class_id().value());
165 }
166 else if (to.value().type_name() == "objc_method") {
167 const auto &class_participant =
168 model()
169 .get_participant<model::objc_method>(to.value().id())
170 .value();
171
172 msg["to"]["participant_id"] =
173 std::to_string(class_participant.class_id().value());
174 }
175 else if (to.value().type_name() == "function" ||
176 to.value().type_name() == "function_template") {
177 if (config().combine_free_functions_into_file_participants()) {
178 const auto &file_participant =
179 model()
180 .get_participant<model::function>(to.value().id())
181 .value();
182 msg["to"]["participant_id"] = std::to_string(
183 common::to_id(file_participant.file_relative()).value());
184 }
185 else {
186 msg["to"]["participant_id"] =
187 std::to_string(to.value().id().value());
188 }
189 }
190 else if (to.value().type_name() == "lambda") {
191 msg["to"]["participant_id"] = std::to_string(to.value().id().value());
192 }
193
194 msg["source_location"] =
195 dynamic_cast<const clanguml::common::model::source_location &>(m);
196
197 msg["scope"] = to_string(m.message_scope());
198 msg["return_type"] = config().simplify_template_type(m.return_type());
199
200 parent["messages"].push_back(std::move(msg));
201
202 LOG_DBG("Generated call '{}' from {} [{}] to {} [{}]", message,
203 from.value().full_name(false), m.from(), to.value().full_name(false),
204 m.to());
205}

◆ generate_diagram()

void clanguml::sequence_diagram::generators::json::generator::generate_diagram ( nlohmann::json &  parent) const
overridevirtual

Main generator method.

This method is called first and coordinates the entire diagram generation.

Parameters
ostrOutput stream.

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

Definition at line 752 of file sequence_diagram_generator.cc.

753{
754 model().print();
755
756 if (config().using_namespace)
757 parent["using_namespace"] = config().using_namespace().to_string();
758
759 if (config().participants_order.has_value) {
760 for (const auto &p : config().participants_order()) {
761 LOG_DBG("Pregenerating participant {}", p);
763 }
764 }
765
767
768 generate_to_sequences(parent);
769
771
772 // Perform config dependent postprocessing on generated participants
773 for (auto &p : json_["participants"]) {
774 if (p.contains("display_name")) {
775 p["display_name"] = make_display_name(p["display_name"]);
776 }
777 }
778
779 parent["participants"] = json_["participants"];
780}

◆ generate_from_sequences()

void clanguml::sequence_diagram::generators::json::generator::generate_from_sequences ( nlohmann::json &  parent) const
private

Definition at line 782 of file sequence_diagram_generator.cc.

783{
784 std::vector<eid_t> start_from = find_from_activities();
785
786 // Use this to break out of recurrent loops
787 std::vector<eid_t> visited_participants;
788 for (const auto from_id : start_from) {
789
790 const auto &from = model().get_participant<model::function>(from_id);
791
792 if (!from.has_value()) {
793 LOG_WARN("Failed to find participant {} for 'from' "
794 "condition");
795 continue;
796 }
797
798 generate_participant(json_, from_id);
799
800 [[maybe_unused]] model::function::message_render_mode render_mode =
802
803 nlohmann::json sequence;
804 sequence["from"]["location"] = from.value().full_name(false);
805 sequence["from"]["id"] = std::to_string(from_id.value());
806
807 block_statements_stack_.push_back(std::ref(sequence));
808
809 generate_activity(model().get_activity(from_id), visited_participants);
810
811 block_statements_stack_.pop_back();
812
813 if (from.value().type_name() == "method" ||
814 config().combine_free_functions_into_file_participants()) {
815
816 sequence["return_type"] =
817 make_display_name(from.value().return_type());
818 }
819
820 parent["sequences"].push_back(std::move(sequence));
821 }
822}

◆ generate_from_to_sequences()

void clanguml::sequence_diagram::generators::json::generator::generate_from_to_sequences ( nlohmann::json &  parent) const
private

Definition at line 875 of file sequence_diagram_generator.cc.

876{
877 for (const auto &ft : config().from_to()) {
878 // First, find the sequence of activities from 'from' location
879 // to 'to' location
880 assert(ft.size() == 2);
881
882 const auto &from_location = ft.front();
883 const auto &to_location = ft.back();
884
885 auto from_activity_ids = model().get_from_activity_ids(from_location);
886 auto to_activity_ids = model().get_to_activity_ids(to_location);
887
888 if (from_activity_ids.empty()) {
889 throw error::invalid_sequence_from_condition(model().type(),
890 model().name(),
891 fmt::format("Failed to find participant matching '{}' for "
892 "'from' condition: ",
893 from_location.location.to_string()));
894 }
895
896 if (from_activity_ids.empty() || to_activity_ids.empty()) {
897 throw error::invalid_sequence_to_condition(model().type(),
898 model().name(),
899 fmt::format("Failed to find participant matching '{}' for "
900 "'to' condition: ",
901 to_location.location.to_string()));
902 }
903
904 for (const auto from_activity_id : from_activity_ids) {
905 if (model().participants().count(from_activity_id) == 0)
906 continue;
907
908 const auto &from =
909 model().get_participant<model::function>(from_activity_id);
910
911 for (const auto to_activity_id : to_activity_ids) {
912 if (model().participants().count(to_activity_id) == 0)
913 continue;
914
915 const auto &to =
916 model().get_participant<model::function>(to_activity_id);
917
918 auto message_chains_unique =
919 model().get_all_from_to_message_chains(
920 from_activity_id, to_activity_id);
921
922 nlohmann::json sequence;
923 sequence["from_to"]["from"]["location"] =
924 from.value().full_name(false);
925 sequence["from_to"]["from"]["id"] =
926 std::to_string(from_activity_id.value());
927 sequence["from_to"]["to"]["location"] =
928 to.value().full_name(false);
929 sequence["from_to"]["to"]["id"] =
930 std::to_string(to_activity_id.value());
931
932 block_statements_stack_.push_back(std::ref(sequence));
933
934 sequence["message_chains"] = nlohmann::json::array();
935
936 for (const auto &mc : message_chains_unique) {
937 nlohmann::json message_chain;
938
939 block_statements_stack_.push_back(std::ref(message_chain));
940
941 for (const auto &m : mc) {
943 }
944
945 block_statements_stack_.pop_back();
946
947 sequence["message_chains"].push_back(
948 std::move(message_chain));
949 }
950
951 block_statements_stack_.pop_back();
952
953 parent["sequences"].push_back(std::move(sequence));
954 }
955 }
956 }
957}

◆ generate_participant() [1/2]

void clanguml::sequence_diagram::generators::json::generator::generate_participant ( nlohmann::json &  parent,
const std::string &  name 
) const

Generate sequence diagram participant by name.

This is convienience wrapper over generate_participant() by id.

Parameters
parentJSON node
nameFull participant name

Definition at line 549 of file sequence_diagram_generator.cc.

551{
552 auto p = model().get(name);
553
554 if (!p.has_value()) {
555 LOG_WARN("Cannot find participant {} from `participants_order` option",
556 name);
557 return;
558 }
559
560 generate_participant(parent, p.value().id(), true);
561}

◆ generate_participant() [2/2]

std::optional< eid_t > clanguml::sequence_diagram::generators::json::generator::generate_participant ( nlohmann::json &  parent,
eid_t  id,
bool  force = false 
) const

Generate sequence diagram participant.

Parameters
parentJSON node
idParticipant id
forceIf true, generate the participant even if its not in the set of active participants
Returns
Id of the generated participant

Definition at line 563 of file sequence_diagram_generator.cc.

565{
566 std::optional<eid_t> participant_id{};
567
568 if (!force) {
569 for (const auto pid : model().active_participants()) {
570 if (pid == id) {
571 participant_id = pid;
572 break;
573 }
574 }
575 }
576 else
577 participant_id = id;
578
579 if (!participant_id.has_value())
580 return participant_id;
581
582 if (is_participant_generated(*participant_id))
583 return participant_id;
584
585 const auto &participant =
586 model().get_participant<model::participant>(*participant_id).value();
587
588 const auto participant_type = participant.type_name();
589
590 if (participant_type == "method") {
591 auto class_participant_id =
592 model()
593 .get_participant<model::method>(*participant_id)
594 .value()
595 .class_id();
596
597 LOG_DBG("Generating JSON method participant: {}",
598 model()
599 .get_participant<model::method>(*participant_id)
600 .value()
601 .full_name(false));
602
603 if (!is_participant_generated(class_participant_id)) {
604 const auto &class_participant =
605 model()
606 .get_participant<model::participant>(class_participant_id)
607 .value();
608
609 generated_participants_.emplace(*participant_id);
610 generated_participants_.emplace(class_participant_id);
611
612 json_["participants"].push_back(class_participant);
613 json_["participants"].back()["activities"].push_back(participant);
614
615 // Perform config dependent postprocessing on generated class
616 const auto class_participant_full_name =
617 display_name_adapter(class_participant).full_name(false);
618
619 json_["participants"].back().at("display_name") =
620 make_display_name(class_participant_full_name);
621
622 return class_participant_id;
623 }
624
625 if (!is_participant_generated(*participant_id)) {
626 for (auto &p : json_["participants"]) {
627 if (p.at("id") ==
628 std::to_string(class_participant_id.value())) {
629 generated_participants_.emplace(*participant_id);
630 p["activities"].push_back(participant);
631 return class_participant_id;
632 }
633 }
634 }
635 }
636 if (participant_type == "objc_method") {
637 auto class_participant_id =
638 model()
639 .get_participant<model::objc_method>(*participant_id)
640 .value()
641 .class_id();
642
643 LOG_DBG("Generating JSON ObjC method participant: {}",
644 model()
645 .get_participant<model::objc_method>(*participant_id)
646 .value()
647 .full_name(false));
648
649 if (!is_participant_generated(class_participant_id)) {
650 const auto &class_participant =
651 model()
652 .get_participant<model::participant>(class_participant_id)
653 .value();
654
655 generated_participants_.emplace(*participant_id);
656 generated_participants_.emplace(class_participant_id);
657
658 json_["participants"].push_back(class_participant);
659 json_["participants"].back()["activities"].push_back(participant);
660
661 // Perform config dependent postprocessing on generated class
662 const auto class_participant_full_name =
663 display_name_adapter(class_participant).full_name(false);
664
665 json_["participants"].back().at("display_name") =
666 make_display_name(class_participant_full_name);
667
668 return class_participant_id;
669 }
670
671 if (!is_participant_generated(*participant_id)) {
672 for (auto &p : json_["participants"]) {
673 if (p.at("id") ==
674 std::to_string(class_participant_id.value())) {
675 generated_participants_.emplace(*participant_id);
676 p["activities"].push_back(participant);
677 return class_participant_id;
678 }
679 }
680 }
681 }
682 else if ((participant_type == "function" ||
683 participant_type == "function_template") &&
684 config().combine_free_functions_into_file_participants()) {
685 // Create a single participant for all functions declared in a
686 // single file
687 // participant_id will become activity_id within a file participant
688 const auto &function_participant =
689 model().get_participant<model::function>(*participant_id).value();
690
691 const auto file_participant_id =
692 common::to_id(function_participant.file_relative());
693
694 if (!is_participant_generated(file_participant_id)) {
695 nlohmann::json p = function_participant;
696
697 const auto file_path =
698 config().make_path_relative(function_participant.file());
699
700 p["display_name"] = util::path_to_url(file_path.string());
701 p["name"] = file_path.filename();
702
703 if (is_participant_generated(file_participant_id))
704 return participant_id;
705
706 p["id"] = std::to_string(file_participant_id.value());
707 p["type"] = "file";
708 p.erase("source_location");
709
710 generated_participants_.emplace(participant_id.value());
711
712 p["activities"].push_back(participant);
713 json_["participants"].push_back(p);
714
715 generated_participants_.emplace(file_participant_id);
716
717 return file_participant_id;
718 }
719
720 if (!is_participant_generated(*participant_id)) {
721 for (auto &p : json_["participants"]) {
722 if (p.at("id") == std::to_string(file_participant_id.value())) {
723 generated_participants_.emplace(*participant_id);
724 p["activities"].push_back(participant);
725 }
726 }
727 }
728
729 return file_participant_id;
730 }
731 else {
732 json_["participants"].push_back(participant);
733 const auto function_participant_full_name =
734 display_name_adapter(participant).full_name(false);
735
736 json_["participants"].back().at("display_name") =
737 make_display_name(function_participant_full_name);
738 }
739
740 generated_participants_.emplace(*participant_id);
741
742 return participant_id;
743}

◆ generate_to_sequences()

void clanguml::sequence_diagram::generators::json::generator::generate_to_sequences ( nlohmann::json &  parent) const
private

Definition at line 824 of file sequence_diagram_generator.cc.

825{
826 for (const auto &to_location : config().to()) {
827 auto to_activity_ids = model().get_to_activity_ids(to_location);
828
829 if (to_activity_ids.empty()) {
830 LOG_WARN("Failed to find participant matching '{}' for "
831 "'to' condition: ",
832 to_location.location.to_string());
833 }
834
835 for (const auto to_activity_id : to_activity_ids) {
836 const auto &to =
837 model().get_participant<model::function>(to_activity_id);
838
839 nlohmann::json sequence;
840 sequence["to"]["location"] = to.value().full_name(false);
841 sequence["to"]["id"] = std::to_string(to_activity_id.value());
842 sequence["message_chains"] = nlohmann::json::array();
843
844 block_statements_stack_.push_back(std::ref(sequence));
845
846 std::vector<model::message_chain_t> message_chains =
847 model().get_all_from_to_message_chains(eid_t{}, to_activity_id);
848
849 for (const auto &mc : message_chains) {
850 const auto from_activity_id = mc.front().from();
851
852 if (model().participants().count(from_activity_id) == 0)
853 continue;
854
855 nlohmann::json message_chain;
856
857 block_statements_stack_.push_back(std::ref(message_chain));
858
859 for (const auto &m : mc) {
861 }
862
863 block_statements_stack_.pop_back();
864
865 sequence["message_chains"].push_back(std::move(message_chain));
866 }
867
868 block_statements_stack_.pop_back();
869
870 parent["sequences"].push_back(std::move(sequence));
871 }
872 }
873}

◆ is_participant_generated()

bool clanguml::sequence_diagram::generators::json::generator::is_participant_generated ( eid_t  id) const
private

Check if specified participant has already been generated.

Parameters
idParticipant id.
Returns
True, if participant has already been generated.

Definition at line 745 of file sequence_diagram_generator.cc.

746{
747 return std::find(generated_participants_.begin(),
749 id) != generated_participants_.end();
750}

◆ make_display_name()

std::string clanguml::sequence_diagram::generators::json::generator::make_display_name ( const std::string &  full_name) const

Definition at line 990 of file sequence_diagram_generator.cc.

991{
992 auto result = config().simplify_template_type(full_name);
993 result = config().using_namespace().relative(result);
995
996 return result;
997}

◆ process_call_message()

void clanguml::sequence_diagram::generators::json::generator::process_call_message ( const model::message m,
std::vector< eid_t > &  visited 
) const
private

Process call message.

Parameters
mMessage model
visitedList of already visited participants

Definition at line 284 of file sequence_diagram_generator.cc.

286{
287 visited.push_back(m.from());
288
289 if (m.in_static_declaration_context()) {
291 visited.pop_back();
292 return;
293 }
294
296 }
297
298 LOG_DBG("Generating message {} --> {}", m.from(), m.to());
299
301
302 if (model().sequences().find(m.to()) != model().sequences().end()) {
303 if (std::find(visited.begin(), visited.end(), m.to()) ==
304 visited.end()) { // break infinite recursion on recursive calls
305
306 LOG_DBG("Creating activity {} --> {} - missing sequence {}",
307 m.from(), m.to(), m.to());
308
309 generate_activity(model().get_activity(m.to()), visited);
310 }
311 }
312 else
313 LOG_DBG("Skipping activity {} --> {} - missing sequence {}", m.from(),
314 m.to(), m.to());
315
316 visited.pop_back();
317}

◆ process_case_message()

void clanguml::sequence_diagram::generators::json::generator::process_case_message ( const model::message m) const
private

Process switch case statement message.

Parameters
mMessage model

Definition at line 437 of file sequence_diagram_generator.cc.

438{
439 if (current_block_statement()["type"] == "case")
440 block_statements_stack_.pop_back();
441
442 nlohmann::json case_block;
443 case_block["type"] = "case";
444 case_block["name"] = m.message_name();
445 current_block_statement()["branches"].push_back(std::move(case_block));
446
447 block_statements_stack_.push_back(
448 std::ref(current_block_statement()["branches"].back()));
449}

◆ process_catch_message()

void clanguml::sequence_diagram::generators::json::generator::process_catch_message ( ) const
private

Process catch statement message.

Definition at line 402 of file sequence_diagram_generator.cc.

403{
404 // remove previous block from the stack
405 block_statements_stack_.pop_back();
406
407 nlohmann::json branch;
408 branch["type"] = "catch";
409 current_block_statement()["branches"].push_back(std::move(branch));
410
411 block_statements_stack_.push_back(
412 std::ref(current_block_statement()["branches"].back()));
413}

◆ process_conditional_else_message()

void clanguml::sequence_diagram::generators::json::generator::process_conditional_else_message ( const model::message m) const
private

Process conditional else statement message.

Parameters
mMessage model

Definition at line 481 of file sequence_diagram_generator.cc.

482{
483 // remove previous branch from the stack
484 block_statements_stack_.pop_back();
485
486 nlohmann::json branch;
487 branch["type"] = "alternative";
488 if (auto text = m.condition_text(); text.has_value())
489 branch["condition_text"] = *text;
490 current_block_statement()["branches"].push_back(std::move(branch));
491
492 block_statements_stack_.push_back(
493 std::ref(current_block_statement()["branches"].back()));
494}

◆ process_conditional_message()

void clanguml::sequence_diagram::generators::json::generator::process_conditional_message ( const model::message m) const
private

Process :? statement message.

Parameters
mMessage model

Definition at line 459 of file sequence_diagram_generator.cc.

460{
461 nlohmann::json if_block;
462 if_block["type"] = "alt";
463 if_block["name"] = "conditional";
464 if_block["activity_id"] = std::to_string(m.from().value());
465 if (auto text = m.condition_text(); text.has_value())
466 if_block["condition_text"] = *text;
467
468 current_block_statement()["messages"].push_back(std::move(if_block));
469
470 block_statements_stack_.push_back(
471 std::ref(current_block_statement()["messages"].back()));
472
473 nlohmann::json branch;
474 branch["type"] = "consequent";
475 current_block_statement()["branches"].push_back(std::move(branch));
476
477 block_statements_stack_.push_back(
478 std::ref(current_block_statement()["branches"].back()));
479}

◆ process_do_message()

void clanguml::sequence_diagram::generators::json::generator::process_do_message ( const model::message m) const
private

Process do loop statement message.

Parameters
mMessage model

Definition at line 361 of file sequence_diagram_generator.cc.

362{
363 nlohmann::json do_block;
364 do_block["type"] = "loop";
365 do_block["name"] = "do";
366 do_block["activity_id"] = std::to_string(m.from().value());
367 if (auto text = m.condition_text(); text.has_value())
368 do_block["condition_text"] = *text;
369
370 current_block_statement()["messages"].push_back(std::move(do_block));
371
372 block_statements_stack_.push_back(
373 std::ref(current_block_statement()["messages"].back()));
374}

◆ process_else_if_message()

void clanguml::sequence_diagram::generators::json::generator::process_else_if_message ( ) const
private

Process else if statement message.

Definition at line 514 of file sequence_diagram_generator.cc.

515{
516 // remove previous branch from the stack
517 block_statements_stack_.pop_back();
518
519 nlohmann::json branch;
520 branch["type"] = "alternative";
521 current_block_statement()["branches"].push_back(std::move(branch));
522
523 block_statements_stack_.push_back(
524 std::ref(current_block_statement()["branches"].back()));
525}

◆ process_end_conditional_message()

void clanguml::sequence_diagram::generators::json::generator::process_end_conditional_message ( ) const
private

Process end of conditional statement message.

Definition at line 496 of file sequence_diagram_generator.cc.

497{
498 // Remove last if branch from the stack
499 block_statements_stack_.pop_back();
500
501 // Remove the if statement block from the stack
502 block_statements_stack_.pop_back();
503}

◆ process_end_do_message()

void clanguml::sequence_diagram::generators::json::generator::process_end_do_message ( ) const
private

Process do end statement message.

Definition at line 376 of file sequence_diagram_generator.cc.

377{
378 // Remove the do statement block from the stack
379 block_statements_stack_.pop_back();
380}

◆ process_end_for_message()

void clanguml::sequence_diagram::generators::json::generator::process_end_for_message ( ) const
private

Process for end statement message.

Definition at line 355 of file sequence_diagram_generator.cc.

356{
357 // Remove the while statement block from the stack
358 block_statements_stack_.pop_back();
359}

◆ process_end_if_message()

void clanguml::sequence_diagram::generators::json::generator::process_end_if_message ( ) const
private

Process end if statement message.

Definition at line 505 of file sequence_diagram_generator.cc.

506{
507 // Remove last if branch from the stack
508 block_statements_stack_.pop_back();
509
510 // Remove the if statement block from the stack
511 block_statements_stack_.pop_back();
512}

◆ process_end_switch_message()

void clanguml::sequence_diagram::generators::json::generator::process_end_switch_message ( ) const
private

Process switch end statement message.

Definition at line 451 of file sequence_diagram_generator.cc.

452{ // Remove last case block from the stack
453 block_statements_stack_.pop_back();
454
455 // Remove the switch statement block from the stack
456 block_statements_stack_.pop_back();
457}

◆ process_end_try_message()

void clanguml::sequence_diagram::generators::json::generator::process_end_try_message ( ) const
private

Process try end statement message.

Definition at line 415 of file sequence_diagram_generator.cc.

416{
417 // Remove last if block from the stack
418 block_statements_stack_.pop_back();
419
420 // Remove the try statement block from the stack
421 block_statements_stack_.pop_back();
422}

◆ process_end_while_message()

void clanguml::sequence_diagram::generators::json::generator::process_end_while_message ( ) const
private

Process while end loop message.

Definition at line 334 of file sequence_diagram_generator.cc.

335{
336 // Remove the while statement block from the stack
337 block_statements_stack_.pop_back();
338}

◆ process_for_message()

void clanguml::sequence_diagram::generators::json::generator::process_for_message ( const model::message m) const
private

Process for loop statement message.

Parameters
mMessage model

Definition at line 340 of file sequence_diagram_generator.cc.

341{
342 nlohmann::json for_block;
343 for_block["type"] = "loop";
344 for_block["name"] = "for";
345 for_block["activity_id"] = std::to_string(m.from().value());
346 if (auto text = m.condition_text(); text.has_value())
347 for_block["condition_text"] = *text;
348
349 current_block_statement()["messages"].push_back(std::move(for_block));
350
351 block_statements_stack_.push_back(
352 std::ref(current_block_statement()["messages"].back()));
353}

◆ process_if_message()

void clanguml::sequence_diagram::generators::json::generator::process_if_message ( const model::message m) const
private

Process if statement message.

Parameters
mMessage model

Definition at line 527 of file sequence_diagram_generator.cc.

528{
529 nlohmann::json if_block;
530 if_block["type"] = "alt";
531 if_block["name"] = "if";
532 if_block["activity_id"] = std::to_string(m.from().value());
533 if (auto text = m.condition_text(); text.has_value())
534 if_block["condition_text"] = *text;
535
536 current_block_statement()["messages"].push_back(std::move(if_block));
537
538 block_statements_stack_.push_back(
539 std::ref(current_block_statement()["messages"].back()));
540
541 nlohmann::json branch;
542 branch["type"] = "consequent";
543 current_block_statement()["branches"].push_back(std::move(branch));
544
545 block_statements_stack_.push_back(
546 std::ref(current_block_statement()["branches"].back()));
547}

◆ process_switch_message()

void clanguml::sequence_diagram::generators::json::generator::process_switch_message ( const model::message m) const
private

Process switch statement message.

Parameters
mMessage model

Definition at line 424 of file sequence_diagram_generator.cc.

425{
426 nlohmann::json if_block;
427 if_block["type"] = "alt";
428 if_block["name"] = "switch";
429 if_block["activity_id"] = std::to_string(m.from().value());
430
431 current_block_statement()["messages"].push_back(std::move(if_block));
432
433 block_statements_stack_.push_back(
434 std::ref(current_block_statement()["messages"].back()));
435}

◆ process_try_message()

void clanguml::sequence_diagram::generators::json::generator::process_try_message ( const model::message m) const
private

Process try statement message.

Parameters
mMessage model

Definition at line 382 of file sequence_diagram_generator.cc.

383{
384 nlohmann::json try_block;
385 try_block["type"] = "break";
386 try_block["name"] = "try";
387 try_block["activity_id"] = std::to_string(m.from().value());
388
389 current_block_statement()["messages"].push_back(std::move(try_block));
390
391 block_statements_stack_.push_back(
392 std::ref(current_block_statement()["messages"].back()));
393
394 nlohmann::json branch;
395 branch["type"] = "main";
396 current_block_statement()["branches"].push_back(std::move(branch));
397
398 block_statements_stack_.push_back(
399 std::ref(current_block_statement()["branches"].back()));
400}

◆ process_while_message()

void clanguml::sequence_diagram::generators::json::generator::process_while_message ( const model::message m) const
private

Process while loop message.

Parameters
mMessage model

Definition at line 319 of file sequence_diagram_generator.cc.

320{
321 nlohmann::json while_block;
322 while_block["type"] = "loop";
323 while_block["name"] = "while";
324 while_block["activity_id"] = std::to_string(m.from().value());
325 if (auto text = m.condition_text(); text.has_value())
326 while_block["condition_text"] = *text;
327
328 current_block_statement()["messages"].push_back(std::move(while_block));
329
330 block_statements_stack_.push_back(
331 std::ref(current_block_statement()["messages"].back()));
332}

Member Data Documentation

◆ already_generated_in_static_context_

std::vector<model::message> clanguml::sequence_diagram::generators::json::generator::already_generated_in_static_context_
mutableprivate

Definition at line 259 of file sequence_diagram_generator.h.

◆ block_statements_stack_

std::vector<std::reference_wrapper<nlohmann::json> > clanguml::sequence_diagram::generators::json::generator::block_statements_stack_
mutableprivate

Definition at line 257 of file sequence_diagram_generator.h.

◆ generated_participants_

std::set<eid_t> clanguml::sequence_diagram::generators::json::generator::generated_participants_
mutableprivate

Definition at line 250 of file sequence_diagram_generator.h.

◆ json_

nlohmann::json clanguml::sequence_diagram::generators::json::generator::json_
mutableprivate

Definition at line 254 of file sequence_diagram_generator.h.


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