diff --git a/libminifi/include/core/PropertyValidation.h b/libminifi/include/core/PropertyValidation.h index b0e59e9774..27a69d0acf 100644 --- a/libminifi/include/core/PropertyValidation.h +++ b/libminifi/include/core/PropertyValidation.h @@ -22,8 +22,10 @@ #include "core/state/Value.h" #include "TypedValues.h" #include "utils/StringUtils.h" +#include "utils/RegexUtils.h" #include #include +#include namespace org { namespace apache { @@ -88,11 +90,10 @@ class PropertyValidator { PropertyValidator(const std::string &name) : name_(name) { } - virtual ~PropertyValidator() { - } + virtual ~PropertyValidator() {} - std::string getName() const { + virtual std::string getName() const { return name_; } @@ -124,8 +125,7 @@ class AlwaysValid : public PropertyValidator { PropertyValidator(name) { } - virtual ~AlwaysValid() { - } + ValidationResult validate(const std::string &subject, const std::shared_ptr &input) const { return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input->getStringValue()).isValid(always_valid_).build(); } @@ -141,9 +141,6 @@ class BooleanValidator : public PropertyValidator { BooleanValidator(const std::string &name) : PropertyValidator(name) { } - virtual ~BooleanValidator() { - - } ValidationResult validate(const std::string &subject, const std::shared_ptr &input) const { return PropertyValidator::_validate_internal(subject, input); @@ -162,8 +159,6 @@ class IntegerValidator : public PropertyValidator { IntegerValidator(const std::string &name) : PropertyValidator(name) { } - virtual ~IntegerValidator() { - } ValidationResult validate(const std::string &subject, const std::shared_ptr &input) const { return PropertyValidator::_validate_internal(subject, input); @@ -187,9 +182,7 @@ class LongValidator : public PropertyValidator { min_(min), max_(max) { } - virtual ~LongValidator() { - } ValidationResult validate(const std::string &subject, const std::shared_ptr &input) const { auto in64 = std::dynamic_pointer_cast(input); if (in64) { @@ -221,9 +214,7 @@ class UnsignedLongValidator : public PropertyValidator { explicit UnsignedLongValidator(const std::string &name) : PropertyValidator(name) { } - virtual ~UnsignedLongValidator() { - } ValidationResult validate(const std::string &subject, const std::shared_ptr &input) const { return PropertyValidator::_validate_internal(subject, input); } @@ -249,9 +240,7 @@ class DataSizeValidator : public PropertyValidator { DataSizeValidator(const std::string &name) : PropertyValidator(name) { } - virtual ~DataSizeValidator() { - } ValidationResult validate(const std::string &subject, const std::shared_ptr &input) const { return PropertyValidator::_validate_internal(subject, input); } @@ -270,9 +259,6 @@ class PortValidator : public LongValidator { PortValidator(const std::string &name) : LongValidator(name, 1, 65535) { } - virtual ~PortValidator() { - - } }; //Use only for specifying listen ports, where 0 means a randomly chosen one! @@ -281,18 +267,12 @@ class ListenPortValidator : public LongValidator { ListenPortValidator(const std::string &name) : LongValidator(name, 0, 65535) { } - virtual ~ListenPortValidator() { - - } }; class TimePeriodValidator : public PropertyValidator { public: TimePeriodValidator(const std::string &name) : PropertyValidator(name) { - } - virtual ~TimePeriodValidator() { - } ValidationResult validate(const std::string &subject, const std::shared_ptr &input) const { return PropertyValidator::_validate_internal(subject, input); @@ -308,6 +288,66 @@ class TimePeriodValidator : public PropertyValidator { } }; +class RegexValidator : public PropertyValidator { + public: + explicit RegexValidator(const std::string& pattern) + : PropertyValidator("REGULAR_EXPRESSION_VALIDATOR"){ + regex_ = utils::Regex(pattern); + } + ValidationResult validate(const std::string &subject, const std::shared_ptr &input) const { + return validate(subject, input->getStringValue()); + } + + ValidationResult validate(const std::string &subject, const std::string &input) const { + bool result = regex_.match(input); + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input).isValid(result).build(); + } + private: + mutable utils::Regex regex_; +}; + +template ::value>::type* = nullptr> +class ListValidator : public PropertyValidator{ + public: + explicit ListValidator(T val) + : PropertyValidator("LIST_VALIDATOR"), + inner_validator_(std::move(val)){ + } + ValidationResult validate(const std::string &subject, const std::shared_ptr &input) const { + return validate(subject, input->getStringValue()); + } + + ValidationResult validate(const std::string &subject, const std::string &input) const { + const auto& tokens = utils::StringUtils::split(input, ","); + for(const auto& token: tokens) { + if(!inner_validator_.validate(subject, token).valid()){ + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input).isValid(false).build(); + } + } + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input).isValid(true).build(); + } + + private: + T inner_validator_; +}; + +class MultiChoiceValidator : PropertyValidator { + public: + explicit MultiChoiceValidator (const std::set& choices) + : PropertyValidator("LIST_VALIDATOR"), + val_(RegexValidator("(" + utils::StringUtils::join("|", choices) + ")")) { + } + ValidationResult validate(const std::string &subject, const std::shared_ptr &input) const { + return validate(subject, input->getStringValue()); + } + + ValidationResult validate(const std::string &subject, const std::string &input) const { + return val_.validate(subject, input); + } + private: + ListValidator val_; +}; + // STATIC DEFINITIONS class StandardValidators { diff --git a/libminifi/test/unit/PropertyTests.cpp b/libminifi/test/unit/PropertyTests.cpp index dfdd071433..75ad800677 100644 --- a/libminifi/test/unit/PropertyTests.cpp +++ b/libminifi/test/unit/PropertyTests.cpp @@ -19,6 +19,7 @@ #include #include "utils/StringUtils.h" #include "core/Property.h" +#include "core/PropertyValidation.h" #include "../TestBase.h" TEST_CASE("Test Boolean Conversion", "[testboolConversion]") { @@ -173,3 +174,24 @@ TEST_CASE("Test DateTime Conversion", "[testDateTime]") { REQUIRE(false == org::apache::nifi::minifi::core::Property::StringToDateTime("foobar", timestamp)); } + +TEST_CASE("Regex validator tests", "[TestRegexValidator]") { + core::RegexValidator rv("dog"); + REQUIRE(rv.validate("", "mad dog").valid()); + REQUIRE(rv.validate("", "dogfooded test").valid()); + REQUIRE_FALSE(rv.validate("", "d_o_g").valid()); + REQUIRE_THROWS(core::RegexValidator("(unclosed]")); +} + +TEST_CASE("List validator tests", "[TestListValidator]") { + core::ListValidator listintvalidator(core::IntegerValidator("IV")); + REQUIRE(listintvalidator.validate("", "1,42,8").valid()); + REQUIRE_FALSE(listintvalidator.validate("","4,three").valid()); + REQUIRE_FALSE(listintvalidator.validate("", "cats, dogs").valid()); +} + +TEST_CASE("Multichoice validator tests", "[TestMultichoiceValidator]") { + core::MultiChoiceValidator mv({"cat", "dog", "pig"}); + REQUIRE(mv.validate("", "pig,cat").valid()); + REQUIRE_FALSE(mv.validate("", "rat,dog").valid()); +}