[ https://issues.apache.org/jira/browse/MINIFICPP-479?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16719469#comment-16719469 ]
ASF GitHub Bot commented on MINIFICPP-479: ------------------------------------------ Github user phrocker commented on a diff in the pull request: https://github.com/apache/nifi-minifi-cpp/pull/460#discussion_r241193264 --- Diff: libminifi/include/core/PropertyValidation.h --- @@ -0,0 +1,347 @@ +/** + * + * 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. + */ +#ifndef LIBMINIFI_INCLUDE_CORE_PROPERTYVALIDATION_H_ +#define LIBMINIFI_INCLUDE_CORE_PROPERTYVALIDATION_H_ + +#include "core/Core.h" +#include "core/state/Value.h" +#include "TypedValues.h" +#include "utils/StringUtils.h" +#include <memory> + +namespace org { +namespace apache { +namespace nifi { +namespace minifi { +namespace core { + +class ValidationResult; + +class ValidationResult { + public: + bool valid() const { + return valid_; + } + + class Builder { + public: + static Builder createBuilder() { + return Builder(); + } + Builder &isValid(bool valid) { + valid_ = valid; + return *this; + } + Builder &withSubject(const std::string &subject) { + subject_ = subject; + return *this; + } + Builder &withInput(const std::string &input) { + input_ = input; + return *this; + } + + ValidationResult build() { + return ValidationResult(*this); + } + + protected: + bool valid_; + std::string subject_; + std::string input_; + friend class ValidationResult; + }; + private: + + bool valid_; + std::string subject_; + std::string input_; + + ValidationResult(const Builder &builder) + : valid_(builder.valid_), + subject_(builder.subject_), + input_(builder.input_) { + } + + friend class Builder; +}; + +class PropertyValidator { + public: + + PropertyValidator(const std::string &name) + : name_(name) { + } + virtual ~PropertyValidator() { + + } + + std::string getName() const { + return name_; + } + + virtual ValidationResult validate(const std::string &subject, const std::shared_ptr<minifi::state::response::Value> &input) const = 0; + + virtual ValidationResult validate(const std::string &subject, const std::string &input) const = 0; + + protected: + template<typename T> + ValidationResult _validate_internal(const std::string &subject, const std::shared_ptr<minifi::state::response::Value> &input) const { + if (std::dynamic_pointer_cast<T>(input) != nullptr) { + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input->getStringValue()).isValid(true).build(); + } else { + state::response::ValueNode vn; + vn = input->getStringValue(); + return validate(subject, input->getStringValue()); + } + + } + + std::string name_; +}; + +class AlwaysValid : public PropertyValidator { + bool always_valid_; + public: + AlwaysValid(bool isalwaysvalid, const std::string &name) + : always_valid_(isalwaysvalid), + PropertyValidator(name) { + + } + virtual ~AlwaysValid() { + } + ValidationResult validate(const std::string &subject, const std::shared_ptr<minifi::state::response::Value> &input) const { + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input->getStringValue()).isValid(always_valid_).build(); + } + + ValidationResult validate(const std::string &subject, const std::string &input) const { + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input).isValid(always_valid_).build(); + } + +}; + +class BooleanValidator : public PropertyValidator { + public: + BooleanValidator(const std::string &name) + : PropertyValidator(name) { + } + virtual ~BooleanValidator() { + + } + + ValidationResult validate(const std::string &subject, const std::shared_ptr<minifi::state::response::Value> &input) const { + return PropertyValidator::_validate_internal<minifi::state::response::BoolValue>(subject, input); + } + + ValidationResult validate(const std::string &subject, const std::string &input) const { + if (utils::StringUtils::equalsIgnoreCase(input, "true") || utils::StringUtils::equalsIgnoreCase(input, "false")) + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input).isValid(true).build(); + else + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input).isValid(false).build(); + } +}; + +class IntegerValidator : public PropertyValidator { + public: + IntegerValidator(const std::string &name) + : PropertyValidator(name) { + } + virtual ~IntegerValidator() { + } + + ValidationResult validate(const std::string &subject, const std::shared_ptr<minifi::state::response::Value> &input) const { + return PropertyValidator::_validate_internal<minifi::state::response::IntValue>(subject, input); + } + + ValidationResult validate(const std::string &subject, const std::string &input) const { + try { + std::stoi(input); + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input).isValid(true).build(); + } catch (...) { + + } + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input).isValid(false).build(); + } +}; + +class LongValidator : public PropertyValidator { + public: + explicit LongValidator(const std::string &name, int64_t min = std::numeric_limits<int64_t>::min(), int64_t max = std::numeric_limits<int64_t>::max()) + : PropertyValidator(name), + min_(min), + max_(max) { + } + virtual ~LongValidator() { + + } + ValidationResult validate(const std::string &subject, const std::shared_ptr<minifi::state::response::Value> &input) const { + auto in64 = std::dynamic_pointer_cast<minifi::state::response::Int64Value>(input); + if (in64) { + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(in64->getStringValue()).isValid(in64->getValue() >= min_ && in64->getValue() <= max_).build(); + } else { + auto intb = std::dynamic_pointer_cast<minifi::state::response::IntValue>(input); + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(intb->getStringValue()).isValid(intb->getValue() >= min_ && intb->getValue() <= max_).build(); + } + } + + ValidationResult validate(const std::string &subject, const std::string &input) const { + try { + auto res = std::stoll(input); + + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input).isValid(res >= min_ && res <= max_).build(); + } catch (...) { + + } + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input).isValid(false).build(); + } + + private: + int64_t min_; + int64_t max_; +}; + +class UnsignedLongValidator : public PropertyValidator { + public: + explicit UnsignedLongValidator(const std::string &name) + : PropertyValidator(name) { + } + virtual ~UnsignedLongValidator() { + + } + ValidationResult validate(const std::string &subject, const std::shared_ptr<minifi::state::response::Value> &input) const { + return PropertyValidator::_validate_internal<minifi::state::response::UInt64Value>(subject, input); + } + + ValidationResult validate(const std::string &subject, const std::string &input) const { + try { + std::stoull(input); + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input).isValid(true).build(); + } catch (...) { + + } + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input).isValid(false).build(); + } + +}; + +class DataSizeValidator : public PropertyValidator { + public: + DataSizeValidator(const std::string &name) + : PropertyValidator(name) { + } + virtual ~DataSizeValidator() { + + } + ValidationResult validate(const std::string &subject, const std::shared_ptr<minifi::state::response::Value> &input) const { + return PropertyValidator::_validate_internal<core::DataSizeValue>(subject, input); + } + + ValidationResult validate(const std::string &subject, const std::string &input) const { + uint64_t out; + if (core::DataSizeValue::StringToInt(input, out)) + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input).isValid(true).build(); + else + return ValidationResult::Builder::createBuilder().withSubject(subject).withInput(input).isValid(false).build(); + } +}; + +class PortValidator : public LongValidator { + public: + PortValidator(const std::string &name) + : LongValidator(name, 1, 65535) { + } + virtual ~PortValidator() { + + } +}; + +class DataTimeValidator : public PropertyValidator { --- End diff -- Good call thanks. I think the name in NiFi is TIME_PERIOD_VALIDATOR, so I will probably rename this. It's a little old in its name. > Incorporate property validation information into manifest > --------------------------------------------------------- > > Key: MINIFICPP-479 > URL: https://issues.apache.org/jira/browse/MINIFICPP-479 > Project: NiFi MiNiFi C++ > Issue Type: Improvement > Reporter: Andrew Christianson > Assignee: Mr TheSegfault > Priority: Major > > High-level intent is to avoid round-trip to c2 to know that flow is valid > (or, invalid in common/trivial ways). -- This message was sent by Atlassian JIRA (v7.6.3#76005)