AbstractSecurityAnalysisCommandOptions.java
/**
* Copyright (c) 2023, 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.security.distributed;
import com.google.common.base.Preconditions;
import com.powsybl.computation.Partition;
import com.powsybl.computation.SimpleCommand;
import com.powsybl.computation.SimpleCommandBuilder;
import com.powsybl.security.LimitViolationType;
import org.apache.commons.lang3.SystemUtils;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.stream.Collectors;
import static com.powsybl.security.tools.SecurityAnalysisToolConstants.*;
import static com.powsybl.tools.ToolConstants.TASK;
import static com.powsybl.tools.ToolConstants.TASK_COUNT;
import static java.util.Objects.requireNonNull;
/**
* @author Laurent Issertial {@literal <laurent.issertial at rte-france.com>}
*/
public abstract class AbstractSecurityAnalysisCommandOptions<T extends AbstractSecurityAnalysisCommandOptions<T>> {
private String itoolsCommand;
private String id;
private Path caseFile;
private Path contingenciesFile;
private Path parametersFile;
private Path actionsFile;
private Path strategiesFile;
private Path limitReductionsFile;
private Integer taskCount;
private IntFunction<Path> outputFile;
private IntFunction<Path> logFile;
private IntFunction<Partition> task;
private String outputFileFormat;
private List<String> resultExtensions;
private List<LimitViolationType> violationTypes;
private boolean absolutePaths;
protected AbstractSecurityAnalysisCommandOptions(String id) {
this.id = id;
this.resultExtensions = new ArrayList<>();
this.violationTypes = new ArrayList<>();
this.absolutePaths = false;
}
public T itoolsCommand(String itoolsCommand) {
this.itoolsCommand = requireNonNull(itoolsCommand);
return self();
}
public T id(String id) {
this.id = requireNonNull(id);
return self();
}
public T absolutePaths(boolean absolutePaths) {
this.absolutePaths = absolutePaths;
return self();
}
public T caseFile(Path caseFile) {
this.caseFile = requireNonNull(caseFile);
return self();
}
public T contingenciesFile(Path contingenciesFile) {
this.contingenciesFile = requireNonNull(contingenciesFile);
return self();
}
public T parametersFile(Path parametersFile) {
this.parametersFile = requireNonNull(parametersFile);
return self();
}
public T actionsFile(Path actionsFile) {
this.actionsFile = actionsFile;
return self();
}
public T strategiesFile(Path strategiesFile) {
this.strategiesFile = strategiesFile;
return self();
}
public T limitReductionsFile(Path limitReductionsFile) {
this.limitReductionsFile = limitReductionsFile;
return self();
}
public T taskCount(int taskCount) {
this.taskCount = taskCount;
return self();
}
public T outputFile(IntFunction<Path> outputFile, String format) {
this.outputFile = requireNonNull(outputFile);
this.outputFileFormat = requireNonNull(format);
return self();
}
public T logFile(Path logFile) {
requireNonNull(logFile);
this.logFile = i -> logFile;
return self();
}
public T logFile(IntFunction<Path> logFile) {
this.logFile = requireNonNull(logFile);
return self();
}
public T outputFile(Path outputFile, String format) {
requireNonNull(outputFile);
this.outputFile = i -> outputFile;
this.outputFileFormat = requireNonNull(format);
return self();
}
public T taskBasedOnIndex(int taskCount) {
return task(i -> new Partition(i + 1, taskCount));
}
public T task(IntFunction<Partition> task) {
this.task = requireNonNull(task);
return self();
}
public T task(Partition task) {
requireNonNull(task);
this.task = i -> task;
return self();
}
public T resultExtension(String extensionName) {
this.resultExtensions.add(requireNonNull(extensionName));
return self();
}
public T resultExtensions(Collection<String> extensionNames) {
this.resultExtensions.addAll(requireNonNull(extensionNames));
return self();
}
public T violationType(LimitViolationType violationType) {
this.violationTypes.add(requireNonNull(violationType));
return self();
}
public T violationTypes(Collection<LimitViolationType> violationTypes) {
this.violationTypes.addAll(requireNonNull(violationTypes));
return self();
}
protected String pathToString(Path path) {
return (absolutePaths ? path.toAbsolutePath() : path).toString();
}
public SimpleCommand toCommand() {
return toCommandBuilder().build();
}
protected SimpleCommandBuilder toCommandBuilder() {
Objects.requireNonNull(caseFile, "Case file is not defined.");
Preconditions.checkArgument(task == null || taskCount == null,
"Options task and task-count may not be defined together.");
SimpleCommandBuilder commandBuilder = new SimpleCommandBuilder()
.id(id)
.program(itoolsCommand != null ? itoolsCommand : getDefaultItoolsCommand())
.arg(getCommandName())
.option(CASE_FILE_OPTION, pathToString(caseFile));
setOptionIfPresent(commandBuilder, PARAMETERS_FILE_OPTION, parametersFile, this::pathToString);
setOptionIfPresent(commandBuilder, ACTIONS_FILE, actionsFile, this::pathToString);
setOptionIfPresent(commandBuilder, STRATEGIES_FILE, strategiesFile, this::pathToString);
setOptionIfPresent(commandBuilder, CONTINGENCIES_FILE_OPTION, contingenciesFile, this::pathToString);
setOptionIfPresent(commandBuilder, LIMIT_REDUCTIONS_FILE, limitReductionsFile, this::pathToString);
setOptionIfPresent(commandBuilder, OUTPUT_FILE_OPTION, outputFile, this::pathToString);
setOptionIfPresent(commandBuilder, OUTPUT_FORMAT_OPTION, outputFileFormat);
setOptionIfPresent(commandBuilder, OUTPUT_LOG_OPTION, logFile, this::pathToString);
if (!resultExtensions.isEmpty()) {
commandBuilder.option(WITH_EXTENSIONS_OPTION, String.join(",", resultExtensions));
}
if (!violationTypes.isEmpty()) {
commandBuilder.option(LIMIT_TYPES_OPTION, violationTypes.stream().map(LimitViolationType::name).collect(Collectors.joining(",")));
}
setOptionIfPresent(commandBuilder, TASK_COUNT, taskCount, i -> Integer.toString(i));
setOptionIfPresent(commandBuilder, TASK, task, Partition::toString);
return commandBuilder;
}
protected void setOptionIfPresent(SimpleCommandBuilder commandBuilder, String optionName, String optionValue) {
if (optionValue != null) {
commandBuilder.option(optionName, optionValue);
}
}
protected <R> void setOptionIfPresent(SimpleCommandBuilder commandBuilder, String optionName, R optionValue, Function<R, String> toString) {
if (optionValue != null) {
commandBuilder.option(optionName, toString.apply(optionValue));
}
}
protected <R> void setOptionIfPresent(SimpleCommandBuilder commandBuilder, String optionName, IntFunction<R> optionValue, Function<R, String> toString) {
if (optionValue != null) {
commandBuilder.option(optionName, i -> toString.apply(optionValue.apply(i)));
}
}
protected abstract String getCommandName();
protected abstract T self();
private static String getDefaultItoolsCommand() {
return SystemUtils.IS_OS_WINDOWS ? "itools.bat" : "itools";
}
}