eu.itesla_project.modules.rules.CheckSecurityTool.java Source code

Java tutorial

Introduction

Here is the source code for eu.itesla_project.modules.rules.CheckSecurityTool.java

Source

/**
 * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium)
 * 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/.
 */
package eu.itesla_project.modules.rules;

import com.google.auto.service.AutoService;
import eu.itesla_project.commons.tools.Command;
import eu.itesla_project.commons.tools.Tool;
import eu.itesla_project.iidm.import_.Importers;
import eu.itesla_project.iidm.network.Network;
import eu.itesla_project.modules.offline.OfflineConfig;
import eu.itesla_project.simulation.securityindexes.SecurityIndexId;
import eu.itesla_project.simulation.securityindexes.SecurityIndexType;
import org.apache.commons.cli.CommandLine;
import org.nocrala.tools.texttablefmt.BorderStyle;
import org.nocrala.tools.texttablefmt.Table;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 * @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
 */
@AutoService(Tool.class)
public class CheckSecurityTool implements Tool {

    private static final Logger LOGGER = LoggerFactory.getLogger(CheckSecurityTool.class);

    private static final char CSV_SEPARATOR = ';';

    @Override
    public Command getCommand() {
        return CheckSecurityCommand.INSTANCE;
    }

    private static void prettyPrint(
            Map<String, Map<SecurityIndexType, SecurityRuleCheckStatus>> checkStatusPerContingency,
            Set<SecurityIndexType> securityIndexTypes) {
        Table table = new Table(1 + securityIndexTypes.size(), BorderStyle.CLASSIC_WIDE);
        table.addCell("Contingency");
        for (SecurityIndexType securityIndexType : securityIndexTypes) {
            table.addCell(securityIndexType.toString());
        }

        for (Map.Entry<String, Map<SecurityIndexType, SecurityRuleCheckStatus>> entry : checkStatusPerContingency
                .entrySet()) {
            String contingencyId = entry.getKey();
            Map<SecurityIndexType, SecurityRuleCheckStatus> checkStatus = entry.getValue();

            table.addCell(contingencyId);

            for (SecurityIndexType securityIndexType : securityIndexTypes) {
                table.addCell(checkStatus.get(securityIndexType).name());
            }
        }

        System.out.println(table.render());
    }

    private static void writeCsv(
            Map<String, Map<SecurityIndexType, SecurityRuleCheckStatus>> checkStatusPerContingency,
            Set<SecurityIndexType> securityIndexTypes, Path outputCsvFile) throws IOException {
        Objects.requireNonNull(outputCsvFile);

        try (BufferedWriter writer = Files.newBufferedWriter(outputCsvFile, StandardCharsets.UTF_8)) {
            writer.write("Contingency");
            for (SecurityIndexType securityIndexType : securityIndexTypes) {
                writer.write(CSV_SEPARATOR);
                writer.write(securityIndexType.toString());
            }
            writer.newLine();

            for (Map.Entry<String, Map<SecurityIndexType, SecurityRuleCheckStatus>> entry : checkStatusPerContingency
                    .entrySet()) {
                String contingencyId = entry.getKey();
                Map<SecurityIndexType, SecurityRuleCheckStatus> checkStatus = entry.getValue();

                writer.write(contingencyId);

                for (SecurityIndexType securityIndexType : securityIndexTypes) {
                    writer.write(CSV_SEPARATOR);
                    writer.write(checkStatus.get(securityIndexType).name());
                }

                writer.newLine();
            }
        }
    }

    private static void writeCsv2(Map<String, Map<SecurityIndexId, SecurityRuleCheckStatus>> checkStatusPerBaseCase,
            Path outputCsvFile) throws IOException {
        Objects.requireNonNull(outputCsvFile);

        Set<SecurityIndexId> securityIndexIds = new LinkedHashSet<>();
        for (Map<SecurityIndexId, SecurityRuleCheckStatus> checkStatus : checkStatusPerBaseCase.values()) {
            securityIndexIds.addAll(checkStatus.keySet());
        }

        try (BufferedWriter writer = Files.newBufferedWriter(outputCsvFile, StandardCharsets.UTF_8)) {
            writer.write("Base case");
            for (SecurityIndexId securityIndexId : securityIndexIds) {
                writer.write(CSV_SEPARATOR);
                writer.write(securityIndexId.toString());
            }
            writer.newLine();

            for (Map.Entry<String, Map<SecurityIndexId, SecurityRuleCheckStatus>> entry : checkStatusPerBaseCase
                    .entrySet()) {
                String baseCaseName = entry.getKey();
                writer.write(baseCaseName);

                Map<SecurityIndexId, SecurityRuleCheckStatus> checkStatus = entry.getValue();
                for (SecurityIndexId securityIndexId : securityIndexIds) {
                    writer.write(CSV_SEPARATOR);
                    SecurityRuleCheckStatus status = checkStatus.get(securityIndexId);
                    writer.write(status.name());
                }

                writer.newLine();
            }
        }
    }

    @Override
    public void run(CommandLine line) throws Exception {
        OfflineConfig config = OfflineConfig.load();
        Path caseFile = Paths.get(line.getOptionValue("case-file"));
        Objects.requireNonNull(caseFile);
        String rulesDbName = line.hasOption("rules-db-name") ? line.getOptionValue("rules-db-name")
                : OfflineConfig.DEFAULT_RULES_DB_NAME;
        RulesDbClientFactory rulesDbClientFactory = config.getRulesDbClientFactoryClass().newInstance();
        String workflowId = line.getOptionValue("workflow");
        RuleAttributeSet attributeSet = RuleAttributeSet.valueOf(line.getOptionValue("attribute-set"));
        double purityThreshold = line.hasOption("purity-threshold")
                ? Double.parseDouble(line.getOptionValue("purity-threshold"))
                : CheckSecurityCommand.DEFAULT_PURITY_THRESHOLD;
        Path outputCsvFile = null;
        if (line.hasOption("output-csv-file")) {
            outputCsvFile = Paths.get(line.getOptionValue("output-csv-file"));
        }
        Set<SecurityIndexType> securityIndexTypes = line.hasOption("security-index-types")
                ? Arrays.stream(line.getOptionValue("security-index-types").split(","))
                        .map(SecurityIndexType::valueOf).collect(Collectors.toSet())
                : EnumSet.allOf(SecurityIndexType.class);
        final Set<String> contingencies = line.hasOption("contingencies")
                ? Arrays.stream(line.getOptionValue("contingencies").split(",")).collect(Collectors.toSet())
                : null;

        try (RulesDbClient rulesDb = rulesDbClientFactory.create(rulesDbName)) {

            if (Files.isRegularFile(caseFile)) {
                System.out.println("loading case " + caseFile + "...");
                // load the network
                Network network = Importers.loadNetwork(caseFile);
                if (network == null) {
                    throw new RuntimeException("Case '" + caseFile + "' not found");
                }
                network.getStateManager().allowStateMultiThreadAccess(true);

                System.out.println("checking rules...");

                Map<String, Map<SecurityIndexType, SecurityRuleCheckStatus>> checkStatusPerContingency = SecurityRuleUtil
                        .checkRules(network, rulesDb, workflowId, attributeSet, securityIndexTypes, contingencies,
                                purityThreshold);

                if (outputCsvFile == null) {
                    prettyPrint(checkStatusPerContingency, securityIndexTypes);
                } else {
                    writeCsv(checkStatusPerContingency, securityIndexTypes, outputCsvFile);
                }
            } else if (Files.isDirectory(caseFile)) {
                if (outputCsvFile == null) {
                    throw new RuntimeException(
                            "In case of multiple impact security checks, only output to csv file is supported");
                }
                Map<String, Map<SecurityIndexId, SecurityRuleCheckStatus>> checkStatusPerBaseCase = Collections
                        .synchronizedMap(new LinkedHashMap<>());
                Importers.loadNetworks(caseFile, true, network -> {
                    try {
                        Map<String, Map<SecurityIndexType, SecurityRuleCheckStatus>> checkStatusPerContingency = SecurityRuleUtil
                                .checkRules(network, rulesDb, workflowId, attributeSet, securityIndexTypes,
                                        contingencies, purityThreshold);

                        Map<SecurityIndexId, SecurityRuleCheckStatus> checkStatusMap = new HashMap<>();
                        for (Map.Entry<String, Map<SecurityIndexType, SecurityRuleCheckStatus>> entry : checkStatusPerContingency
                                .entrySet()) {
                            String contingencyId = entry.getKey();
                            for (Map.Entry<SecurityIndexType, SecurityRuleCheckStatus> entry1 : entry.getValue()
                                    .entrySet()) {
                                SecurityIndexType type = entry1.getKey();
                                SecurityRuleCheckStatus status = entry1.getValue();
                                checkStatusMap.put(new SecurityIndexId(contingencyId, type), status);
                            }
                        }

                        checkStatusPerBaseCase.put(network.getId(), checkStatusMap);
                    } catch (Exception e) {
                        LOGGER.error(e.toString(), e);
                    }
                }, dataSource -> System.out.println("loading case " + dataSource.getBaseName() + "..."));

                writeCsv2(checkStatusPerBaseCase, outputCsvFile);
            }
        }
    }

}