BaseVoltagesConfig.java
/**
* Copyright (c) 2019, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.commons.config;
import com.powsybl.commons.PowsyblException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;
/**
*
* @author Massimo Ferraro {@literal <massimo.ferraro@techrain.eu>}
* @author Florian Dupuy {@literal <florian.dupuy at rte-france.com>}
*/
public class BaseVoltagesConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(BaseVoltagesConfig.class);
private static final String DEFAULT_CONFIG_FILE_NAME = "base-voltages.yml";
private List<BaseVoltageConfig> baseVoltages = new ArrayList<>();
private String defaultProfile;
public List<BaseVoltageConfig> getBaseVoltages() {
return baseVoltages;
}
public void setBaseVoltages(List<BaseVoltageConfig> baseVoltages) {
this.baseVoltages = baseVoltages == null ? Collections.emptyList() : baseVoltages;
}
public String getDefaultProfile() {
return defaultProfile;
}
public void setDefaultProfile(String defaultProfile) {
this.defaultProfile = Objects.requireNonNull(defaultProfile);
}
public static BaseVoltagesConfig fromPlatformConfig() {
return fromPlatformConfig(PlatformConfig.defaultConfig());
}
public static BaseVoltagesConfig fromPlatformConfig(PlatformConfig platformConfig) {
return fromPlatformConfig(platformConfig, DEFAULT_CONFIG_FILE_NAME);
}
public static BaseVoltagesConfig fromPlatformConfig(PlatformConfig platformConfig, String configFileName) {
return platformConfig.getConfigDir()
.map(configDir -> fromPath(configDir, configFileName))
.orElseGet(() -> {
LOGGER.warn("Configuration directory not defined in platform config, trying to load file '{}' from resources", configFileName);
return fromResources(configFileName);
});
}
public static BaseVoltagesConfig fromInputStream(InputStream configInputStream) {
Objects.requireNonNull(configInputStream);
Yaml yaml = new Yaml(new BaseVoltagesConfigConstructor());
return yaml.load(configInputStream);
}
public static BaseVoltagesConfig fromPath(Path configDir, String configFileName) {
Objects.requireNonNull(configDir);
Objects.requireNonNull(configFileName);
Path configFile = configDir.resolve(configFileName);
if (Files.exists(configFile)) {
try (InputStream configInputStream = Files.newInputStream(configFile)) {
return fromInputStream(configInputStream);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
} else {
LOGGER.warn("Base voltage configuration file '{}' not found, trying to load file '{}' from resources", configFile, configFileName);
return fromResources(configFileName);
}
}
private static BaseVoltagesConfig fromResources(String configFileName) {
InputStream configInputStream = BaseVoltagesConfig.class.getResourceAsStream("/" + configFileName);
if (configInputStream != null) {
return fromInputStream(configInputStream);
} else {
throw new PowsyblException("No base voltages configuration found in resources: " + configFileName);
}
}
public List<String> getProfiles() {
return getBaseVoltages()
.stream()
.map(BaseVoltageConfig::getProfile)
.distinct()
.collect(Collectors.toList());
}
public List<String> getBaseVoltageNames(String profile) {
Objects.requireNonNull(profile);
return getBaseVoltages()
.stream()
.filter(baseVoltage -> baseVoltage.getProfile().equals(profile))
.map(BaseVoltageConfig::getName)
.collect(Collectors.toList());
}
public Optional<String> getBaseVoltageName(double baseVoltage, String profile) {
Objects.requireNonNull(profile);
return getBaseVoltages()
.stream()
.filter(v -> v.getProfile().equals(profile)
&& v.getMinValue() <= baseVoltage
&& v.getMaxValue() > baseVoltage)
.map(BaseVoltageConfig::getName)
.findFirst();
}
private static class BaseVoltagesConfigConstructor extends Constructor {
private static final List<String> BASE_VOLTAGES_CONFIG_REQUIRED_FIELDS = Arrays.asList("baseVoltages", "defaultProfile");
private static final List<String> BASE_VOLTAGE_CONFIG_REQUIRED_FIELDS = Arrays.asList("name", "minValue", "maxValue", "profile");
BaseVoltagesConfigConstructor() {
super(BaseVoltagesConfig.class, new LoaderOptions());
}
@Override
protected Object constructObject(Node node) {
if (node.getTag().equals(rootTag)) {
checkRequiredFields(node, new LinkedList<>(BASE_VOLTAGES_CONFIG_REQUIRED_FIELDS), BaseVoltagesConfig.class);
} else if (node.getType().equals(BaseVoltageConfig.class)) {
checkRequiredFields(node, new LinkedList<>(BASE_VOLTAGE_CONFIG_REQUIRED_FIELDS), node.getType());
}
return super.constructObject(node);
}
private void checkRequiredFields(Node node, List<String> requiredFields, Class<?> aClass) {
if (node instanceof MappingNode mappingNode) {
for (NodeTuple nodeTuple : mappingNode.getValue()) {
Node keyNode = nodeTuple.getKeyNode();
if (keyNode instanceof ScalarNode scalarNode) {
requiredFields.remove(scalarNode.getValue());
}
}
}
if (!requiredFields.isEmpty()) {
throw new YAMLException(aClass + " is missing " + String.join(", ", requiredFields));
}
}
}
}