blob: eed8ce9b6e7911f0e71e9904f5b75a4f44a2e1a6 [file] [log] [blame]
/**
*
* 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_view>
#include <tuple>
#include <optional>
#include <string>
#include <memory>
#include <utility>
#include "nonstd/expected.hpp"
#include "utils/StringUtils.h"
#include "utils/gsl.h"
namespace org::apache::nifi::minifi::core::flow {
class Node {
public:
struct Cursor {
int line{0};
int column{0};
int pos{0};
};
class Iterator {
friend class Node;
public:
class Value;
class IteratorImpl {
public:
virtual IteratorImpl& operator++() = 0;
virtual bool operator==(const IteratorImpl& other) const = 0;
virtual Value operator*() const = 0;
bool operator!=(const IteratorImpl& other) const {return !(*this == other);}
virtual std::unique_ptr<IteratorImpl> clone() const = 0;
virtual ~IteratorImpl() = default;
std::string path_;
};
Iterator& operator++() {
impl_->operator++();
++idx_;
return *this;
}
explicit Iterator(std::unique_ptr<IteratorImpl> impl) : impl_(std::move(impl)) {}
Iterator(const Iterator& other): impl_(other.impl_->clone()) {}
Iterator(Iterator&&) = default;
Iterator& operator=(const Iterator& other) {
if (this == &other) {
return *this;
}
impl_ = other.impl_->clone();
return *this;
}
Iterator& operator=(Iterator&&) = default;
bool operator==(const Iterator& other) const {return impl_->operator==(*other.impl_);}
bool operator!=(const Iterator& other) const {return !(*this == other);}
Value operator*() const;
private:
std::unique_ptr<IteratorImpl> impl_;
int idx_{0};
};
class NodeImpl {
public:
virtual explicit operator bool() const = 0;
virtual bool isSequence() const = 0;
virtual bool isMap() const = 0;
virtual bool isNull() const = 0;
virtual nonstd::expected<std::string, std::exception_ptr> getString() const = 0;
virtual nonstd::expected<bool, std::exception_ptr> getBool() const = 0;
virtual nonstd::expected<int64_t, std::exception_ptr> getInt64() const = 0;
virtual nonstd::expected<std::string, std::exception_ptr> getIntegerAsString() const = 0;
virtual nonstd::expected<std::string, std::exception_ptr> getScalarAsString() const = 0;
virtual std::string getDebugString() const = 0;
virtual size_t size() const = 0;
virtual Iterator begin() const = 0;
virtual Iterator end() const = 0;
virtual Node operator[](std::string_view key) const = 0;
virtual std::optional<Cursor> getCursor() const = 0;
virtual Node createEmpty() const = 0;
virtual ~NodeImpl() = default;
std::string path_;
};
Node() = default;
explicit Node(std::shared_ptr<NodeImpl> impl): impl_(std::move(impl)) {}
explicit operator bool() const {return impl_->operator bool();}
bool isSequence() const {return impl_->isSequence();}
bool isMap() const {return impl_->isMap();}
bool isNull() const {return impl_->isNull();}
nonstd::expected<std::string, std::exception_ptr> getString() const {return impl_->getString();}
nonstd::expected<bool, std::exception_ptr> getBool() const {return impl_->getBool();}
nonstd::expected<int64_t, std::exception_ptr> getInt64() const {return impl_->getInt64();}
nonstd::expected<std::string, std::exception_ptr> getIntegerAsString() const {return impl_->getIntegerAsString();}
nonstd::expected<std::string, std::exception_ptr> getScalarAsString() const {return impl_->getScalarAsString();}
// return a string representation of the node (need not be deserializable)
std::string getDebugString() const {return impl_->getDebugString();}
size_t size() const {return impl_->size();}
size_t empty() const {
return size() == 0;
}
Iterator begin() const {
Iterator it = impl_->begin();
it.impl_->path_ = impl_->path_;
return it;
}
Iterator end() const {
Iterator it = impl_->end();
it.impl_->path_ = impl_->path_;
return it;
}
// considers @key to be a member of this node as is
Node getMember(std::string_view key) {
Node result = impl_->operator[](key);
result.impl_->path_ = utils::string::join_pack(impl_->path_, "/", key);
return result;
}
// considers @key to be a '/'-delimited access path
Node operator[](std::string_view key) const {
Node result = *this;
for (auto& field : utils::string::split(std::string{key}, "/")) {
if (key == ".") {
// pass: self
} else {
result = result.getMember(field);
}
if (!result) {
break;
}
}
return result;
}
// considers @keys to be a set of viable access paths, the first viable is returned
Node operator[](std::span<const std::string> keys) const {
for (auto& key : keys) {
if (Node result = (*this)[key]) {
return result;
}
}
return impl_->createEmpty();
}
std::string getPath() const {return impl_->path_;}
std::optional<Cursor> getCursor() const {return impl_->getCursor();}
private:
std::shared_ptr<NodeImpl> impl_;
};
class Node::Iterator::Value : public Node, public std::pair<Node, Node> {
public:
Value(Node node, Node key, Node value): Node{std::move(node)}, std::pair<Node, Node>{std::move(key), std::move(value)} {}
};
} // namespace org::apache::nifi::minifi::core::flow