Repository: nifi-minifi-cpp Updated Branches: refs/heads/master 6084f71a9 -> 2ecb997c7
MINIFICPP-598: Add relationship support into manifest MINIFICPP-600: Add default value into property descriptors Project: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/repo Commit: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/commit/7ac309ba Tree: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/tree/7ac309ba Diff: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/diff/7ac309ba Branch: refs/heads/master Commit: 7ac309ba76813e5dbdb1e1857da4c6115a4c2fd1 Parents: 6084f71 Author: Marc Parisi <[email protected]> Authored: Mon Aug 20 12:26:14 2018 -0400 Committer: Marc Parisi <[email protected]> Committed: Tue Aug 21 15:26:41 2018 -0400 ---------------------------------------------------------------------- CMakeLists.txt | 5 +- extensions/http-curl/processors/InvokeHTTP.cpp | 23 ++-- libminifi/include/agent/build_description.h | 26 ++++- libminifi/include/core/ClassLoader.h | 52 ++++++--- libminifi/include/core/ConfigurableComponent.h | 9 ++ libminifi/include/core/Connectable.h | 2 + libminifi/include/core/Property.h | 116 ++++++++++++++++--- libminifi/include/core/Relationship.h | 12 ++ libminifi/include/core/Resource.h | 6 +- libminifi/include/core/state/Value.h | 6 +- .../include/core/state/nodes/AgentInformation.h | 75 +++++++++++- libminifi/include/processors/RouteOnAttribute.h | 5 + libminifi/src/core/Connectable.cpp | 10 +- libminifi/src/core/Property.cpp | 10 ++ .../unit/PropertyValidationAgentInfoTests.cpp | 40 ++++++- 15 files changed, 327 insertions(+), 70 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7ac309ba/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c33509..728042e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -412,11 +412,10 @@ endif() get_property(selected_extensions GLOBAL PROPERTY EXTENSION-OPTIONS) +# Generate the build identifier if one is not provided if (NOT BUILD_IDENTIFIER) - if (NOT BUILD_IDENTIFIER) string(RANDOM LENGTH 24 BUILD_IDENTIFIER) - set(BUILD_IDENTIFIER "${BUILD_IDENTIFIER}" CACHE STRING "Build identifier") - endif() + set(BUILD_IDENTIFIER "${BUILD_IDENTIFIER}" CACHE STRING "Build identifier" FORCE) endif() message("BUILD_IDENTIFIER is ${BUILD_IDENTIFIER}") http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7ac309ba/extensions/http-curl/processors/InvokeHTTP.cpp ---------------------------------------------------------------------- diff --git a/extensions/http-curl/processors/InvokeHTTP.cpp b/extensions/http-curl/processors/InvokeHTTP.cpp index 7ad5aef..9cff5aa 100644 --- a/extensions/http-curl/processors/InvokeHTTP.cpp +++ b/extensions/http-curl/processors/InvokeHTTP.cpp @@ -65,18 +65,15 @@ core::Property InvokeHTTP::FollowRedirects("Follow Redirects", "Follow HTTP redi core::Property InvokeHTTP::AttributesToSend("Attributes to Send", "Regular expression that defines which attributes to send as HTTP" " headers in the request. If not defined, no attributes are sent as headers.", ""); -core::Property InvokeHTTP::SSLContext("SSL Context Service", - "The SSL Context Service used to provide client certificate " - "information for TLS/SSL (https) connections.", - "", - false, - "", - {}, - {{"Remote URL", "^http:.*$"}}); +core::Property InvokeHTTP::SSLContext( + core::PropertyBuilder::createProperty("SSL Context Service")->withDescription("The SSL Context Service used to provide client certificate " + "information for TLS/SSL (https) connections.")->isRequired(false)->withExclusiveProperty("Remote URL", "^http:.*$") + ->asType<minifi::controllers::SSLContextService>()->build()); core::Property InvokeHTTP::ProxyHost("Proxy Host", "The fully qualified hostname or IP address of the proxy server", ""); core::Property InvokeHTTP::ProxyPort("Proxy Port", "The port of the proxy server", ""); core::Property InvokeHTTP::ProxyUser("invokehttp-proxy-user", "Username to set when authenticating against proxy", ""); -core::Property InvokeHTTP::ProxyPassword("invokehttp-proxy-password", "Password to set when authenticating against proxy", ""); +core::Property InvokeHTTP::ProxyPassword( + core::PropertyBuilder::createProperty("invokehttp-proxy-password", "Proxy Password")->withDescription("Password to set when authenticating against proxy")->isRequired(false)->build()); core::Property InvokeHTTP::ContentType("Content-type", "The Content-Type to specify for when content is being transmitted through a PUT, " "POST or PATCH. In the case of an empty value after evaluating an expression language expression, " "Content-Type defaults to", @@ -366,12 +363,8 @@ void InvokeHTTP::onTrigger(const std::shared_ptr<core::ProcessContext> &context, } } -void InvokeHTTP::route(std::shared_ptr<FlowFileRecord> &request, - std::shared_ptr<FlowFileRecord> &response, - const std::shared_ptr<core::ProcessSession> &session, - const std::shared_ptr<core::ProcessContext> &context, - bool isSuccess, - int statusCode) { +void InvokeHTTP::route(std::shared_ptr<FlowFileRecord> &request, std::shared_ptr<FlowFileRecord> &response, const std::shared_ptr<core::ProcessSession> &session, + const std::shared_ptr<core::ProcessContext> &context, bool isSuccess, int statusCode) { // check if we should yield the processor if (!isSuccess && request == nullptr) { context->yield(); http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7ac309ba/libminifi/include/agent/build_description.h ---------------------------------------------------------------------- diff --git a/libminifi/include/agent/build_description.h b/libminifi/include/agent/build_description.h index aa4b9e0..e02911c 100644 --- a/libminifi/include/agent/build_description.h +++ b/libminifi/include/agent/build_description.h @@ -29,17 +29,28 @@ namespace minifi { struct ClassDescription { explicit ClassDescription(std::string name) : class_name_(name), - support_dynamic_(false) { + dynamic_properties_(false), + dynamic_relationships_(false) { } - explicit ClassDescription(std::string name, std::map<std::string, core::Property> props, bool dyn) + explicit ClassDescription(std::string name, std::map<std::string, core::Property> props, bool dyn_prop) : class_name_(name), class_properties_(props), - support_dynamic_(dyn) { + dynamic_properties_(dyn_prop), + dynamic_relationships_(false) { } + explicit ClassDescription(std::string name, std::map<std::string, core::Property> props, std::vector<core::Relationship> class_relationships, bool dyn_prop, bool dyn_rel) + : class_name_(name), + class_properties_(props), + class_relationships_(class_relationships), + dynamic_properties_(dyn_prop), + dynamic_relationships_(dyn_rel) { + } std::string class_name_; std::map<std::string, core::Property> class_properties_; - bool support_dynamic_; + std::vector<core::Relationship> class_relationships_; + bool dynamic_properties_; + bool dynamic_relationships_; }; struct Components { @@ -69,13 +80,16 @@ class BuildDescription { ClassDescription description(clazz); if (nullptr != component) { - bool is_processor = std::dynamic_pointer_cast<core::Processor>(obj) != nullptr; + auto processor = std::dynamic_pointer_cast<core::Processor>(obj) ; + bool is_processor = processor != nullptr; bool is_controller_service = LIKELY(is_processor == true) ? false : std::dynamic_pointer_cast<core::controller::ControllerService>(obj) != nullptr; component->initialize(); description.class_properties_ = component->getProperties(); - description.support_dynamic_ = component->supportsDynamicProperties(); + description.dynamic_properties_ = component->supportsDynamicProperties(); + description.dynamic_relationships_ = component->supportsDynamicRelationships(); if (is_processor) { + description.class_relationships_ = processor->getSupportedRelationships(); class_mappings[group].processors_.emplace_back(description); } else if (is_controller_service) { class_mappings[group].controller_services_.emplace_back(description); http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7ac309ba/libminifi/include/core/ClassLoader.h ---------------------------------------------------------------------- diff --git a/libminifi/include/core/ClassLoader.h b/libminifi/include/core/ClassLoader.h index b1ecaf8..cc8d322 100644 --- a/libminifi/include/core/ClassLoader.h +++ b/libminifi/include/core/ClassLoader.h @@ -43,6 +43,14 @@ namespace core { class ObjectFactory { public: + + ObjectFactory(const std::string &group) + : group_(group) { + } + + ObjectFactory() { + } + /** * Virtual destructor. */ @@ -84,6 +92,10 @@ class ObjectFactory { */ virtual std::string getName() = 0; + virtual std::string getGroupName() const { + return group_; + } + virtual std::string getClassName() = 0; /** * Gets the class name for the object @@ -93,6 +105,10 @@ class ObjectFactory { virtual std::unique_ptr<ObjectFactory> assign(const std::string &class_name) = 0; + private: + + std::string group_; + }; /** @@ -107,6 +123,11 @@ class DefautObjectFactory : public ObjectFactory { DefautObjectFactory() { className = core::getClassName<T>(); } + + DefautObjectFactory(const std::string &group_name) + : ObjectFactory(group_name) { + className = core::getClassName<T>(); + } /** * Virtual destructor. */ @@ -223,21 +244,14 @@ class ClassLoader { std::lock_guard<std::mutex> lock(internal_mutex_); - loaded_factories_.insert(std::make_pair(name, std::move(factory))); - - } - - /** - * Register a class with the give ProcessorFactory - */ - void registerClass(const std::string &group, const std::string &name, std::unique_ptr<ObjectFactory> factory) { - if (loaded_factories_.find(name) != loaded_factories_.end()) { - return; - } + auto canonical_name = factory->getClassName(); - std::lock_guard<std::mutex> lock(internal_mutex_); + auto group_name = factory->getGroupName(); - module_mapping_[group].push_back(factory->getName()); + module_mapping_[group_name].push_back(canonical_name); + if (canonical_name != name) + class_to_group_[canonical_name] = group_name; + class_to_group_[name] = group_name; loaded_factories_.insert(std::make_pair(name, std::move(factory))); } @@ -269,6 +283,16 @@ class ClassLoader { return groups; } + std::string getGroupForClass(const std::string &class_name) { + std::lock_guard<std::mutex> lock(internal_mutex_); + auto factory_entry = class_to_group_.find(class_name); + if (factory_entry != class_to_group_.end()) { + return factory_entry->second; + } else { + return ""; + } + } + /** * Instantiate object based on class_name * @param class_name class to create @@ -311,6 +335,8 @@ class ClassLoader { std::map<std::string, std::unique_ptr<ObjectFactory>> loaded_factories_; + std::map<std::string, std::string> class_to_group_; + std::mutex internal_mutex_; std::vector<void *> dl_handles_; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7ac309ba/libminifi/include/core/ConfigurableComponent.h ---------------------------------------------------------------------- diff --git a/libminifi/include/core/ConfigurableComponent.h b/libminifi/include/core/ConfigurableComponent.h index d69e1c7..53835b4 100644 --- a/libminifi/include/core/ConfigurableComponent.h +++ b/libminifi/include/core/ConfigurableComponent.h @@ -100,6 +100,15 @@ class __attribute__((visibility("default"))) ConfigurableComponent { virtual bool supportsDynamicProperties() = 0; /** + * Gets whether or not this processor supports dynamic relationships. + * + * @return true if this component supports dynamic relationships (default is false) + */ + virtual bool supportsDynamicRelationships() { + return false; + } + + /** * Gets the value of a dynamic property (if it was set). * * @param name http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7ac309ba/libminifi/include/core/Connectable.h ---------------------------------------------------------------------- diff --git a/libminifi/include/core/Connectable.h b/libminifi/include/core/Connectable.h index ec2fd3a..1c1fd45 100644 --- a/libminifi/include/core/Connectable.h +++ b/libminifi/include/core/Connectable.h @@ -49,6 +49,8 @@ class __attribute__((visibility("default"))) Connectable : public CoreComponent // Whether the relationship is supported bool isSupportedRelationship(Relationship relationship); + std::vector<Relationship> getSupportedRelationships() const; + /** * Sets auto terminated relationships * @param relationships http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7ac309ba/libminifi/include/core/Property.h ---------------------------------------------------------------------- diff --git a/libminifi/include/core/Property.h b/libminifi/include/core/Property.h index a59a53d..1b1b587 100644 --- a/libminifi/include/core/Property.h +++ b/libminifi/include/core/Property.h @@ -19,11 +19,13 @@ #define __PROPERTY_H__ #include <algorithm> +#include "core/Core.h" #include <sstream> #include <string> #include <vector> #include <queue> #include <map> +#include <memory> #include <mutex> #include <atomic> #include <functional> @@ -47,18 +49,15 @@ enum TimeUnit { NANOSECOND }; +class PropertyBuilder; + class Property { public: /*! * Create a new property */ - Property(std::string name, - std::string description, - std::string value, - bool is_required, - std::string valid_regex, - std::vector<std::string> dependent_properties, + Property(std::string name, std::string description, std::string value, bool is_required, std::string valid_regex, std::vector<std::string> dependent_properties, std::vector<std::pair<std::string, std::string>> exclusive_of_properties) : name_(std::move(name)), description_(std::move(description)), @@ -85,6 +84,32 @@ class Property { is_collection_(true) { } + Property(Property &&other) + : name_(std::move(other.name_)), + description_(std::move(other.description_)), + is_required_(other.is_required_), + valid_regex_(std::move(other.valid_regex_)), + dependent_properties_(std::move(other.dependent_properties_)), + exclusive_of_properties_(std::move(other.exclusive_of_properties_)), + is_collection_(other.is_collection_), + values_(std::move(other.values_)), + display_name_(std::move(other.display_name_)), + types_(std::move(other.types_)){ + } + + Property(const Property &other) + : name_(other.name_), + description_(other.description_), + is_required_(other.is_required_), + valid_regex_(other.valid_regex_), + dependent_properties_(other.dependent_properties_), + exclusive_of_properties_(other.exclusive_of_properties_), + is_collection_(other.is_collection_), + values_(other.values_), + display_name_(other.display_name_), + types_(other.types_){ + } + Property() : name_(""), description_(""), @@ -95,6 +120,8 @@ class Property { virtual ~Property() = default; std::string getName() const; + std::string getDisplayName() const; + std::vector<std::string> getAllowedTypes() const; std::string getDescription() const; std::string getValue() const; bool getRequired() const; @@ -109,10 +136,10 @@ class Property { */ void addValue(std::string value); const Property &operator=(const Property &other); - // Compare +// Compare bool operator <(const Property & right) const; - // Convert TimeUnit to MilliSecond +// Convert TimeUnit to MilliSecond template<typename T> static bool ConvertTimeUnitToMS(int64_t input, TimeUnit unit, T &out) { if (unit == MILLISECOND) { @@ -146,7 +173,7 @@ class Property { return ConvertTimeUnitToMS<uint64_t>(input, unit, out); } - // Convert TimeUnit to NanoSecond +// Convert TimeUnit to NanoSecond template<typename T> static bool ConvertTimeUnitToNS(int64_t input, TimeUnit unit, T &out) { if (unit == MILLISECOND) { @@ -169,17 +196,17 @@ class Property { } } - // Convert TimeUnit to NanoSecond +// Convert TimeUnit to NanoSecond static bool ConvertTimeUnitToNS(int64_t input, TimeUnit unit, uint64_t &out) { return ConvertTimeUnitToNS<uint64_t>(input, unit, out); } - // Convert TimeUnit to NanoSecond +// Convert TimeUnit to NanoSecond static bool ConvertTimeUnitToNS(int64_t input, TimeUnit unit, int64_t &out) { return ConvertTimeUnitToNS<int64_t>(input, unit, out); } - // Convert String +// Convert String static bool StringToTime(std::string input, uint64_t &output, TimeUnit &timeunit) { if (input.size() == 0) { return false; @@ -233,7 +260,7 @@ class Property { return false; } - // Convert String +// Convert String static bool StringToTime(std::string input, int64_t &output, TimeUnit &timeunit) { if (input.size() == 0) { return false; @@ -287,7 +314,7 @@ class Property { return false; } - // Convert String to Integer +// Convert String to Integer template<typename T> static bool StringToInt(std::string input, T &output) { if (input.size() == 0) { @@ -359,7 +386,7 @@ class Property { return StringToInt<int64_t>(input, output); } - // Convert String to Integer +// Convert String to Integer static bool StringToInt(std::string input, uint64_t &output) { return StringToInt<uint64_t>(input, output); } @@ -368,12 +395,13 @@ class Property { return StringToInt<int32_t>(input, output); } - // Convert String to Integer +// Convert String to Integer static bool StringToInt(std::string input, uint32_t &output) { return StringToInt<uint32_t>(input, output); } protected: + std::string name_; std::string description_; bool is_required_; @@ -382,11 +410,65 @@ class Property { std::vector<std::pair<std::string, std::string>> exclusive_of_properties_; bool is_collection_; std::vector<std::string> values_; - + std::string display_name_; + // types represents the allowable types for this property + // these types should be the canonical name. + std::vector<std::string> types_; private: + friend class PropertyBuilder; }; +class PropertyBuilder : public std::enable_shared_from_this<PropertyBuilder> { + public: + static std::shared_ptr<PropertyBuilder> createProperty(const std::string &name) { + std::shared_ptr<PropertyBuilder> builder = std::unique_ptr<PropertyBuilder>(new PropertyBuilder()); + builder->prop.name_ = name; + return builder; + } + + static std::shared_ptr<PropertyBuilder> createProperty(const std::string &name, const std::string &displayName) { + std::shared_ptr<PropertyBuilder> builder = std::unique_ptr<PropertyBuilder>(new PropertyBuilder()); + builder->prop.name_ = name; + builder->prop.display_name_ = displayName; + return builder; + } + + std::shared_ptr<PropertyBuilder> withDescription(const std::string &description) { + prop.description_ = description; + return shared_from_this(); + } + + std::shared_ptr<PropertyBuilder> isRequired(bool required) { + prop.is_required_ = false; + return shared_from_this(); + } + + std::shared_ptr<PropertyBuilder> withDefaultValue(const std::string &df) { + prop.values_.push_back(std::move(df)); + return shared_from_this(); + } + + template<typename T> + std::shared_ptr<PropertyBuilder> asType() { + prop.types_.push_back(core::getClassName<T>()); + return shared_from_this(); + } + + std::shared_ptr<PropertyBuilder> withExclusiveProperty(const std::string &property, const std::string regex) { + prop.exclusive_of_properties_.push_back( { property, regex }); + return shared_from_this(); + } + + Property &&build() { + return std::move(prop); + } + private: + Property prop; + + PropertyBuilder() { + } +}; } /* namespace core */ } /* namespace minifi */ } /* namespace nifi */ http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7ac309ba/libminifi/include/core/Relationship.h ---------------------------------------------------------------------- diff --git a/libminifi/include/core/Relationship.h b/libminifi/include/core/Relationship.h index d0157d9..f2c442a 100644 --- a/libminifi/include/core/Relationship.h +++ b/libminifi/include/core/Relationship.h @@ -55,6 +55,12 @@ class Relationship { : name_(name), description_(description) { } + + Relationship(const Relationship &other) + : name_(other.name_), + description_(other.description_) { + } + Relationship() : name_(UNDEFINED_RELATIONSHIP) { } @@ -73,6 +79,12 @@ class Relationship { bool operator <(const Relationship & right) const { return name_ < right.name_; } + + Relationship &operator=(const Relationship &other) { + name_ = other.name_; + description_ = other.description_; + return *this; + } // Whether it is a undefined relationship bool isRelationshipUndefined() { return isRelationshipNameUndefined(name_); http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7ac309ba/libminifi/include/core/Resource.h ---------------------------------------------------------------------- diff --git a/libminifi/include/core/Resource.h b/libminifi/include/core/Resource.h index 410b947..742d879 100644 --- a/libminifi/include/core/Resource.h +++ b/libminifi/include/core/Resource.h @@ -26,11 +26,9 @@ namespace nifi { namespace minifi { namespace core { - #define MKSOC(x) #x #define MAKESTRING(x) MKSOC(x) - template<class T> class StaticClassType { public: @@ -38,9 +36,9 @@ class StaticClassType { StaticClassType(const std::string &name) { // Notify when the static member is created #ifdef MODULE_NAME - ClassLoader::getDefaultClassLoader().registerClass(MAKESTRING(MODULE_NAME), name, std::unique_ptr<ObjectFactory>(new DefautObjectFactory<T>())); + ClassLoader::getDefaultClassLoader().registerClass(name, std::unique_ptr<ObjectFactory>(new DefautObjectFactory<T>(MAKESTRING(MODULE_NAME)))); #else - ClassLoader::getDefaultClassLoader().registerClass("minifi-system", name, std::unique_ptr<ObjectFactory>(new DefautObjectFactory<T>())); + ClassLoader::getDefaultClassLoader().registerClass(name, std::unique_ptr<ObjectFactory>(new DefautObjectFactory<T>("minifi-system"))); #endif } }; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7ac309ba/libminifi/include/core/state/Value.h ---------------------------------------------------------------------- diff --git a/libminifi/include/core/state/Value.h b/libminifi/include/core/state/Value.h index f4a92ad..a80404c 100644 --- a/libminifi/include/core/state/Value.h +++ b/libminifi/include/core/state/Value.h @@ -46,6 +46,10 @@ class Value { return string_value; } + bool empty(){ + return string_value.empty(); + } + protected: std::string string_value; @@ -184,7 +188,7 @@ class ValueNode { } bool empty() const { - return value_ == nullptr; + return value_ == nullptr || value_->empty(); } protected: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7ac309ba/libminifi/include/core/state/nodes/AgentInformation.h ---------------------------------------------------------------------- diff --git a/libminifi/include/core/state/nodes/AgentInformation.h b/libminifi/include/core/state/nodes/AgentInformation.h index 7b72908..baafbbe 100644 --- a/libminifi/include/core/state/nodes/AgentInformation.h +++ b/libminifi/include/core/state/nodes/AgentInformation.h @@ -58,7 +58,6 @@ namespace response { #define GROUP_STR "org::apache::nifi::minifi" - class ComponentManifest : public DeviceInformation { public: ComponentManifest(std::string name, uuid_t uuid) @@ -99,7 +98,6 @@ class ComponentManifest : public DeviceInformation { className.name = "type"; className.value = group.class_name_; - if (!group.class_properties_.empty()) { SerializedResponseNode props; props.name = "propertyDescriptors"; @@ -124,6 +122,10 @@ class ComponentManifest : public DeviceInformation { descriptorValidRegex.name = "validRegex"; descriptorValidRegex.value = prop.second.getValidRegex(); + SerializedResponseNode descriptorDefaultValue; + descriptorDefaultValue.name = "defaultValue"; + descriptorDefaultValue.value = prop.second.getValue(); + SerializedResponseNode descriptorDependentProperties; descriptorDependentProperties.name = "dependentProperties"; @@ -143,9 +145,42 @@ class ComponentManifest : public DeviceInformation { descriptorExclusiveOfProperties.children.push_back(descriptorExclusiveOfProperty); } + const auto &allowed_types = prop.second.getAllowedTypes(); + if (!allowed_types.empty()) { + SerializedResponseNode allowed_type; + allowed_type.name = "typeProvidedByValue"; + for (const auto &type : allowed_types) { + SerializedResponseNode typeNode; + typeNode.name = "type"; + typeNode.value = type; + allowed_type.children.push_back(typeNode); + + SerializedResponseNode bgroup; + bgroup.name = "group"; + bgroup.value = GROUP_STR; + SerializedResponseNode artifact; + artifact.name = "artifact"; + artifact.value = core::ClassLoader::getDefaultClassLoader().getGroupForClass(type); + allowed_type.children.push_back(typeNode); + allowed_type.children.push_back(bgroup); + allowed_type.children.push_back(artifact); + + } + child.children.push_back(allowed_type); + + } + child.children.push_back(descriptorName); + + if (prop.first != prop.second.getDisplayName()) { + SerializedResponseNode displayName; + displayName.name = "displayName"; + displayName.value = prop.second.getDisplayName(); + child.children.push_back(displayName); + } child.children.push_back(descriptorDescription); child.children.push_back(descriptorRequired); + child.children.push_back(descriptorDefaultValue); child.children.push_back(descriptorValidRegex); child.children.push_back(descriptorDependentProperties); child.children.push_back(descriptorExclusiveOfProperties); @@ -158,10 +193,39 @@ class ComponentManifest : public DeviceInformation { SerializedResponseNode dyn_prop; dyn_prop.name = "supportsDynamicProperties"; - dyn_prop.value = group.support_dynamic_; + dyn_prop.value = group.dynamic_properties_; + + SerializedResponseNode dyn_relat; + dyn_relat.name = "supportsDynamicRelationships"; + dyn_relat.value = group.dynamic_relationships_; + if (group.class_relationships_.size() > 0) { + SerializedResponseNode relationships; + relationships.name = "supportedRelationships"; + relationships.array = true; + + for (const auto &relationship : group.class_relationships_) { + SerializedResponseNode child; + child.name = "supportedRelationships"; + + SerializedResponseNode nameNode; + nameNode.name = "name"; + nameNode.value = relationship.getName(); + + SerializedResponseNode descriptorDescription; + descriptorDescription.name = "description"; + descriptorDescription.value = relationship.getDescription(); + child.children.push_back(nameNode); + child.children.push_back(descriptorDescription); + + relationships.children.push_back(child); + } + desc.children.push_back(relationships); + } + desc.children.push_back(dyn_relat); desc.children.push_back(dyn_prop); desc.children.push_back(className); + type.children.push_back(desc); } response.children.push_back(type); @@ -170,7 +234,6 @@ class ComponentManifest : public DeviceInformation { } }; - class Bundles : public DeviceInformation { public: Bundles(std::string name, uuid_t uuid) @@ -519,7 +582,7 @@ class AgentInformation : public DeviceInformation, public AgentMonitor, public A SerializedResponseNode dyn_prop; dyn_prop.name = "supportsDynamicProperties"; - dyn_prop.value = group.support_dynamic_; + dyn_prop.value = group.dynamic_properties_; desc.children.push_back(dyn_prop); @@ -554,7 +617,7 @@ class AgentInformation : public DeviceInformation, public AgentMonitor, public A SerializedResponseNode dyn_prop; dyn_prop.name = "supportsDynamicProperties"; - dyn_prop.value = group.support_dynamic_; + dyn_prop.value = group.dynamic_properties_; desc.children.push_back(dyn_prop); http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7ac309ba/libminifi/include/processors/RouteOnAttribute.h ---------------------------------------------------------------------- diff --git a/libminifi/include/processors/RouteOnAttribute.h b/libminifi/include/processors/RouteOnAttribute.h index eac392e..1c1eb45 100644 --- a/libminifi/include/processors/RouteOnAttribute.h +++ b/libminifi/include/processors/RouteOnAttribute.h @@ -56,6 +56,11 @@ class RouteOnAttribute : public core::Processor { return true; }; + + virtual bool supportsDynamicRelationships() { + return true; + } + virtual void onDynamicPropertyModified(const core::Property &orig_property, const core::Property &new_property); virtual void onTrigger(core::ProcessContext *context, http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7ac309ba/libminifi/src/core/Connectable.cpp ---------------------------------------------------------------------- diff --git a/libminifi/src/core/Connectable.cpp b/libminifi/src/core/Connectable.cpp index 746f5ec..2a98818 100644 --- a/libminifi/src/core/Connectable.cpp +++ b/libminifi/src/core/Connectable.cpp @@ -65,6 +65,14 @@ bool Connectable::setSupportedRelationships(std::set<core::Relationship> relatio return true; } +std::vector<Relationship> Connectable::getSupportedRelationships() const { + std::vector<Relationship> relationships; + for (auto const &item : relationships_) { + relationships.push_back(item.second); + } + return relationships; +} + // Whether the relationship is supported bool Connectable::isSupportedRelationship(core::Relationship relationship) { // if we are running we do not need a lock since the function to change relationships_ ( setSupportedRelationships) @@ -100,7 +108,7 @@ bool Connectable::setAutoTerminatedRelationships(std::set<Relationship> relation // Check whether the relationship is auto terminated bool Connectable::isAutoTerminated(core::Relationship relationship) { // if we are running we do not need a lock since the function to change relationships_ ( setSupportedRelationships) - // cannot be executed while we are running + // cannot be executed while we are running const bool isConnectableRunning = isRunning(); const auto conditionalLock = isConnectableRunning ? std::unique_lock<std::mutex>() : std::unique_lock<std::mutex>(relationship_mutex_); http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7ac309ba/libminifi/src/core/Property.cpp ---------------------------------------------------------------------- diff --git a/libminifi/src/core/Property.cpp b/libminifi/src/core/Property.cpp index 4065dc7..bb84e44 100644 --- a/libminifi/src/core/Property.cpp +++ b/libminifi/src/core/Property.cpp @@ -27,10 +27,18 @@ std::string Property::getName() const { return name_; } +std::string Property::getDisplayName() const { + return display_name_.empty() ? name_ : display_name_; +} + std::string Property::getDescription() const { return description_; } +std::vector<std::string> Property::getAllowedTypes() const { + return types_; +} + std::string Property::getValue() const { if (!values_.empty()) return values_.front(); @@ -69,6 +77,8 @@ bool Property::operator<(const Property &right) const { const Property &Property::operator=(const Property &other) { name_ = other.name_; + display_name_ = other.display_name_; + types_ = other.types_; values_ = other.values_; description_ = other.description_; is_collection_ = other.is_collection_; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7ac309ba/libminifi/test/unit/PropertyValidationAgentInfoTests.cpp ---------------------------------------------------------------------- diff --git a/libminifi/test/unit/PropertyValidationAgentInfoTests.cpp b/libminifi/test/unit/PropertyValidationAgentInfoTests.cpp index 7a393c5..31f9b7b 100644 --- a/libminifi/test/unit/PropertyValidationAgentInfoTests.cpp +++ b/libminifi/test/unit/PropertyValidationAgentInfoTests.cpp @@ -58,10 +58,42 @@ TEST_CASE("Test Valid Regex", "[validRegex]") { REQUIRE(prop_descriptors.children.size() > 0); const auto &prop_0 = prop_descriptors.children[0]; REQUIRE(prop_0.children.size() >= 3); - const auto &prop_0_valid_regex = prop_0.children[3]; + const auto &df = prop_0.children[3]; + REQUIRE("defaultValue" == df.name); + const auto &prop_0_valid_regex = prop_0.children[4]; REQUIRE("validRegex" == prop_0_valid_regex.name); } +TEST_CASE("Test Relationships", "[rel1]") { + minifi::state::response::ComponentManifest manifest("minifi-system"); + auto serialized = manifest.serialize(); + REQUIRE(serialized.size() > 0); + const auto &resp = serialized[0]; + REQUIRE(resp.children.size() > 0); + const auto &processors = resp.children[0]; + REQUIRE(processors.children.size() > 0); + minifi::state::response::SerializedResponseNode proc_0; + for (const auto &node : processors.children) { + if ("org::apache::nifi::minifi::processors::PutFile" == node.name) { + proc_0 = node; + } + } + REQUIRE(proc_0.children.size() > 0); + const auto &relationships = proc_0.children[1]; + REQUIRE("supportedRelationships" == relationships.name); + // this is because they are now nested + REQUIRE("supportedRelationships" == relationships.children[0].name); + REQUIRE("name" == relationships.children[0].children[0].name); + REQUIRE("failure" == relationships.children[0].children[0].value.to_string()); + REQUIRE("description" == relationships.children[0].children[1].name); + + REQUIRE("success" == relationships.children[1].children[0].value.to_string()); + REQUIRE("description" == relationships.children[1].children[1].name); + + +} + + TEST_CASE("Test Dependent", "[dependent]") { minifi::state::response::ComponentManifest manifest("minifi-system"); auto serialized = manifest.serialize(); @@ -81,8 +113,8 @@ TEST_CASE("Test Dependent", "[dependent]") { REQUIRE(prop_descriptors.children.size() > 0); const auto &prop_0 = prop_descriptors.children[1]; REQUIRE(prop_0.children.size() >= 3); - const auto &prop_0_dependent = prop_0.children[4]; - REQUIRE("dependentProperties" == prop_0_dependent.name); - const auto &prop_0_dependent_0 = prop_0_dependent.children[0]; + REQUIRE("defaultValue" == prop_0.children[3].name); + REQUIRE("validRegex" == prop_0.children[4].name); + const auto &prop_0_dependent_0 = prop_descriptors.children[2]; REQUIRE("Directory" == prop_0_dependent_0.name); }
