From 7c7f8a3b14f5a1b14770d4622cbd09755e035edf Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Tue, 29 Mar 2022 18:56:00 +0200 Subject: [PATCH] Moved diagram_filter methods to implementation file --- src/common/model/diagram_filter.cc | 239 ++++++++++++++++++++++++++- src/common/model/diagram_filter.h | 252 ++++++----------------------- 2 files changed, 281 insertions(+), 210 deletions(-) diff --git a/src/common/model/diagram_filter.cc b/src/common/model/diagram_filter.cc index ba35e946..3f24868d 100644 --- a/src/common/model/diagram_filter.cc +++ b/src/common/model/diagram_filter.cc @@ -21,31 +21,260 @@ namespace clanguml::common::model { std::optional filter_visitor::match( - const diagram &d, const common::model::element &e) + const diagram &d, const common::model::element &e) const { return {}; } std::optional filter_visitor::match( - const diagram &d, const common::model::relationship_t &r) + const diagram &d, const common::model::relationship_t &r) const { return {}; } std::optional filter_visitor::match( - const diagram &d, const common::model::scope_t &r) + const diagram &d, const common::model::scope_t &r) const { return {}; } std::optional filter_visitor::match( - const diagram &d, const common::model::namespace_ &ns) + const diagram &d, const common::model::namespace_ &ns) const { return {}; } +bool filter_visitor::is_inclusive() const +{ + return type_ == filter_t::kInclusive; +} + +bool filter_visitor::is_exclusive() const +{ + return type_ == filter_t::kExclusive; +} + +filter_t filter_visitor::type() const { return type_; } + +namespace_filter::namespace_filter( + filter_t type, std::vector namespaces) + : filter_visitor{type} + , namespaces_{namespaces} +{ +} + +std::optional namespace_filter::match( + const diagram &d, const namespace_ &ns) const +{ + if (namespaces_.empty() || ns.is_empty()) + return {}; + + return std::any_of(namespaces_.begin(), namespaces_.end(), + [&ns](const auto &nsit) { return ns.starts_with(nsit) || ns == nsit; }); +} + +std::optional namespace_filter::match( + const diagram &d, const element &e) const +{ + if (namespaces_.empty()) + return {}; + + if (dynamic_cast(&e) != nullptr) { + return std::any_of( + namespaces_.begin(), namespaces_.end(), [&e](const auto &nsit) { + return (e.get_namespace() | e.name()).starts_with(nsit) || + nsit.starts_with(e.get_namespace() | e.name()) || + (e.get_namespace() | e.name()) == nsit; + }); + } + else { + return std::any_of( + namespaces_.begin(), namespaces_.end(), [&e](const auto &nsit) { + return e.get_namespace().starts_with(nsit); + }); + } +} + +element_filter::element_filter(filter_t type, std::vector elements) + : filter_visitor{type} + , elements_{elements} +{ +} + +std::optional element_filter::match( + const diagram &d, const element &e) const +{ + if (elements_.empty()) + return {}; + + return std::any_of(elements_.begin(), elements_.end(), + [&e](const auto &el) { return e.full_name(false) == el; }); +} + +subclass_filter::subclass_filter(filter_t type, std::vector roots) + : filter_visitor{type} + , roots_{roots} +{ +} + +std::optional subclass_filter::match( + const diagram &d, const element &e) const +{ + if (roots_.empty()) + return {}; + + if (!d.complete()) + return {}; + + const auto &cd = dynamic_cast(d); + + // First get all parents of element e + std::unordered_set< + type_safe::object_ref> + parents; + + const auto &fn = e.full_name(false); + auto class_ref = cd.get_class(fn); + + if (!class_ref.has_value()) + return false; + + parents.emplace(class_ref.value()); + + cd.get_parents(parents); + + // Now check if any of the parents matches the roots specified in the + // filter config + for (const auto &root : roots_) { + for (const auto &parent : parents) { + if (root == parent.get().full_name(false)) + return true; + } + } + + return false; +} + +relationship_filter::relationship_filter( + filter_t type, std::vector relationships) + : filter_visitor{type} + , relationships_{std::move(relationships)} +{ +} + +std::optional relationship_filter::match( + const diagram &d, const relationship_t &r) const +{ + if (relationships_.empty()) + return {}; + + return std::any_of(relationships_.begin(), relationships_.end(), + [&r](const auto &rel) { return r == rel; }); +} + +scope_filter::scope_filter(filter_t type, std::vector scopes) + : filter_visitor{type} + , scopes_{std::move(scopes)} +{ +} + +std::optional scope_filter::match( + const diagram &d, const scope_t &s) const +{ + if (scopes_.empty()) + return {}; + + return std::any_of(scopes_.begin(), scopes_.end(), + [&s](const auto &scope) { return s == scope; }); +} + +context_filter::context_filter(filter_t type, std::vector context) + : filter_visitor{type} + , context_{context} +{ +} + +std::optional context_filter::match( + const diagram &d, const element &r) const +{ + if (!d.complete()) + return {}; + + if (context_.empty()) + return {}; + + return std::any_of(context_.begin(), context_.end(), + [&r](const auto &rel) { return std::optional{}; }); +} + +diagram_filter::diagram_filter( + const common::model::diagram &d, const config::diagram &c) + : diagram_{d} +{ + init_filters(c); +} + +void diagram_filter::add_inclusive_filter(std::unique_ptr fv) +{ + inclusive_.emplace_back(std::move(fv)); +} + +void diagram_filter::add_exclusive_filter(std::unique_ptr fv) +{ + exclusive_.emplace_back(std::move(fv)); +} + +bool diagram_filter::should_include( + namespace_ ns, const std::string &name) const +{ + if (should_include(ns)) { + element e{namespace_{}}; + e.set_name(name); + e.set_namespace(ns); + + return should_include(e); + } + + return false; +} + +void diagram_filter::init_filters(const config::diagram &c) +{ + // Process inclusive filters + if (c.include) { + inclusive_.emplace_back(std::make_unique( + filter_t::kInclusive, c.include().namespaces)); + inclusive_.emplace_back(std::make_unique( + filter_t::kInclusive, c.include().relationships)); + inclusive_.emplace_back(std::make_unique( + filter_t::kInclusive, c.include().scopes)); + inclusive_.emplace_back(std::make_unique( + filter_t::kInclusive, c.include().elements)); + inclusive_.emplace_back(std::make_unique( + filter_t::kInclusive, c.include().subclasses)); + inclusive_.emplace_back(std::make_unique( + filter_t::kInclusive, c.include().context)); + } + + // Process exclusive filters + if (c.exclude) { + exclusive_.emplace_back(std::make_unique( + filter_t::kExclusive, c.exclude().namespaces)); + exclusive_.emplace_back(std::make_unique( + filter_t::kExclusive, c.exclude().elements)); + exclusive_.emplace_back(std::make_unique( + filter_t::kExclusive, c.include().relationships)); + exclusive_.emplace_back(std::make_unique( + filter_t::kExclusive, c.include().scopes)); + exclusive_.emplace_back(std::make_unique( + filter_t::kExclusive, c.exclude().subclasses)); + exclusive_.emplace_back(std::make_unique( + filter_t::kExclusive, c.exclude().context)); + } +} + template <> -bool diagram_filter::should_include(const std::string &name) +bool diagram_filter::should_include(const std::string &name) const { auto [ns, n] = cx::util::split_ns(name); diff --git a/src/common/model/diagram_filter.h b/src/common/model/diagram_filter.h index 3a02db5b..64045315 100644 --- a/src/common/model/diagram_filter.h +++ b/src/common/model/diagram_filter.h @@ -38,226 +38,101 @@ public: } virtual std::optional match( - const diagram &d, const common::model::element &e); - virtual std::optional match( - const diagram &d, const common::model::relationship_t &r); - virtual std::optional match( - const diagram &d, const common::model::scope_t &r); - virtual std::optional match( - const diagram &d, const common::model::namespace_ &ns); + const diagram &d, const common::model::element &e) const; - bool is_inclusive() const { return type_ == filter_t::kInclusive; } - bool is_exclusive() const { return type_ == filter_t::kExclusive; } + virtual std::optional match( + const diagram &d, const common::model::relationship_t &r) const; + virtual std::optional match( + const diagram &d, const common::model::scope_t &r) const; + + virtual std::optional match( + const diagram &d, const common::model::namespace_ &ns) const; + + bool is_inclusive() const; + bool is_exclusive() const; + + filter_t type() const; + +private: filter_t type_; }; struct namespace_filter : public filter_visitor { - namespace_filter(filter_t type, std::vector namespaces) - : filter_visitor{type} - , namespaces_{namespaces} - { - } + namespace_filter(filter_t type, std::vector namespaces); - std::optional match(const diagram &d, const namespace_ &ns) override - { - if (namespaces_.empty() || ns.is_empty()) - return {}; + std::optional match( + const diagram &d, const namespace_ &ns) const override; - return std::any_of( - namespaces_.begin(), namespaces_.end(), [&ns](const auto &nsit) { - return ns.starts_with(nsit) || ns == nsit; - }); - } - - std::optional match(const diagram &d, const element &e) override - { - if (namespaces_.empty()) - return {}; - - if (dynamic_cast(&e) != nullptr) { - return std::any_of( - namespaces_.begin(), namespaces_.end(), [&e](const auto &nsit) { - return (e.get_namespace() | e.name()).starts_with(nsit) || - nsit.starts_with(e.get_namespace() | e.name()) || - (e.get_namespace() | e.name()) == nsit; - }); - } - else { - return std::any_of( - namespaces_.begin(), namespaces_.end(), [&e](const auto &nsit) { - return e.get_namespace().starts_with(nsit); - }); - } - } + std::optional match( + const diagram &d, const element &e) const override; +private: std::vector namespaces_; }; struct element_filter : public filter_visitor { - element_filter(filter_t type, std::vector elements) - : filter_visitor{type} - , elements_{elements} - { - } + element_filter(filter_t type, std::vector elements); - std::optional match(const diagram &d, const element &e) override - { - if (elements_.empty()) - return {}; - - return std::any_of( - elements_.begin(), elements_.end(), [&e](const auto &el) { - auto fn = e.full_name(false); - bool result = fn == el; - return result; - }); - } + std::optional match( + const diagram &d, const element &e) const override; +private: std::vector elements_; }; struct subclass_filter : public filter_visitor { - subclass_filter(filter_t type, std::vector roots) - : filter_visitor{type} - , roots_{roots} - { - } + subclass_filter(filter_t type, std::vector roots); - std::optional match(const diagram &d, const element &e) override - { - if (roots_.empty()) - return {}; - - if (!d.complete()) - return {}; - - const auto &cd = dynamic_cast(d); - - // First get all parents of element e - std::unordered_set< - type_safe::object_ref> - parents; - - const auto &fn = e.full_name(false); - auto class_ref = cd.get_class(fn); - - if (!class_ref.has_value()) - return false; - - parents.emplace(class_ref.value()); - - cd.get_parents(parents); - - // Now check if any of the parents matches the roots specified in the - // filter config - for (const auto &root : roots_) { - for (const auto &parent : parents) { - if (root == parent.get().full_name(false)) - return true; - } - } - - return false; - } + std::optional match( + const diagram &d, const element &e) const override; +private: std::vector roots_; }; struct relationship_filter : public filter_visitor { relationship_filter( - filter_t type, std::vector relationships) - : filter_visitor{type} - , relationships_{std::move(relationships)} - { - } + filter_t type, std::vector relationships); std::optional match( - const diagram &d, const relationship_t &r) override - { - if (relationships_.empty()) - return {}; - - return std::any_of(relationships_.begin(), relationships_.end(), - [&r](const auto &rel) { return r == rel; }); - } + const diagram &d, const relationship_t &r) const override; +private: std::vector relationships_; }; struct scope_filter : public filter_visitor { - scope_filter(filter_t type, std::vector scopes) - : filter_visitor{type} - , scopes_{std::move(scopes)} - { - } + scope_filter(filter_t type, std::vector scopes); - std::optional match(const diagram &d, const scope_t &s) override - { - if (scopes_.empty()) - return {}; - - return std::any_of(scopes_.begin(), scopes_.end(), - [&s](const auto &scope) { return s == scope; }); - } + std::optional match( + const diagram &d, const scope_t &s) const override; +private: std::vector scopes_; }; struct context_filter : public filter_visitor { - context_filter(filter_t type, std::vector context) - : filter_visitor{type} - , context_{context} - { - } + context_filter(filter_t type, std::vector context); - std::optional match(const diagram &d, const element &r) override - { - if (!d.complete()) - return {}; - - if (context_.empty()) - return {}; - - return std::any_of(context_.begin(), context_.end(), - [&r](const auto &rel) { return std::optional{}; }); - } + std::optional match( + const diagram &d, const element &r) const override; +private: std::vector context_; }; class diagram_filter { public: - diagram_filter(const common::model::diagram &d, const config::diagram &c) - : diagram_{d} - { - init_filters(c); - } + diagram_filter(const common::model::diagram &d, const config::diagram &c); - void add_inclusive_filter(std::unique_ptr fv) - { - inclusive_.emplace_back(std::move(fv)); - } + void add_inclusive_filter(std::unique_ptr fv); - void add_exclusive_filter(std::unique_ptr fv) - { - exclusive_.emplace_back(std::move(fv)); - } + void add_exclusive_filter(std::unique_ptr fv); - bool should_include(namespace_ ns, const std::string &name) - { - if (should_include(ns)) { - element e{namespace_{}}; - e.set_name(name); - e.set_namespace(ns); + bool should_include(namespace_ ns, const std::string &name) const; - return should_include(e); - } - - return false; - } - - template bool should_include(const T &e) + template bool should_include(const T &e) const { bool exc = std::any_of( exclusive_.begin(), exclusive_.end(), [this, &e](const auto &ex) { @@ -284,40 +159,7 @@ public: } private: - void init_filters(const config::diagram &c) - { - // Process inclusive filters - if (c.include) { - inclusive_.emplace_back(std::make_unique( - filter_t::kInclusive, c.include().namespaces)); - inclusive_.emplace_back(std::make_unique( - filter_t::kInclusive, c.include().relationships)); - inclusive_.emplace_back(std::make_unique( - filter_t::kInclusive, c.include().scopes)); - inclusive_.emplace_back(std::make_unique( - filter_t::kInclusive, c.include().elements)); - inclusive_.emplace_back(std::make_unique( - filter_t::kInclusive, c.include().subclasses)); - inclusive_.emplace_back(std::make_unique( - filter_t::kInclusive, c.include().context)); - } - - // Process exclusive filters - if (c.exclude) { - exclusive_.emplace_back(std::make_unique( - filter_t::kExclusive, c.exclude().namespaces)); - exclusive_.emplace_back(std::make_unique( - filter_t::kExclusive, c.exclude().elements)); - exclusive_.emplace_back(std::make_unique( - filter_t::kExclusive, c.include().relationships)); - exclusive_.emplace_back(std::make_unique( - filter_t::kExclusive, c.include().scopes)); - exclusive_.emplace_back(std::make_unique( - filter_t::kExclusive, c.exclude().subclasses)); - exclusive_.emplace_back(std::make_unique( - filter_t::kExclusive, c.exclude().context)); - } - } + void init_filters(const config::diagram &c); std::vector> inclusive_; std::vector> exclusive_; @@ -326,5 +168,5 @@ private: }; template <> -bool diagram_filter::should_include(const std::string &name); +bool diagram_filter::should_include(const std::string &name) const; } \ No newline at end of file