0.6.1
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 603 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)
 
virtual void reset ()
 

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 NestedTraitT >
void process_elements (const diagram &d, const NestedTraitT &nt, const config::context_config &context_cfg, std::set< eid_t > &effective_context, std::set< eid_t > &current_iteration_context) const
 
template<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 972 of file diagram_filter.cc.

975 , context_{std::move(context)}
976{
977}

◆ ~context_filter()

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

Member Function Documentation

◆ find_elements_in_direct_relationship()

template<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 778 of file diagram_filter.h.

782 {
783 const auto &cd = dynamic_cast<const DiagramT &>(d);
784
786 cd, cd, context_cfg, effective_context, current_iteration_context);
787 }

◆ initialize()

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

Definition at line 1107 of file diagram_filter.cc.

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

◆ initialize_effective_context()

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

Definition at line 1090 of file diagram_filter.cc.

1092{
1093 if (d.type() == diagram_t::kClass)
1095 else if (d.type() == diagram_t::kPackage) {
1097 }
1098}

◆ 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 979 of file diagram_filter.cc.

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

◆ 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 1043 of file diagram_filter.cc.

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

◆ is_inward()

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

Definition at line 1163 of file diagram_filter.cc.

1164{
1165 return r == relationship_t::kAssociation;
1166}

◆ is_outward()

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

Definition at line 1168 of file diagram_filter.cc.

1169{
1170 return r != relationship_t::kAssociation;
1171}

◆ 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 1121 of file diagram_filter.cc.

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

◆ process_elements()

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

Definition at line 626 of file diagram_filter.h.

630 {
631 if (d.type() == diagram_t::kClass) {
632 for (const auto &p : nt) {
633 if (auto *pkg = dynamic_cast<package *>(p.get());
634 pkg != nullptr) {
635 process_elements(d, *pkg, context_cfg, effective_context,
636 current_iteration_context);
637 }
638 else {
639 for (const relationship &rel : p.get()->relationships()) {
640 if (!should_include(context_cfg, rel.type()) ||
641 !d.should_include(rel.type())) {
642 continue;
643 }
644 // At the moment aggregation and composition are added
645 // in the model in reverse direction, so we don't
646 // consider them here
647 if (context_cfg.direction ==
649 (rel.type() == relationship_t::kAggregation ||
650 rel.type() == relationship_t::kComposition)) {
651 continue;
652 }
653 if (context_cfg.direction ==
655 (rel.type() != relationship_t::kAggregation &&
656 rel.type() != relationship_t::kComposition)) {
657 continue;
658 }
659 for (const auto &element_id : effective_context) {
660 if (rel.destination() == element_id)
661 current_iteration_context.emplace(
662 p.get()->id());
663 }
664 }
665
666 // Now search current effective_context elements and add any
667 // elements of any type in the diagram which have a
668 // relationship to that element
669 for (const auto element_id : effective_context) {
670 const auto &maybe_element = d.get(element_id);
671
672 if (!maybe_element)
673 continue;
674
675 for (const relationship &rel :
676 maybe_element.value().relationships()) {
677 if (!should_include(context_cfg, rel.type()) ||
678 !d.should_include(rel.type())) {
679 continue;
680 }
681
682 if ((context_cfg.direction ==
684 (rel.type() != relationship_t::kAggregation &&
685 rel.type() !=
687 continue;
688 }
689 if (context_cfg.direction ==
691 (rel.type() == relationship_t::kAggregation ||
692 rel.type() ==
694 continue;
695 }
696
697 if (rel.destination() == p.get()->id())
698 current_iteration_context.emplace(
699 p.get()->id());
700 }
701 }
702 }
703 }
704 }
705 else if (d.type() == diagram_t::kPackage) {
706 for (const auto &p : nt) {
707 auto *pkg = dynamic_cast<package *>(p.get());
708 if (pkg == nullptr)
709 continue;
710
711 process_elements(d, *pkg, context_cfg, effective_context,
712 current_iteration_context);
713
714 for (const relationship &rel : p.get()->relationships()) {
715 if (!should_include(context_cfg, rel.type()) ||
716 !d.should_include(rel.type())) {
717 continue;
718 }
719 // At the moment aggregation and composition are added
720 // in the model in reverse direction, so we don't
721 // consider them here
722 if (context_cfg.direction ==
724 (rel.type() == relationship_t::kAggregation ||
725 rel.type() == relationship_t::kComposition)) {
726 continue;
727 }
728 if (context_cfg.direction ==
730 (rel.type() != relationship_t::kAggregation &&
731 rel.type() != relationship_t::kComposition)) {
732 continue;
733 }
734 for (const auto &element_id : effective_context) {
735 if (rel.destination() == element_id)
736 current_iteration_context.emplace(p.get()->id());
737 }
738 }
739
740 // Now search current effective_context elements and add any
741 // elements of any type in the diagram which have a
742 // relationship to that element
743 for (const auto element_id : effective_context) {
744 const auto &maybe_element = d.get(element_id);
745
746 if (!maybe_element)
747 continue;
748
749 for (const relationship &rel :
750 maybe_element.value().relationships()) {
751 if (!should_include(context_cfg, rel.type()) ||
752 !d.should_include(rel.type())) {
753 continue;
754 }
755
756 if ((context_cfg.direction ==
758 (rel.type() != relationship_t::kAggregation &&
759 rel.type() != relationship_t::kComposition)) {
760 continue;
761 }
762 if (context_cfg.direction ==
764 (rel.type() == relationship_t::kAggregation ||
765 rel.type() == relationship_t::kComposition)) {
766 continue;
767 }
768
769 if (rel.destination() == p.get()->id())
770 current_iteration_context.emplace(p.get()->id());
771 }
772 }
773 }
774 }
775 }

◆ should_include()

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

Definition at line 1100 of file diagram_filter.cc.

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

Member Data Documentation

◆ context_

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

Definition at line 792 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 798 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 801 of file diagram_filter.h.


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