Refactored filter diagrams to three value logic

This commit is contained in:
Bartek Kryza
2022-03-31 23:11:58 +02:00
parent a42598357b
commit 18b0624f7a
3 changed files with 116 additions and 90 deletions

View File

@@ -25,25 +25,25 @@ filter_visitor::filter_visitor(filter_t type)
{
}
std::optional<bool> filter_visitor::match(
tvl::value_t filter_visitor::match(
const diagram &d, const common::model::element &e) const
{
return {};
}
std::optional<bool> filter_visitor::match(
tvl::value_t filter_visitor::match(
const diagram &d, const common::model::relationship_t &r) const
{
return {};
}
std::optional<bool> filter_visitor::match(
tvl::value_t filter_visitor::match(
const diagram &d, const common::model::access_t &a) const
{
return {};
}
std::optional<bool> 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<bool> anyof_filter::match(
tvl::value_t anyof_filter::match(
const diagram &d, const common::model::element &e) const
{
std::optional<bool> 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<bool> 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<bool> 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<const package *>(&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<bool> 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<std::string> elements)
{
}
std::optional<bool> 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<std::string> roots)
{
}
std::optional<bool> 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<bool> 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_t> access)
{
}
std::optional<bool> 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<std::string> context)
{
}
std::optional<bool> 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<bool> 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<const class_diagram::model::diagram &>(d).get_class(

View File

@@ -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<bool> match(
virtual tvl::value_t match(
const diagram &d, const common::model::element &e) const;
virtual std::optional<bool> match(
virtual tvl::value_t match(
const diagram &d, const common::model::relationship_t &r) const;
virtual std::optional<bool> match(
virtual tvl::value_t match(
const diagram &d, const common::model::access_t &a) const;
virtual std::optional<bool> 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<std::unique_ptr<filter_visitor>> filters);
std::optional<bool> 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<namespace_> namespaces);
std::optional<bool> match(
const diagram &d, const namespace_ &ns) const override;
tvl::value_t match(const diagram &d, const namespace_ &ns) const override;
std::optional<bool> match(
const diagram &d, const element &e) const override;
tvl::value_t match(const diagram &d, const element &e) const override;
private:
std::vector<namespace_> namespaces_;
@@ -82,8 +81,7 @@ private:
struct element_filter : public filter_visitor {
element_filter(filter_t type, std::vector<std::string> elements);
std::optional<bool> match(
const diagram &d, const element &e) const override;
tvl::value_t match(const diagram &d, const element &e) const override;
private:
std::vector<std::string> elements_;
@@ -92,8 +90,7 @@ private:
struct subclass_filter : public filter_visitor {
subclass_filter(filter_t type, std::vector<std::string> roots);
std::optional<bool> match(
const diagram &d, const element &e) const override;
tvl::value_t match(const diagram &d, const element &e) const override;
private:
std::vector<std::string> roots_;
@@ -103,7 +100,7 @@ struct relationship_filter : public filter_visitor {
relationship_filter(
filter_t type, std::vector<relationship_t> relationships);
std::optional<bool> 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_t> access);
std::optional<bool> 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_t> access_;
@@ -123,8 +119,7 @@ private:
struct context_filter : public filter_visitor {
context_filter(filter_t type, std::vector<std::string> context);
std::optional<bool> match(
const diagram &d, const element &r) const override;
tvl::value_t match(const diagram &d, const element &r) const override;
private:
std::vector<std::string> context_;
@@ -142,25 +137,16 @@ public:
template <typename T> 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;

74
src/common/model/tvl.h Normal file
View File

@@ -0,0 +1,74 @@
/**
* src/class_diagram/model/tvl.h
*
* Copyright (c) 2021-2022 Bartek Kryza <bkryza@gmail.com>
*
* 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 <optional>
#include <string>
namespace clanguml::common::model::tvl {
using value_t = std::optional<bool>;
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 <typename InputIterator, typename Predicate>
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 <typename InputIterator, typename Predicate>
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;
}
};