Skip to content
Yaml_Conf.cpp 5.46 KiB
Newer Older
Valerio Pastore's avatar
Valerio Pastore committed
#include <Yaml_Conf.h>
#include <fstream>
#include <filesystem>
#include <algorithm>
#include <iterator>
#include <cctype>
Valerio Pastore's avatar
Valerio Pastore committed
#include <boost/algorithm/string.hpp>
Valerio Pastore's avatar
Valerio Pastore committed
#include <iostream>
Valerio Pastore's avatar
Valerio Pastore committed
#include <ctime>
#include <iomanip>
Valerio Pastore's avatar
Valerio Pastore committed

using namespace inaf::oasbo::Configurators;

YamlConfigurator::YamlConfigurator(std::string path) {
	this->path = path;
	load(path);
}

void YamlConfigurator::load(std::string path) {
	if (!std::filesystem::exists(path)) {
Valerio Pastore's avatar
Valerio Pastore committed
		time_t now = time(nullptr);
		std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
				<< "]\t[YAML Configurator]\t" << "file: " << path
Valerio Pastore's avatar
Valerio Pastore committed
				<< " does not exits." << std::endl;
		return;
	}
	file = YAML::LoadFile(path);
	if (file.IsNull()) {
Valerio Pastore's avatar
Valerio Pastore committed
		time_t now = time(nullptr);
		std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
				<< "]\t[YAML Configurator]\t" << "file." << std::endl;
Valerio Pastore's avatar
Valerio Pastore committed
	}
	if (!file.IsSequence()) {
Valerio Pastore's avatar
Valerio Pastore committed
		time_t now = time(nullptr);
		std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
				<< "]\t[YAML Configurator]\t"
				<< "file does not contains a yaml sequence." << std::endl;
Valerio Pastore's avatar
Valerio Pastore committed
	}
}

/**
Valerio Pastore's avatar
Valerio Pastore committed

Valerio Pastore's avatar
Valerio Pastore committed
 Updates the YAML configuration file by adding new configuration entries for the target key.
 It also removes old configurations corresponding to the target key.
 @param target The target key for which to add and remove configuration entries.
 */
Valerio Pastore's avatar
Valerio Pastore committed
int YamlConfigurator::pushConfigToSource(std::string target) {
	boost::to_lower(target);
	// Extracrs only target entries
	std::map<std::string, std::string> filteredMap;
	for (const auto &pair : this->config) {
Valerio Pastore's avatar
Valerio Pastore committed
		if (pair.first.compare(0, target.length(), target) == 0) {
Valerio Pastore's avatar
Valerio Pastore committed
			std::string key = pair.first.substr(target.length() + 1);
			boost::to_lower(key);
			filteredMap[key] = pair.second;
		}
	}

	// save the file content in a vector
	std::fstream ifile(path);
	std::vector<std::string> file_content;
	std::string line;
	while (std::getline(ifile, line)) {
		file_content.push_back(line);
	}
	ifile.close();
	// update the file content into the vector
	size_t pos = 0;
	for (; pos < file_content.size(); pos++) {
		if (file_content[pos].find(std::string("- ").append(target))
				!= std::string::npos) {
			for (auto pair : filteredMap) {
				pos += 1;
				std::string new_line("    " + pair.first + ": " + pair.second);
				auto insertionPoint = file_content.begin() + pos;
				file_content.insert(insertionPoint, new_line);
			}
			pos += 1;
			break;
		}
	}

	// remove the old configuration
	for (; pos < file_content.size(); pos++) {
		if (file_content[pos][0] != '-') {
			line = file_content[pos];
			// Elimina gli spazi vuoti all'inizio della stringa e  Ferma l'analisi al carattere ":" escluso
			line = line.erase(0, line.find_first_not_of(' ')).substr(0,
					line.find(':'));
			boost::to_lower(line);
			bool found = false; // Controlla se la riga è stata sostituita dalla nuova conf
			for (auto key : filteredMap) {
				if (key.first.compare(line) == 0) {
					found = true;
					break;
				}
			}
			if (found) {
				file_content.erase(file_content.begin() + pos);
				pos--;
			}

		} else
			break;
	}

	// update the file with the content of the vector
	std::ofstream ofile(path, std::ofstream::trunc); // Open the file in truncation mode
	for (const auto &line : file_content) {
		ofile << line << std::endl;
	}
	ofile.close();

	load(path);
	return 1;
}

int YamlConfigurator::pushConfigToSource() {
Valerio Pastore's avatar
Valerio Pastore committed
	// extract targets
Valerio Pastore's avatar
Valerio Pastore committed
	std::vector<std::string> tagets;
	for (const auto &pair : config) {
		std::string key = pair.first;
		size_t pos = key.find('_');

		if (pos != std::string::npos) {
			std::string prefix = key.substr(0, pos);
			if (std::find(tagets.begin(), tagets.end(), prefix)
					== tagets.end()) {
				tagets.push_back(prefix);
			}
		}
	}
Valerio Pastore's avatar
Valerio Pastore committed
	// call push for each target
Valerio Pastore's avatar
Valerio Pastore committed
	for (auto target : tagets)
		pushConfigToSource(target);
	return 1;
}

int YamlConfigurator::readConfigFromSource(std::string target) {
	boost::to_lower(target);
	if (file.IsNull())
		return -1;
	try {
		for (auto element : file) {
			if (element[target]) {
				YAML::Node node = element[target];
				for (const auto &kvp : node) {
					config[target + "_" + kvp.first.as<std::string>()] =
							kvp.second.as<std::string>();
				}
			}
		}
	} catch (const YAML::Exception &e) {
Valerio Pastore's avatar
Valerio Pastore committed
		time_t now = time(nullptr);
		std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
				<< "]\t[YAML Configurator]\t" << "reading error: " << e.what()
Valerio Pastore's avatar
Valerio Pastore committed
				<< std::endl;
		return -1;
	}
	return 1;
}

int YamlConfigurator::readConfigFromSource() {
	if (file.IsNull())
		return -1;
	try {
		// Itera sugli elementi del documento YAML
		for (const auto &element : file) {
			for (const auto &pair : element) {
				std::string elementName = element.first.as<std::string>();
				boost::to_lower(elementName);
				// Se l'elemento è una mappa, estrai le chiavi e i valori
				if (pair.second.IsMap()) {
					for (const auto &subPair : pair.second) {
						std::string key = elementName + "_"
								+ subPair.first.as<std::string>();
						std::string value = subPair.second.as<std::string>();
						config[key] = value;
					}
				}
			}
		}
	} catch (const YAML::Exception &e) {
Valerio Pastore's avatar
Valerio Pastore committed
		time_t now = time(nullptr);
		std::cerr << "[" << std::put_time(localtime(&now), "%Y-%m-%d %H:%M:%S")
				<< "]\t[YAML Configurator]\t" << " reading error: " << e.what()
Valerio Pastore's avatar
Valerio Pastore committed
				<< std::endl;
		return -1;
	}
	return 1;
}

int YamlConfigurator::insert(std::map<std::string, std::string> conf,
		std::string target) {
	boost::to_lower(target);
	for (const auto &kvp : conf) {
		this->config[target + "_" + kvp.first] = kvp.second;
	}
	return 1;
}