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::context_filter Struct Reference

Detailed Description

Match diagram elements which are in within a 'radius' distance relationship to any of the elements specified in context.

Definition at line 589 of file diagram_filter.h.

#include <diagram_filter.h>

Public Member Functions

 context_filter (filter_t type, std::vector< config::context_config > context)
 
 ~context_filter () override=default
 
tvl::value_t match (const diagram &d, const element &r) const override
 
- Public Member Functions inherited from clanguml::common::model::filter_visitor
 filter_visitor (filter_t type)
 
virtual ~filter_visitor ()=default
 
virtual tvl::value_t match (const diagram &d, const common::model::element &e) const
 
virtual tvl::value_t match (const diagram &d, const common::model::relationship &r) const
 
virtual tvl::value_t match (const diagram &d, const common::model::relationship_t &r) const
 
virtual tvl::value_t match (const diagram &d, const common::model::access_t &a) const
 
virtual tvl::value_t match (const diagram &d, const common::model::namespace_ &ns) const
 
virtual tvl::value_t match (const diagram &d, const common::model::source_file &f) const
 
virtual tvl::value_t match (const diagram &d, const common::model::source_location &f) const
 
virtual tvl::value_t match (const diagram &d, const class_diagram::model::class_method &m) const
 
virtual tvl::value_t match (const diagram &d, const class_diagram::model::class_member &m) const
 
virtual tvl::value_t match (const diagram &d, const class_diagram::model::objc_method &m) const
 
virtual tvl::value_t match (const diagram &d, const class_diagram::model::objc_member &m) const
 
virtual tvl::value_t match (const diagram &d, const sequence_diagram::model::participant &p) const
 
bool is_inclusive () const
 
bool is_exclusive () const
 
filter_t type () const
 
filter_mode_t mode () const
 
void set_mode (filter_mode_t mode)
 

Private Member Functions

void initialize (const diagram &d) const
 
void initialize_effective_context (const diagram &d, unsigned idx) const
 
void initialize_effective_context_class_diagram (const diagram &d, unsigned idx) const
 
void initialize_effective_context_package_diagram (const diagram &d, unsigned idx) const
 
bool is_inward (relationship_t r) const
 
bool is_outward (relationship_t r) const
 
template<typename ElementT , typename DiagramT >
void find_elements_in_direct_relationship (const diagram &d, const config::context_config &context_cfg, std::set< eid_t > &effective_context, std::set< eid_t > &current_iteration_context) const
 
bool should_include (const config::context_config &context_cfg, relationship_t r) const
 

Private Attributes

std::vector< config::context_configcontext_
 
std::vector< std::set< eid_t > > effective_contexts_
 
bool initialized_ {false}
 

Constructor & Destructor Documentation

◆ context_filter()

clanguml::common::model::context_filter::context_filter ( filter_t  type,
std::vector< config::context_config context 
)

Definition at line 959 of file diagram_filter.cc.

962 , context_{std::move(context)}
963{
964}

◆ ~context_filter()

clanguml::common::model::context_filter::~context_filter ( )
overridedefault

Member Function Documentation

◆ find_elements_in_direct_relationship()

template<typename ElementT , typename DiagramT >
void clanguml::common::model::context_filter::find_elements_in_direct_relationship ( const diagram d,
const config::context_config context_cfg,
std::set< eid_t > &  effective_context,
std::set< eid_t > &  current_iteration_context 
) const
inlineprivate

Definition at line 612 of file diagram_filter.h.

616 {
617 static_assert(std::is_same_v<ElementT, class_diagram::model::class_> ||
618 std::is_same_v<ElementT, class_diagram::model::enum_> ||
619 std::is_same_v<ElementT, class_diagram::model::concept_> ||
620 std::is_same_v<ElementT, common::model::package>,
621 "ElementT must be either class_ or enum_ or concept_");
622
623 const auto &cd = dynamic_cast<const DiagramT &>(d);
624
625 for (const auto &el : cd.template elements<ElementT>()) {
626 // First search all elements of type ElementT in the diagram
627 // which have a relationship to any of the effective_context
628 // elements
629 for (const relationship &rel : el.get().relationships()) {
630 if (!should_include(context_cfg, rel.type()) ||
631 !d.should_include(rel.type())) {
632 continue;
633 }
634 // At the moment aggregation and composition are added in the
635 // model in reverse direction, so we don't consider them here
636 if (context_cfg.direction ==
638 (rel.type() == relationship_t::kAggregation ||
639 rel.type() == relationship_t::kComposition)) {
640 continue;
641 }
642 if (context_cfg.direction ==
644 (rel.type() != relationship_t::kAggregation &&
645 rel.type() != relationship_t::kComposition)) {
646 continue;
647 }
648 for (const auto &element_id : effective_context) {
649 if (rel.destination() == element_id)
650 current_iteration_context.emplace(el.get().id());
651 }
652 }
653
654 // Now search current effective_context elements and add any
655 // elements of any type in the diagram which have a relationship
656 // to that element
657 for (const auto element_id : effective_context) {
658 const auto &maybe_element = cd.get(element_id);
659
660 if (!maybe_element)
661 continue;
662
663 for (const relationship &rel :
664 maybe_element.value().relationships()) {
665 if (!should_include(context_cfg, rel.type()) ||
666 !d.should_include(rel.type())) {
667 continue;
668 }
669
670 if ((context_cfg.direction ==
672 (rel.type() != relationship_t::kAggregation &&
673 rel.type() != relationship_t::kComposition)) {
674 continue;
675 }
676 if (context_cfg.direction ==
678 (rel.type() == relationship_t::kAggregation ||
679 rel.type() == relationship_t::kComposition)) {
680 continue;
681 }
682
683 if (rel.destination() == el.get().id())
684 current_iteration_context.emplace(el.get().id());
685 }
686 }
687 }
688 }

◆ initialize()

void clanguml::common::model::context_filter::initialize ( const diagram d) const
private

Definition at line 1105 of file diagram_filter.cc.

1106{
1107 if (initialized_)
1108 return;
1109
1110 initialized_ = true;
1111
1112 // Prepare effective_contexts_
1113 for (auto i = 0U; i < context_.size(); i++) {
1114 effective_contexts_.push_back({}); // NOLINT
1116 }
1117}

◆ initialize_effective_context()

void clanguml::common::model::context_filter::initialize_effective_context ( const diagram d,
unsigned  idx 
) const
private

Definition at line 1088 of file diagram_filter.cc.

1090{
1091 if (d.type() == diagram_t::kClass)
1093 else if (d.type() == diagram_t::kPackage) {
1095 }
1096}

◆ initialize_effective_context_class_diagram()

void clanguml::common::model::context_filter::initialize_effective_context_class_diagram ( const diagram d,
unsigned  idx 
) const
private

Definition at line 966 of file diagram_filter.cc.

968{
969 bool effective_context_extended{true};
970
971 auto &effective_context = effective_contexts_[idx];
972
973 // First add to effective context all elements matching context_
974 // patterns
975 const auto &context_cfg = context_.at(idx);
976 const auto &context_matches =
977 dynamic_cast<const class_diagram::model::diagram &>(d)
978 .find<class_diagram::model::class_>(context_cfg.pattern);
979
980 for (const auto &maybe_match : context_matches) {
981 if (maybe_match)
982 effective_context.emplace(maybe_match.value().id());
983 }
984
985 const auto &context_enum_matches =
986 dynamic_cast<const class_diagram::model::diagram &>(d)
987 .find<class_diagram::model::enum_>(context_cfg.pattern);
988
989 for (const auto &maybe_match : context_enum_matches) {
990 if (maybe_match)
991 effective_context.emplace(maybe_match.value().id());
992 }
993
994 const auto &context_concept_matches =
995 dynamic_cast<const class_diagram::model::diagram &>(d)
996 .find<class_diagram::model::concept_>(context_cfg.pattern);
997
998 for (const auto &maybe_match : context_concept_matches) {
999 if (maybe_match)
1000 effective_context.emplace(maybe_match.value().id());
1001 }
1002
1003 // Now repeat radius times - extend the effective context with elements
1004 // matching in direct relationship to what is in context
1005 auto radius_counter = context_cfg.radius;
1006 std::set<eid_t> current_iteration_context;
1007
1008 while (radius_counter > 0 && effective_context_extended) {
1009 // If at any iteration the effective context was not extended - we
1010 // don't to need to continue
1011 radius_counter--;
1012 effective_context_extended = false;
1013 current_iteration_context.clear();
1014
1015 // For each class in the model
1016 find_elements_in_direct_relationship<class_diagram::model::class_,
1017 class_diagram::model::diagram>(
1018 d, context_cfg, effective_context, current_iteration_context);
1019
1020 // For each concept in the model
1021 find_elements_in_direct_relationship<class_diagram::model::concept_,
1022 class_diagram::model::diagram>(
1023 d, context_cfg, effective_context, current_iteration_context);
1024
1025 // For each enum in the model
1026 find_elements_in_direct_relationship<class_diagram::model::enum_,
1027 class_diagram::model::diagram>(
1028 d, context_cfg, effective_context, current_iteration_context);
1029
1030 for (auto id : current_iteration_context) {
1031 if (effective_context.count(id) == 0) {
1032 // Found new element to add to context
1033 effective_context.emplace(id);
1034 effective_context_extended = true;
1035 }
1036 }
1037 }
1038}

◆ initialize_effective_context_package_diagram()

void clanguml::common::model::context_filter::initialize_effective_context_package_diagram ( const diagram d,
unsigned  idx 
) const
private

Definition at line 1040 of file diagram_filter.cc.

1042{
1043 assert(d.type() == diagram_t::kPackage);
1044
1045 bool effective_context_extended{true};
1046
1047 auto &effective_context = effective_contexts_[idx];
1048
1049 // First add to effective context all elements matching context_
1050 // patterns
1051 const auto &context_cfg = context_.at(idx);
1052 const auto &context_matches =
1053 dynamic_cast<const package_diagram::model::diagram &>(d)
1054 .find<package_diagram::model::package>(context_cfg.pattern);
1055
1056 for (const auto &maybe_match : context_matches) {
1057 if (maybe_match)
1058 effective_context.emplace(maybe_match.value().id());
1059 }
1060
1061 // Now repeat radius times - extend the effective context with elements
1062 // matching in direct relationship to what is in context
1063 auto radius_counter = context_cfg.radius;
1064 std::set<eid_t> current_iteration_context;
1065
1066 while (radius_counter > 0 && effective_context_extended) {
1067 // If at any iteration the effective context was not extended - we
1068 // don't to need to continue
1069 radius_counter--;
1070 effective_context_extended = false;
1071 current_iteration_context.clear();
1072
1073 // For each class in the model
1074 find_elements_in_direct_relationship<common::model::package,
1075 package_diagram::model::diagram>(
1076 d, context_cfg, effective_context, current_iteration_context);
1077
1078 for (auto id : current_iteration_context) {
1079 if (effective_context.count(id) == 0) {
1080 // Found new element to add to context
1081 effective_context.emplace(id);
1082 effective_context_extended = true;
1083 }
1084 }
1085 }
1086}

◆ is_inward()

bool clanguml::common::model::context_filter::is_inward ( relationship_t  r) const
private

Definition at line 1161 of file diagram_filter.cc.

1162{
1163 return r == relationship_t::kAssociation;
1164}

◆ is_outward()

bool clanguml::common::model::context_filter::is_outward ( relationship_t  r) const
private

Definition at line 1166 of file diagram_filter.cc.

1167{
1168 return r != relationship_t::kAssociation;
1169}

◆ match()

tvl::value_t clanguml::common::model::context_filter::match ( const diagram d,
const element r 
) const
overridevirtual

Reimplemented from clanguml::common::model::filter_visitor.

Definition at line 1119 of file diagram_filter.cc.

1120{
1121 if (d.type() != diagram_t::kClass && d.type() != diagram_t::kPackage)
1122 return {};
1123
1124 // Running this filter makes sense only after the entire diagram is
1125 // generated - i.e. during diagram generation
1126 if (!d.complete())
1127 return {};
1128
1129 // Context filter only makes sense for packages which are empty, i.e. are
1130 // leafs in the package diagram tree
1131 if (d.type() == diagram_t::kPackage) {
1132 if (const auto *package_ptr =
1133 dynamic_cast<const common::model::package *>(&e);
1134 package_ptr != nullptr) {
1135 if (!package_ptr->is_empty(true)) {
1136 return {};
1137 }
1138 }
1139 }
1140
1141 initialize(d);
1142
1143 if (std::all_of(effective_contexts_.begin(), effective_contexts_.end(),
1144 [](const auto &ec) { return ec.empty(); }))
1145 return {};
1146
1147 for (const auto &ec : effective_contexts_) {
1148 if (ec.count(e.id()) > 0) {
1149 if (type() == filter_t::kExclusive)
1150 LOG_TRACE("Element {} rejected by context_filter",
1151 e.full_name(false));
1152 return true;
1153 }
1154 }
1155 if (type() == filter_t::kInclusive)
1156 LOG_TRACE("Element {} rejected by context_filter", e.full_name(false));
1157
1158 return false;
1159}

◆ should_include()

bool clanguml::common::model::context_filter::should_include ( const config::context_config context_cfg,
relationship_t  r 
) const
private

Definition at line 1098 of file diagram_filter.cc.

1100{
1101 return context_cfg.relationships.empty() ||
1102 util::contains(context_cfg.relationships, r);
1103}

Member Data Documentation

◆ context_

std::vector<config::context_config> clanguml::common::model::context_filter::context_
private

Definition at line 693 of file diagram_filter.h.

◆ effective_contexts_

std::vector<std::set<eid_t> > clanguml::common::model::context_filter::effective_contexts_
mutableprivate

Represents all elements which should belong to the diagram based on this filter. It is populated by the initialize() method.

Definition at line 699 of file diagram_filter.h.

◆ initialized_

bool clanguml::common::model::context_filter::initialized_ {false}
mutableprivate

Flag to mark whether the filter context has been computed

Definition at line 702 of file diagram_filter.h.


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