1+ /* *
2+ * @file
3+ * @brief Implementation of FieldMap that applies OutputActions to available fields.
4+ * @author Damir Zainullin <[email protected] > 5+ *
6+ * @copyright Copyright (c) 2025 CESNET, z.s.p.o.
7+ */
8+
9+ #pragma once
10+
11+ #include " outputAction.hpp"
12+
13+ #include < ranges>
14+ #include < stdexcept>
15+ #include < string_view>
16+ #include < unordered_map>
17+ #include < variant>
18+ #include < vector>
19+
20+ #include < fieldDescriptor.hpp>
21+
22+ namespace ipxp {
23+
24+ class FieldMap {
25+ public:
26+ constexpr FieldMap (const std::vector<process::FieldDescriptor>& availableFields) noexcept
27+ {
28+ std::ranges::for_each (availableFields, [&](const process::FieldDescriptor& field) {
29+ m_map[field.getGroup ()][field.getName ()] = &field;
30+ });
31+ }
32+
33+ constexpr std::vector<const process::FieldDescriptor*>
34+ applyActions (const std::vector<OutputAction>& actions) const
35+ {
36+ std::vector<const process::FieldDescriptor*> res;
37+ applyGlobalAction (res, OutputAction::Type::Include);
38+
39+ for (const OutputAction& action : actions) {
40+ if (std::holds_alternative<OutputAction::GlobalAction>(action.action )) {
41+ applyGlobalAction (res, action.type );
42+ } else if (std::holds_alternative<OutputAction::PluginAction>(action.action )) {
43+ applyPluginAction (res, action);
44+ } else if (std::holds_alternative<OutputAction::FieldAction>(action.action )) {
45+ applyFieldAction (res, action);
46+ }
47+ }
48+
49+ std::ranges::sort (res);
50+ res.erase (std::ranges::unique (res).begin (), res.end ());
51+ return res;
52+ }
53+
54+ private:
55+ void applyGlobalAction (
56+ std::vector<const process::FieldDescriptor*>& res,
57+ const OutputAction::Type type) const noexcept
58+ {
59+ if (type == OutputAction::Type::Include) {
60+ const auto allFields = m_map | std::views::values | std::views::join
61+ | std::views::transform ([](const auto & pair) { return pair.second ; })
62+ | std::ranges::to<std::vector>();
63+ res.insert (res.end (), allFields.begin (), allFields.end ());
64+ } else {
65+ res.clear ();
66+ }
67+ }
68+
69+ void applyPluginAction (
70+ std::vector<const process::FieldDescriptor*>& res,
71+ const OutputAction& action) const
72+ {
73+ const OutputAction::PluginAction& pluginAction
74+ = std::get<OutputAction::PluginAction>(action.action );
75+ if (action.type == OutputAction::Type::Include) {
76+ auto pluginIt = m_map.find (pluginAction.pluginName );
77+ if (pluginIt == m_map.end ()) {
78+ throw std::invalid_argument (
79+ " Plugin name '" + pluginAction.pluginName
80+ + " ' not found among available plugins." );
81+ }
82+ const auto pluginFields
83+ = pluginIt->second | std::views::values | std::ranges::to<std::vector>();
84+ res.insert (res.end (), pluginFields.begin (), pluginFields.end ());
85+ } else {
86+ res.erase (
87+ std::remove_if (
88+ res.begin (),
89+ res.end (),
90+ [&](const process::FieldDescriptor* field) {
91+ return field->getGroup () == pluginAction.pluginName ;
92+ }),
93+ res.end ());
94+ }
95+ }
96+
97+ void applyFieldAction (
98+ std::vector<const process::FieldDescriptor*>& res,
99+ const OutputAction& action) const
100+ {
101+ const OutputAction::FieldAction& fieldAction
102+ = std::get<OutputAction::FieldAction>(action.action );
103+ if (action.type == OutputAction::Type::Include) {
104+ auto pluginIt = m_map.find (fieldAction.pluginName );
105+ if (pluginIt == m_map.end ()) {
106+ throw std::invalid_argument (
107+ " Plugin name '" + fieldAction.pluginName
108+ + " ' not found among available plugins." );
109+ }
110+ auto fieldIt = pluginIt->second .find (fieldAction.fieldName );
111+ if (fieldIt == pluginIt->second .end ()) {
112+ throw std::invalid_argument (
113+ " Field name '" + fieldAction.fieldName + " ' not found in plugin '"
114+ + fieldAction.pluginName + " '." );
115+ }
116+ res.push_back (fieldIt->second );
117+ } else {
118+ res.erase (
119+ std::remove_if (
120+ res.begin (),
121+ res.end (),
122+ [&](const process::FieldDescriptor* field) {
123+ return field->getGroup () == fieldAction.pluginName
124+ && field->getName () == fieldAction.fieldName ;
125+ }),
126+ res.end ());
127+ }
128+ }
129+
130+ std::unordered_map<
131+ std::string_view,
132+ std::unordered_map<std::string_view, const process::FieldDescriptor*>>
133+ m_map;
134+ };
135+
136+ } // namespace ipxp
0 commit comments