Skip to content

Commit 53248cf

Browse files
Zainullin DamirZainullin Damir
authored andcommitted
OutputConfigurationParser - Introduce FieldMap class
1 parent 2eeff03 commit 53248cf

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
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

Comments
 (0)