This is an automated email from the ASF dual-hosted git repository.
szaszm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git
The following commit(s) were added to refs/heads/main by this push:
new 0a1e39e MINIFICPP-1288 - Refactor
YamlConfiguration::parsePropertiesNodeYaml
0a1e39e is described below
commit 0a1e39e5bdd3ba592eeff8eb1c8f0def03216f59
Author: Adam Hunyadi <[email protected]>
AuthorDate: Wed Dec 16 15:12:53 2020 +0100
MINIFICPP-1288 - Refactor YamlConfiguration::parsePropertiesNodeYaml
Signed-off-by: Marton Szasz <[email protected]>
This closes #901
---
libminifi/include/core/yaml/YamlConfiguration.h | 5 +
libminifi/src/core/yaml/YamlConfiguration.cpp | 204 +++++++++++++-----------
2 files changed, 115 insertions(+), 94 deletions(-)
diff --git a/libminifi/include/core/yaml/YamlConfiguration.h
b/libminifi/include/core/yaml/YamlConfiguration.h
index 4ff9a41..83aa204 100644
--- a/libminifi/include/core/yaml/YamlConfiguration.h
+++ b/libminifi/include/core/yaml/YamlConfiguration.h
@@ -332,6 +332,11 @@ class YamlConfiguration : public FlowConfiguration {
std::shared_ptr<io::StreamFactory> stream_factory_;
private:
+ PropertyValue getValidatedProcessorPropertyForDefaultTypeInfo(const
core::Property& propertyFromProcessor, const YAML::Node& propertyValueNode);
+ void parsePropertyValueSequence(const std::string& propertyName, const
YAML::Node& propertyValueNode, std::shared_ptr<core::ConfigurableComponent>
processor, const std::string &yaml_section);
+ void parseSingleProperty(const std::string& propertyName, const YAML::Node&
propertyValueNode, std::shared_ptr<core::ConfigurableComponent> processor);
+ void parsePropertyNodeElement(const std::string& propertyName, const
YAML::Node& propertyValueNode, std::shared_ptr<core::ConfigurableComponent>
processor, const std::string &yaml_section);
+
std::shared_ptr<logging::Logger> logger_;
static std::shared_ptr<utils::IdGenerator> id_generator_;
diff --git a/libminifi/src/core/yaml/YamlConfiguration.cpp
b/libminifi/src/core/yaml/YamlConfiguration.cpp
index 3d1cb9f..2f33f0b 100644
--- a/libminifi/src/core/yaml/YamlConfiguration.cpp
+++ b/libminifi/src/core/yaml/YamlConfiguration.cpp
@@ -770,106 +770,122 @@ void YamlConfiguration::parsePortYaml(YAML::Node
*portNode, core::ProcessGroup *
}
}
-void YamlConfiguration::parsePropertiesNodeYaml(YAML::Node *propertiesNode,
std::shared_ptr<core::ConfigurableComponent> processor, const std::string
&component_name,
- const std::string
&yaml_section) {
- // Treat generically as a YAML node so we can perform inspection on entries
to ensure they are populated
- logger_->log_trace("Entered %s", component_name);
- for (YAML::const_iterator propsIter = propertiesNode->begin(); propsIter !=
propertiesNode->end(); ++propsIter) {
- std::string propertyName = propsIter->first.as<std::string>();
- YAML::Node propertyValueNode = propsIter->second;
- logger_->log_trace("Encountered %s", propertyName);
- if (!propertyValueNode.IsNull() && propertyValueNode.IsDefined()) {
- if (propertyValueNode.IsSequence()) {
- for (auto iter : propertyValueNode) {
- if (iter.IsDefined()) {
- YAML::Node nodeVal = iter.as<YAML::Node>();
- YAML::Node propertiesNode = nodeVal["value"];
- // must insert the sequence in differently.
- std::string rawValueString = propertiesNode.as<std::string>();
- logger_->log_debug("Found %s=%s", propertyName, rawValueString);
- if (!processor->updateProperty(propertyName, rawValueString)) {
- std::shared_ptr<core::Connectable> proc =
std::dynamic_pointer_cast<core::Connectable>(processor);
- if (proc != 0) {
- logger_->log_warn("Received property %s with value %s but is
not one of the properties for %s. "
- "Attempting to add as dynamic property.",
- propertyName, rawValueString,
proc->getName());
- if (!processor->setDynamicProperty(propertyName,
rawValueString)) {
- logger_->log_warn("Unable to set the dynamic property %s
with value %s", propertyName.c_str(), rawValueString.c_str());
- } else {
- logger_->log_warn("Dynamic property %s with value %s set",
propertyName.c_str(), rawValueString.c_str());
- }
- }
- }
- }
- }
- } else {
- core::Property myProp(propertyName, "", "");
- processor->getProperty(propertyName, myProp);
- PropertyValue defaultValue;
- defaultValue = myProp.getDefaultValue();
- auto defaultType = defaultValue.getTypeInfo();
- PropertyValue coercedValue = defaultValue;
-
- // coerce the types. upon failure we will either exit or use the
default value.
- // we do this here ( in addition to the PropertyValue class ) to get
the earliest
- // possible YAML failure.
- try {
- if (defaultType == typeid(std::string)) {
- auto typedValue = propertyValueNode.as<std::string>();
- coercedValue = typedValue;
- } else if (defaultType == typeid(int64_t)) {
- auto typedValue = propertyValueNode.as<int64_t>();
- coercedValue = typedValue;
- } else if (defaultType == typeid(uint64_t)) {
- try {
- auto typedValue = propertyValueNode.as<uint64_t>();
- coercedValue = typedValue;
- } catch (...) {
- auto typedValue = propertyValueNode.as<std::string>();
- coercedValue = typedValue;
- }
- } else if (defaultType == typeid(int)) {
- auto typedValue = propertyValueNode.as<int>();
- coercedValue = typedValue;
- } else if (defaultType == typeid(bool)) {
- auto typedValue = propertyValueNode.as<bool>();
- coercedValue = typedValue;
- } else {
- auto typedValue = propertyValueNode.as<std::string>();
- coercedValue = typedValue;
- }
- } catch (...) {
- std::string eof;
- bool exit_on_failure = false;
- if
(configuration_->get(Configure::nifi_flow_configuration_file_exit_failure,
eof)) {
- utils::StringUtils::StringToBool(eof, exit_on_failure);
- }
- logger_->log_error("Invalid conversion for field %s. Value %s",
myProp.getName(), propertyValueNode.as<std::string>());
- if (exit_on_failure) {
- std::cerr << "Invalid conversion for " << myProp.getName() << " to
" << defaultType.name() << std::endl;
+void YamlConfiguration::parsePropertyValueSequence(const std::string&
propertyName, const YAML::Node& propertyValueNode,
std::shared_ptr<core::ConfigurableComponent> processor,
+ const std::string &yaml_section) {
+ for (auto iter : propertyValueNode) {
+ if (iter.IsDefined()) {
+ YAML::Node nodeVal = iter.as<YAML::Node>();
+ YAML::Node propertiesNode = nodeVal["value"];
+ // must insert the sequence in differently.
+ std::string rawValueString = propertiesNode.as<std::string>();
+ logger_->log_debug("Found %s=%s", propertyName, rawValueString);
+ if (!processor->updateProperty(propertyName, rawValueString)) {
+ std::shared_ptr<core::Connectable> proc =
std::dynamic_pointer_cast<core::Connectable>(processor);
+ if (proc) {
+ logger_->log_warn("Received property %s with value %s but is not one
of the properties for %s. Attempting to add as dynamic property.",
propertyName, rawValueString, proc->getName());
+ if (!processor->setDynamicProperty(propertyName, rawValueString)) {
+ logger_->log_warn("Unable to set the dynamic property %s with
value %s", propertyName, rawValueString);
} else {
- coercedValue = defaultValue;
- }
- }
- std::string rawValueString = propertyValueNode.as<std::string>();
- if (!processor->setProperty(myProp, coercedValue)) {
- std::shared_ptr<core::Connectable> proc =
std::dynamic_pointer_cast<core::Connectable>(processor);
- if (proc != 0) {
- logger_->log_warn("Received property %s with value %s but is not
one of the properties for %s. "
- "Attempting to add as dynamic property.",
- propertyName, rawValueString, proc->getName());
- if (!processor->setDynamicProperty(propertyName, rawValueString)) {
- logger_->log_warn("Unable to set the dynamic property %s with
value %s", propertyName.c_str(), rawValueString.c_str());
- } else {
- logger_->log_warn("Dynamic property %s with value %s set",
propertyName.c_str(), rawValueString.c_str());
- }
+ logger_->log_warn("Dynamic property %s with value %s set",
propertyName, rawValueString);
}
- } else {
- logger_->log_debug("Property %s with value %s set",
propertyName.c_str(), rawValueString.c_str());
}
}
}
}
+}
+
+namespace {
+ void handleExceptionOnValidatedProcessorPropertyRead(const core::Property&
propertyFromProcessor, const YAML::Node& propertyValueNode,
+ const std::shared_ptr<Configure>& config, const std::type_index&
defaultType, std::shared_ptr<logging::Logger>& logger) {
+ std::string eof;
+ bool exit_on_failure = false;
+ if (config->get(Configure::nifi_flow_configuration_file_exit_failure,
eof)) {
+ utils::StringUtils::StringToBool(eof, exit_on_failure);
+ }
+ logger->log_error("Invalid conversion for field %s. Value %s",
propertyFromProcessor.getName(), propertyValueNode.as<std::string>());
+ if (exit_on_failure) {
+ // We do not exit here even if exit_on_failure is set. Maybe we should?
+ logger->log_error("Invalid conversion for %s to %s.",
propertyFromProcessor.getName(), defaultType.name());
+ }
+ }
+} // namespace
+
+// coerce the types. upon failure we will either exit or use the default value.
+// we do this here ( in addition to the PropertyValue class ) to get the
earliest
+// possible YAML failure.
+PropertyValue
YamlConfiguration::getValidatedProcessorPropertyForDefaultTypeInfo(const
core::Property& propertyFromProcessor, const YAML::Node& propertyValueNode) {
+ PropertyValue defaultValue;
+ defaultValue = propertyFromProcessor.getDefaultValue();
+ const std::type_index defaultType = defaultValue.getTypeInfo();
+ try {
+ PropertyValue coercedValue = defaultValue;
+ if (defaultType == typeid(int64_t)) {
+ coercedValue = propertyValueNode.as<int64_t>();
+ } else if (defaultType == typeid(uint64_t)) {
+ try {
+ coercedValue = propertyValueNode.as<uint64_t>();
+ } catch (...) {
+ coercedValue = propertyValueNode.as<std::string>();
+ }
+ } else if (defaultType == typeid(int)) {
+ coercedValue = propertyValueNode.as<int>();
+ } else if (defaultType == typeid(bool)) {
+ coercedValue = propertyValueNode.as<bool>();
+ } else {
+ coercedValue = propertyValueNode.as<std::string>();
+ }
+ return coercedValue;
+ } catch (const std::exception& e) {
+ logger_->log_error("Fetching property failed with an exception of %s",
e.what());
+ handleExceptionOnValidatedProcessorPropertyRead(propertyFromProcessor,
propertyValueNode, configuration_, defaultType, logger_);
+ } catch (...) {
+ handleExceptionOnValidatedProcessorPropertyRead(propertyFromProcessor,
propertyValueNode, configuration_, defaultType, logger_);
+ }
+ return defaultValue;
+}
+
+void YamlConfiguration::parseSingleProperty(const std::string& propertyName,
const YAML::Node& propertyValueNode,
std::shared_ptr<core::ConfigurableComponent> processor) {
+ core::Property myProp(propertyName, "", "");
+ processor->getProperty(propertyName, myProp);
+ const PropertyValue coercedValue =
getValidatedProcessorPropertyForDefaultTypeInfo(myProp, propertyValueNode);
+ const std::string rawValueString = propertyValueNode.as<std::string>();
+ if (!processor->setProperty(myProp, coercedValue)) {
+ std::shared_ptr<core::Connectable> proc =
std::dynamic_pointer_cast<core::Connectable>(processor);
+ if (proc) {
+ logger_->log_warn("Received property %s with value %s but is not one of
the properties for %s. Attempting to add as dynamic property.", propertyName,
rawValueString, proc->getName());
+ if (!processor->setDynamicProperty(propertyName, rawValueString)) {
+ logger_->log_warn("Unable to set the dynamic property %s with value
%s", propertyName, rawValueString);
+ } else {
+ logger_->log_warn("Dynamic property %s with value %s set",
propertyName, rawValueString);
+ }
+ }
+ } else {
+ logger_->log_debug("Property %s with value %s set", propertyName,
rawValueString);
+ }
+}
+
+void YamlConfiguration::parsePropertyNodeElement(const std::string&
propertyName, const YAML::Node& propertyValueNode,
std::shared_ptr<core::ConfigurableComponent> processor,
+ const std::string &yaml_section) {
+ logger_->log_trace("Encountered %s", propertyName);
+ if (propertyValueNode.IsNull() || !propertyValueNode.IsDefined()) {
+ return;
+ }
+ if (propertyValueNode.IsSequence()) {
+ parsePropertyValueSequence(propertyName, propertyValueNode, processor,
yaml_section);
+ } else {
+ parseSingleProperty(propertyName, propertyValueNode, processor);
+ }
+}
+
+void YamlConfiguration::parsePropertiesNodeYaml(YAML::Node *propertiesNode,
std::shared_ptr<core::ConfigurableComponent> processor, const std::string
&component_name,
+ const std::string &yaml_section) {
+ // Treat generically as a YAML node so we can perform inspection on entries
to ensure they are populated
+ logger_->log_trace("Entered %s", component_name);
+ for (const auto propertyElem : *propertiesNode) {
+ const std::string propertyName = propertyElem.first.as<std::string>();
+ const YAML::Node propertyValueNode = propertyElem.second;
+ parsePropertyNodeElement(propertyName, propertyValueNode, processor,
yaml_section);
+ }
validateComponentProperties(processor, component_name, yaml_section);
}