Skip to content

Commit 6893973

Browse files
adamdebrecenifgerlits
authored andcommitted
MINIFICPP-2662 - Remove dependent and exclusive properties
Signed-off-by: Ferenc Gerlits <fgerlits@gmail.com> Closes #2060
1 parent 1b37c3f commit 6893973

File tree

13 files changed

+28
-199
lines changed

13 files changed

+28
-199
lines changed

core-framework/include/core/PropertyDefinitionBuilder.h

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -29,76 +29,64 @@ template<typename... Types>
2929
inline constexpr auto TypeNames = std::array<std::string_view, sizeof...(Types)>{core::className<Types>()...};
3030
}
3131

32-
template<size_t NumAllowedValues = 0, size_t NumDependentProperties = 0, size_t NumExclusiveOfProperties = 0>
32+
template<size_t NumAllowedValues = 0>
3333
struct PropertyDefinitionBuilder {
34-
static constexpr PropertyDefinitionBuilder<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> createProperty(std::string_view name) {
35-
PropertyDefinitionBuilder<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> builder;
34+
static constexpr PropertyDefinitionBuilder<NumAllowedValues> createProperty(std::string_view name) {
35+
PropertyDefinitionBuilder<NumAllowedValues> builder;
3636
builder.property.name = name;
3737
return builder;
3838
}
3939

40-
static constexpr PropertyDefinitionBuilder<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> createProperty(std::string_view name, std::string_view display_name) {
41-
PropertyDefinitionBuilder<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> builder;
40+
static constexpr PropertyDefinitionBuilder<NumAllowedValues> createProperty(std::string_view name, std::string_view display_name) {
41+
PropertyDefinitionBuilder<NumAllowedValues> builder;
4242
builder.property.name = name;
4343
builder.property.display_name = display_name;
4444
return builder;
4545
}
4646

47-
constexpr PropertyDefinitionBuilder<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> withDescription(std::string_view description) {
47+
constexpr PropertyDefinitionBuilder<NumAllowedValues> withDescription(std::string_view description) {
4848
property.description = description;
4949
return *this;
5050
}
5151

52-
constexpr PropertyDefinitionBuilder<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> isRequired(bool required) {
52+
constexpr PropertyDefinitionBuilder<NumAllowedValues> isRequired(bool required) {
5353
property.is_required = required;
5454
return *this;
5555
}
5656

57-
constexpr PropertyDefinitionBuilder<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> isSensitive(bool sensitive) {
57+
constexpr PropertyDefinitionBuilder<NumAllowedValues> isSensitive(bool sensitive) {
5858
property.is_sensitive = sensitive;
5959
return *this;
6060
}
6161

62-
constexpr PropertyDefinitionBuilder<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> supportsExpressionLanguage(bool supports_expression_language) {
62+
constexpr PropertyDefinitionBuilder<NumAllowedValues> supportsExpressionLanguage(bool supports_expression_language) {
6363
property.supports_expression_language = supports_expression_language;
6464
return *this;
6565
}
6666

67-
constexpr PropertyDefinitionBuilder<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> withDefaultValue(std::string_view default_value) {
67+
constexpr PropertyDefinitionBuilder<NumAllowedValues> withDefaultValue(std::string_view default_value) {
6868
property.default_value = std::optional<std::string_view>{default_value}; // workaround for gcc 11.1; on gcc 11.3 and later, `property.default_value = default_value` works, too
6969
return *this;
7070
}
7171

72-
constexpr PropertyDefinitionBuilder<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> withAllowedValues(
72+
constexpr PropertyDefinitionBuilder<NumAllowedValues> withAllowedValues(
7373
std::array<std::string_view, NumAllowedValues> allowed_values) {
7474
property.allowed_values = allowed_values;
7575
return *this;
7676
}
7777

7878
template<typename... AllowedTypes>
79-
constexpr PropertyDefinitionBuilder<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> withAllowedTypes() {
79+
constexpr PropertyDefinitionBuilder<NumAllowedValues> withAllowedTypes() {
8080
property.allowed_types = {detail::TypeNames<AllowedTypes...>};
8181
return *this;
8282
}
8383

84-
constexpr PropertyDefinitionBuilder<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> withDependentProperties(
85-
std::array<std::string_view, NumDependentProperties> dependent_properties) {
86-
property.dependent_properties = dependent_properties;
87-
return *this;
88-
}
89-
90-
constexpr PropertyDefinitionBuilder<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> withExclusiveOfProperties(
91-
std::array<std::pair<std::string_view, std::string_view>, NumExclusiveOfProperties> exclusive_of_properties) {
92-
property.exclusive_of_properties = exclusive_of_properties;
93-
return *this;
94-
}
95-
96-
constexpr PropertyDefinitionBuilder<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> withValidator(const PropertyValidator& property_validator) {
84+
constexpr PropertyDefinitionBuilder<NumAllowedValues> withValidator(const PropertyValidator& property_validator) {
9785
property.validator = gsl::make_not_null(&property_validator);
9886
return *this;
9987
}
10088

101-
constexpr PropertyDefinition<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> build() {
89+
constexpr PropertyDefinition<NumAllowedValues> build() {
10290
if (property.name.size() == 0) {
10391
throw std::logic_error("A Property must have a name");
10492
}
@@ -113,16 +101,14 @@ struct PropertyDefinitionBuilder {
113101
return property;
114102
}
115103

116-
PropertyDefinition<NumAllowedValues, NumDependentProperties, NumExclusiveOfProperties> property{
104+
PropertyDefinition<NumAllowedValues> property{
117105
.name = {},
118106
.display_name = {},
119107
.description = {},
120108
.is_required = false,
121109
.is_sensitive = false,
122110
.allowed_values = {},
123111
.allowed_types = {},
124-
.dependent_properties = {},
125-
.exclusive_of_properties = {},
126112
.default_value = {},
127113
.validator = gsl::make_not_null(&StandardPropertyValidators::ALWAYS_VALID_VALIDATOR),
128114
.supports_expression_language = false,

core-framework/src/core/Property.cpp

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -68,22 +68,10 @@ bool Property::operator<(const Property& right) const {
6868
return name_ < right.name_;
6969
}
7070

71-
std::vector<std::string> Property::getDependentProperties() const {
72-
return dependent_properties_;
73-
}
74-
75-
std::vector<std::pair<std::string, std::string>> Property::getExclusiveOfProperties() const {
76-
return exclusive_of_properties_;
77-
}
78-
7971
namespace {
8072
inline std::vector<std::string> createStrings(std::span<const std::string_view> string_views) {
8173
return ranges::views::transform(string_views, [](const auto& string_view) { return std::string{string_view}; }) | ranges::to<std::vector>;
8274
}
83-
84-
inline std::vector<std::pair<std::string, std::string>> createStrings(std::span<const std::pair<std::string_view, std::string_view>> pairs_of_string_views) {
85-
return ranges::views::transform(pairs_of_string_views, [](const auto& pair_of_string_views) { return std::pair<std::string, std::string>(pair_of_string_views); }) | ranges::to<std::vector>;
86-
}
8775
} // namespace
8876

8977
Property::Property(const PropertyReference& compile_time_property)
@@ -92,8 +80,6 @@ Property::Property(const PropertyReference& compile_time_property)
9280
description_(compile_time_property.description),
9381
is_required_(compile_time_property.is_required),
9482
is_sensitive_(compile_time_property.is_sensitive),
95-
dependent_properties_(createStrings(compile_time_property.dependent_properties)),
96-
exclusive_of_properties_(createStrings(compile_time_property.exclusive_of_properties)),
9783
is_collection_(false),
9884
default_value_(compile_time_property.default_value),
9985
allowed_values_(createStrings(compile_time_property.allowed_values)),
@@ -102,13 +88,10 @@ Property::Property(const PropertyReference& compile_time_property)
10288
supports_el_(compile_time_property.supports_expression_language),
10389
is_transient_(false) {}
10490

105-
Property::Property(std::string name, std::string description, const std::string& value, bool is_required, std::vector<std::string> dependent_properties,
106-
std::vector<std::pair<std::string, std::string>> exclusive_of_properties)
91+
Property::Property(std::string name, std::string description, const std::string& value, bool is_required)
10792
: name_(std::move(name)),
10893
description_(std::move(description)),
10994
is_required_(is_required),
110-
dependent_properties_(std::move(dependent_properties)),
111-
exclusive_of_properties_(std::move(exclusive_of_properties)),
11295
is_collection_(false),
11396
default_value_(value),
11497
validator_(&StandardPropertyValidators::ALWAYS_VALID_VALIDATOR),

extensions/smb/PutSmb.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,10 @@ class PutSmb final : public core::ProcessorImpl {
5757
.withDefaultValue(magic_enum::enum_name(FileExistsResolutionStrategy::fail))
5858
.withAllowedValues(magic_enum::enum_names<FileExistsResolutionStrategy>())
5959
.build();
60-
EXTENSIONAPI static constexpr auto CreateMissingDirectories = core::PropertyDefinitionBuilder<0, 0, 1>::createProperty("Create Missing Directories")
60+
EXTENSIONAPI static constexpr auto CreateMissingDirectories = core::PropertyDefinitionBuilder<0>::createProperty("Create Missing Directories")
6161
.withDescription("If true, then missing destination directories will be created. If false, flowfiles are penalized and sent to failure.")
6262
.withDefaultValue("true")
6363
.isRequired(true)
64-
.withDependentProperties({Directory.name})
6564
.build();
6665

6766
EXTENSIONAPI static constexpr auto Properties = std::to_array<core::PropertyReference>({ ConnectionControllerService, Directory, ConflictResolution, CreateMissingDirectories});

extensions/smb/SmbConnectionControllerService.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,10 @@ class SmbConnectionControllerService : public core::controller::ControllerServic
5353
EXTENSIONAPI static constexpr auto Username = core::PropertyDefinitionBuilder<>::createProperty("Username")
5454
.withDescription("The username used for authentication. If no username is set then anonymous authentication is attempted.")
5555
.isRequired(false)
56-
.withDependentProperties({"Password"})
5756
.build();
5857
EXTENSIONAPI static constexpr auto Password = core::PropertyDefinitionBuilder<>::createProperty("Password")
5958
.withDescription("The password used for authentication. Required if Username is set.")
6059
.isRequired(false)
61-
.withDependentProperties({"Username"})
6260
.isSensitive(true)
6361
.build();
6462

extensions/splunk/SplunkHECProcessor.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,9 @@ class SplunkHECProcessor : public core::ProcessorImpl {
5555
.withDescription("Identifier of the used request channel.")
5656
.isRequired(true)
5757
.build();
58-
EXTENSIONAPI static constexpr auto SSLContext = core::PropertyDefinitionBuilder<0, 0, 1>::createProperty("SSL Context Service")
58+
EXTENSIONAPI static constexpr auto SSLContext = core::PropertyDefinitionBuilder<0>::createProperty("SSL Context Service")
5959
.withDescription("The SSL Context Service used to provide client certificate information for TLS/SSL (https) connections.")
6060
.isRequired(false)
61-
.withExclusiveOfProperties({{{"Hostname", "^http:.*$"}}})
6261
.withAllowedTypes<minifi::controllers::SSLContextServiceInterface>()
6362
.build();
6463
EXTENSIONAPI static constexpr auto Properties = std::to_array<core::PropertyReference>({

extensions/standard-processors/processors/InvokeHTTP.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,10 @@ class InvokeHTTP : public core::ProcessorImpl {
172172
EXTENSIONAPI static constexpr auto AttributesToSend = core::PropertyDefinitionBuilder<>::createProperty("Attributes to Send")
173173
.withDescription("Regular expression that defines which attributes to send as HTTP headers in the request. If not defined, no attributes are sent as headers.")
174174
.build();
175-
EXTENSIONAPI static constexpr auto SSLContext = core::PropertyDefinitionBuilder<0, 0, 1>::createProperty("SSL Context Service")
175+
EXTENSIONAPI static constexpr auto SSLContext = core::PropertyDefinitionBuilder<0>::createProperty("SSL Context Service")
176176
.withDescription("The SSL Context Service used to provide client certificate information for TLS/SSL (https) connections.")
177177
.isRequired(false)
178178
.withAllowedTypes<controllers::SSLContextServiceInterface>()
179-
.withExclusiveOfProperties({{{"Remote URL", "^http:.*$"}}})
180179
.build();
181180
EXTENSIONAPI static constexpr auto ProxyHost = core::PropertyDefinitionBuilder<>::createProperty("Proxy Host")
182181
.withDescription("The fully qualified hostname or IP address of the proxy server")

extensions/standard-processors/processors/PutFile.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,11 @@ class PutFile : public core::ProcessorImpl {
6969
.withDefaultValue(magic_enum::enum_name(FileExistsResolutionStrategy::fail))
7070
.withAllowedValues(magic_enum::enum_names<FileExistsResolutionStrategy>())
7171
.build();
72-
EXTENSIONAPI static constexpr auto CreateDirs = core::PropertyDefinitionBuilder<0, 1>::createProperty("Create Missing Directories")
72+
EXTENSIONAPI static constexpr auto CreateDirs = core::PropertyDefinitionBuilder<0>::createProperty("Create Missing Directories")
7373
.withDescription("If true, then missing destination directories will be created. If false, flowfiles are penalized and sent to failure.")
7474
.withDefaultValue("true")
7575
.withValidator(core::StandardPropertyValidators::BOOLEAN_VALIDATOR)
7676
.isRequired(true)
77-
.withDependentProperties({Directory.name})
7877
.build();
7978
EXTENSIONAPI static constexpr auto MaxDestFiles = core::PropertyDefinitionBuilder<>::createProperty("Maximum File Count")
8079
.withDescription("Specifies the maximum number of files that can exist in the output directory")

extensions/standard-processors/tests/unit/ManifestTests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ TEST_CASE("Test Valid Regex", "[validRegex]") {
7474
const auto &prop_descriptors = processor_with_properties.children[0];
7575
REQUIRE_FALSE(prop_descriptors.children.empty());
7676
const auto &prop_0 = prop_descriptors.children[0];
77-
REQUIRE(prop_0.children.size() >= 7);
77+
REQUIRE(prop_0.children.size() >= 6);
7878
CHECK("required" == prop_0.children[3].name);
7979
CHECK("sensitive" == prop_0.children[4].name);
8080
CHECK("expressionLanguageScope" == prop_0.children[5].name);
@@ -138,7 +138,7 @@ TEST_CASE("Test Dependent", "[dependent]") {
138138
const auto &prop_descriptors = proc_0.children[0];
139139
REQUIRE(prop_descriptors.children.size() >= 3);
140140
const auto &prop_0 = prop_descriptors.children[1];
141-
REQUIRE(prop_0.children.size() >= 7);
141+
REQUIRE(prop_0.children.size() >= 6);
142142
CHECK("required" == prop_0.children[3].name);
143143
CHECK("sensitive" == prop_0.children[4].name);
144144
CHECK("expressionLanguageScope" == prop_0.children[5].name);

extensions/standard-processors/tests/unit/YamlConfigurationTests.cpp

Lines changed: 0 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -594,76 +594,6 @@ class DummyComponent : public core::ConfigurableComponentImpl, public core::Core
594594
}
595595
};
596596

597-
TEST_CASE("Test Dependent Property", "[YamlConfigurationDependentProperty]") {
598-
ConfigurationTestController test_controller;
599-
600-
core::YamlConfiguration yamlConfig(test_controller.getContext());
601-
const auto component = std::make_shared<DummyComponent>();
602-
component->setSupportedProperties(std::to_array<core::PropertyReference>({
603-
core::PropertyDefinitionBuilder<>::createProperty("Prop A").withDescription("Prop A desc").withDefaultValue("val A").isRequired(true).build(),
604-
core::PropertyDefinitionBuilder<0, 1>::createProperty("Prop B").withDescription("Prop B desc").withDefaultValue("val B").isRequired(true).withDependentProperties({ "Prop A" }).build()
605-
}));
606-
yamlConfig.validateComponentProperties(*component, "component A", "section A");
607-
REQUIRE(true); // Expected to get here w/o any exceptions
608-
}
609-
610-
TEST_CASE("Test Dependent Property 2", "[YamlConfigurationDependentProperty2]") {
611-
ConfigurationTestController test_controller;
612-
613-
core::YamlConfiguration yamlConfig(test_controller.getContext());
614-
const auto component = std::make_shared<DummyComponent>();
615-
component->setSupportedProperties(std::to_array<core::PropertyReference>({
616-
core::PropertyDefinitionBuilder<>::createProperty("Prop A").withDescription("Prop A desc").isRequired(false).build(),
617-
core::PropertyDefinitionBuilder<0, 1>::createProperty("Prop B").withDescription("Prop B desc").withDefaultValue("val B").isRequired(true).withDependentProperties({ "Prop A" }).build()
618-
}));
619-
bool config_failed = false;
620-
try {
621-
yamlConfig.validateComponentProperties(*component, "component A", "section A");
622-
} catch (const std::exception &e) {
623-
config_failed = true;
624-
REQUIRE("Unable to parse configuration file for component named 'component A' because property "
625-
"'Prop B' depends on property 'Prop A' which is not set "
626-
"[in 'section A' section of configuration file]" == std::string(e.what()));
627-
}
628-
REQUIRE(config_failed);
629-
}
630-
631-
TEST_CASE("Test Exclusive Property", "[YamlConfigurationExclusiveOfProperty]") {
632-
ConfigurationTestController test_controller;
633-
634-
core::YamlConfiguration yamlConfig(test_controller.getContext());
635-
const auto component = std::make_shared<DummyComponent>();
636-
component->setSupportedProperties(std::to_array<core::PropertyReference>({
637-
core::PropertyDefinitionBuilder<>::createProperty("Prop A").withDescription("Prop A desc").withDefaultValue("val A").isRequired(true).build(),
638-
core::PropertyDefinitionBuilder<0, 0, 1>::createProperty("Prop B").withDescription("Prop B desc").withDefaultValue("val B").isRequired(true)
639-
.withExclusiveOfProperties({{ { "Prop A", "^abcd.*$" } }}).build()
640-
}));
641-
yamlConfig.validateComponentProperties(*component, "component A", "section A");
642-
REQUIRE(true); // Expected to get here w/o any exceptions
643-
}
644-
645-
TEST_CASE("Test Exclusive Property 2", "[YamlConfigurationExclusiveOfProperty2]") {
646-
ConfigurationTestController test_controller;
647-
648-
core::YamlConfiguration yamlConfig(test_controller.getContext());
649-
const auto component = std::make_shared<DummyComponent>();
650-
component->setSupportedProperties(std::to_array<core::PropertyReference>({
651-
core::PropertyDefinitionBuilder<>::createProperty("Prop A").withDescription("Prop A desc").withDefaultValue("val A").isRequired(true).build(),
652-
core::PropertyDefinitionBuilder<0, 0, 1>::createProperty("Prop B").withDescription("Prop B desc").withDefaultValue("val B").isRequired(true)
653-
.withExclusiveOfProperties({{ { "Prop A", "^val.*$" } }}).build()
654-
}));
655-
bool config_failed = false;
656-
try {
657-
yamlConfig.validateComponentProperties(*component, "component A", "section A");
658-
} catch (const std::exception &e) {
659-
config_failed = true;
660-
REQUIRE("Unable to parse configuration file for component named 'component A' because "
661-
"property 'Prop B' must not be set when the value of property 'Prop A' matches '^val.*$' "
662-
"[in 'section A' section of configuration file]" == std::string(e.what()));
663-
}
664-
REQUIRE(config_failed);
665-
}
666-
667597
TEST_CASE("Test YAML Config With Funnel", "[YamlConfiguration]") {
668598
ConfigurationTestController test_controller;
669599

libminifi/src/core/flow/StructuredConfiguration.cpp

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,42 +1055,6 @@ void StructuredConfiguration::validateComponentProperties(ConfigurableComponent&
10551055
}
10561056
}
10571057
}
1058-
1059-
// Validate dependent properties
1060-
for (const auto & [property_name, property] : component_properties) {
1061-
const auto &dep_props = property.getDependentProperties();
1062-
1063-
const auto property_value = property.getValue();
1064-
if (!property_value) {
1065-
continue;
1066-
}
1067-
1068-
for (const auto &dep_prop_key : dep_props) {
1069-
if (auto dep_prop_value = component_properties.at(dep_prop_key).getValue(); !dep_prop_value) {
1070-
std::string reason = utils::string::join_pack("property '", property.getName(),
1071-
"' depends on property '", dep_prop_key, "' which is not set");
1072-
raiseComponentError(component_name, section, reason);
1073-
}
1074-
}
1075-
}
1076-
1077-
// Validate mutually-exclusive properties
1078-
for (const auto& [prop_name, prop] : component_properties) {
1079-
const auto& excl_props = prop.getExclusiveOfProperties();
1080-
1081-
if (!prop.getValue()) {
1082-
continue;
1083-
}
1084-
1085-
for (const auto &[excl_prop_key, excl_prop_regex] : excl_props) {
1086-
utils::Regex excl_expr(excl_prop_regex);
1087-
if (utils::regexMatch(component_properties.at(excl_prop_key).getValue().value_or(""), excl_expr)) {
1088-
std::string reason = utils::string::join_pack("property '", prop.getName(),
1089-
"' must not be set when the value of property '", excl_prop_key, "' matches '", excl_prop_regex, "'");
1090-
raiseComponentError(component_name, section, reason);
1091-
}
1092-
}
1093-
}
10941058
}
10951059

10961060
void StructuredConfiguration::raiseComponentError(const std::string &component_name, const std::string &section, const std::string &reason) const {

0 commit comments

Comments
 (0)