libminifi/include/core/ConfigurableComponent.h (100 lines of code) (raw):

/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 <string> #include <vector> #include "Core.h" #include <mutex> #include <iostream> #include <map> #include <memory> #include "logging/Logger.h" #include "Property.h" #include "PropertyDefinition.h" #include "utils/gsl.h" namespace org::apache::nifi::minifi::core { /** * Represents a configurable component * Purpose: Extracts configuration items for all components and localized them */ class ConfigurableComponent { public: ConfigurableComponent(); ConfigurableComponent(const ConfigurableComponent &other) = delete; ConfigurableComponent(ConfigurableComponent &&other) = delete; ConfigurableComponent& operator=(const ConfigurableComponent &other) = delete; ConfigurableComponent& operator=(ConfigurableComponent &&other) = delete; /** * Get property using the provided name. * @param name property name. * @param value value passed in by reference * @return result of getting property. */ template<typename T> bool getProperty(const std::string& name, T &value) const; template<typename T> bool getProperty(const core::PropertyReference& property, T& value) const { return getProperty(std::string{property.name}, value); } template<typename T = std::string> requires(std::is_default_constructible_v<T>) std::optional<T> getProperty(const std::string& property_name) const { T value; try { if (!getProperty(property_name, value)) return std::nullopt; } catch (const utils::internal::ValueException&) { return std::nullopt; } return value; } template<typename T = std::string> requires(std::is_default_constructible_v<T>) std::optional<T> getProperty(const core::PropertyReference& property) const { return getProperty<T>(std::string(property.name)); } /** * Provides a reference for the property. */ bool getProperty(const std::string &name, Property &prop) const; /** * Sets the property using the provided name * @param property name * @param value property value. * @return result of setting property. */ bool setProperty(const std::string& name, const std::string& value); /** * Updates the Property from the key (name), adding value * to the collection of values within the Property. */ bool updateProperty(const std::string &name, const std::string &value); bool updateProperty(const PropertyReference& property, std::string_view value); /** * Sets the property using the provided name * @param property name * @param value property value. * @return whether property was set or not */ bool setProperty(const Property& prop, const std::string& value); bool setProperty(const PropertyReference& property, std::string_view value); /** * Sets the property using the provided name * @param property name * @param value property value. * @return whether property was set or not */ bool setProperty(const Property& prop, PropertyValue &value); void setSupportedProperties(std::span<const core::PropertyReference> properties); /** * Gets whether or not this processor supports dynamic properties. * * @return true if this component supports dynamic properties (default is false) */ virtual bool supportsDynamicProperties() const = 0; /** * Gets whether or not this processor supports dynamic relationships. * * @return true if this component supports dynamic relationships (default is false) */ virtual bool supportsDynamicRelationships() const = 0; /** * Gets the value of a dynamic property (if it was set). * * @param name * @param value * @return */ bool getDynamicProperty(const std::string& name, std::string &value) const; /** * Sets the value of a new dynamic property. * * @param name * @param value * @return */ bool setDynamicProperty(const std::string& name, const std::string& value); /** * Updates the value of an existing dynamic property. * * @param name * @param value * @return */ bool updateDynamicProperty(const std::string &name, const std::string &value); /** * Invoked anytime a static property is modified */ virtual void onPropertyModified(const Property& /*old_property*/, const Property& /*new_property*/) { } /** * Invoked anytime a dynamic property is modified. */ virtual void onDynamicPropertyModified(const Property& /*old_property*/, const Property& /*new_property*/) { } /** * Provides all dynamic property keys that have been set. * * @return vector of property keys */ std::vector<std::string> getDynamicPropertyKeys() const; /** * Returns a vector all properties * * @return map of property keys to Property instances. */ std::map<std::string, Property> getProperties() const; /** * @return if property exists and is explicitly set, not just falling back to default value */ bool isPropertyExplicitlySet(const Property&) const; bool isPropertyExplicitlySet(const PropertyReference&) const; virtual ~ConfigurableComponent(); virtual void initialize() { } protected: void setAcceptAllProperties() { accept_all_properties_ = true; } /** * Returns true if the instance can be edited. * @return true/false */ virtual bool canEdit() = 0; mutable std::mutex configuration_mutex_; bool accept_all_properties_; // Supported properties std::map<std::string, Property> properties_; // Dynamic properties std::map<std::string, Property> dynamic_properties_; private: std::shared_ptr<logging::Logger> logger_; bool createDynamicProperty(const std::string &name, const std::string &value); }; template<typename T> bool ConfigurableComponent::getProperty(const std::string& name, T &value) const { std::lock_guard<std::mutex> lock(configuration_mutex_); const auto property_name_and_object = properties_.find(name); if (property_name_and_object != properties_.end()) { const Property& property = property_name_and_object->second; if (property.getValue().getValue() == nullptr) { // empty value if (property.getRequired()) { logger_->log_error("Component %s required property %s is empty", name, property.getName()); throw utils::internal::RequiredPropertyMissingException("Required property is empty: " + property.getName()); } logger_->log_debug("Component %s property name %s, empty value", name, property.getName()); return false; } logger_->log_debug("Component %s property name %s value %s", name, property.getName(), property.getValue().to_string()); if constexpr (std::is_base_of<TransformableValue, T>::value) { value = T(property.getValue().operator std::string()); } else { value = static_cast<T>(property.getValue()); // cast throws if the value is invalid } return true; } else { logger_->log_warn("Could not find property %s", name); return false; } } } // namespace org::apache::nifi::minifi::core