blob: 32383eeb9efd2f748775652aa1bc1963b2a79064 [file] [log] [blame]
/**
* @file ApplyTemplate.cpp
* ApplyTemplate class implementation
*
* 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.
*/
#include "ApplyTemplate.h"
#include <unordered_map>
#include <memory>
#include <string>
#include <utility>
#include "core/Resource.h"
#include "bustache/model.hpp"
#include "bustache/render/string.hpp"
namespace org::apache::nifi::minifi::processors {
void ApplyTemplate::initialize() {
setSupportedProperties(Properties);
setSupportedRelationships(Relationships);
}
void ApplyTemplate::onTrigger(core::ProcessContext& context, core::ProcessSession& session) {
auto flow_file = session.get();
if (!flow_file) {
return;
}
std::string template_file;
context.getProperty(Template, template_file, flow_file);
session.write(flow_file, [&template_file, &flow_file, this](const auto& output_stream) {
logger_->log_info("ApplyTemplate reading template file from {}", template_file);
// TODO(szaszm): we might want to return to memory-mapped input files when the next todo is done. Until then, the agents stores the whole result in memory anyway, so no point in not doing the same
// with the template file itself
const auto template_file_contents = [&] {
std::ifstream ifs{template_file};
return std::string{std::istreambuf_iterator<char>{ifs}, std::istreambuf_iterator<char>{}};
}();
bustache::format format(template_file_contents);
std::unordered_map<std::string, std::string> data;
for (const auto &attr : flow_file->getAttributes()) {
data[attr.first] = attr.second;
}
// TODO(calebj) write ostream reciever for format() to prevent excessive copying
std::string ostring = bustache::to_string(format(data));
output_stream->write(gsl::make_span(ostring).as_span<const std::byte>());
return gsl::narrow<int64_t>(ostring.length());
});
session.transfer(flow_file, Success);
}
REGISTER_RESOURCE(ApplyTemplate, Processor);
} // namespace org::apache::nifi::minifi::processors