src/core/config/ConfigManager.cpp

Implementation of config manager. More…

Detailed Description

Implementation of config manager.

Copyright: Copyright (c) 2017-2024 CERN and the Allpix Squared authors. This software is distributed under the terms of the MIT License, copied verbatim in the file “LICENSE.md”. In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an Intergovernmental Organization or submit itself to any jurisdiction. SPDX-License-Identifier: MIT

Source code


#include "ConfigManager.hpp"

#include <algorithm>
#include <filesystem>
#include <fstream>
#include <string>
#include <vector>

#include "Configuration.hpp"
#include "core/config/exceptions.h"
#include "core/utils/log.h"

using namespace allpix;

ConfigManager::ConfigManager(std::filesystem::path file_name,
                             std::initializer_list<std::string> global,
                             std::initializer_list<std::string> ignore) {
    // Check if the file exists
    std::ifstream file(file_name);
    if(!file || !std::filesystem::is_regular_file(file_name)) {
        throw ConfigFileUnavailableError(file_name);
    }

    // Convert main file to absolute path
    file_name = std::filesystem::canonical(file_name);
    LOG(TRACE) << "Reading main configuration";

    // Read the file
    ConfigReader reader(file, std::move(file_name));

    // Convert all global and ignored names to lower case and store them
    auto lowercase = [](const std::string& in) { return allpix::transform(in, ::tolower); };
    std::transform(global.begin(), global.end(), std::inserter(global_names_, global_names_.end()), lowercase);
    std::transform(ignore.begin(), ignore.end(), std::inserter(ignore_names_, ignore_names_.end()), lowercase);

    // Initialize global base configuration
    global_config_ = reader.getHeaderConfiguration();

    // Store all the configurations read
    for(auto& config : reader.getConfigurations()) {
        // Skip all ignored sections
        std::string config_name = allpix::transform(config.getName(), ::tolower);
        if(ignore_names_.find(config_name) != ignore_names_.end()) {
            continue;
        }

        // Merge all global section with the global config
        if(global_names_.find(config_name) != global_names_.end()) {
            global_config_.merge(config);
            continue;
        }

        module_configs_.push_back(config);
    }
}

void ConfigManager::parse_detectors() {
    // If detector configurations have been parsed already, skip:
    if(!detector_configs_.empty()) {
        return;
    }

    // Reading detector file
    std::string detector_file_name = global_config_.getPath("detectors_file", true);
    LOG(TRACE) << "Reading detector configuration";

    std::ifstream detector_file(detector_file_name);
    ConfigReader detector_reader(detector_file, detector_file_name);
    auto detector_configs = detector_reader.getConfigurations();
    detector_configs_ = std::list<Configuration>(detector_configs.begin(), detector_configs.end());
}

bool ConfigManager::loadModuleOptions(const std::vector<std::string>& options) {
    bool optionsApplied = false;

    // Parse the options
    for(const auto& option : options) {
        module_option_parser_.parseOption(option);
    }

    // Apply global options
    optionsApplied = module_option_parser_.applyGlobalOptions(global_config_) || optionsApplied;

    // Apply module options
    for(auto& config : module_configs_) {
        optionsApplied = module_option_parser_.applyOptions(config.getName(), config) || optionsApplied;
    }

    return optionsApplied;
}

bool ConfigManager::loadDetectorOptions(const std::vector<std::string>& options) {
    bool optionsApplied = false;

    // Create the parser
    OptionParser detector_option_parser;

    // Parse the options
    for(const auto& option : options) {
        detector_option_parser.parseOption(option);
    }

    // Apply detector options
    parse_detectors();
    for(auto& config : detector_configs_) {
        optionsApplied = detector_option_parser.applyOptions(config.getName(), config) || optionsApplied;
    }

    return optionsApplied;
}

std::list<Configuration>& ConfigManager::getDetectorConfigurations() {
    parse_detectors();
    return detector_configs_;
}

Configuration& ConfigManager::addInstanceConfiguration(const ModuleIdentifier& identifier, const Configuration& config) {
    // Check uniqueness
    if(instance_identifier_to_config_.find(identifier) != instance_identifier_to_config_.end()) {
        throw ModuleIdentifierAlreadyAddedError(identifier);
    }

    // Add configuration
    instance_configs_.push_back(config);
    Configuration& ret_config = instance_configs_.back();
    instance_identifier_to_config_[identifier] = --instance_configs_.end();

    // Add identifier key to config
    ret_config.set<std::string>("identifier", identifier.getIdentifier());

    // Apply instance options
    module_option_parser_.applyOptions(identifier.getUniqueName(), ret_config);
    return ret_config;
}

void ConfigManager::dropInstanceConfiguration(const ModuleIdentifier& identifier) {
    // Remove config from instance configs and from instance identifier map
    if(instance_identifier_to_config_.find(identifier) != instance_identifier_to_config_.end()) {
        instance_configs_.erase(instance_identifier_to_config_[identifier]);
        instance_identifier_to_config_.erase(identifier);
    } else {
        throw ModuleIdentifierNotFoundError(identifier);
    }
}

Updated on 2024-12-13 at 08:31:37 +0000