From 18b0624f7ae745773f22fd7deeb3c0edf68c4fb5 Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Thu, 31 Mar 2022 23:11:58 +0200 Subject: [PATCH] Refactored filter diagrams to three value logic --- src/common/model/diagram_filter.cc | 78 +++++++++--------------------- src/common/model/diagram_filter.h | 54 ++++++++------------- src/common/model/tvl.h | 74 ++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 90 deletions(-) create mode 100644 src/common/model/tvl.h diff --git a/src/common/model/diagram_filter.cc b/src/common/model/diagram_filter.cc index 6644c17c..0d3d0d50 100644 --- a/src/common/model/diagram_filter.cc +++ b/src/common/model/diagram_filter.cc @@ -25,25 +25,25 @@ filter_visitor::filter_visitor(filter_t type) { } -std::optional filter_visitor::match( +tvl::value_t filter_visitor::match( const diagram &d, const common::model::element &e) const { return {}; } -std::optional filter_visitor::match( +tvl::value_t filter_visitor::match( const diagram &d, const common::model::relationship_t &r) const { return {}; } -std::optional filter_visitor::match( +tvl::value_t filter_visitor::match( const diagram &d, const common::model::access_t &a) const { return {}; } -std::optional filter_visitor::match( +tvl::value_t filter_visitor::match( const diagram &d, const common::model::namespace_ &ns) const { return {}; @@ -68,25 +68,11 @@ anyof_filter::anyof_filter( { } -std::optional anyof_filter::match( +tvl::value_t anyof_filter::match( const diagram &d, const common::model::element &e) const { - std::optional res{}; - - for (const auto &filter : filters_) { - auto m = filter->match(d, e); - if (m.has_value()) { - if (m.value() == true) { - res = true; - break; - } - else { - res = false; - } - } - } - - return res; + return tvl::any_of(filters_.begin(), filters_.end(), + [&d, &e](const auto &f) { return f->match(d, e); }); } namespace_filter::namespace_filter( @@ -96,24 +82,20 @@ namespace_filter::namespace_filter( { } -std::optional namespace_filter::match( +tvl::value_t namespace_filter::match( const diagram &d, const namespace_ &ns) const { - if (namespaces_.empty() || ns.is_empty()) + if (ns.is_empty()) return {}; - return std::any_of(namespaces_.begin(), namespaces_.end(), + return tvl::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 +tvl::value_t namespace_filter::match(const diagram &d, const element &e) const { - if (namespaces_.empty()) - return {}; - if (dynamic_cast(&e) != nullptr) { - return std::any_of( + return tvl::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()) || @@ -121,7 +103,7 @@ std::optional namespace_filter::match( }); } else { - return std::any_of( + return tvl::any_of( namespaces_.begin(), namespaces_.end(), [&e](const auto &nsit) { return e.get_namespace().starts_with(nsit); }); @@ -134,13 +116,9 @@ element_filter::element_filter(filter_t type, std::vector elements) { } -std::optional element_filter::match( - const diagram &d, const element &e) const +tvl::value_t element_filter::match(const diagram &d, const element &e) const { - if (elements_.empty()) - return {}; - - return std::any_of(elements_.begin(), elements_.end(), + return tvl::any_of(elements_.begin(), elements_.end(), [&e](const auto &el) { return e.full_name(false) == el; }); } @@ -150,8 +128,7 @@ subclass_filter::subclass_filter(filter_t type, std::vector roots) { } -std::optional subclass_filter::match( - const diagram &d, const element &e) const +tvl::value_t subclass_filter::match(const diagram &d, const element &e) const { if (d.type() != diagram_t::kClass) return {}; @@ -198,13 +175,10 @@ relationship_filter::relationship_filter( { } -std::optional relationship_filter::match( +tvl::value_t relationship_filter::match( const diagram &d, const relationship_t &r) const { - if (relationships_.empty()) - return {}; - - return std::any_of(relationships_.begin(), relationships_.end(), + return tvl::any_of(relationships_.begin(), relationships_.end(), [&r](const auto &rel) { return r == rel; }); } @@ -214,13 +188,9 @@ access_filter::access_filter(filter_t type, std::vector access) { } -std::optional access_filter::match( - const diagram &d, const access_t &a) const +tvl::value_t access_filter::match(const diagram &d, const access_t &a) const { - if (access_.empty()) - return {}; - - return std::any_of(access_.begin(), access_.end(), + return tvl::any_of(access_.begin(), access_.end(), [&a](const auto &access) { return a == access; }); } @@ -230,8 +200,7 @@ context_filter::context_filter(filter_t type, std::vector context) { } -std::optional context_filter::match( - const diagram &d, const element &e) const +tvl::value_t context_filter::match(const diagram &d, const element &e) const { if (d.type() != diagram_t::kClass) return {}; @@ -239,10 +208,7 @@ std::optional context_filter::match( if (!d.complete()) return {}; - if (context_.empty()) - return {}; - - return std::any_of(context_.begin(), context_.end(), + return tvl::any_of(context_.begin(), context_.end(), [&e, &d](const auto &context_root_name) { const auto &context_root = static_cast(d).get_class( diff --git a/src/common/model/diagram_filter.h b/src/common/model/diagram_filter.h index 468a9f1d..dfbc8886 100644 --- a/src/common/model/diagram_filter.h +++ b/src/common/model/diagram_filter.h @@ -25,6 +25,7 @@ #include "config/config.h" #include "cx/util.h" #include "diagram.h" +#include "tvl.h" namespace clanguml::common::model { @@ -34,16 +35,16 @@ class filter_visitor { public: filter_visitor(filter_t type); - virtual std::optional match( + virtual tvl::value_t match( const diagram &d, const common::model::element &e) const; - virtual std::optional match( + virtual tvl::value_t match( const diagram &d, const common::model::relationship_t &r) const; - virtual std::optional match( + virtual tvl::value_t match( const diagram &d, const common::model::access_t &a) const; - virtual std::optional match( + virtual tvl::value_t match( const diagram &d, const common::model::namespace_ &ns) const; bool is_inclusive() const; @@ -59,7 +60,7 @@ struct anyof_filter : public filter_visitor { anyof_filter( filter_t type, std::vector> filters); - std::optional match( + tvl::value_t match( const diagram &d, const common::model::element &e) const override; private: @@ -69,11 +70,9 @@ private: struct namespace_filter : public filter_visitor { namespace_filter(filter_t type, std::vector namespaces); - std::optional match( - const diagram &d, const namespace_ &ns) const override; + tvl::value_t match(const diagram &d, const namespace_ &ns) const override; - std::optional match( - const diagram &d, const element &e) const override; + tvl::value_t match(const diagram &d, const element &e) const override; private: std::vector namespaces_; @@ -82,8 +81,7 @@ private: struct element_filter : public filter_visitor { element_filter(filter_t type, std::vector elements); - std::optional match( - const diagram &d, const element &e) const override; + tvl::value_t match(const diagram &d, const element &e) const override; private: std::vector elements_; @@ -92,8 +90,7 @@ private: struct subclass_filter : public filter_visitor { subclass_filter(filter_t type, std::vector roots); - std::optional match( - const diagram &d, const element &e) const override; + tvl::value_t match(const diagram &d, const element &e) const override; private: std::vector roots_; @@ -103,7 +100,7 @@ struct relationship_filter : public filter_visitor { relationship_filter( filter_t type, std::vector relationships); - std::optional match( + tvl::value_t match( const diagram &d, const relationship_t &r) const override; private: @@ -113,8 +110,7 @@ private: struct access_filter : public filter_visitor { access_filter(filter_t type, std::vector access); - std::optional match( - const diagram &d, const access_t &a) const override; + tvl::value_t match(const diagram &d, const access_t &a) const override; private: std::vector access_; @@ -123,8 +119,7 @@ private: struct context_filter : public filter_visitor { context_filter(filter_t type, std::vector context); - std::optional match( - const diagram &d, const element &r) const override; + tvl::value_t match(const diagram &d, const element &r) const override; private: std::vector context_; @@ -142,25 +137,16 @@ public: template bool should_include(const T &e) const { - bool exc = std::any_of( - exclusive_.begin(), exclusive_.end(), [this, &e](const auto &ex) { - auto m = ex->match(diagram_, e); - // Return true if a filter is defined for specific element - // and it's a match - return m.has_value() && m.value(); - }); - if (exc) + auto exc = tvl::any_of(exclusive_.begin(), exclusive_.end(), + [this, &e](const auto &ex) { return ex->match(diagram_, e); }); + + if (tvl::is_true(exc)) return false; - bool inc = std::all_of( - inclusive_.begin(), inclusive_.end(), [this, &e](const auto &in) { - auto m = in->match(diagram_, e); - // Return true if a filter is undefined for specific element - // or it's a match - return !m.has_value() || m.value(); - }); + auto inc = tvl::all_of(inclusive_.begin(), inclusive_.end(), + [this, &e](const auto &in) { return in->match(diagram_, e); }); - if (inc) + if (tvl::is_undefined(inc) || tvl::is_true(inc)) return true; return false; diff --git a/src/common/model/tvl.h b/src/common/model/tvl.h new file mode 100644 index 00000000..7889c789 --- /dev/null +++ b/src/common/model/tvl.h @@ -0,0 +1,74 @@ +/** + * src/class_diagram/model/tvl.h + * + * Copyright (c) 2021-2022 Bartek Kryza + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include +#include + +namespace clanguml::common::model::tvl { + +using value_t = std::optional; + +inline bool is_true(const value_t &v) { return v.has_value() && v.value(); } + +inline bool is_false(const value_t &v) { return v.has_value() && !v.value(); } + +inline bool is_undefined(const value_t &v) { return !v.has_value(); } + +template +inline value_t all_of(InputIterator first, InputIterator last, Predicate pred) +{ + value_t res{}; + + for (InputIterator it = first; it != last; it++) { + value_t m = pred(*it); + if (m.has_value()) { + if (m.value() == true) { + res = true; + } + else { + res = false; + break; + } + } + } + + return res; +} + +template +inline value_t any_of(InputIterator first, InputIterator last, Predicate pred) +{ + value_t res{}; + + for (InputIterator it = first; it != last; it++) { + value_t m = pred(*it); + if (m.has_value()) { + if (m.value() == true) { + res = true; + break; + } + else { + res = false; + } + } + } + + return res; +} +}; \ No newline at end of file