diff --git a/case-repository/pom.xml b/case-repository/pom.xml index 5c03568f..6f556767 100644 --- a/case-repository/pom.xml +++ b/case-repository/pom.xml @@ -39,11 +39,6 @@ ucte-util ${project.version} - - junit - junit - 4.12 - org.jboss.shrinkwrap shrinkwrap-impl-nio2 diff --git a/modules/pom.xml b/modules/pom.xml index f9a72cfd..c133b7d2 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -114,6 +114,17 @@ mockito-all test + + ${project.groupId} + iidm-network-impl + ${project.version} + test + + + org.slf4j + log4j-over-slf4j + test + diff --git a/modules/src/main/java/eu/itesla_project/modules/constraints/ConstraintsModifier.java b/modules/src/main/java/eu/itesla_project/modules/constraints/ConstraintsModifier.java new file mode 100644 index 00000000..226388a2 --- /dev/null +++ b/modules/src/main/java/eu/itesla_project/modules/constraints/ConstraintsModifier.java @@ -0,0 +1,296 @@ +/** + * Copyright (c) 2016, 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/. + */ +package eu.itesla_project.modules.constraints; + +import java.util.HashSet; +import java.util.List; +import java.util.Objects; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import eu.itesla_project.iidm.network.Line; +import eu.itesla_project.iidm.network.Network; +import eu.itesla_project.iidm.network.StateManager; +import eu.itesla_project.iidm.network.TwoTerminalsConnectable; +import eu.itesla_project.iidm.network.TwoWindingsTransformer; +import eu.itesla_project.iidm.network.VoltageLevel; +import eu.itesla_project.modules.security.LimitViolation; +import eu.itesla_project.modules.security.LimitViolationFilter; +import eu.itesla_project.modules.security.LimitViolationType; +import eu.itesla_project.modules.security.Security; + +/** + * + * @author Quinary + */ +public class ConstraintsModifier { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConstraintsModifier.class); + + private Network network; + private ConstraintsModifierConfig config; + + public ConstraintsModifier(Network network) { + this(network, ConstraintsModifierConfig.load()); + } + + public ConstraintsModifier(Network network, ConstraintsModifierConfig config) { + LOGGER.info(config.toString()); + this.network = network; + this.config = config; + } + + public void looseConstraints(String stateId) { + looseConstraints(stateId, 0f, false); + } + + public void looseConstraints(String stateId, float margin) { + looseConstraints(stateId, margin, false); + } + + public void looseConstraints(String stateId, float margin, boolean applyToBaseCase) { + if ( network.getStateManager().getStateIds().contains(stateId) ) { + String workingStateId = network.getStateManager().getWorkingStateId(); + network.getStateManager().setWorkingState(stateId); + List violations = Security.checkLimits(network); + looseConstraints(stateId, violations, margin, applyToBaseCase); + network.getStateManager().setWorkingState(workingStateId); + } else { + throw new RuntimeException("No "+stateId+" in network "+network.getId()+": cannot loose constraints"); + } + } + + public void looseConstraints(String stateId, List violations) { + looseConstraints(stateId, violations, 0f, false); + } + + public void looseConstraints(String stateId, List violations, float margin) { + looseConstraints(stateId, violations, margin, false); + } + + public void looseConstraints(String stateId, List violations, float margin, boolean applyToBaseCase) { + Objects.requireNonNull(stateId, "state id is null"); + Objects.requireNonNull(violations, "violations is null"); + if ( network.getStateManager().getStateIds().contains(stateId) ) { + String workingStateId = network.getStateManager().getWorkingStateId(); + network.getStateManager().setWorkingState(stateId); + LOGGER.info("Loosening constraints of network {}, state {}, using margin {}", + network.getId(), + network.getStateManager().getWorkingStateId(), + margin); + LimitViolationFilter violationsFilter = new LimitViolationFilter(new HashSet(config.getViolationsTypes()), 0); + List filteredViolations = violationsFilter.apply(violations); + String report = Security.printLimitsViolations(violations, violationsFilter);; + if (report != null) { + LOGGER.debug("Fixing constraints of network {}, state {}, causing the following {} violations:\n{}", + network.getId(), + network.getStateManager().getWorkingStateId(), + filteredViolations.size(), + report); + } + for (LimitViolation violation : filteredViolations) { + LOGGER.debug("Fixing the constraints causing the {} violation on equipment {}", + violation.getLimitType(), + violation.getSubject().getId()); + switch (violation.getLimitType()) { + case CURRENT: + setNewCurrentLimit(stateId, violation, margin, applyToBaseCase); + break; + case HIGH_VOLTAGE: + setNewHighVoltageLimit(stateId, violation, margin, applyToBaseCase); + break; + case LOW_VOLTAGE: + setNewLowVoltageLimit(stateId, violation, margin, applyToBaseCase); + break; + } + } + network.getStateManager().setWorkingState(workingStateId); + } else { + throw new RuntimeException("No "+stateId+" in network "+network.getId()+": cannot loose constraints"); + } + } + + private void setNewCurrentLimit(String stateId, LimitViolation violation, float margin, boolean applyToBaseCase) { + TwoTerminalsConnectable violatedBranch = (TwoTerminalsConnectable) violation.getSubject(); + // not sure if I need to reload the branch from the network ... + TwoTerminalsConnectable branch = null; + if ( violatedBranch instanceof Line ) + branch = network.getLine(violatedBranch.getId()); + else if ( violatedBranch instanceof TwoWindingsTransformer ) + branch = network.getTwoWindingsTransformer(violatedBranch.getId()); + if ( branch != null ) { + float newLimit = getNewUpperLimit(violation, margin); + if ( branch.getTerminal1().getI() == violation.getValue() ) { + LOGGER.debug("State {}: changing current limit 1 of branch {}: {} -> {}", + stateId, + branch.getId(), + violation.getLimit(), + newLimit); + branch.newCurrentLimits1().setPermanentLimit(newLimit).add(); + if ( applyToBaseCase && !StateManager.INITIAL_STATE_ID.equals(stateId) ) { // change the limit also to basecase + String initialStateId = StateManager.INITIAL_STATE_ID; + network.getStateManager().setWorkingState(initialStateId); + if ( violatedBranch instanceof Line ) + branch = network.getLine(violatedBranch.getId()); + else if ( violatedBranch instanceof TwoWindingsTransformer ) + branch = network.getTwoWindingsTransformer(violatedBranch.getId()); + if ( branch != null ) { + LOGGER.debug("State {}: changing current limit 1 of branch {}: {} -> {}", + initialStateId, + branch.getId(), + violation.getLimit(), + newLimit); + branch.newCurrentLimits1().setPermanentLimit(newLimit).add(); + } else { + LOGGER.warn("State {}: cannot change current limit of branch {}: no branch with this id in the network", + initialStateId, + violatedBranch.getId()); + } + network.getStateManager().setWorkingState(stateId); + } + } else if ( branch.getTerminal2().getI() == violation.getValue() ) { + LOGGER.debug("State {}: changing current limit 2 of branch {}: {} -> {}", + stateId, + branch.getId(), + violation.getLimit(), + newLimit); + branch.newCurrentLimits2().setPermanentLimit(newLimit).add(); + if ( applyToBaseCase && !StateManager.INITIAL_STATE_ID.equals(stateId) ) { // change the limit also to basecase + String initialStateId = StateManager.INITIAL_STATE_ID; + network.getStateManager().setWorkingState(initialStateId); + if ( violatedBranch instanceof Line ) + branch = network.getLine(violatedBranch.getId()); + else if ( violatedBranch instanceof TwoWindingsTransformer ) + branch = network.getTwoWindingsTransformer(violatedBranch.getId()); + if ( branch != null ) { + LOGGER.debug("State {}: changing current limit 2 of branch {}: {} -> {}", + initialStateId, + branch.getId(), + violation.getLimit(), + newLimit); + branch.newCurrentLimits2().setPermanentLimit(newLimit).add(); + } else { + LOGGER.warn("State {}: cannot change current limit of branch {}: no branch with this id in the network", + initialStateId, + violatedBranch.getId()); + } + network.getStateManager().setWorkingState(stateId); + } + } + } else { + LOGGER.warn("State {}: cannot change current limit of branch {}: no branch with this id in the network", + stateId, + violatedBranch.getId()); + } + } + + private void setNewHighVoltageLimit(String stateId, LimitViolation violation, float margin, boolean applyToBaseCase) { + VoltageLevel violatedVoltageLevel = (VoltageLevel) violation.getSubject(); + VoltageLevel voltageLevel = network.getVoltageLevel(violatedVoltageLevel.getId()); + if ( voltageLevel != null ) { + if ( violation.getValue() > voltageLevel.getHighVoltageLimit() ) { // it could already have been fixed + float newLimit = getNewUpperLimit(violation, margin); + LOGGER.debug("State {}: changing high voltage limit of voltage level {}: {} -> {}", + stateId, + voltageLevel.getId(), + violation.getLimit(), + newLimit); + voltageLevel.setHighVoltageLimit(newLimit); + if ( applyToBaseCase && !StateManager.INITIAL_STATE_ID.equals(stateId) ) { // change the limit also to basecase + String initialStateId = StateManager.INITIAL_STATE_ID; + network.getStateManager().setWorkingState(initialStateId); + voltageLevel = network.getVoltageLevel(violatedVoltageLevel.getId()); + if ( voltageLevel != null ) { + LOGGER.debug("State {}: changing high voltage limit of voltage level {}: {} -> {}", + initialStateId, + voltageLevel.getId(), + violation.getLimit(), + newLimit); + voltageLevel.setHighVoltageLimit(newLimit); + } else { + LOGGER.warn("State {}: cannot change high voltage limit of voltage level {}: no voltage level with this id in the network", + initialStateId, + violatedVoltageLevel.getId()); + } + network.getStateManager().setWorkingState(stateId); + } + } + } else { + LOGGER.warn("State {}: cannot change high voltage limit of voltage level {}: no voltage level with this id in the network", + stateId, + violatedVoltageLevel.getId()); + } + } + + private void setNewLowVoltageLimit(String stateId, LimitViolation violation, float margin, boolean applyToBaseCase) { + VoltageLevel violatedVoltageLevel = (VoltageLevel) violation.getSubject(); + VoltageLevel voltageLevel = network.getVoltageLevel(violatedVoltageLevel.getId()); + if ( voltageLevel != null ) { + if ( violation.getValue() < voltageLevel.getLowVoltageLimit() ) { // it could already have been fixed + float newLimit = getNewLowerLimit(violation, margin); + LOGGER.debug("State {}: changing low voltage limit of voltage level {}: {} -> {}", + stateId, + voltageLevel.getId(), + violation.getLimit(), + newLimit); + voltageLevel.setLowVoltageLimit(newLimit); + if ( applyToBaseCase && !StateManager.INITIAL_STATE_ID.equals(stateId) ) { // change the limit also to basecase + String initialStateId = StateManager.INITIAL_STATE_ID; + network.getStateManager().setWorkingState(initialStateId); + voltageLevel = network.getVoltageLevel(violatedVoltageLevel.getId()); + if ( voltageLevel != null ) { + LOGGER.debug("State {}: changing low voltage limit of voltage level {}: {} -> {}", + initialStateId, + voltageLevel.getId(), + violation.getLimit(), + newLimit); + voltageLevel.setLowVoltageLimit(newLimit); + } else { + LOGGER.warn("State {}: cannot change high voltage limit of voltage level {}: no voltage level with this id in the network", + initialStateId, + violatedVoltageLevel.getId()); + } + network.getStateManager().setWorkingState(stateId); + } + } + } else { + LOGGER.warn("State {}: cannot change low voltage limit of voltage level {}: no voltage level with this id in the network", + stateId, + violatedVoltageLevel.getId()); + } + } + + private float getNewUpperLimit(LimitViolation violation, float margin) { + float newLimit = 9999; + if ( config.isInAreaOfInterest(violation, network) ) { + float increment = (float) ((violation.getLimit() == 0) + ? Math.ceil(violation.getValue()*100) + : Math.ceil((violation.getValue()-violation.getLimit())*100/violation.getLimit())); + increment += margin; + newLimit = (violation.getLimit() == 0) + ? (increment/100) + : (violation.getLimit()+(violation.getLimit()*increment/100)); + } + return newLimit; + } + + private float getNewLowerLimit(LimitViolation violation, float margin) { + float newLimit = -9999; + if ( config.isInAreaOfInterest(violation, network) ) { + float increment = (float) ((violation.getLimit() == 0) + ? Math.ceil(-violation.getValue()*100) + : Math.ceil((violation.getLimit()-violation.getValue())*100/violation.getLimit())); + increment += margin; + newLimit = (violation.getLimit() == 0) + ? (increment/100) + : (violation.getLimit()-(violation.getLimit()*increment/100)); + } + return newLimit; + } + +} diff --git a/modules/src/main/java/eu/itesla_project/modules/constraints/ConstraintsModifierConfig.java b/modules/src/main/java/eu/itesla_project/modules/constraints/ConstraintsModifierConfig.java new file mode 100644 index 00000000..f49b670b --- /dev/null +++ b/modules/src/main/java/eu/itesla_project/modules/constraints/ConstraintsModifierConfig.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2016, 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/. + */ +package eu.itesla_project.modules.constraints; + +import java.util.Arrays; +import java.util.List; + +import eu.itesla_project.commons.io.ModuleConfig; +import eu.itesla_project.commons.io.PlatformConfig; +import eu.itesla_project.iidm.network.Country; +import eu.itesla_project.iidm.network.Network; +import eu.itesla_project.modules.security.LimitViolation; +import eu.itesla_project.modules.security.LimitViolationType; + +/** + * + * @author Quinary + */ +public class ConstraintsModifierConfig { + + public static final List DEFAULT_VIOLATION_TYPES = Arrays.asList(LimitViolationType.CURRENT); + public static final Country DEFAULT_COUNTRY = null; + + private final Country country; + private final List violationsTypes; + + public static ConstraintsModifierConfig load() { + return load(PlatformConfig.defaultConfig()); + } + + public static ConstraintsModifierConfig load(PlatformConfig platformConfig) { + List violationsTypes; + Country country; + if (platformConfig.moduleExists("constraintsModifier")) { + ModuleConfig config = platformConfig.getModuleConfig("constraintsModifier"); + violationsTypes = config.getEnumListProperty("violationsTypes", LimitViolationType.class, DEFAULT_VIOLATION_TYPES); + String countryStr = config.getStringProperty("country", null); + country = ( countryStr == null ) ? DEFAULT_COUNTRY : Country.valueOf(countryStr); + } else { + violationsTypes = DEFAULT_VIOLATION_TYPES; + country = DEFAULT_COUNTRY; + } + return new ConstraintsModifierConfig(country, violationsTypes); + } + + public ConstraintsModifierConfig(Country country, List violationsTypes) { + this.country = country; + this.violationsTypes = violationsTypes; + } + + public Country getCountry() { + return country; + } + + public List getViolationsTypes() { + return violationsTypes; + } + + public boolean isInAreaOfInterest(LimitViolation violation, Network network) { + if ( country != null ) + return violation.getCountry() == country; + return true; + } + + @Override + public String toString() { + return "ConstraintsModifierConfig[country="+country+",violation types="+violationsTypes.toString()+"]"; + } + +} diff --git a/modules/src/main/java/eu/itesla_project/modules/online/OnlineWorkflowParameters.java b/modules/src/main/java/eu/itesla_project/modules/online/OnlineWorkflowParameters.java index e2cab614..823a6e0b 100644 --- a/modules/src/main/java/eu/itesla_project/modules/online/OnlineWorkflowParameters.java +++ b/modules/src/main/java/eu/itesla_project/modules/online/OnlineWorkflowParameters.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) + * Copyright (c) 2016, 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/. @@ -28,11 +29,11 @@ * @author Quinary */ public class OnlineWorkflowParameters implements Serializable { - - /* - * example of online-default-parameters.properties file. - * - + + /* + * example of online-default-parameters.properties file. + * + # basecase to be analyzed baseCaseDate=2013-01-15T18:30:00+01:00 # number of states @@ -56,13 +57,15 @@ public class OnlineWorkflowParameters implements Serializable { # list of security indexes to be used by the workflow, leave empty to use all the available ones securityIndexes=SMALLSIGNAL,TSO_SYNCHROLOSS,TSO_GENERATOR_VOLTAGE_AUTOMATON - */ + */ private static final long serialVersionUID = 1L; public static final CaseType DEFAULT_CASE_TYPE = CaseType.FO; public static final List DEFAULT_COUNTRIES = Arrays.asList(Country.FR); public static final boolean DAFAULT_MERGE_OPTIMIZED = false; public static final float DEFAULT_LIMIT_REDUCTION = 1f; + public static final boolean DAFAULT_HANDLE_VIOLATIONS_IN_N = false; + public static final float DEFAULT_CONSTRAINT_MARGIN = 0f; private DateTime baseCaseDate; private int states; @@ -71,7 +74,7 @@ public class OnlineWorkflowParameters implements Serializable { private TimeHorizon timeHorizon; private String feAnalysisId; private double rulesPurityThreshold; - private boolean storeStates; + private boolean storeStates; private boolean analyseBasecase; private boolean validation; private Set securityIndexes; @@ -79,8 +82,10 @@ public class OnlineWorkflowParameters implements Serializable { private Set countries; private boolean mergeOptimized; private float limitReduction; + private boolean handleViolationsInN; + private float constraintMargin; - public static OnlineWorkflowParameters loadDefault() { + public static OnlineWorkflowParameters loadDefault() { ModuleConfig config = PlatformConfig.defaultConfig().getModuleConfig("online-default-parameters"); DateTime baseCaseDate = DateTime.parse(config.getStringProperty("baseCaseDate")); int states = config.getIntProperty("states"); @@ -93,38 +98,43 @@ public static OnlineWorkflowParameters loadDefault() { boolean analyseBasecase = config.getBooleanProperty("analyseBasecase", true); boolean validation = config.getBooleanProperty("validation", false); Set securityIndexes = null; - String securityIndexesAsString = config.getStringProperty("securityIndexes", ""); - if ( !"".equals(securityIndexesAsString) ) { - securityIndexes = Arrays.stream(securityIndexesAsString.split(",")) + String securityIndexesAsString = config.getStringProperty("securityIndexes", ""); + if ( !"".equals(securityIndexesAsString) ) { + securityIndexes = Arrays.stream(securityIndexesAsString.split(",")) .map(SecurityIndexType::valueOf) .collect(Collectors.toSet()); - } - CaseType caseType = config.getEnumProperty("caseType", CaseType.class, DEFAULT_CASE_TYPE); - Set countries = new HashSet<>(config.getEnumListProperty("countries", Country.class, DEFAULT_COUNTRIES)); - boolean mergeOptimized = config.getBooleanProperty("mergeOptimized", DAFAULT_MERGE_OPTIMIZED); - float limitReduction = config.getFloatProperty("limitReduction", DEFAULT_LIMIT_REDUCTION); - + } + CaseType caseType = config.getEnumProperty("caseType", CaseType.class, DEFAULT_CASE_TYPE); + Set countries = new HashSet<>(config.getEnumListProperty("countries", Country.class, DEFAULT_COUNTRIES)); + boolean mergeOptimized = config.getBooleanProperty("mergeOptimized", DAFAULT_MERGE_OPTIMIZED); + float limitReduction = config.getFloatProperty("limitReduction", DEFAULT_LIMIT_REDUCTION); + boolean handleViolationsInN = config.getBooleanProperty("handleViolationsInN", DAFAULT_HANDLE_VIOLATIONS_IN_N); + float constraintMargin = config.getFloatProperty("constraintMargin", DEFAULT_CONSTRAINT_MARGIN); + return new OnlineWorkflowParameters(baseCaseDate, - states, - histoInterval, - offlineWorkflowId, - timeHorizon, - feAnalysisId, - rulesPurityThreshold, - storeStates, - analyseBasecase, - validation, - securityIndexes, - caseType, - countries, - mergeOptimized, - limitReduction - ); + states, + histoInterval, + offlineWorkflowId, + timeHorizon, + feAnalysisId, + rulesPurityThreshold, + storeStates, + analyseBasecase, + validation, + securityIndexes, + caseType, + countries, + mergeOptimized, + limitReduction, + handleViolationsInN, + constraintMargin + ); } public OnlineWorkflowParameters(DateTime baseCaseDate, int states, Interval histoInterval, String offlineWorkflowId, TimeHorizon timeHorizon, - String feAnalysisId, double rulesPurityThreshold, boolean storeStates, boolean analyseBasecase, boolean validation, - Set securityIndexes, CaseType caseType, Set countries, boolean mergeOptimized, float limitReduction) { + String feAnalysisId, double rulesPurityThreshold, boolean storeStates, boolean analyseBasecase, boolean validation, + Set securityIndexes, CaseType caseType, Set countries, boolean mergeOptimized, + float limitReduction, boolean handleViolationsInN, float constraintMargin) { Objects.requireNonNull(baseCaseDate); Objects.requireNonNull(histoInterval); this.baseCaseDate = baseCaseDate; @@ -142,6 +152,8 @@ public OnlineWorkflowParameters(DateTime baseCaseDate, int states, Interval hist this.countries = countries; this.mergeOptimized = mergeOptimized; this.limitReduction = limitReduction; + this.handleViolationsInN = handleViolationsInN; + this.constraintMargin = constraintMargin; } public DateTime getBaseCaseDate() { @@ -153,56 +165,64 @@ public Interval getHistoInterval() { } public int getStates() { - return states; + return states; } public String getOfflineWorkflowId() { - return offlineWorkflowId; + return offlineWorkflowId; } public TimeHorizon getTimeHorizon() { - return timeHorizon; + return timeHorizon; } - + public String getFeAnalysisId() { - return feAnalysisId; + return feAnalysisId; } - + public double getRulesPurityThreshold() { - return rulesPurityThreshold; - } + return rulesPurityThreshold; + } public boolean storeStates() { - return storeStates; + return storeStates; } - + public boolean analyseBasecase() { - return analyseBasecase; + return analyseBasecase; } - + public boolean validation() { - return validation; + return validation; } - + public Set getSecurityIndexes() { - return securityIndexes; - } - + return securityIndexes; + } + public CaseType getCaseType() { - return caseType; - } - + return caseType; + } + public Set getCountries() { - return countries; - } - - public boolean isMergeOptimized() { - return mergeOptimized; - } - - public float getLimitReduction() { - return limitReduction; - } + return countries; + } + + public boolean isMergeOptimized() { + return mergeOptimized; + } + + public float getLimitReduction() { + return limitReduction; + } + + public boolean isHandleViolationsInN() { + return handleViolationsInN; + } + + public float getConstraintMargin() { + return constraintMargin; + } @Override public String toString() { @@ -221,67 +241,77 @@ public String toString() { + ", countries=" + countries + ", mergeOptimized=" + mergeOptimized + ", limitReduction=" + limitReduction + + ", handleViolationsInN=" + handleViolationsInN + + ", constraintMargin=" + constraintMargin + "}"; } - public void setStates(int states) { - this.states = states; - } - - public void setBaseCaseDate(DateTime baseCaseDate) { - this.baseCaseDate = baseCaseDate; - } - - public void setHistoInterval(Interval histoInterval) { - this.histoInterval = histoInterval; - } - - public void setOfflineWorkflowId(String offlineWorkflowId) { - this.offlineWorkflowId = offlineWorkflowId; - } - - public void setTimeHorizon(TimeHorizon timeHorizon) { - this.timeHorizon = timeHorizon; - } - - public void setFeAnalysisId(String feAnalysisId) { - this.feAnalysisId = feAnalysisId; - } - - public void setRulesPurityThreshold(double rulesPurityThreshold) { - this.rulesPurityThreshold = rulesPurityThreshold; - } - - public void setStoreStates(boolean storeStates) { - this.storeStates = storeStates; - } - - public void setAnalyseBasecase(boolean analyseBasecase) { - this.analyseBasecase = analyseBasecase; - } - - public void setValidation(boolean validation) { - this.validation = validation; - } - - public void setSecurityIndexes(Set securityIndexes) { - this.securityIndexes = securityIndexes; - } - - public void setCaseType(CaseType caseType) { - this.caseType = caseType; - } - - public void setCountries(Set countries) { - this.countries = countries; - } - - public void setMergeOptimized(boolean mergeOptimized) { - this.mergeOptimized = mergeOptimized; - } - - public void setLimitReduction(float limitReduction) { - this.limitReduction = limitReduction; - } - + public void setStates(int states) { + this.states = states; + } + + public void setBaseCaseDate(DateTime baseCaseDate) { + this.baseCaseDate = baseCaseDate; + } + + public void setHistoInterval(Interval histoInterval) { + this.histoInterval = histoInterval; + } + + public void setOfflineWorkflowId(String offlineWorkflowId) { + this.offlineWorkflowId = offlineWorkflowId; + } + + public void setTimeHorizon(TimeHorizon timeHorizon) { + this.timeHorizon = timeHorizon; + } + + public void setFeAnalysisId(String feAnalysisId) { + this.feAnalysisId = feAnalysisId; + } + + public void setRulesPurityThreshold(double rulesPurityThreshold) { + this.rulesPurityThreshold = rulesPurityThreshold; + } + + public void setStoreStates(boolean storeStates) { + this.storeStates = storeStates; + } + + public void setAnalyseBasecase(boolean analyseBasecase) { + this.analyseBasecase = analyseBasecase; + } + + public void setValidation(boolean validation) { + this.validation = validation; + } + + public void setSecurityIndexes(Set securityIndexes) { + this.securityIndexes = securityIndexes; + } + + public void setCaseType(CaseType caseType) { + this.caseType = caseType; + } + + public void setCountries(Set countries) { + this.countries = countries; + } + + public void setMergeOptimized(boolean mergeOptimized) { + this.mergeOptimized = mergeOptimized; + } + + public void setLimitReduction(float limitReduction) { + this.limitReduction = limitReduction; + } + + public void setHandleViolationsInN(boolean handleViolationsInN) { + this.handleViolationsInN = handleViolationsInN; + } + + public void setConstraintMargin(float constraintMargin) { + this.constraintMargin = constraintMargin; + } + } diff --git a/modules/src/main/java/eu/itesla_project/modules/online/OnlineWorkflowRulesResults.java b/modules/src/main/java/eu/itesla_project/modules/online/OnlineWorkflowRulesResults.java index 1830c18b..3976eea7 100644 --- a/modules/src/main/java/eu/itesla_project/modules/online/OnlineWorkflowRulesResults.java +++ b/modules/src/main/java/eu/itesla_project/modules/online/OnlineWorkflowRulesResults.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) + * Copyright (c) 2016, 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/. @@ -10,6 +11,8 @@ import java.util.List; import java.util.Map; +import eu.itesla_project.modules.securityindexes.SecurityIndexType; + /** * The results of the security rules application during a run of the online workflow * @@ -17,46 +20,62 @@ * @author Quinary */ public interface OnlineWorkflowRulesResults { - - /** - * Get the id of the workflow where the rules have been applied - * @return the id of the workflow - */ - String getWorkflowId(); - - /** - * Get the time horizon used for the workflow where the rules have been applied - * @return the time horizon of the workflow - */ - TimeHorizon getTimeHorizon(); - - /** - * Get the contingencies analyzed by the workflow with security rules - * @return the collection of ids of the contingencies analyzed with security rules - */ - Collection getContingenciesWithSecurityRulesResults(); - - /** - * Get the states analyzed by the workflow with security rules for a specific contingency - * @param contingencyId the id of the contingency - * @return the list of ids of the states analyzed with security rules - */ - List getStatesWithSecurityRulesResults(String contingencyId); - - /** - * Get the status (SAFE, SAFE_WITH_CORRECTIVE_ACTIONS, UNSAFE) of a state for a specific contingency - * @param contingencyId the id of the contingency - * @param stateId the id of the state - * @return the status (SAFE, SAFE_WITH_CORRECTIVE_ACTIONS, UNSAFE) of the state - */ - StateStatus getStateStatus(String contingencyId, Integer stateId); - - /** - * Get the results of the application of the security rules to a state for a contingency - * @param contingencyId the id of the contingency - * @param stateId the id of the state - * @return the map of [index, security flag] pair, output of the application of the security rules on a state for a contingency - */ - Map getStateResults(String contingencyId, Integer stateId); + + /** + * Get the id of the workflow where the rules have been applied + * @return the id of the workflow + */ + String getWorkflowId(); + + /** + * Get the time horizon used for the workflow where the rules have been applied + * @return the time horizon of the workflow + */ + TimeHorizon getTimeHorizon(); + + /** + * Get the contingencies analyzed by the workflow with security rules + * @return the collection of ids of the contingencies analyzed with security rules + */ + Collection getContingenciesWithSecurityRulesResults(); + + /** + * Get the states analyzed by the workflow with security rules for a specific contingency + * @param contingencyId the id of the contingency + * @return the list of ids of the states analyzed with security rules + */ + List getStatesWithSecurityRulesResults(String contingencyId); + + /** + * Get the status (SAFE, SAFE_WITH_CORRECTIVE_ACTIONS, UNSAFE) of a state for a specific contingency + * @param contingencyId the id of the contingency + * @param stateId the id of the state + * @return the status (SAFE, SAFE_WITH_CORRECTIVE_ACTIONS, UNSAFE) of the state + */ + StateStatus getStateStatus(String contingencyId, Integer stateId); + + /** + * Get the results of the application of the security rules to a state for a contingency + * @param contingencyId the id of the contingency + * @param stateId the id of the state + * @return the map of [index, security flag] pair, output of the application of the security rules on a state for a contingency + */ + Map getStateResults(String contingencyId, Integer stateId); + + /** + * Return if there are available rules for a state and a contingency + * @param contingencyId the id of the contingency + * @param stateId the id of the state + * @return true if there are available rules for a state and a contingency, false otherwise + */ + boolean areValidRulesAvailable(String contingencyId, Integer stateId); + + /** + * Get the list of invalid rules types (phenomena), for a state and a contingency + * @param contingencyId the id of the contingency + * @param stateId the id of the state + * @return the list of invalid rules types (phenomena), for a state and a contingency + */ + List getInvalidRules(String contingencyId, Integer stateId); } diff --git a/modules/src/main/java/eu/itesla_project/modules/online/RulesFacadeParameters.java b/modules/src/main/java/eu/itesla_project/modules/online/RulesFacadeParameters.java index c79f31ca..ab661689 100644 --- a/modules/src/main/java/eu/itesla_project/modules/online/RulesFacadeParameters.java +++ b/modules/src/main/java/eu/itesla_project/modules/online/RulesFacadeParameters.java @@ -20,37 +20,44 @@ public class RulesFacadeParameters { private final String offlineWorkflowId; - private final List contingencies; - private final double purityThreshold; - private final Set securityIndexTypes; // all security index types if null - private final boolean wcaRules; - - public RulesFacadeParameters(String offlineWorkflowId, List contingencies, double purityThreshold, - Set securityIndexTypes, boolean wcaRules) { + private final List contingencies; + private final double purityThreshold; + private final Set securityIndexTypes; // all security index types if null + private final boolean wcaRules; + private final boolean checkRules; + + public RulesFacadeParameters(String offlineWorkflowId, List contingencies, double purityThreshold, + Set securityIndexTypes, boolean wcaRules, boolean checkRules) { this.offlineWorkflowId = offlineWorkflowId; - this.contingencies = contingencies; - this.purityThreshold = purityThreshold; - this.securityIndexTypes = securityIndexTypes; - this.wcaRules = wcaRules; - } + this.contingencies = contingencies; + this.purityThreshold = purityThreshold; + this.securityIndexTypes = securityIndexTypes; + this.wcaRules = wcaRules; + this.checkRules = checkRules; + } public String getOfflineWorkflowId() { return offlineWorkflowId; } - public List getContingencies() { - return contingencies; - } - - public double getPurityThreshold() { - return purityThreshold; - } - - public Set getSecurityIndexTypes() { - return securityIndexTypes; - } - - public boolean wcaRules() { - return wcaRules; - } + public List getContingencies() { + return contingencies; + } + + public double getPurityThreshold() { + return purityThreshold; + } + + public Set getSecurityIndexTypes() { + return securityIndexTypes; + } + + public boolean wcaRules() { + return wcaRules; + } + + public boolean isCheckRules() { + return checkRules; + } + } diff --git a/modules/src/main/java/eu/itesla_project/modules/online/RulesFacadeResults.java b/modules/src/main/java/eu/itesla_project/modules/online/RulesFacadeResults.java index 686fe937..c272a6b9 100644 --- a/modules/src/main/java/eu/itesla_project/modules/online/RulesFacadeResults.java +++ b/modules/src/main/java/eu/itesla_project/modules/online/RulesFacadeResults.java @@ -7,42 +7,56 @@ */ package eu.itesla_project.modules.online; -import eu.itesla_project.modules.securityindexes.SecurityIndexType; - +import java.util.List; import java.util.Map; +import eu.itesla_project.modules.securityindexes.SecurityIndexType; + /** * * @author Quinary */ public class RulesFacadeResults { - private final String stateId; - private final String contingencyId; - private final StateStatus stateStatus; - private final Map indexesResults; - - public RulesFacadeResults(String stateId, String contingencyId, StateStatus stateStatus, Map indexesResults) { - this.stateId = stateId; - this.contingencyId = contingencyId; - this.stateStatus = stateStatus; - this.indexesResults = indexesResults; - } - - public String getStateId() { - return stateId; - } - - public String getContingencyId() { - return contingencyId; + private final String stateId; + private final String contingencyId; + private final StateStatus stateStatus; + private final Map indexesResults; + private final List invalidRules; + private final boolean rulesAvailable; + + public RulesFacadeResults(String stateId, String contingencyId, StateStatus stateStatus, Map indexesResults, + List invalidRules, boolean rulesAvailable) { + this.stateId = stateId; + this.contingencyId = contingencyId; + this.stateStatus = stateStatus; + this.indexesResults = indexesResults; + this.invalidRules = invalidRules; + this.rulesAvailable = rulesAvailable; + } + + public String getStateId() { + return stateId; + } + + public String getContingencyId() { + return contingencyId; + } + + public StateStatus getStateStatus() { + return stateStatus; + } + + public Map getIndexesResults() { + return indexesResults; + } + + public List getInvalidRules() { + return invalidRules; } - - public StateStatus getStateStatus() { - return stateStatus; - } - - public Map getIndexesResults() { - return indexesResults; + + public boolean areRulesAvailable() { + return rulesAvailable; } } diff --git a/modules/src/test/java/eu/itesla_project/modules/constraints/ConstraintsModifierConfigTest.java b/modules/src/test/java/eu/itesla_project/modules/constraints/ConstraintsModifierConfigTest.java new file mode 100644 index 00000000..f1ec2373 --- /dev/null +++ b/modules/src/test/java/eu/itesla_project/modules/constraints/ConstraintsModifierConfigTest.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2016, 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/. + */ +package eu.itesla_project.modules.constraints; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.nio.file.FileSystem; +import java.util.Arrays; +import java.util.List; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.nio.file.ShrinkWrapFileSystems; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import eu.itesla_project.commons.io.InMemoryPlatformConfig; +import eu.itesla_project.commons.io.MapModuleConfig; +import eu.itesla_project.iidm.network.Country; +import eu.itesla_project.iidm.network.Network; +import eu.itesla_project.modules.security.LimitViolation; +import eu.itesla_project.modules.security.LimitViolationType; + +/** + * + * @author Quinary + */ +public class ConstraintsModifierConfigTest { + + private FileSystem fileSystem; + private InMemoryPlatformConfig platformConfig; + private Network network; + private List violations; + + @Before + public void setUp() throws Exception { + JavaArchive archive = ShrinkWrap.create(JavaArchive.class); + fileSystem = ShrinkWrapFileSystems.newFileSystem(archive); + platformConfig = new InMemoryPlatformConfig(fileSystem); + network = ConstraintsModifierTestUtils.getNetwork(); + violations = ConstraintsModifierTestUtils.getViolations(network); + } + + @After + public void tearDown() throws Exception { + fileSystem.close(); + } + + @Test + public void testNoConfig() throws Exception { + ConstraintsModifierConfig config = ConstraintsModifierConfig.load(platformConfig); + checkValues(config, ConstraintsModifierConfig.DEFAULT_COUNTRY, ConstraintsModifierConfig.DEFAULT_VIOLATION_TYPES); + } + + @Test + public void testLoadConfig() throws Exception { + Country country = Country.FR; + LimitViolationType violationType = LimitViolationType.CURRENT; + MapModuleConfig moduleConfig = platformConfig.createModuleConfig("constraintsModifier"); + moduleConfig.setStringListProperty("country", Arrays.asList(country.name())); + moduleConfig.setStringListProperty("violationsTypes", Arrays.asList(violationType.name())); + ConstraintsModifierConfig config = ConstraintsModifierConfig.load(platformConfig); + checkValues(config, country, Arrays.asList(violationType)); + } + + private void checkValues(ConstraintsModifierConfig config, Country expectedCountry, List expectedViolationTypes) { + assertEquals(expectedCountry, config.getCountry()); + assertArrayEquals(expectedViolationTypes.toArray(), config.getViolationsTypes().toArray()); + for(LimitViolation violation : violations) { + assertTrue(config.isInAreaOfInterest(violation, network)); + } + } + +} diff --git a/modules/src/test/java/eu/itesla_project/modules/constraints/ConstraintsModifierTest.java b/modules/src/test/java/eu/itesla_project/modules/constraints/ConstraintsModifierTest.java new file mode 100644 index 00000000..6e2df6d1 --- /dev/null +++ b/modules/src/test/java/eu/itesla_project/modules/constraints/ConstraintsModifierTest.java @@ -0,0 +1,180 @@ +/** + * Copyright (c) 2016, 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/. + */ +package eu.itesla_project.modules.constraints; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import eu.itesla_project.iidm.network.Line; +import eu.itesla_project.iidm.network.Network; +import eu.itesla_project.iidm.network.StateManager; +import eu.itesla_project.iidm.network.VoltageLevel; +import eu.itesla_project.modules.security.LimitViolation; +import eu.itesla_project.modules.security.LimitViolationType; + +/** + * + * @author Quinary + */ +public class ConstraintsModifierTest { + + private Network network; + private List violations; + private ConstraintsModifierConfig config; + + @Before + public void setUp() throws Exception { + network = ConstraintsModifierTestUtils.getNetwork(); + violations = ConstraintsModifierTestUtils.getViolations(network); + List violationTypes = Arrays.asList(LimitViolationType.CURRENT, + LimitViolationType.HIGH_VOLTAGE, + LimitViolationType.LOW_VOLTAGE); + config = new ConstraintsModifierConfig(ConstraintsModifierConfig.DEFAULT_COUNTRY, violationTypes); + } + + private void checkOriginalNetworkLimits() { + Line line = network.getLine(ConstraintsModifierTestUtils.LINE_ID); + assertEquals(line.getCurrentLimits1().getPermanentLimit(), ConstraintsModifierTestUtils.CURRENT_LIMIT, 0); + VoltageLevel voltageLevel1 = network.getVoltageLevel(ConstraintsModifierTestUtils.VOLTAGE_LEVEL_1_ID); + assertEquals(voltageLevel1.getHighVoltageLimit(), ConstraintsModifierTestUtils.HIGH_VOLTAGE_LIMIT, 0); + VoltageLevel voltageLevel2 = network.getVoltageLevel(ConstraintsModifierTestUtils.VOLTAGE_LEVEL_2_ID); + assertEquals(voltageLevel2.getLowVoltageLimit(), ConstraintsModifierTestUtils.LOW_VOLTAGE_LIMIT, 0); + } + + private void checkModifiedNetworkLimits(int margin) { + Line line = network.getLine(ConstraintsModifierTestUtils.LINE_ID); + float newCurrentLimit = ConstraintsModifierTestUtils.NEW_CURRENT_LIMIT + (ConstraintsModifierTestUtils.CURRENT_LIMIT * margin / 100); + assertEquals(newCurrentLimit, line.getCurrentLimits1().getPermanentLimit(), 0); + VoltageLevel voltageLevel1 = network.getVoltageLevel(ConstraintsModifierTestUtils.VOLTAGE_LEVEL_1_ID); + float newHighVoltageLimit = ConstraintsModifierTestUtils.NEW_HIGH_VOLTAGE_LIMIT + (ConstraintsModifierTestUtils.HIGH_VOLTAGE_LIMIT * margin / 100); + assertEquals(newHighVoltageLimit, voltageLevel1.getHighVoltageLimit(), 0); + VoltageLevel voltageLevel2 = network.getVoltageLevel(ConstraintsModifierTestUtils.VOLTAGE_LEVEL_2_ID); + float newLowVoltageLimit = ConstraintsModifierTestUtils.NEW_LOW_VOLTAGE_LIMIT - (ConstraintsModifierTestUtils.LOW_VOLTAGE_LIMIT * margin / 100); + assertEquals(newLowVoltageLimit, voltageLevel2.getLowVoltageLimit(), 0); + } + + @Test + public void testNoMargin() throws Exception { + checkOriginalNetworkLimits(); + + ConstraintsModifier constraintsModifier = new ConstraintsModifier(network, config); + constraintsModifier.looseConstraints(StateManager.INITIAL_STATE_ID); + + checkModifiedNetworkLimits(0); + } + + @Test + public void testWithMargin() throws Exception { + int margin = 3; + + checkOriginalNetworkLimits(); + + ConstraintsModifier constraintsModifier = new ConstraintsModifier(network, config); + constraintsModifier.looseConstraints(StateManager.INITIAL_STATE_ID, margin); + + checkModifiedNetworkLimits(margin); + } + + @Test + public void testWithViolationsNoMargin() throws Exception { + checkOriginalNetworkLimits(); + + ConstraintsModifier constraintsModifier = new ConstraintsModifier(network, config); + constraintsModifier.looseConstraints(StateManager.INITIAL_STATE_ID, violations); + + checkModifiedNetworkLimits(0); + } + + @Test + public void testWithViolationsAndMargin() throws Exception { + int margin = 3; + + checkOriginalNetworkLimits(); + + ConstraintsModifier constraintsModifier = new ConstraintsModifier(network, config); + constraintsModifier.looseConstraints(StateManager.INITIAL_STATE_ID, violations, margin); + + checkModifiedNetworkLimits(margin); + } + + @Test + public void testWithViolationsAndMarginApplyBasecase() throws Exception { + int margin = 3; + + checkOriginalNetworkLimits(); + + String stateId = "0"; + network.getStateManager().cloneState(StateManager.INITIAL_STATE_ID, stateId); + network.getStateManager().setWorkingState(stateId); + checkOriginalNetworkLimits(); + + ConstraintsModifier constraintsModifier = new ConstraintsModifier(network, config); + constraintsModifier.looseConstraints(stateId, violations, margin, true); + + checkModifiedNetworkLimits(margin); + + network.getStateManager().setWorkingState(StateManager.INITIAL_STATE_ID); + checkModifiedNetworkLimits(margin); + + network.getStateManager().removeState(stateId); + } + + @Test + public void testWithMarginApplyBasecase() throws Exception { + int margin = 3; + + checkOriginalNetworkLimits(); + + String stateId = "0"; + network.getStateManager().cloneState(StateManager.INITIAL_STATE_ID, stateId); + network.getStateManager().setWorkingState(stateId); + checkOriginalNetworkLimits(); + + ConstraintsModifier constraintsModifier = new ConstraintsModifier(network, config); + constraintsModifier.looseConstraints(stateId, margin, true); + + checkModifiedNetworkLimits(margin); + + network.getStateManager().setWorkingState(StateManager.INITIAL_STATE_ID); + checkModifiedNetworkLimits(margin); + + network.getStateManager().removeState(stateId); + } + + @Test + public void testWithNullValues() throws Exception { + ConstraintsModifier constraintsModifier = new ConstraintsModifier(network, config); + try { + constraintsModifier.looseConstraints(null, violations); + fail(); + } catch (Throwable e) { + + } + try { + constraintsModifier.looseConstraints(StateManager.INITIAL_STATE_ID, null); + fail(); + } catch (Throwable e) { + } + } + + @Test + public void testWithWrongState() throws Exception { + ConstraintsModifier constraintsModifier = new ConstraintsModifier(network, config); + try { + constraintsModifier.looseConstraints("wrongState", violations); + fail(); + } catch (Throwable e) { + } + } + +} diff --git a/modules/src/test/java/eu/itesla_project/modules/constraints/ConstraintsModifierTestUtils.java b/modules/src/test/java/eu/itesla_project/modules/constraints/ConstraintsModifierTestUtils.java new file mode 100644 index 00000000..3dbb3bbc --- /dev/null +++ b/modules/src/test/java/eu/itesla_project/modules/constraints/ConstraintsModifierTestUtils.java @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2016, 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/. + */ +package eu.itesla_project.modules.constraints; + +import java.util.ArrayList; +import java.util.List; + +import eu.itesla_project.iidm.network.Bus; +import eu.itesla_project.iidm.network.Country; +import eu.itesla_project.iidm.network.Line; +import eu.itesla_project.iidm.network.Network; +import eu.itesla_project.iidm.network.NetworkFactory; +import eu.itesla_project.iidm.network.Substation; +import eu.itesla_project.iidm.network.TopologyKind; +import eu.itesla_project.iidm.network.VoltageLevel; +import eu.itesla_project.modules.security.LimitViolation; +import eu.itesla_project.modules.security.LimitViolationType; + +/** + * + * @author Quinary + */ +public class ConstraintsModifierTestUtils { + + public static final String VOLTAGE_LEVEL_1_ID = "vl1"; + public static final float HIGH_VOLTAGE_LIMIT = 300f; + public static final float NEW_HIGH_VOLTAGE_LIMIT = 381f; + public static final String VOLTAGE_LEVEL_2_ID = "vl2"; + public static final float LOW_VOLTAGE_LIMIT = 420f; + public static final float NEW_LOW_VOLTAGE_LIMIT = 378f; + public static final String LINE_ID = "line1"; + public static final float CURRENT_LIMIT = 100f; + public static final float NEW_CURRENT_LIMIT = 120f; + private static final float CURRENT_VALUE = 119.25632f; + private static final float V = 380f; + private static final float Q = 55f; + private static final float P = 56f; + private static final Country COUNTRY = Country.FR; + + public static Network getNetwork() { + Network n = NetworkFactory.create("test1", "test"); + Substation s1 = n.newSubstation() + .setId("s1") + .setCountry(COUNTRY) + .add(); + VoltageLevel vl1 = s1.newVoltageLevel() + .setId(VOLTAGE_LEVEL_1_ID) + .setNominalV(V) + .setTopologyKind(TopologyKind.BUS_BREAKER) + .setHighVoltageLimit(HIGH_VOLTAGE_LIMIT) + .setLowVoltageLimit(200f) + .add(); + Bus b1 = vl1.getBusBreakerView().newBus() + .setId("b1") + .add(); + b1.setV(V); + Substation s2 = n.newSubstation() + .setId("s2") + .setCountry(COUNTRY) + .add(); + VoltageLevel vl2 = s2.newVoltageLevel() + .setId(VOLTAGE_LEVEL_2_ID) + .setNominalV(V) + .setTopologyKind(TopologyKind.BUS_BREAKER) + .setHighVoltageLimit(550f) + .setLowVoltageLimit(LOW_VOLTAGE_LIMIT) + .add(); + Bus b2 = vl2.getBusBreakerView().newBus() + .setId("b2") + .add(); + b2.setV(V); + Line l1 = n.newLine() + .setId(LINE_ID) + .setVoltageLevel1(VOLTAGE_LEVEL_1_ID) + .setBus1("b1") + .setConnectableBus1("b1") + .setVoltageLevel2(VOLTAGE_LEVEL_2_ID) + .setBus2("b2") + .setConnectableBus2("b2") + .setR(3) + .setX(33) + .setG1(0) + .setB1(386E-6f / 2) + .setG2(0f) + .setB2(386E-6f / 2) + .add(); + l1.newCurrentLimits1() + .setPermanentLimit(CURRENT_LIMIT) + .add(); + l1.newCurrentLimits2() + .setPermanentLimit(CURRENT_LIMIT) + .add(); + l1.getTerminal1().setP(P); + l1.getTerminal1().setQ(Q); + l1.getTerminal2().setP(P); + l1.getTerminal2().setQ(Q); + return n; + } + + public static List getViolations(Network network) { + List violations = new ArrayList(); + Line line = network.getLine(LINE_ID); + violations.add(new LimitViolation(line, LimitViolationType.CURRENT, CURRENT_LIMIT, 1, CURRENT_VALUE, COUNTRY, Float.NaN)); + VoltageLevel voltageLevel = network.getVoltageLevel(VOLTAGE_LEVEL_1_ID); + violations.add(new LimitViolation(voltageLevel, LimitViolationType.HIGH_VOLTAGE, HIGH_VOLTAGE_LIMIT, 1, V, COUNTRY, Float.NaN)); + VoltageLevel voltageLevel2 = network.getVoltageLevel(VOLTAGE_LEVEL_2_ID); + violations.add(new LimitViolation(voltageLevel2, LimitViolationType.LOW_VOLTAGE, LOW_VOLTAGE_LIMIT, 1, V, COUNTRY, Float.NaN)); + return violations; + } + +} diff --git a/online-workflow/src/main/java/eu/itesla_project/online/OnlineWorkflowImpl.java b/online-workflow/src/main/java/eu/itesla_project/online/OnlineWorkflowImpl.java index 32bca213..b3fd7983 100644 --- a/online-workflow/src/main/java/eu/itesla_project/online/OnlineWorkflowImpl.java +++ b/online-workflow/src/main/java/eu/itesla_project/online/OnlineWorkflowImpl.java @@ -32,6 +32,7 @@ import eu.itesla_project.merge.MergeOptimizerFactory; import eu.itesla_project.merge.MergeUtil; import eu.itesla_project.cases.CaseRepository; +import eu.itesla_project.modules.constraints.ConstraintsModifier; import eu.itesla_project.modules.contingencies.ContingenciesAndActionsDatabaseClient; import eu.itesla_project.modules.ddb.DynamicDatabaseClientFactory; import eu.itesla_project.modules.histo.HistoDbClient; @@ -69,354 +70,364 @@ */ public class OnlineWorkflowImpl implements OnlineWorkflow { - Logger logger = LoggerFactory.getLogger(OnlineWorkflowImpl.class); + Logger logger = LoggerFactory.getLogger(OnlineWorkflowImpl.class); - private final ComputationManager computationManager; - private final ContingenciesAndActionsDatabaseClient cadbClient; - private final DynamicDatabaseClientFactory ddbClientFactory; - private final HistoDbClient histoDbClient; - private final RulesDbClient rulesDbClient; - private final ForecastErrorsDataStorage feDataStorage; + private final ComputationManager computationManager; + private final ContingenciesAndActionsDatabaseClient cadbClient; + private final DynamicDatabaseClientFactory ddbClientFactory; + private final HistoDbClient histoDbClient; + private final RulesDbClient rulesDbClient; + private final ForecastErrorsDataStorage feDataStorage; private final OnlineWorkflowParameters parameters; - private List listeners=new ArrayList(); + private List listeners=new ArrayList(); private final CaseRepository caseRepository; private final WCAFactory wcaFactory; private final LoadFlowFactory loadFlowFactory; private final OnlineDb onlineDb; private final UncertaintiesAnalyserFactory uncertaintiesAnalyserFactory; private final CorrectiveControlOptimizerFactory optimizerFactory; - private final SimulatorFactory simulatorFactory; - private final MontecarloSamplerFactory montecarloSamplerFactory; - private final MergeOptimizerFactory mergeOptimizerFactory; - private final RulesFacadeFactory rulesFacadeFactory; - private final OnlineWorkflowStartParameters startParameters; - + private final SimulatorFactory simulatorFactory; + private final MontecarloSamplerFactory montecarloSamplerFactory; + private final MergeOptimizerFactory mergeOptimizerFactory; + private final RulesFacadeFactory rulesFacadeFactory; + private final OnlineWorkflowStartParameters startParameters; + private String id; - public OnlineWorkflowImpl( - ComputationManager computationManager, - ContingenciesAndActionsDatabaseClient cadbClient, - DynamicDatabaseClientFactory ddbClientFactory, - HistoDbClient histoDbClient, - RulesDbClient rulesDbClient, + public OnlineWorkflowImpl( + ComputationManager computationManager, + ContingenciesAndActionsDatabaseClient cadbClient, + DynamicDatabaseClientFactory ddbClientFactory, + HistoDbClient histoDbClient, + RulesDbClient rulesDbClient, WCAFactory wcaFactory, LoadFlowFactory loadFlowFactory, - ForecastErrorsDataStorage feDataStorage, - OnlineDb onlineDB, + ForecastErrorsDataStorage feDataStorage, + OnlineDb onlineDB, UncertaintiesAnalyserFactory uncertaintiesAnalyserFactory, CorrectiveControlOptimizerFactory optimizerFactory, - SimulatorFactory simulatorFactory, + SimulatorFactory simulatorFactory, CaseRepository caseRepository, - MontecarloSamplerFactory montecarloSamplerFactory, - MergeOptimizerFactory mergeOptimizerFactory, - RulesFacadeFactory rulesFacadeFactory, + MontecarloSamplerFactory montecarloSamplerFactory, + MergeOptimizerFactory mergeOptimizerFactory, + RulesFacadeFactory rulesFacadeFactory, OnlineWorkflowParameters parameters, OnlineWorkflowStartParameters startParameters - ) { - Objects.requireNonNull(computationManager, "computation manager is null"); - Objects.requireNonNull(cadbClient, "contingencies and actions DB client is null"); - Objects.requireNonNull(ddbClientFactory, "dynamic DB client factory is null"); - Objects.requireNonNull(histoDbClient, "histo DB client is null"); - Objects.requireNonNull(rulesDbClient, "rules DB client is null"); + ) { + Objects.requireNonNull(computationManager, "computation manager is null"); + Objects.requireNonNull(cadbClient, "contingencies and actions DB client is null"); + Objects.requireNonNull(ddbClientFactory, "dynamic DB client factory is null"); + Objects.requireNonNull(histoDbClient, "histo DB client is null"); + Objects.requireNonNull(rulesDbClient, "rules DB client is null"); Objects.requireNonNull(wcaFactory, "WCA factory is null"); Objects.requireNonNull(loadFlowFactory, "loadFlow factory is null"); - Objects.requireNonNull(feDataStorage, "forecast errors data storage is null"); - Objects.requireNonNull(onlineDB, "online db is null"); - Objects.requireNonNull(optimizerFactory, "corrective control optimizer factory is null"); - Objects.requireNonNull(simulatorFactory, "simulator factory is null"); - Objects.requireNonNull(caseRepository, "case repository is null"); - Objects.requireNonNull(montecarloSamplerFactory, "montecarlo sampler factory is null"); - Objects.requireNonNull(parameters, "parameters is null"); - Objects.requireNonNull(startParameters, "start parameters is null"); - this.computationManager = computationManager; - this.cadbClient = cadbClient; - this.ddbClientFactory = ddbClientFactory; - this.histoDbClient = histoDbClient; - this.rulesDbClient = rulesDbClient; + Objects.requireNonNull(feDataStorage, "forecast errors data storage is null"); + Objects.requireNonNull(onlineDB, "online db is null"); + Objects.requireNonNull(optimizerFactory, "corrective control optimizer factory is null"); + Objects.requireNonNull(simulatorFactory, "simulator factory is null"); + Objects.requireNonNull(caseRepository, "case repository is null"); + Objects.requireNonNull(montecarloSamplerFactory, "montecarlo sampler factory is null"); + Objects.requireNonNull(parameters, "parameters is null"); + Objects.requireNonNull(startParameters, "start parameters is null"); + this.computationManager = computationManager; + this.cadbClient = cadbClient; + this.ddbClientFactory = ddbClientFactory; + this.histoDbClient = histoDbClient; + this.rulesDbClient = rulesDbClient; this.wcaFactory = wcaFactory; this.loadFlowFactory = loadFlowFactory; - this.feDataStorage = feDataStorage; - this.onlineDb = onlineDB; + this.feDataStorage = feDataStorage; + this.onlineDb = onlineDB; this.uncertaintiesAnalyserFactory = Objects.requireNonNull(uncertaintiesAnalyserFactory); this.optimizerFactory = optimizerFactory; this.simulatorFactory = simulatorFactory; this.caseRepository = caseRepository; - this.montecarloSamplerFactory = montecarloSamplerFactory; - this.mergeOptimizerFactory = Objects.requireNonNull(mergeOptimizerFactory); - this.rulesFacadeFactory = rulesFacadeFactory; - this.parameters = parameters; - this.startParameters = startParameters; - this.id = DateTimeFormat.forPattern("yyyyMMdd_HHmm_").print(parameters.getBaseCaseDate())+new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()); - logger.info(parameters.toString()); - } - - - /* (non-Javadoc) - * @see eu.itesla_project.online.OnlineWorkflowInterface#getId() - */ - @Override - public String getId() { - return id; - } - - /* (non-Javadoc) - * @see eu.itesla_project.online.OnlineWorkflowInterface#start(eu.itesla_project.online.OnlineWorkflowContext) - */ - @Override - public void start(OnlineWorkflowContext oCtx) throws Exception { - logger.info("{} Online workflow processing, started.",id); - for (OnlineApplicationListener l :listeners) - l.onWorkflowUpdate(new StatusSynthesis(id,StatusSynthesis.STATUS_RUNNING)); - - Network network = MergeUtil.merge(caseRepository, parameters.getBaseCaseDate(), parameters.getCaseType(), parameters.getCountries(), - loadFlowFactory, 0, mergeOptimizerFactory, computationManager, parameters.isMergeOptimized()); + this.montecarloSamplerFactory = montecarloSamplerFactory; + this.mergeOptimizerFactory = Objects.requireNonNull(mergeOptimizerFactory); + this.rulesFacadeFactory = rulesFacadeFactory; + this.parameters = parameters; + this.startParameters = startParameters; + this.id = DateTimeFormat.forPattern("yyyyMMdd_HHmm_").print(parameters.getBaseCaseDate())+new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()); + logger.info(parameters.toString()); + } + + + /* (non-Javadoc) + * @see eu.itesla_project.online.OnlineWorkflowInterface#getId() + */ + @Override + public String getId() { + return id; + } + + /* (non-Javadoc) + * @see eu.itesla_project.online.OnlineWorkflowInterface#start(eu.itesla_project.online.OnlineWorkflowContext) + */ + @Override + public void start(OnlineWorkflowContext oCtx) throws Exception { + logger.info("{} Online workflow processing, started.",id); + for (OnlineApplicationListener l :listeners) + l.onWorkflowUpdate(new StatusSynthesis(id,StatusSynthesis.STATUS_RUNNING)); + + Network network = MergeUtil.merge(caseRepository, parameters.getBaseCaseDate(), parameters.getCaseType(), parameters.getCountries(), + loadFlowFactory, 0, mergeOptimizerFactory, computationManager, parameters.isMergeOptimized()); logger.info("- Network id: " + network.getId()); logger.info("- Network name: "+ network.getName()); - // needed in order to correctly handle multithreading access to network - network.getStateManager().allowStateMultiThreadAccess(true); + // needed in order to correctly handle multithreading access to network + network.getStateManager().allowStateMultiThreadAccess(true); + - oCtx.setWorkflowId(id); - oCtx.setNetwork(network); + oCtx.setNetwork(network); oCtx.setOfflineWorkflowId(parameters.getOfflineWorkflowId()); oCtx.setTimeHorizon(parameters.getTimeHorizon()); - + // prepare the objects where the results of the forecast analysis will be saved oCtx.setResults(new ForecastAnalysisResults(this.getId(), oCtx.getTimeHorizon())); oCtx.setSecurityRulesResults(new SecurityRulesApplicationResults(this.getId(), oCtx.getTimeHorizon())); oCtx.setWcaResults(new WCAResults(this.getId(), oCtx.getTimeHorizon())); if ( parameters.validation() ) - oCtx.setWcaSecurityRulesResults(new SecurityRulesApplicationResults(this.getId(), oCtx.getTimeHorizon())); + oCtx.setWcaSecurityRulesResults(new SecurityRulesApplicationResults(this.getId(), oCtx.getTimeHorizon())); - logger.info(" - WCA processing......"); + logger.info(" - WCA processing......"); for (OnlineApplicationListener l :listeners) l.onWcaUpdate(new RunningSynthesis(id,true)); WCAParameters wcaParameters = new WCAParameters(parameters.getHistoInterval(), parameters.getOfflineWorkflowId(), parameters.getSecurityIndexes(), parameters.getRulesPurityThreshold()); - WCA wca = wcaFactory.create(oCtx.getNetwork(), computationManager, histoDbClient, rulesDbClient, uncertaintiesAnalyserFactory, cadbClient, loadFlowFactory); + WCA wca = wcaFactory.create(oCtx.getNetwork(), computationManager, histoDbClient, rulesDbClient, uncertaintiesAnalyserFactory, cadbClient, loadFlowFactory); WCAResult result = wca.run(wcaParameters); - for (OnlineApplicationListener l :listeners) - l.onWcaUpdate(new RunningSynthesis(id,false)); + for (OnlineApplicationListener l :listeners) + l.onWcaUpdate(new RunningSynthesis(id,false)); + + // ArrayList stables = new ArrayList(); - // ArrayList stables = new ArrayList(); - for (WCACluster cluster : result.getClusters()) { - logger.info("WCA: contingency {} in cluster {}", cluster.getContingency().getId(), cluster.getNum().toString()); - oCtx.getWcaResults().addContingencyWithCluster(cluster.getContingency().getId(), cluster); - if ( parameters.validation() ) { // if validation - // do not filter out the contingencies - oCtx.getContingenciesToAnalyze().add(cluster.getContingency()); - } else { - if ( cluster.getNum() != WCAClusterNum.ONE ) { // cluster 1 -> contingency classified as "stable" -> no need for further analysis - // contingencies in clusters 2, 3 and 4 need further analysis - oCtx.getContingenciesToAnalyze().add(cluster.getContingency()); - - } - } + logger.info("WCA: contingency {} in cluster {}", cluster.getContingency().getId(), cluster.getNum().toString()); + oCtx.getWcaResults().addContingencyWithCluster(cluster.getContingency().getId(), cluster); + if ( parameters.validation() ) { // if validation + // do not filter out the contingencies + oCtx.getContingenciesToAnalyze().add(cluster.getContingency()); + } else { + if ( cluster.getNum() != WCAClusterNum.ONE ) { // cluster 1 -> contingency classified as "stable" -> no need for further analysis + // contingencies in clusters 2, 3 and 4 need further analysis + oCtx.getContingenciesToAnalyze().add(cluster.getContingency()); + + } + } } - + // notify all contingency stable and unstable for (OnlineApplicationListener l :listeners) - l.onWcaContingencies(new WcaContingenciesSynthesis(id, oCtx.getWcaResults().getContingenciesWithClusters())); - - + l.onWcaContingencies(new WcaContingenciesSynthesis(id, oCtx.getWcaResults().getContingenciesWithClusters())); + + logger.info("{} Online workflow - Analysis of states, started.", id); - // create modules used in the states analysis - MontecarloSampler sampler = montecarloSamplerFactory.create(oCtx.getNetwork(), computationManager, feDataStorage); - OnlineRulesFacade rulesFacade = rulesFacadeFactory.create(rulesDbClient); - CorrectiveControlOptimizer optimizer = optimizerFactory.create(cadbClient,computationManager); - Stabilization stabilization = simulatorFactory.createStabilization(oCtx.getNetwork(), computationManager, Integer.MAX_VALUE, ddbClientFactory); - ImpactAnalysis impactAnalysis = simulatorFactory.createImpactAnalysis(oCtx.getNetwork(), computationManager, Integer.MAX_VALUE, cadbClient); - - // initialize modules - sampler.init(new MontecarloSamplerParameters(oCtx.getTimeHorizon(), parameters.getFeAnalysisId(), parameters.getStates())); - rulesFacade.init(new RulesFacadeParameters(oCtx.getOfflineWorkflowId(), - oCtx.getContingenciesToAnalyze(), - parameters.getRulesPurityThreshold(), - parameters.getSecurityIndexes(), - parameters.validation())); - Map simulationInitContext = new HashMap<>(); + // create modules used in the states analysis + MontecarloSampler sampler = montecarloSamplerFactory.create(oCtx.getNetwork(), computationManager, feDataStorage); + OnlineRulesFacade rulesFacade = rulesFacadeFactory.create(rulesDbClient); + CorrectiveControlOptimizer optimizer = optimizerFactory.create(cadbClient,computationManager); + Stabilization stabilization = simulatorFactory.createStabilization(oCtx.getNetwork(), computationManager, Integer.MAX_VALUE, ddbClientFactory); + ImpactAnalysis impactAnalysis = simulatorFactory.createImpactAnalysis(oCtx.getNetwork(), computationManager, Integer.MAX_VALUE, cadbClient); + LoadFlow loadflow = loadFlowFactory.create(oCtx.getNetwork(), computationManager, 0); + ConstraintsModifier constraintsModifier = new ConstraintsModifier(oCtx.getNetwork()); + StateAnalizerListener stateListener = new StateAnalizerListener(); + + // initialize modules + rulesFacade.init(new RulesFacadeParameters(oCtx.getOfflineWorkflowId(), + oCtx.getContingenciesToAnalyze(), + parameters.getRulesPurityThreshold(), + parameters.getSecurityIndexes(), + parameters.validation(), + parameters.isHandleViolationsInN())); + Map simulationInitContext = new HashMap<>(); SimulationParameters simulationParameters = SimulationParameters.load(); stabilization.init(simulationParameters, simulationInitContext); impactAnalysis.init(simulationParameters, simulationInitContext); - optimizer.init(new CorrectiveControlOptimizerParameters()); - - LoadFlow loadflow = loadFlowFactory.create(oCtx.getNetwork(), computationManager, 0); - StateAnalizerListener stateListener = new StateAnalizerListener(); - // run states analysis - List> tasks = new ArrayList<>(parameters.getStates()); - for ( int i=0; i> tasks = new ArrayList<>(statesNumber); + for ( int i=0; i statusMap = new HashMap(); WorkSynthesis work=new WorkSynthesis(id,statusMap); ContingencyStatesActionsSynthesis acts=new ContingencyStatesActionsSynthesis(id); - ContingencyStatesIndexesSynthesis stindex=new ContingencyStatesIndexesSynthesis(id); - IndexSecurityRulesResultsSynthesis stateWithSecRulesResults = new IndexSecurityRulesResultsSynthesis(id); - + ContingencyStatesIndexesSynthesis stindex=new ContingencyStatesIndexesSynthesis(id); + IndexSecurityRulesResultsSynthesis stateWithSecRulesResults = new IndexSecurityRulesResultsSynthesis(id); + public void onUpdate(Integer stateId, EnumMap status, TimeHorizon t) { //statusMap.put(stateId, new WorkStatus(stateId, status, t.toString())); - - if (statusMap.containsKey(stateId)) { - WorkStatus ws = statusMap.get(stateId); - ws.setStatus(status); - ws.setTimeHorizon(t.toString()); - statusMap.put(stateId,ws); - } else - statusMap.put(stateId,new WorkStatus(stateId, status,t.toString() )); + + if (statusMap.containsKey(stateId)) { + WorkStatus ws = statusMap.get(stateId); + ws.setStatus(status); + ws.setTimeHorizon(t.toString()); + statusMap.put(stateId,ws); + } else + statusMap.put(stateId,new WorkStatus(stateId, status,t.toString() )); for (OnlineApplicationListener l : listeners) l.onWorkflowStateUpdate(work); } - - public void onSecurityRulesApplicationResults(String contingencyId, Integer stateId, OnlineWorkflowContext oCtx ) + + public void onSecurityRulesApplicationResults(String contingencyId, Integer stateId, OnlineWorkflowContext oCtx ) { - - SecurityRulesApplicationResults rulesApplicationResults = oCtx.getSecurityRulesResults(); - stateWithSecRulesResults.addStateSecurityRuleIndexes(contingencyId, stateId, rulesApplicationResults); - for (OnlineApplicationListener l : listeners) + + SecurityRulesApplicationResults rulesApplicationResults = oCtx.getSecurityRulesResults(); + stateWithSecRulesResults.addStateSecurityRuleIndexes(contingencyId, stateId, rulesApplicationResults); + for (OnlineApplicationListener l : listeners) l.onStatesWithSecurityRulesResultsUpdate(stateWithSecRulesResults); } - + public void onUpdate(Integer stateId, EnumMap status, TimeHorizon t, String detail) { - // statusMap.put(stateId, new WorkStatus(stateId, status, t.toString(),detail)); - if (statusMap.containsKey(stateId)) { - WorkStatus ws = statusMap.get(stateId); - StringBuffer sb = new StringBuffer(); - - if (ws.getDetail() != null && !ws.getDetail().equals("")) - sb.append(ws.getDetail()).append("
").append(detail); - else - sb.append(detail); - - ws.setDetail(sb.toString()); - ws.setStatus(status); - ws.setTimeHorizon(t.toString()); - statusMap.put(stateId,ws); - } else - statusMap.put(stateId,new WorkStatus(stateId, status,t.toString(),detail )); - + // statusMap.put(stateId, new WorkStatus(stateId, status, t.toString(),detail)); + if (statusMap.containsKey(stateId)) { + WorkStatus ws = statusMap.get(stateId); + StringBuffer sb = new StringBuffer(); + + if (ws.getDetail() != null && !ws.getDetail().equals("")) + sb.append(ws.getDetail()).append("
").append(detail); + else + sb.append(detail); + + ws.setDetail(sb.toString()); + ws.setStatus(status); + ws.setTimeHorizon(t.toString()); + statusMap.put(stateId,ws); + } else + statusMap.put(stateId,new WorkStatus(stateId, status,t.toString(),detail )); + for (OnlineApplicationListener l : listeners) l.onWorkflowStateUpdate(work); } - - - public void onImpactAnalysisResults(Integer stateId, OnlineWorkflowContext oCtx ) { - - ForecastAnalysisResults res = oCtx.getResults(); - Collection unsafes= res.getUnsafeContingencies(); - for(String c :unsafes) - { - - List sts =res.getUnstableStates(c); - for(Integer s:sts) - { - List sec=res.getIndexes(c, s); - ArrayList indexes=new ArrayList(); - for(SecurityIndex idx: sec) - { - indexes.add(stindex.new SecurityIndexInfo(idx)); - } - stindex.addStateIndexes(c,s, indexes); - } - - } - - for (OnlineApplicationListener l :listeners) - l.onStatesWithIndexesUpdate(stindex); - - - } - - public void onOptimizerResults(Integer stateId, OnlineWorkflowContext oCtx ) { - - ForecastAnalysisResults res = oCtx.getResults(); - Collection conts =res.getContingenciesWithActions(); - - - for(String c :conts) - { - Map unsafeStatesWithActions = res.getUnsafeStatesWithActions(c); - if ( unsafeStatesWithActions != null ) { - Set sts =unsafeStatesWithActions.keySet(); - for(Integer s:sts) - { - List actiondIds = res.getActionsIds(c, s); - if ( actiondIds != null ) { - ArrayList infos=new ArrayList(); - for(String a : actiondIds) - infos.add(new ActionInfo(a)); - acts.addStateActions(c,s, infos); - } - } - } - } - for (OnlineApplicationListener l :listeners) - l.onStatesWithActionsUpdate(acts); - - - } + + + public void onImpactAnalysisResults(Integer stateId, OnlineWorkflowContext oCtx ) { + + ForecastAnalysisResults res = oCtx.getResults(); + Collection unsafes= res.getUnsafeContingencies(); + for(String c :unsafes) + { + + List sts =res.getUnstableStates(c); + for(Integer s:sts) + { + List sec=res.getIndexes(c, s); + ArrayList indexes=new ArrayList(); + for(SecurityIndex idx: sec) + { + indexes.add(stindex.new SecurityIndexInfo(idx)); + } + stindex.addStateIndexes(c,s, indexes); + } + + } + + for (OnlineApplicationListener l :listeners) + l.onStatesWithIndexesUpdate(stindex); + + + } + + public void onOptimizerResults(Integer stateId, OnlineWorkflowContext oCtx ) { + + ForecastAnalysisResults res = oCtx.getResults(); + Collection conts =res.getContingenciesWithActions(); + + + for(String c :conts) + { + Map unsafeStatesWithActions = res.getUnsafeStatesWithActions(c); + if ( unsafeStatesWithActions != null ) { + Set sts =unsafeStatesWithActions.keySet(); + for(Integer s:sts) + { + List actiondIds = res.getActionsIds(c, s); + if ( actiondIds != null ) { + ArrayList infos=new ArrayList(); + for(String a : actiondIds) + infos.add(new ActionInfo(a)); + acts.addStateActions(c,s, infos); + } + } + } + } + for (OnlineApplicationListener l :listeners) + l.onStatesWithActionsUpdate(acts); + + + } } } diff --git a/online-workflow/src/main/java/eu/itesla_project/online/SecurityRulesApplicationResults.java b/online-workflow/src/main/java/eu/itesla_project/online/SecurityRulesApplicationResults.java index ab23ba1b..935d8fdb 100644 --- a/online-workflow/src/main/java/eu/itesla_project/online/SecurityRulesApplicationResults.java +++ b/online-workflow/src/main/java/eu/itesla_project/online/SecurityRulesApplicationResults.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) + * Copyright (c) 2016, 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/. @@ -22,139 +23,170 @@ * @author Quinary */ public class SecurityRulesApplicationResults implements OnlineWorkflowRulesResults { - - // the id of the workflow where the rules have been applied - private final String workflowId; - // the time horizon used for the workflow where the rules have been applied - private final TimeHorizon timeHorizon; - - // > - private Map contingenciesWithSecurityRulesResults = new HashMap(); - - public SecurityRulesApplicationResults(String workflowId, TimeHorizon timeHorizon) { - this.workflowId = workflowId; - this.timeHorizon = timeHorizon; - } - - @Override - public String getWorkflowId() { - return workflowId; - } - - @Override - public TimeHorizon getTimeHorizon() { - return timeHorizon; - } - - - public void addStateWithSecurityRulesResults(String contingencyId, Integer stateId, StateStatus stateStatus, Map securityRulesResults) { - StatesWithSecurityRulesResults statesWithSecurityRulesResults = new StatesWithSecurityRulesResults(); - if ( contingenciesWithSecurityRulesResults.containsKey(contingencyId) ) { - statesWithSecurityRulesResults = contingenciesWithSecurityRulesResults.get(contingencyId); - } - statesWithSecurityRulesResults.addState(stateId, stateStatus, securityRulesResults); - contingenciesWithSecurityRulesResults.put(contingencyId, statesWithSecurityRulesResults); - - } - - @Override - public Set getContingenciesWithSecurityRulesResults() { - return contingenciesWithSecurityRulesResults.keySet(); - } - - public List getStatesWithSecurityRulesResults(String contingencyId) { - List statesWithSecurityRulesResults = new ArrayList(); - for(Integer stateId : contingenciesWithSecurityRulesResults.get(contingencyId).getStates()) { - statesWithSecurityRulesResults.add(stateId); - } - return statesWithSecurityRulesResults; - } - - public Map getSecurityRulesResults(String contingencyId, Integer stateId) { - return contingenciesWithSecurityRulesResults.get(contingencyId).getSecurityRulesResults(stateId); - } - - @Override - public Map getStateResults(String contingencyId, Integer stateId) { - Map securityRulesResults = getSecurityRulesResults(contingencyId, stateId); - Map stateResults = new HashMap(); - for(SecurityIndexType index : securityRulesResults.keySet()) { - switch (securityRulesResults.get(index)) { - case SAFE: - stateResults.put(index.getLabel(), true); - break; - case UNSAFE: - stateResults.put(index.getLabel(), false); - break; - default: - break; - } - } - return stateResults; - } - - @Override - public StateStatus getStateStatus(String contingencyId, Integer stateId) { - return contingenciesWithSecurityRulesResults.get(contingencyId).getStateStatus(stateId); - } - - private StatesWithSecurityRulesResults getStatesWithSecurityRulesResults_int(String contingencyId) { - return contingenciesWithSecurityRulesResults.get(contingencyId); - } - - public String toString() { - String output = "time horizon: "+ timeHorizon.getName(); - output += "\n" + "contingencies with security rules results: " + getContingenciesWithSecurityRulesResults(); - for(String contingencyId : getContingenciesWithSecurityRulesResults() ) - output += "\n[contingecy id = " + contingencyId + ", states = " + getStatesWithSecurityRulesResults_int(contingencyId) + "]"; - return output; - } - - private class StatesWithSecurityRulesResults { - - // - Map> states = new HashMap>(); - // - Map statesStatus = new HashMap(); - - public boolean addState(Integer stateId, StateStatus stateStatus, Map securityRulesResults) { - boolean added = false; - if ( !states.containsKey(stateId) && !statesStatus.containsKey(stateId) ) { - states.put(stateId, securityRulesResults); - statesStatus.put(stateId, stateStatus); - added = true; - } - return added; - } - - public Set getStates() { - return states.keySet(); - } - - public Map getSecurityRulesResults(Integer stateId) { - return states.get(stateId); - } - - public StateStatus getStateStatus(Integer stateId) { - return statesStatus.get(stateId); - } - - public String toString() { - String output = ""; - for(Integer stateId : getStates()) { - output += "[stateId " + stateId + ", " + getStateStatus(stateId) + ", rules = " + securityRulesResultsToString(getSecurityRulesResults(stateId)) + "]"; - } - return output; - } - - private String securityRulesResultsToString(Map securityRulesResults) { - String results = "["; - for (SecurityIndexType securityIndexType : securityRulesResults.keySet()) { - results += "[" + securityIndexType.getLabel().replaceAll(" ", "_") + " " + securityRulesResults.get(securityIndexType) + "]"; - } - results += " ]"; - return results; - } - } + + // the id of the workflow where the rules have been applied + private final String workflowId; + // the time horizon used for the workflow where the rules have been applied + private final TimeHorizon timeHorizon; + + // > + private Map contingenciesWithSecurityRulesResults = new HashMap(); + + public SecurityRulesApplicationResults(String workflowId, TimeHorizon timeHorizon) { + this.workflowId = workflowId; + this.timeHorizon = timeHorizon; + } + + @Override + public String getWorkflowId() { + return workflowId; + } + + @Override + public TimeHorizon getTimeHorizon() { + return timeHorizon; + } + + + public void addStateWithSecurityRulesResults(String contingencyId, Integer stateId, StateStatus stateStatus, Map securityRulesResults, + boolean rulesAvailable, List invalidRules) { + StatesWithSecurityRulesResults statesWithSecurityRulesResults = new StatesWithSecurityRulesResults(); + if ( contingenciesWithSecurityRulesResults.containsKey(contingencyId) ) { + statesWithSecurityRulesResults = contingenciesWithSecurityRulesResults.get(contingencyId); + } + statesWithSecurityRulesResults.addState(stateId, stateStatus, securityRulesResults, rulesAvailable, invalidRules); + contingenciesWithSecurityRulesResults.put(contingencyId, statesWithSecurityRulesResults); + } + + @Override + public Set getContingenciesWithSecurityRulesResults() { + return contingenciesWithSecurityRulesResults.keySet(); + } + + public List getStatesWithSecurityRulesResults(String contingencyId) { + List statesWithSecurityRulesResults = new ArrayList(); + for(Integer stateId : contingenciesWithSecurityRulesResults.get(contingencyId).getStates()) { + statesWithSecurityRulesResults.add(stateId); + } + return statesWithSecurityRulesResults; + } + + public Map getSecurityRulesResults(String contingencyId, Integer stateId) { + return contingenciesWithSecurityRulesResults.get(contingencyId).getSecurityRulesResults(stateId); + } + + @Override + public Map getStateResults(String contingencyId, Integer stateId) { + Map securityRulesResults = getSecurityRulesResults(contingencyId, stateId); + Map stateResults = new HashMap(); + for(SecurityIndexType index : securityRulesResults.keySet()) { + switch (securityRulesResults.get(index)) { + case SAFE: + stateResults.put(index.getLabel(), true); + break; + case UNSAFE: + stateResults.put(index.getLabel(), false); + break; + default: + break; + } + } + return stateResults; + } + + @Override + public StateStatus getStateStatus(String contingencyId, Integer stateId) { + return contingenciesWithSecurityRulesResults.get(contingencyId).getStateStatus(stateId); + } + + private StatesWithSecurityRulesResults getStatesWithSecurityRulesResults_int(String contingencyId) { + return contingenciesWithSecurityRulesResults.get(contingencyId); + } + + @Override + public boolean areValidRulesAvailable(String contingencyId, Integer stateId) { + boolean rulesAvailable = false; + if ( contingenciesWithSecurityRulesResults.containsKey(contingencyId) ) + rulesAvailable = contingenciesWithSecurityRulesResults.get(contingencyId).getRulesAvailability(stateId); + return rulesAvailable; + } + + @Override + public List getInvalidRules(String contingencyId, Integer stateId) { + List invalidRules = new ArrayList(); + if ( contingenciesWithSecurityRulesResults.containsKey(contingencyId) ) + invalidRules = contingenciesWithSecurityRulesResults.get(contingencyId).getInvalidRules(stateId); + return invalidRules; + } + + public String toString() { + String output = "time horizon: "+ timeHorizon.getName(); + output += "\n" + "contingencies with security rules results: " + getContingenciesWithSecurityRulesResults(); + for(String contingencyId : getContingenciesWithSecurityRulesResults() ) + output += "\n[contingecy id = " + contingencyId + ", states = " + getStatesWithSecurityRulesResults_int(contingencyId) + "]"; + return output; + } + + private class StatesWithSecurityRulesResults { + + // + Map> states = new HashMap>(); + // + Map statesStatus = new HashMap(); + // + Map statesWithRules = new HashMap(); + // + Map> statesWithInvalidRules = new HashMap>(); + + boolean addState(Integer stateId, StateStatus stateStatus, Map securityRulesResults, + Boolean rulesAvailable, List invalidRules) { + boolean added = false; + if ( !states.containsKey(stateId) && !statesStatus.containsKey(stateId) ) { + states.put(stateId, securityRulesResults); + statesStatus.put(stateId, stateStatus); + statesWithRules.put(stateId, rulesAvailable); + statesWithInvalidRules.put(stateId, invalidRules); + added = true; + } + return added; + } + + Set getStates() { + return states.keySet(); + } + + Map getSecurityRulesResults(Integer stateId) { + return states.get(stateId); + } + + StateStatus getStateStatus(Integer stateId) { + return statesStatus.get(stateId); + } + + boolean getRulesAvailability(Integer stateId) { + return statesWithRules.get(stateId); + } + + List getInvalidRules(Integer stateId) { + return statesWithInvalidRules.get(stateId); + } + + public String toString() { + String output = ""; + for(Integer stateId : getStates()) { + output += "[stateId " + stateId + ", " + getStateStatus(stateId) + ", rules = " + securityRulesResultsToString(getSecurityRulesResults(stateId)) + "]"; + } + return output; + } + + private String securityRulesResultsToString(Map securityRulesResults) { + String results = "["; + for (SecurityIndexType securityIndexType : securityRulesResults.keySet()) { + results += "[" + securityIndexType.getLabel().replaceAll(" ", "_") + " " + securityRulesResults.get(securityIndexType) + "]"; + } + results += " ]"; + return results; + } + } } diff --git a/online-workflow/src/main/java/eu/itesla_project/online/StateAnalyzer.java b/online-workflow/src/main/java/eu/itesla_project/online/StateAnalyzer.java index 02cf8d64..ad9240be 100644 --- a/online-workflow/src/main/java/eu/itesla_project/online/StateAnalyzer.java +++ b/online-workflow/src/main/java/eu/itesla_project/online/StateAnalyzer.java @@ -30,6 +30,7 @@ import eu.itesla_project.iidm.network.StateManager; import eu.itesla_project.loadflow.api.LoadFlow; import eu.itesla_project.loadflow.api.LoadFlowResult; +import eu.itesla_project.modules.constraints.ConstraintsModifier; import eu.itesla_project.modules.contingencies.ActionParameters; import eu.itesla_project.modules.contingencies.Contingency; import eu.itesla_project.modules.mcla.MontecarloSampler; @@ -60,193 +61,217 @@ */ public class StateAnalyzer implements Callable { - Logger logger = LoggerFactory.getLogger(StateAnalyzer.class); + Logger logger = LoggerFactory.getLogger(StateAnalyzer.class); - private OnlineWorkflowContext context; - private MontecarloSampler sampler; - private LoadFlow loadFlow; - private OnlineRulesFacade rulesFacade; - private CorrectiveControlOptimizer optimizer; - private Stabilization stabilization; - private ImpactAnalysis impactAnalysis; - private OnlineDb onlineDb; - private Integer stateId; - private OnlineWorkflowParameters parameters; - private StateAnalizerListener stateListener; - private EnumMap status=new EnumMap(OnlineTaskType.class); - Map loadflowResults = new HashMap(); + private OnlineWorkflowContext context; + private MontecarloSampler sampler; + private LoadFlow loadFlow; + private OnlineRulesFacade rulesFacade; + private CorrectiveControlOptimizer optimizer; + private Stabilization stabilization; + private ImpactAnalysis impactAnalysis; + private OnlineDb onlineDb; + private Integer stateId; + private OnlineWorkflowParameters parameters; + private StateAnalizerListener stateListener; + private EnumMap status=new EnumMap(OnlineTaskType.class); + Map loadflowResults = new HashMap(); + private ConstraintsModifier constraintsModifier; - public StateAnalyzer(OnlineWorkflowContext context, MontecarloSampler sampler, LoadFlow loadFlow, - OnlineRulesFacade rulesFacade, CorrectiveControlOptimizer optimizer, Stabilization stabilization, - ImpactAnalysis impactAnalysis, OnlineDb onlineDb, StateAnalizerListener stateListener, OnlineWorkflowParameters parameters) { - this.context = context; - this.sampler = sampler; - this.loadFlow = loadFlow; - this.rulesFacade = rulesFacade; - this.optimizer = optimizer; - this.stabilization = stabilization; - this.impactAnalysis = impactAnalysis; - this.onlineDb = onlineDb; - this.stateListener=stateListener; - this.parameters = parameters; - //stateId = "STATE-" + context.incrementStateCounter(); - stateId = context.incrementStateCounter(); - initStatus(); - stateListener.onUpdate(stateId, status,context.timeHorizon); - } + public StateAnalyzer(OnlineWorkflowContext context, MontecarloSampler sampler, LoadFlow loadFlow, + OnlineRulesFacade rulesFacade, CorrectiveControlOptimizer optimizer, Stabilization stabilization, + ImpactAnalysis impactAnalysis, OnlineDb onlineDb, StateAnalizerListener stateListener, ConstraintsModifier constraintsModifier, + OnlineWorkflowParameters parameters) { + this.context = context; + this.sampler = sampler; + this.loadFlow = loadFlow; + this.rulesFacade = rulesFacade; + this.optimizer = optimizer; + this.stabilization = stabilization; + this.impactAnalysis = impactAnalysis; + this.onlineDb = onlineDb; + this.stateListener=stateListener; + this.constraintsModifier = constraintsModifier; + this.parameters = parameters; + //stateId = "STATE-" + context.incrementStateCounter(); + stateId = context.incrementStateCounter(); + initStatus(); + stateListener.onUpdate(stateId, status,context.timeHorizon); + } - private void initStatus(){ - status.put(OnlineTaskType.SAMPLING, OnlineTaskStatus.IDLE); - status.put(OnlineTaskType.LOAD_FLOW, OnlineTaskStatus.IDLE); - status.put(OnlineTaskType.SECURITY_RULES, OnlineTaskStatus.IDLE); - status.put(OnlineTaskType.OPTIMIZER, OnlineTaskStatus.IDLE); - status.put(OnlineTaskType.TIME_DOMAIN_SIM, OnlineTaskStatus.IDLE); - } - - @Override - public Void call() throws Exception { - OnlineTaskType currentStatus=OnlineTaskType.SAMPLING; - - try { - // create new state - logger.info("Analyzing state {}", stateId); - String stateIdStr=String.valueOf(stateId); - context.getNetwork().getStateManager().cloneState(StateManager.INITIAL_STATE_ID, stateIdStr); - context.getNetwork().getStateManager().setWorkingState(stateIdStr); - // sample - logger.info("{}: sampling started", stateId); - status.put(currentStatus, OnlineTaskStatus.RUNNING); - stateListener.onUpdate(stateId, status,context.timeHorizon); - if ( !parameters.analyseBasecase() || stateId > 0 ) - sampler.sample(); - else - logger.info("{}: state = basecase", stateId); - status.put(currentStatus, OnlineTaskStatus.SUCCESS); - stateListener.onUpdate(stateId, status,context.timeHorizon); - logger.info("{}: sampling terminated", stateId); - - // complete state with loadflow - currentStatus=OnlineTaskType.LOAD_FLOW; - status.put(currentStatus, OnlineTaskStatus.RUNNING); - stateListener.onUpdate(stateId, status,context.timeHorizon); - logger.info("{}: loadflow started", stateId); + private void initStatus(){ + status.put(OnlineTaskType.SAMPLING, OnlineTaskStatus.IDLE); + status.put(OnlineTaskType.LOAD_FLOW, OnlineTaskStatus.IDLE); + status.put(OnlineTaskType.SECURITY_RULES, OnlineTaskStatus.IDLE); + status.put(OnlineTaskType.OPTIMIZER, OnlineTaskStatus.IDLE); + status.put(OnlineTaskType.TIME_DOMAIN_SIM, OnlineTaskStatus.IDLE); + } + + @Override + public Void call() throws Exception { + OnlineTaskType currentStatus=OnlineTaskType.SAMPLING; + + try { + // create new state + logger.info("Analyzing state {}", stateId); + String stateIdStr=String.valueOf(stateId); + context.getNetwork().getStateManager().cloneState(StateManager.INITIAL_STATE_ID, stateIdStr); + context.getNetwork().getStateManager().setWorkingState(stateIdStr); + // sample + logger.info("{}: sampling started", stateId); + status.put(currentStatus, OnlineTaskStatus.RUNNING); + stateListener.onUpdate(stateId, status,context.timeHorizon); + if ( !parameters.analyseBasecase() || stateId > 0 ) + sampler.sample(); + else + logger.info("{}: state = basecase", stateId); + status.put(currentStatus, OnlineTaskStatus.SUCCESS); + stateListener.onUpdate(stateId, status,context.timeHorizon); + logger.info("{}: sampling terminated", stateId); + + // complete state with loadflow + currentStatus=OnlineTaskType.LOAD_FLOW; + status.put(currentStatus, OnlineTaskStatus.RUNNING); + stateListener.onUpdate(stateId, status,context.timeHorizon); + logger.info("{}: loadflow started", stateId); LoadFlowResult result = loadFlow.run(); - status.put(currentStatus, result.isOk()?OnlineTaskStatus.SUCCESS:OnlineTaskStatus.FAILED); - stateListener.onUpdate(stateId, status,context.timeHorizon); - logger.info("{}: loadflow terminated", stateId); - if ( result.getMetrics() != null ) { - logger.info("{}: loadflow metrics: {}", stateId, result.getMetrics()); - if ( !result.getMetrics().isEmpty() ) - onlineDb.storeMetrics(context.getWorkflowId(), stateId, OnlineStep.LOAD_FLOW, result.getMetrics()); - } - status.put(currentStatus, result.isOk()?OnlineTaskStatus.SUCCESS:OnlineTaskStatus.FAILED); - - if ( parameters.storeStates() ) { - logger.info("{}: storing state in online db", stateId); - onlineDb.storeState(context.getWorkflowId(), stateId, context.getNetwork()); - } - - if ( result.isOk() ) { - // stores violations only if loadflow converges - logger.info("{}: storing violations after {} in online db", stateId, OnlineStep.LOAD_FLOW); - List violations = Security.checkLimits(context.getNetwork(), CurrentLimitType.PATL, Integer.MAX_VALUE, parameters.getLimitReduction()); - if ( violations != null && !violations.isEmpty() ) - onlineDb.storeViolations(context.getWorkflowId(), stateId, OnlineStep.LOAD_FLOW, violations); - else - logger.info("{}: no violations after {}", stateId, OnlineStep.LOAD_FLOW); + status.put(currentStatus, result.isOk()?OnlineTaskStatus.SUCCESS:OnlineTaskStatus.FAILED); + stateListener.onUpdate(stateId, status,context.timeHorizon); + logger.info("{}: loadflow terminated", stateId); + if ( result.getMetrics() != null ) { + logger.info("{}: loadflow metrics: {}", stateId, result.getMetrics()); + if ( !result.getMetrics().isEmpty() ) + onlineDb.storeMetrics(context.getWorkflowId(), stateId, OnlineStep.LOAD_FLOW, result.getMetrics()); + } + status.put(currentStatus, result.isOk()?OnlineTaskStatus.SUCCESS:OnlineTaskStatus.FAILED); + + if ( parameters.storeStates() ) { + logger.info("{}: storing state in online db", stateId); + onlineDb.storeState(context.getWorkflowId(), stateId, context.getNetwork()); + } - - stateListener.onUpdate(stateId, status,context.timeHorizon); - // check state against contingencies - boolean isStateSafe = true; - List contingenciesForOptimizer = new ArrayList(); - List contingenciesForSimulator = new ArrayList(); - currentStatus=OnlineTaskType.SECURITY_RULES; - status.put(currentStatus, OnlineTaskStatus.RUNNING); - stateListener.onUpdate(stateId, status,context.timeHorizon); - - for (Contingency contingency : context.getContingenciesToAnalyze()) { - logger.info("{}: check security rules against contingency {}", stateId, contingency.getId()); - RulesFacadeResults rulesResults = rulesFacade.evaluate(contingency, context.getNetwork()); - if ( rulesResults.getStateStatus() == StateStatus.SAFE ) { // check if this contingency is ok - logger.info("{}: is safe for contingency {}", stateId, contingency.getId()); - if ( parameters.validation() ) { // if validation - // send all [contingency,state] pairs to simulation - contingenciesForSimulator.add(contingency); - // send safe [contingency,state] pairs to optimizer - contingenciesForOptimizer.add(contingency); - } - } else if( rulesResults.getStateStatus() == StateStatus.SAFE_WITH_CORRECTIVE_ACTIONS ) { // check if this contingency could be ok with corrective actions - logger.info("{}: requires corrective actions for contingency {}", stateId, contingency.getId()); - isStateSafe = false; - contingenciesForOptimizer.add(contingency); - if ( parameters.validation() ) { // if validation - // send all [contingency,state] pairs to simulation - contingenciesForSimulator.add(contingency); - } - } else { // we need to perform a time-domain simulation on this state for this contingency - logger.info("{}: requires time-domain simulation for contingency {}", stateId, contingency.getId()); - isStateSafe = false; - contingenciesForSimulator.add(contingency); - } + if ( result.isOk() ) { + // stores violations only if loadflow converges + logger.info("{}: storing violations after {} in online db", stateId, OnlineStep.LOAD_FLOW); + List violations = Security.checkLimits(context.getNetwork(), + CurrentLimitType.PATL, + Integer.MAX_VALUE, + parameters.getLimitReduction()); + if ( violations != null && !violations.isEmpty() ) { + onlineDb.storeViolations(context.getWorkflowId(), stateId, OnlineStep.LOAD_FLOW, violations); + if ( parameters.isHandleViolationsInN() ) { + if ( parameters.analyseBasecase() && stateId == 0 ) { + constraintsModifier.looseConstraints(stateIdStr, + violations, + parameters.getConstraintMargin(), + true); // loose constraints on state 0 (=basecase) + } else { + constraintsModifier.looseConstraints(stateIdStr, violations); // loose constraints on sampled state + } + } + } else + logger.info("{}: no violations after {}", stateId, OnlineStep.LOAD_FLOW); - synchronized (context.getSecurityRulesResults()) { - context.getSecurityRulesResults().addStateWithSecurityRulesResults(contingency.getId(), stateId, rulesResults.getStateStatus(), rulesResults.getIndexesResults()); - stateListener.onSecurityRulesApplicationResults(contingency.getId(),stateId, context); - } - - if ( parameters.validation() ) { - RulesFacadeResults wcaRulesResults = rulesFacade.wcaEvaluate(contingency, context.getNetwork()); - synchronized (context.getWcaSecurityRulesResults()) { - context.getWcaSecurityRulesResults().addStateWithSecurityRulesResults(contingency.getId(), stateId, wcaRulesResults.getStateStatus(), wcaRulesResults.getIndexesResults()); - } - } + stateListener.onUpdate(stateId, status,context.timeHorizon); + // check state against contingencies + boolean isStateSafe = true; + List contingenciesForOptimizer = new ArrayList(); + List contingenciesForSimulator = new ArrayList(); + currentStatus=OnlineTaskType.SECURITY_RULES; + status.put(currentStatus, OnlineTaskStatus.RUNNING); + stateListener.onUpdate(stateId, status,context.timeHorizon); + + for (Contingency contingency : context.getContingenciesToAnalyze()) { + logger.info("{}: check security rules against contingency {}", stateId, contingency.getId()); + RulesFacadeResults rulesResults = rulesFacade.evaluate(contingency, context.getNetwork()); + if ( rulesResults.areRulesAvailable() ) { + if ( rulesResults.getStateStatus() == StateStatus.SAFE ) { // check if this contingency is ok + logger.info("{}: is safe for contingency {}", stateId, contingency.getId()); + if ( parameters.validation() ) { // if validation + // send all [contingency,state] pairs to simulation + contingenciesForSimulator.add(contingency); + // send safe [contingency,state] pairs to optimizer + contingenciesForOptimizer.add(contingency); + } + } else if( rulesResults.getStateStatus() == StateStatus.SAFE_WITH_CORRECTIVE_ACTIONS ) { // check if this contingency could be ok with corrective actions + logger.info("{}: requires corrective actions for contingency {}", stateId, contingency.getId()); + isStateSafe = false; + contingenciesForOptimizer.add(contingency); + if ( parameters.validation() ) { // if validation + // send all [contingency,state] pairs to simulation + contingenciesForSimulator.add(contingency); + } + } else { // we need to perform a time-domain simulation on this state for this contingency + logger.info("{}: requires time-domain simulation for contingency {}", stateId, contingency.getId()); + isStateSafe = false; + contingenciesForSimulator.add(contingency); + } + } else { + logger.warn("{}: no valid rules for contingency {}", stateId, contingency.getId()); + contingenciesForSimulator.add(contingency); + } + + synchronized (context.getSecurityRulesResults()) { + context.getSecurityRulesResults().addStateWithSecurityRulesResults(contingency.getId(), stateId, rulesResults.getStateStatus(), + rulesResults.getIndexesResults(), rulesResults.areRulesAvailable(), + rulesResults.getInvalidRules()); + stateListener.onSecurityRulesApplicationResults(contingency.getId(),stateId, context); + } + + if ( parameters.validation() ) { + RulesFacadeResults wcaRulesResults = rulesFacade.wcaEvaluate(contingency, context.getNetwork()); + synchronized (context.getWcaSecurityRulesResults()) { + context.getWcaSecurityRulesResults().addStateWithSecurityRulesResults(contingency.getId(), stateId, wcaRulesResults.getStateStatus(), + wcaRulesResults.getIndexesResults(), rulesResults.areRulesAvailable(), + rulesResults.getInvalidRules()); + } + } } - status.put(currentStatus, OnlineTaskStatus.SUCCESS); - stateListener.onUpdate(stateId, status,context.timeHorizon); - computeAndStorePostContingencyViolations(context.getNetwork(), context.getContingenciesToAnalyze()); - if ( isStateSafe && !parameters.validation() ) { - // state is safe: stop analysis and destroy the state - logger.info("{}: is safe for every contingency: stopping analysis", stateId); - //context.getNetwork().getStateManager().removeState(stateIdStr); // the state is still needed - return null; - } else { - if ( contingenciesForOptimizer.size() > 0 ) { - // perform corrective control optimization - currentStatus=OnlineTaskType.OPTIMIZER; - status.put(currentStatus, OnlineTaskStatus.RUNNING); - stateListener.onUpdate(stateId, status,context.timeHorizon); - logger.info("{}: corrective control optimization started - working on {} contingencies", stateId, contingenciesForOptimizer.size()); - runOptimizer(context.getNetwork(), contingenciesForOptimizer, contingenciesForSimulator, context.getResults()); - // the optimizer could possibly have changed the network working state: set the original one - context.getNetwork().getStateManager().setWorkingState(stateIdStr); - stateListener.onOptimizerResults(stateId,context); - logger.info("{}: corrective control optimization terminated", stateId); - status.put(OnlineTaskType.OPTIMIZER, OnlineTaskStatus.SUCCESS); - stateListener.onUpdate(stateId, status,context.timeHorizon); - } - if ( contingenciesForSimulator.size() > 0 ) { - // perform time-domain simulation - currentStatus=OnlineTaskType.TIME_DOMAIN_SIM; - status.put(currentStatus, OnlineTaskStatus.RUNNING); - stateListener.onUpdate(stateId, status,context.timeHorizon); - logger.info("{}: time-domain simulation started - working on {} contingencies", stateId, contingenciesForSimulator.size()); - logger.info("{}: stabilization started", stateId); - StabilizationResult stabilizationResult = stabilization.run(); - logger.info("{}: stabilization terminated", stateId); - if ( stabilizationResult.getMetrics() != null ) { - logger.info("{}: stabilization metrics: {}", stateId, stabilizationResult.getMetrics()); - if ( !stabilizationResult.getMetrics().isEmpty() ) - onlineDb.storeMetrics(context.getWorkflowId(), stateId, OnlineStep.STABILIZATION, stabilizationResult.getMetrics()); - } + status.put(currentStatus, OnlineTaskStatus.SUCCESS); + stateListener.onUpdate(stateId, status,context.timeHorizon); + computeAndStorePostContingencyViolations(context.getNetwork(), context.getContingenciesToAnalyze()); + if ( isStateSafe && !parameters.validation() ) { + // state is safe: stop analysis and destroy the state + logger.info("{}: is safe for every contingency: stopping analysis", stateId); + //context.getNetwork().getStateManager().removeState(stateIdStr); // the state is still needed + return null; + } else { + if ( contingenciesForOptimizer.size() > 0 ) { + // perform corrective control optimization + currentStatus=OnlineTaskType.OPTIMIZER; + status.put(currentStatus, OnlineTaskStatus.RUNNING); + stateListener.onUpdate(stateId, status,context.timeHorizon); + logger.info("{}: corrective control optimization started - working on {} contingencies", stateId, contingenciesForOptimizer.size()); + runOptimizer(context.getNetwork(), contingenciesForOptimizer, contingenciesForSimulator, context.getResults()); + // the optimizer could possibly have changed the network working state: set the original one + context.getNetwork().getStateManager().setWorkingState(stateIdStr); + stateListener.onOptimizerResults(stateId,context); + logger.info("{}: corrective control optimization terminated", stateId); + status.put(OnlineTaskType.OPTIMIZER, OnlineTaskStatus.SUCCESS); + stateListener.onUpdate(stateId, status,context.timeHorizon); + } + if ( contingenciesForSimulator.size() > 0 ) { + // perform time-domain simulation + currentStatus=OnlineTaskType.TIME_DOMAIN_SIM; + status.put(currentStatus, OnlineTaskStatus.RUNNING); + stateListener.onUpdate(stateId, status,context.timeHorizon); + logger.info("{}: time-domain simulation started - working on {} contingencies", stateId, contingenciesForSimulator.size()); + logger.info("{}: stabilization started", stateId); + StabilizationResult stabilizationResult = stabilization.run(); + logger.info("{}: stabilization terminated", stateId); + if ( stabilizationResult.getMetrics() != null ) { + logger.info("{}: stabilization metrics: {}", stateId, stabilizationResult.getMetrics()); + if ( !stabilizationResult.getMetrics().isEmpty() ) + onlineDb.storeMetrics(context.getWorkflowId(), stateId, OnlineStep.STABILIZATION, stabilizationResult.getMetrics()); + } if (stabilizationResult.getStatus() == StabilizationStatus.COMPLETED) { ImpactAnalysisResult impactAnalysisResult = impactAnalysis.run(stabilizationResult.getState(), OnlineUtils.getContingencyIds(contingenciesForSimulator)); logger.info("{}: impact analysis terminated", stateId); - if ( impactAnalysisResult.getMetrics() != null ) { - logger.info("{}: impact analysis metrics: {}", stateId, impactAnalysisResult.getMetrics()); - if ( !impactAnalysisResult.getMetrics().isEmpty() ) - onlineDb.storeMetrics(context.getWorkflowId(), stateId, OnlineStep.IMPACT_ANALYSIS, impactAnalysisResult.getMetrics()); - } + if ( impactAnalysisResult.getMetrics() != null ) { + logger.info("{}: impact analysis metrics: {}", stateId, impactAnalysisResult.getMetrics()); + if ( !impactAnalysisResult.getMetrics().isEmpty() ) + onlineDb.storeMetrics(context.getWorkflowId(), stateId, OnlineStep.IMPACT_ANALYSIS, impactAnalysisResult.getMetrics()); + } putResultsIntoContext(stateId, impactAnalysisResult, context.getResults()); stateListener.onImpactAnalysisResults(stateId, context); logger.info("{}: time-domain simulation terminated", stateId); @@ -257,220 +282,220 @@ public Void call() throws Exception { status.put(OnlineTaskType.TIME_DOMAIN_SIM, OnlineTaskStatus.FAILED); stateListener.onUpdate(stateId, status,context.timeHorizon, "time-domain simulation failed (stabilization): metrics = "+stabilizationResult.getMetrics()); } - } - } - stateListener.onUpdate(stateId, status,context.timeHorizon); - } else { - logger.error("{}: stop analisys of state: loadflow does not converge: metrics = {}", stateIdStr, result.getMetrics()); - stateListener.onUpdate(stateId, status,context.timeHorizon, "LoadFLow does not converge: metrics = " + result.getMetrics()); - } - } catch (Throwable t) { - status.put(currentStatus, OnlineTaskStatus.FAILED); - //TODO manage string ifo detail - stateListener.onUpdate(stateId, status,context.timeHorizon ,currentStatus +" failed ... "); + } + } + stateListener.onUpdate(stateId, status,context.timeHorizon); + } else { + logger.error("{}: stop analisys of state: loadflow does not converge: metrics = {}", stateIdStr, result.getMetrics()); + stateListener.onUpdate(stateId, status,context.timeHorizon, "LoadFLow does not converge: metrics = " + result.getMetrics()); + } + } catch (Throwable t) { + status.put(currentStatus, OnlineTaskStatus.FAILED); + //TODO manage string ifo detail + stateListener.onUpdate(stateId, status,context.timeHorizon ,currentStatus +" failed ... "); logger.error("{}: Error working on state: {}", stateId, t.toString(), t); } - return null; - } - - private void runOptimizer(Network network, List contingencies, List contingenciesForSimulator, ForecastAnalysisResults results) { - String stateId = network.getStateManager().getWorkingStateId(); - logger.info("{}: running optimizer", stateId); - List> postContingencyStateComputations = new ArrayList<>(contingencies.size()); - for (Contingency contingency : contingencies) { - postContingencyStateComputations.add( - new Callable() { + return null; + } + + private void runOptimizer(Network network, List contingencies, List contingenciesForSimulator, ForecastAnalysisResults results) { + String stateId = network.getStateManager().getWorkingStateId(); + logger.info("{}: running optimizer", stateId); + List> postContingencyStateComputations = new ArrayList<>(contingencies.size()); + for (Contingency contingency : contingencies) { + postContingencyStateComputations.add( + new Callable() { + + @Override + public Void call() throws Exception { + String postContingencyStateId = stateId + "-post-" + contingency.getId(); + boolean loadflowConverge = computePostContingencyState(network, stateId, contingency, postContingencyStateId); + if ( loadflowConverge ) { + logger.info("{}: adding state {} to post contingency states for optimizer", stateId, postContingencyStateId); + PostContingencyState postContingencyState = new PostContingencyState(network, postContingencyStateId, contingency); + logger.info("{}: running optimizer on post contingency state {} of contingency {}", stateId, postContingencyStateId, contingency.getId()); + CorrectiveControlOptimizerResult optimizerResult = null; + try { + optimizerResult = optimizer.run(postContingencyState); + } catch (Throwable t) { + logger.error("{}: Error running optimizer on contingency {}: {}", stateId, contingency.getId(), t.getMessage(), t); + optimizerResult = new CorrectiveControlOptimizerResult(contingency.getId(), false); + optimizerResult.setFinalStatus(CCOFinalStatus.OPTIMIZER_EXECUTION_ERROR); + optimizerResult.setCause(t.getMessage()); + } + logger.info("{}: optimizer results for contingency {}: action found = {}, status = {}, cause = {}", stateId, contingency.getId(), optimizerResult.areActionsFound(), optimizerResult.getFinalStatus(), optimizerResult.getCause()); + Map> actions = null; + if ( optimizerResult.areActionsFound() ) { + logger.info("{}: optimizer results: action plan {}, actions {} for contingency {}", stateId, optimizerResult.getActionPlan(), optimizerResult.getActionsIds(), contingency.getId()); + actions = new HashMap>(); + for(String actionId : optimizerResult.getActionsIds()) + actions.put(actionId, optimizerResult.getEquipmentsWithParameters(actionId)); + } else { + logger.error("{}: Error: optimizer didn't find actions for post contingency state {}", stateId, postContingencyStateId); + if ( !parameters.validation() ) { // if validation -> all the [contingency,state] pairs have already been added to the list for simulation -> no need to do it here + // add to contingencies for simulator + synchronized(contingenciesForSimulator) { + contingenciesForSimulator.add(contingency); + } + } + } + synchronized(results) { + results.addStateWithActions(contingency.getId(), + Integer.valueOf(stateId), + optimizerResult.areActionsFound(), + optimizerResult.getFinalStatus(), + optimizerResult.getCause(), + optimizerResult.getActionPlan(), + actions); + } + } else { + logger.info("{}: loadflow does not converge on post contigency state {}, the contingency {} will be analyzed by T-D simulation", stateId, postContingencyStateId, contingency.getId()); + if ( !parameters.validation() ) { // if validation -> all the [contingency,state] pairs have already been added to the list for simulation -> no need to do it here + // add to contingencies for simulator + synchronized(contingenciesForSimulator) { + contingenciesForSimulator.add(contingency); + } + } + } + + return null; + } + + } + ); + } + ExecutorService taskExecutor = Executors.newFixedThreadPool(contingencies.size()); + try { + taskExecutor.invokeAll(postContingencyStateComputations); + } catch (InterruptedException e) { + logger.error("{}: Error running optimizer: {}", stateId, e.getMessage()); + } + taskExecutor.shutdown(); + network.getStateManager().setWorkingState(stateId); + } - @Override - public Void call() throws Exception { - String postContingencyStateId = stateId + "-post-" + contingency.getId(); - boolean loadflowConverge = computePostContingencyState(network, stateId, contingency, postContingencyStateId); - if ( loadflowConverge ) { - logger.info("{}: adding state {} to post contingency states for optimizer", stateId, postContingencyStateId); - PostContingencyState postContingencyState = new PostContingencyState(network, postContingencyStateId, contingency); - logger.info("{}: running optimizer on post contingency state {} of contingency {}", stateId, postContingencyStateId, contingency.getId()); - CorrectiveControlOptimizerResult optimizerResult = null; - try { - optimizerResult = optimizer.run(postContingencyState); - } catch (Throwable t) { - logger.error("{}: Error running optimizer on contingency {}: {}", stateId, contingency.getId(), t.getMessage(), t); - optimizerResult = new CorrectiveControlOptimizerResult(contingency.getId(), false); - optimizerResult.setFinalStatus(CCOFinalStatus.OPTIMIZER_EXECUTION_ERROR); - optimizerResult.setCause(t.getMessage()); - } - logger.info("{}: optimizer results for contingency {}: action found = {}, status = {}, cause = {}", stateId, contingency.getId(), optimizerResult.areActionsFound(), optimizerResult.getFinalStatus(), optimizerResult.getCause()); - Map> actions = null; - if ( optimizerResult.areActionsFound() ) { - logger.info("{}: optimizer results: action plan {}, actions {} for contingency {}", stateId, optimizerResult.getActionPlan(), optimizerResult.getActionsIds(), contingency.getId()); - actions = new HashMap>(); - for(String actionId : optimizerResult.getActionsIds()) - actions.put(actionId, optimizerResult.getEquipmentsWithParameters(actionId)); - } else { - logger.error("{}: Error: optimizer didn't find actions for post contingency state {}", stateId, postContingencyStateId); - if ( !parameters.validation() ) { // if validation -> all the [contingency,state] pairs have already been added to the list for simulation -> no need to do it here - // add to contingencies for simulator - synchronized(contingenciesForSimulator) { - contingenciesForSimulator.add(contingency); - } - } - } - synchronized(results) { - results.addStateWithActions(contingency.getId(), - Integer.valueOf(stateId), - optimizerResult.areActionsFound(), - optimizerResult.getFinalStatus(), - optimizerResult.getCause(), - optimizerResult.getActionPlan(), - actions); - } - } else { - logger.info("{}: loadflow does not converge on post contigency state {}, the contingency {} will be analyzed by T-D simulation", stateId, postContingencyStateId, contingency.getId()); - if ( !parameters.validation() ) { // if validation -> all the [contingency,state] pairs have already been added to the list for simulation -> no need to do it here - // add to contingencies for simulator - synchronized(contingenciesForSimulator) { - contingenciesForSimulator.add(contingency); - } - } - } - - return null; - } - - } - ); - } - ExecutorService taskExecutor = Executors.newFixedThreadPool(contingencies.size()); - try { - taskExecutor.invokeAll(postContingencyStateComputations); - } catch (InterruptedException e) { - logger.error("{}: Error running optimizer: {}", stateId, e.getMessage()); - } - taskExecutor.shutdown(); - network.getStateManager().setWorkingState(stateId); - } - - private void computeAndStorePostContingencyViolations(Network network, List contingencies) { - String stateId = network.getStateManager().getWorkingStateId(); - logger.info("{}: computing post contingency violations", stateId); - List> postContingencyViolationsComputations = new ArrayList<>(contingencies.size()); - for (Contingency contingency : contingencies) { - postContingencyViolationsComputations.add( - new Callable() { + private void computeAndStorePostContingencyViolations(Network network, List contingencies) { + String stateId = network.getStateManager().getWorkingStateId(); + logger.info("{}: computing post contingency violations", stateId); + List> postContingencyViolationsComputations = new ArrayList<>(contingencies.size()); + for (Contingency contingency : contingencies) { + postContingencyViolationsComputations.add( + new Callable() { - @Override - public Void call() throws Exception { - List violations = new ArrayList(); - // compute post contingency state - String postContingencyStateId = stateId + "-post-" + contingency.getId(); - boolean loadflowConverge = computePostContingencyState(network, stateId, contingency, postContingencyStateId); - if ( loadflowConverge ) { - logger.info("{}: computing post contingency violations for contingency {}", stateId, contingency.getId()); - violations = Security.checkLimits(network, CurrentLimitType.PATL, Integer.MAX_VALUE, parameters.getLimitReduction()); - if ( violations == null || violations.isEmpty() ) { - logger.info("{}: no post contingency violations for state {} and contingency {}", stateId, contingency.getId()); - violations = new ArrayList(); - } - } else { - logger.info("{}: post contingency loadflow does not converge for contingency {}, skipping computing post contingency violations", stateId, contingency.getId()); - } - logger.info("{}: storing post contingency violations for state {} and contingency {} in online db", stateId, contingency.getId()); - onlineDb.storePostContingencyViolations(context.getWorkflowId(), Integer.valueOf(stateId), contingency.getId(), loadflowConverge, violations); - network.getStateManager().setWorkingState(stateId); -// network.getStateManager().removeState(postContingencyStateId); - return null; - } - } - ); - } - ExecutorService taskExecutor = Executors.newFixedThreadPool(contingencies.size()); - try { - taskExecutor.invokeAll(postContingencyViolationsComputations); - } catch (InterruptedException e) { - logger.error("{}: Error computing post contingency vioations: {}", stateId, e.getMessage()); - } - taskExecutor.shutdown(); - } - - private boolean computePostContingencyState(Network network, String stateId, Contingency contingency, String postContingencyStateId) { - boolean loadflowConverge = false; - logger.info("{}: computing post contingency state for contingency {}", stateId, contingency.getId()); - //String postContingencyStateId = stateId + "-post-" + contingency.getId(); - boolean alreadyProcessed = false; - synchronized (loadflowResults) { - if ( loadflowResults.containsKey(postContingencyStateId) ) { - alreadyProcessed = true; - loadflowConverge = loadflowResults.get(postContingencyStateId); - } - } - if ( alreadyProcessed && network.getStateManager().getStateIds().contains(postContingencyStateId) ) { - // post contingency state already computed, avoid to run the load flow again - logger.info("{}: post contingency state {} already computed", stateId, postContingencyStateId); - network.getStateManager().setWorkingState(postContingencyStateId); - } else { - // create post contingency state - logger.info("{}: creating post contingency state {}", stateId, postContingencyStateId); - network.getStateManager().cloneState(stateId, postContingencyStateId); - network.getStateManager().setWorkingState(postContingencyStateId); - // apply contingency to post contingency state - logger.info("{}: applying contingency {} to post contingency state {}", stateId, contingency.getId(), postContingencyStateId); - contingency.toTask().modify(network); - try { - // run load flow on post contingency state - logger.info("{}: running load flow on post contingency state {}", stateId, postContingencyStateId); - LoadFlowResult result = loadFlow.run(); - if ( result.isOk() ) { - logger.info("{}: load flow on post contingency state {} converge", stateId, postContingencyStateId); - loadflowConverge = true; - } else { - logger.info("{}: load flow on post contingency state {} does not converge", stateId, postContingencyStateId); - loadflowConverge = false; - } - synchronized (loadflowResults) { - loadflowResults.put(postContingencyStateId, loadflowConverge); - } - } catch (Exception e) { - logger.info("{}: error running load flow on post contingency state {}: {}", stateId, postContingencyStateId, e.getMessage()); - loadflowConverge = false; - } - } - //network.getStateManager().setWorkingState(stateId); - return loadflowConverge; - } + @Override + public Void call() throws Exception { + List violations = new ArrayList(); + // compute post contingency state + String postContingencyStateId = stateId + "-post-" + contingency.getId(); + boolean loadflowConverge = computePostContingencyState(network, stateId, contingency, postContingencyStateId); + if ( loadflowConverge ) { + logger.info("{}: computing post contingency violations for contingency {}", stateId, contingency.getId()); + violations = Security.checkLimits(network, CurrentLimitType.PATL, Integer.MAX_VALUE, parameters.getLimitReduction()); + if ( violations == null || violations.isEmpty() ) { + logger.info("{}: no post contingency violations for contingency {}", stateId, contingency.getId()); + violations = new ArrayList(); + } + } else { + logger.info("{}: post contingency loadflow does not converge for contingency {}, skipping computing post contingency violations", stateId, contingency.getId()); + } + logger.info("{}: storing post contingency violations/loadflow results for contingency {} in online db", stateId, contingency.getId()); + onlineDb.storePostContingencyViolations(context.getWorkflowId(), Integer.valueOf(stateId), contingency.getId(), loadflowConverge, violations); + network.getStateManager().setWorkingState(stateId); + // network.getStateManager().removeState(postContingencyStateId); + return null; + } + } + ); + } + ExecutorService taskExecutor = Executors.newFixedThreadPool(contingencies.size()); + try { + taskExecutor.invokeAll(postContingencyViolationsComputations); + } catch (InterruptedException e) { + logger.error("{}: Error computing post contingency vioations: {}", stateId, e.getMessage()); + } + taskExecutor.shutdown(); + } - private void putResultsIntoContext(Integer stateId, ImpactAnalysisResult simulationResult, ForecastAnalysisResults results) { - Objects.requireNonNull(stateId, "state id is null"); - Objects.requireNonNull(simulationResult, "simulation result is null"); - Objects.requireNonNull(results, "forecast analysis result is null"); - List securityIndexesList = new ArrayList(); - if ( parameters.getSecurityIndexes() == null ) - securityIndexesList = simulationResult.getSecurityIndexes(); - else { - securityIndexesList = simulationResult.getSecurityIndexes().stream().filter(x -> parameters.getSecurityIndexes().contains(x.getId().getSecurityIndexType())).collect(Collectors.toList()); - if (securityIndexesList.isEmpty()) { - logger.info("Empty filter security indexes -> using all the indexes"); - securityIndexesList = simulationResult.getSecurityIndexes(); - } - } + private boolean computePostContingencyState(Network network, String stateId, Contingency contingency, String postContingencyStateId) { + boolean loadflowConverge = false; + logger.info("{}: computing post contingency state for contingency {}", stateId, contingency.getId()); + //String postContingencyStateId = stateId + "-post-" + contingency.getId(); + boolean alreadyProcessed = false; + synchronized (loadflowResults) { + if ( loadflowResults.containsKey(postContingencyStateId) ) { + alreadyProcessed = true; + loadflowConverge = loadflowResults.get(postContingencyStateId); + } + } + if ( alreadyProcessed && network.getStateManager().getStateIds().contains(postContingencyStateId) ) { + // post contingency state already computed, avoid to run the load flow again + logger.info("{}: post contingency state {} already computed", stateId, postContingencyStateId); + network.getStateManager().setWorkingState(postContingencyStateId); + } else { + // create post contingency state + logger.info("{}: creating post contingency state {}", stateId, postContingencyStateId); + network.getStateManager().cloneState(stateId, postContingencyStateId); + network.getStateManager().setWorkingState(postContingencyStateId); + // apply contingency to post contingency state + logger.info("{}: applying contingency {} to post contingency state {}", stateId, contingency.getId(), postContingencyStateId); + contingency.toTask().modify(network); + try { + // run load flow on post contingency state + logger.info("{}: running load flow on post contingency state {}", stateId, postContingencyStateId); + LoadFlowResult result = loadFlow.run(); + if ( result.isOk() ) { + logger.info("{}: load flow on post contingency state {} converge", stateId, postContingencyStateId); + loadflowConverge = true; + } else { + logger.info("{}: load flow on post contingency state {} does not converge", stateId, postContingencyStateId); + loadflowConverge = false; + } + synchronized (loadflowResults) { + loadflowResults.put(postContingencyStateId, loadflowConverge); + } + } catch (Exception e) { + logger.info("{}: error running load flow on post contingency state {}: {}", stateId, postContingencyStateId, e.getMessage()); + loadflowConverge = false; + } + } + //network.getStateManager().setWorkingState(stateId); + return loadflowConverge; + } + + private void putResultsIntoContext(Integer stateId, ImpactAnalysisResult simulationResult, ForecastAnalysisResults results) { + Objects.requireNonNull(stateId, "state id is null"); + Objects.requireNonNull(simulationResult, "simulation result is null"); + Objects.requireNonNull(results, "forecast analysis result is null"); + List securityIndexesList = new ArrayList(); + if ( parameters.getSecurityIndexes() == null ) + securityIndexesList = simulationResult.getSecurityIndexes(); + else { + securityIndexesList = simulationResult.getSecurityIndexes().stream().filter(x -> parameters.getSecurityIndexes().contains(x.getId().getSecurityIndexType())).collect(Collectors.toList()); + if (securityIndexesList.isEmpty()) { + logger.info("Empty filter security indexes -> using all the indexes"); + securityIndexesList = simulationResult.getSecurityIndexes(); + } + } //Multimap securityIndexes = Multimaps.index(simulationResult.getSecurityIndexes(), new Function() { - Multimap securityIndexes = Multimaps.index(securityIndexesList, new Function() { + Multimap securityIndexes = Multimaps.index(securityIndexesList, new Function() { @Override public String apply(SecurityIndex index){ return index.getId().getContingencyId(); } }); - synchronized (results) { - for (Map.Entry> entry : securityIndexes.asMap().entrySet()) { - boolean isSafe = OnlineUtils.isSafe(entry.getValue()); - if ( !isSafe ) { - logger.info("{}: unsafe for contingency {} afer time domain simulation", stateId, entry.getKey()); - results.addUnsafeStateWithIndexes(entry.getKey(), stateId, new ArrayList<>(entry.getValue())); - } else { - logger.info("{}: safe for contingency {} afer time domain simulation", stateId, entry.getKey()); - if ( parameters.validation() ) // if validation add anyway to results - results.addUnsafeStateWithIndexes(entry.getKey(), stateId, new ArrayList<>(entry.getValue())); - } - } - } - } + synchronized (results) { + for (Map.Entry> entry : securityIndexes.asMap().entrySet()) { + boolean isSafe = OnlineUtils.isSafe(entry.getValue()); + if ( !isSafe ) { + logger.info("{}: unsafe for contingency {} afer time domain simulation", stateId, entry.getKey()); + results.addUnsafeStateWithIndexes(entry.getKey(), stateId, new ArrayList<>(entry.getValue())); + } else { + logger.info("{}: safe for contingency {} afer time domain simulation", stateId, entry.getKey()); + if ( parameters.validation() ) // if validation add anyway to results + results.addUnsafeStateWithIndexes(entry.getKey(), stateId, new ArrayList<>(entry.getValue())); + } + } + } + } } diff --git a/online-workflow/src/main/java/eu/itesla_project/online/db/OnlineDbMVStore.java b/online-workflow/src/main/java/eu/itesla_project/online/db/OnlineDbMVStore.java index 165c1e26..dbbe5b98 100644 --- a/online-workflow/src/main/java/eu/itesla_project/online/db/OnlineDbMVStore.java +++ b/online-workflow/src/main/java/eu/itesla_project/online/db/OnlineDbMVStore.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) + * Copyright (c) 2016, 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/. @@ -78,1743 +79,1796 @@ */ public class OnlineDbMVStore implements OnlineDb { - private static final String STORED_WORKFLOW_PREFIX = "wf-"; - private static final String STORED_METRICS_STEPS_MAP_NAME = "storedSteps"; - private static final String STORED_METRICS_STATES_MAP_SUFFIX = "_states"; - private static final String STORED_METRICS_PARAMS_MAP_SUFFIX = "_params"; - private static final String STORED_RESULTS_MAP_NAME = "wfResults"; - private static final String STORED_RESULTS_ACTIONS_MAP_SUFFIX = "_actions"; - private static final String STORED_RESULTS_ACTIONINFO_MAP_SUFFIX = "_actionplans"; // i do not change this, for backward compatibility - private static final String STORED_RESULTS_ACTIONINFO_ACTIONSFOUND_KEY_SUFFIX = "_actionsfound"; - private static final String STORED_RESULTS_ACTIONINFO_STATUS_KEY_SUFFIX = "_status"; - private static final String STORED_RESULTS_ACTIONINFO_CAUSE_KEY_SUFFIX = "_cause"; - private static final String STORED_RESULTS_ACTIONINFO_ACTIONPLAN_KEY_SUFFIX = "_actionplan"; - private static final String STORED_RESULTS_ACTIONS_EQUIPMENTS_MAP_SUFFIX = "_actionequipments"; - private static final String STORED_RESULTS_ACTIONS_PARAMETERS_MAP_SUFFIX = "_actionparameters"; - private static final String STORED_RESULTS_INDEXES_MAP_SUFFIX = "_indexes"; - private static final String STORED_RESULTS_TIMEHORIZON_KEY = "time_orizon"; - private static final String STORED_RESULTS_CONTINGENCIES_WITH_ACTIONS_KEY = "contingiencies_with_actions"; - private static final String STORED_RESULTS_UNSAFE_CONTINGENCIES_KEY = "unsafe_contingiencies"; - private static final String STORED_RULES_RESULTS_MAP_NAME = "wfRulesResults"; - private static final String STORED_RULES_RESULTS_STATE_RESULTS_MAP_SUFFIX = "_rulesresults"; - private static final String STORED_RULES_RESULTS_STATE_STATUS_MAP_SUFFIX = "_rulesstatus"; - private static final String STORED_RULES_RESULTS_CONTINGENCIES_WITH_RULES_KEY = "contingiencies_with_rules"; - private static final String STORED_WCA_RESULTS_MAP_NAME = "wfWcaResults"; - private static final String STORED_WCA_RESULTS_CLUSTERS_MAP_NAME = "contingencies_wcaclusters"; - private static final String STORED_WCA_RESULTS_CAUSES_MAP_NAME = "contingencies_wcacause"; - private static final String STORED_PARAMETERS_MAP_NAME = "wfParameters"; - private static final String STORED_PARAMETERS_BASECASE_KEY = "basecase"; - private static final String STORED_PARAMETERS_STATE_NUMBER_KEY = "state_number"; - private static final String STORED_PARAMETERS_HISTO_INTERVAL_KEY = "histo_interval"; - private static final String STORED_PARAMETERS_OFFLINE_WF_ID_KEY = "offline_wf"; - private static final String STORED_PARAMETERS_FEA_ID_KEY = "fe_analysis"; - private static final String STORED_PARAMETERS_RULES_PURITY_KEY = "rules_purity"; - private static final String STORED_PARAMETERS_STORE_STATES_KEY = "store_states"; - private static final String STORED_PARAMETERS_ANALYSE_BASECASE_KEY = "analyse_basecase"; - private static final String STORED_PARAMETERS_VALIDATION_KEY = "validation"; - private static final String STORED_PARAMETERS_SECURITY_INDEXES_KEY = "security_indexes"; - private static final String STORED_PARAMETERS_CASE_TYPE_KEY = "case_type"; - private static final String STORED_PARAMETERS_COUNTRIES_KEY = "countries"; - private static final String STORED_PARAMETERS_MERGE_OPTIMIZED_KEY = "merge_optimized"; - private static final String STORED_PARAMETERS_LIMIT_REDUCTION_KEY = "limit_reduction"; - private static final String STORED_STATES_PROCESSING_STATUS_MAP_NAME = "statesProcessingStatus"; - private static final String STORED_STATES_LIST_KEY = "states"; - private static final String STORED_STATES_STATE_DETAILS_KEY = "stateStatusDetails"; - private static final String STORED_STATE_PROCESSING_STATUS_MAP_SUFFIX = "_processingstatus"; - private static final String STORED_WORKFLOW_STATES_FOLDER_PREFIX = "states-wf-"; - private static final String STORED_STATE_PREFIX = "state-"; - private static final String STORED_VIOLATIONS_STEPS_MAP_NAME = "storedViolationsSteps"; - private static final String STORED_VIOLATIONS_STATES_MAP_SUFFIX = "_violationsstates"; - private static final String STORED_VIOLATIONS_STATES_MAP_NAME = "storedViolationsStates"; - private static final String STORED_VIOLATIONS_STEPS_MAP_SUFFIX = "_violationssteps"; - private static final String STORED_VIOLATIONS_MAP_PREFIX = "violations_"; - private static final String STORED_PC_VIOLATIONS_CONTINGENCIES_MAP_NAME = "storedPCViolationsContingencies"; - private static final String STORED_PC_VIOLATIONS_STATES_MAP_SUFFIX = "_pcviolationsstates"; - private static final String STORED_PC_VIOLATIONS_STATES_MAP_NAME = "storedPCViolationsStates"; - private static final String STORED_PC_VIOLATIONS_CONTINGENCIES_MAP_SUFFIX = "_pcviolationscontigencies"; - private static final String STORED_PC_VIOLATIONS_MAP_PREFIX = "pcviolations_"; - private static final String STORED_PC_LOADFLOW_CONTINGENCIES_MAP_NAME = "storedPCLoadflowContingencies"; - private static final String STORED_PC_LOADFLOW_STATES_MAP_SUFFIX = "_pcloadflowstates";; - private static final String STORED_PC_LOADFLOW_STATES_MAP_NAME = "storedPCLoadflowStates"; - private static final String STORED_PC_LOADFLOW_CONTINGENCIES_MAP_SUFFIX = "_pcloadflowcontigencies"; - private static final String STORED_WCA_RULES_RESULTS_MAP_NAME = "wfWcaRulesResults"; - private static final String STORED_WCA_RULES_RESULTS_STATE_RESULTS_MAP_SUFFIX = "_wcarulesresults"; - private static final String STORED_WCA_RULES_RESULTS_STATE_STATUS_MAP_SUFFIX = "_wcarulesstatus"; - private static final String SERIALIZED_STATES_FILENAME = "network-states.csv"; - - - private static final Logger LOGGER = LoggerFactory.getLogger(OnlineDbMVStore.class); - - - private OnlineDbMVStoreConfig config = null; - - HashMap storedWFMetrics = new HashMap(); - ConcurrentHashMap>> workflowsStates = new ConcurrentHashMap>>(); - - MVMapConcurrent.Builder mapBuilder; - - - public OnlineDbMVStore(OnlineDbMVStoreConfig config) { - this.config = config; - LOGGER.info(config.toString()); - Path storageFolder = config.getOnlineDbDir(); - if ( !Files.exists(storageFolder) ) { - try { - Files.createDirectories(storageFolder); - } catch (IOException e) { - String errorMessage = "online db folder " + storageFolder + " does not exist and cannot be created: " + e.getMessage(); - LOGGER.error(errorMessage); - throw new RuntimeException(errorMessage); - } - } - mapBuilder = new MVMapConcurrent.Builder(); - } - - public OnlineDbMVStore() { - this(OnlineDbMVStoreConfig.load()); - } - - private synchronized void closeStores() { - ArrayList workflowIds = new ArrayList(); - for (String storedWorkflowId : storedWFMetrics.keySet()) { - MVStore wfMVStore = storedWFMetrics.get(storedWorkflowId); - wfMVStore.close(); - workflowIds.add(storedWorkflowId); - } - for (String workflowId : workflowIds) { - storedWFMetrics.remove(workflowId); - } - } - - private synchronized MVStore getStore(String workflowId) { - MVStore wfMVStore; - if ( storedWFMetrics.containsKey(workflowId)) - wfMVStore = storedWFMetrics.get(workflowId); - else { - LOGGER.debug("Opening file for workflow {}", workflowId); - wfMVStore = MVStore.open(config.getOnlineDbDir().toString() + File.separator + STORED_WORKFLOW_PREFIX + workflowId); - storedWFMetrics.put(workflowId, wfMVStore); - } - return wfMVStore; - } - - @Override - public void storeMetrics(String workflowId, OnlineStep step, Map metrics) { - LOGGER.info("Storing metrics for wf {} and step {}", workflowId, step.name()); - storeMetrics(workflowId, step.name() + "__", metrics); - LOGGER.info("Storing metadata for wf {} and step {}", workflowId, step.name()); - storeStepMetadata(workflowId, "_", step, metrics); - - } - - @Override - public void storeMetrics(String workflowId, Integer stateId, OnlineStep step, Map metrics) { - String stateIdStr=String.valueOf(stateId); - LOGGER.info("Storing metrics for wf {}, step {} and state {}", workflowId, step.name(), stateIdStr); - storeMetrics(workflowId, step.name() + "_" + stateIdStr, metrics); - LOGGER.info("Storing metadata for wf {}, step {} and state {}", workflowId, step.name(), stateIdStr); - storeStepMetadata(workflowId, stateIdStr, step, metrics); - } - - private void storeMetrics(String workflowId, String mapName, Map metrics) { - try { - MVStore wfMVStore = getStore(workflowId); - Map metricsMap = wfMVStore.openMap(mapName, mapBuilder); - for ( String parameter : metrics.keySet() ) { - metricsMap.put(parameter, metrics.get(parameter)); - } - wfMVStore.commit(); - } catch(Throwable e) { - String errorMessage = "Error storing metrics for wf " + workflowId + " in map " + mapName + ": " + e.getMessage(); - LOGGER.error(errorMessage); - throw new RuntimeException(errorMessage); - } - } - - private void storeStepMetadata(String workflowId, String stateId, OnlineStep step, Map metrics) { - try { - MVStore wfMVStore = getStore(workflowId); - // save info about stored wf steps - MVMap storedStepsMap = wfMVStore.openMap(STORED_METRICS_STEPS_MAP_NAME, mapBuilder); - storedStepsMap.putIfAbsent(step.name(), "1"); - // save info about stored states per step - MVMap stepStatesMap = wfMVStore.openMap(step.name() + STORED_METRICS_STATES_MAP_SUFFIX, mapBuilder); - stepStatesMap.putIfAbsent(stateId, ""); - // save info about stored params per step - MVMap stepParamsMap = wfMVStore.openMap(step.name() + STORED_METRICS_PARAMS_MAP_SUFFIX, mapBuilder); - for ( String parameter : metrics.keySet() ) { - stepParamsMap.putIfAbsent(parameter, ""); - } - wfMVStore.commit(); - } catch(Throwable e) { - String errorMessage = "Error storing metadata for wf " + workflowId + ", step "+ step.name() + ", state " + stateId + ": " + e.getMessage(); - LOGGER.error(errorMessage); - throw new RuntimeException(errorMessage); - } - } - - @Override - public Map getMetrics(String workflowId, OnlineStep step) { - LOGGER.info("Getting metrics from wf {} and step {}", workflowId, step.name()); - return getMetrics(workflowId, step.name() + "__"); - } - - @Override - public Map getMetrics(String workflowId, Integer stateId, OnlineStep step) { - String stateIdStr=String.valueOf(stateId); - LOGGER.info("Getting metrics from wf {}, step {} and state {}", workflowId, step.name(), stateIdStr); - return getMetrics(workflowId, step.name() + "_" + stateIdStr); - } - - private Map getMetrics(String workflowId, String mapName) { - if ( isWorkflowStored(workflowId) ) { - HashMap metrics = new HashMap(); - MVStore wfMVStore = getStore(workflowId); - if ( wfMVStore.getMapNames().contains(mapName) ) { - Map storedMap = wfMVStore.openMap(mapName, mapBuilder); - for ( String parameter : storedMap.keySet() ) { - metrics.put(parameter, storedMap.get(parameter)); - } - } - return metrics; - } else { - LOGGER.warn("No data about wf {}", workflowId); - return null; - } - } - - @Override - public String getCsvMetrics(String workflowId, OnlineStep step) { - LOGGER.info("Preparing CSV data for wf {} and step {}", workflowId, step.name()); - if ( isWorkflowStored(workflowId) ) { - StringWriter content = new StringWriter(); - CsvWriter cvsWriter = new CsvWriter(content, ','); - try { - MVStore wfMVStore = getStore(workflowId); - // check if there are stored metrics - Map storedStepsMap = wfMVStore.openMap(STORED_METRICS_STEPS_MAP_NAME, mapBuilder); - if ( storedStepsMap.containsKey(step.name()) ) { - MVMap stepParamsMap = wfMVStore.openMap(step.name() + STORED_METRICS_PARAMS_MAP_SUFFIX, mapBuilder); - MVMap stepStatesMap = wfMVStore.openMap(step.name() + STORED_METRICS_STATES_MAP_SUFFIX, mapBuilder); - // write headers - //LOGGER.debug("Preparing CSV headers for wf {} and step {}", workflowId, step.name()); - String[] headers = new String[stepParamsMap.keySet().size()+1]; - headers[0] = "state"; - HashMap paramsIndexes = new HashMap<>(); - int i = 1; - for ( String parameter : stepParamsMap.keySet() ) { - headers[i] = parameter; - paramsIndexes.put(parameter, i); - i++; - } - cvsWriter.writeRecord(headers); - // write step general metrics, if stored - if ( stepStatesMap.containsKey("_") ) { - //LOGGER.debug("Preparing CSV data for wf {} and step {} - general step metrics", workflowId, step.name()); - String[] values = getStoredMapValues(wfMVStore, "_", step, stepParamsMap.keySet().size(), paramsIndexes); - cvsWriter.writeRecord(values); - } - // write step metrics for each state, if stored - for ( String stateId : stepStatesMap.keySet() ) { - if (!"_".equals(stateId) ) { - //LOGGER.debug("Preparing CSV data for wf {} and step {} - state {} metrics", workflowId, step.name(), stateId); - String[] values = getStoredMapValues(wfMVStore, stateId, step, stepParamsMap.keySet().size(), paramsIndexes); - cvsWriter.writeRecord(values); - } - } - } - } catch (IOException e) { - String errorMessage = "error getting cvs data for step " + step.name() + " and wf id " + workflowId; - LOGGER.error(errorMessage); - throw new RuntimeException(errorMessage); - } - cvsWriter.flush(); - return content.toString(); - } else { - LOGGER.warn("No data about wf {}", workflowId); - return null; - } - } - - private String[] getStoredMapValues(MVStore wfMVStore, String stateId, OnlineStep step, int paramsN, HashMap paramsIndexes) { - String[] values = new String[paramsN+1]; - values[0] = stateId; - Map storedMap = wfMVStore.openMap(step.name() + "_" + stateId, mapBuilder); - for ( String parameter : storedMap.keySet() ) { - int index = paramsIndexes.get(parameter); - values[index] = storedMap.get(parameter); - } - return values; - } - - @Override - public List listWorkflows() { - LOGGER.info("Getting list of stored workflows"); - List workflowIds = new ArrayList(); - File[] files = config.getOnlineDbDir().toFile().listFiles(new FilenameFilter() { - public boolean accept(File dir, String name) { - return name.toLowerCase().startsWith(STORED_WORKFLOW_PREFIX); - } - }); - Arrays.sort(files, new Comparator(){ - public int compare(File f1, File f2) - { - return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); - } }); - for (File file : files) { - if ( file.isFile() ) { - OnlineWorkflowDetails workflowDetails = new OnlineWorkflowDetails(file.getName().substring(STORED_WORKFLOW_PREFIX.length())); - workflowDetails.setWorkflowDate(new DateTime(file.lastModified())); - workflowIds.add(workflowDetails); - } - } - LOGGER.info("Found {} workflow(s)", workflowIds.size()); - return workflowIds; - } - - @Override - public List listWorkflows(DateTime basecaseDate) { - LOGGER.info("Getting list of stored workflows run on basecase {}", basecaseDate); - String wfNamePrefix = DateTimeFormat.forPattern("yyyyMMdd_HHmm_").print(basecaseDate); - List workflowIds = new ArrayList(); - File[] files = config.getOnlineDbDir().toFile().listFiles(new FilenameFilter() { - public boolean accept(File dir, String name) { - return name.toLowerCase().startsWith(STORED_WORKFLOW_PREFIX+wfNamePrefix); - } - }); - Arrays.sort(files, new Comparator(){ - public int compare(File f1, File f2) - { - return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); - } }); - for (File file : files) { - if ( file.isFile() ) { - OnlineWorkflowDetails workflowDetails = new OnlineWorkflowDetails(file.getName().substring(STORED_WORKFLOW_PREFIX.length())); - workflowDetails.setWorkflowDate(new DateTime(file.lastModified())); - workflowIds.add(workflowDetails); - } - } - LOGGER.info("Found {} workflow(s)", workflowIds.size()); - return workflowIds; - } - - @Override - public List listWorkflows(Interval basecaseInterval) { - LOGGER.info("Getting list of stored workflows run on basecases within the interval {}", basecaseInterval); - String dateFormatPattern = "yyyyMMdd_HHmm"; - DateTimeFormatter formatter = DateTimeFormat.forPattern(dateFormatPattern); - List workflowIds = new ArrayList(); - File[] files = config.getOnlineDbDir().toFile().listFiles(new FilenameFilter() { - public boolean accept(File dir, String name) { - return name.toLowerCase().startsWith(STORED_WORKFLOW_PREFIX); - } - }); - Arrays.sort(files, new Comparator(){ - public int compare(File f1, File f2) - { - return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); - } }); - for (File file : files) { - if ( file.isFile() ) { - String wfId = file.getName().substring(STORED_WORKFLOW_PREFIX.length()); - if ( wfId.length() > dateFormatPattern.length() && wfId.substring(dateFormatPattern.length(),dateFormatPattern.length()+1).equals("_")) { - String basecaseName = wfId.substring(0, dateFormatPattern.length()-1); - DateTime basecaseDate = DateTime.parse(basecaseName, formatter); - if ( basecaseInterval.contains(basecaseDate.getMillis())) { - OnlineWorkflowDetails workflowDetails = new OnlineWorkflowDetails(wfId); - workflowDetails.setWorkflowDate(new DateTime(file.lastModified())); - workflowIds.add(workflowDetails); - } - } - } - } - LOGGER.info("Found {} workflow(s)", workflowIds.size()); - return workflowIds; - } - - @Override - public void storeResults(String workflowId, OnlineWorkflowResults results) { - Objects.requireNonNull(workflowId, "workflow id is null"); - Objects.requireNonNull(results, "online workflow results is null"); - LOGGER.info("Storing results for workflow {}", workflowId); - MVStore wfMVStore = getStore(workflowId); - // check if the results for this wf have already been stored - if ( wfMVStore.hasMap(STORED_RESULTS_MAP_NAME) ) - removeWfResults(workflowId, wfMVStore); - MVMap storedResultsMap = wfMVStore.openMap(STORED_RESULTS_MAP_NAME, mapBuilder); - // store time horizon - storedResultsMap.put(STORED_RESULTS_TIMEHORIZON_KEY, results.getTimeHorizon().getName()); - // store contingencies with actions - storedResultsMap.put(STORED_RESULTS_CONTINGENCIES_WITH_ACTIONS_KEY, OnlineDbMVStoreUtils.contingenciesIdsToJson(results.getContingenciesWithActions())); - // store contingencies with actions - storedResultsMap.put(STORED_RESULTS_UNSAFE_CONTINGENCIES_KEY, OnlineDbMVStoreUtils.contingenciesIdsToJson(results.getUnsafeContingencies())); - // store actions for contingencies - for (String contingencyId : results.getContingenciesWithActions()) { - MVMap storedActionsInfosMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONINFO_MAP_SUFFIX, mapBuilder); - MVMap storedActionsMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONS_MAP_SUFFIX, mapBuilder); - MVMap storedActionsEquipmentsMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONS_EQUIPMENTS_MAP_SUFFIX, mapBuilder); - MVMap storedActionsParametersMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONS_PARAMETERS_MAP_SUFFIX, mapBuilder); - for (Integer stateId : results.getUnsafeStatesWithActions(contingencyId).keySet()) { - storedActionsInfosMap.put(stateId.toString() + STORED_RESULTS_ACTIONINFO_ACTIONSFOUND_KEY_SUFFIX, - Boolean.toString(results.getUnsafeStatesWithActions(contingencyId).get(stateId))); - storedActionsInfosMap.put(stateId.toString() + STORED_RESULTS_ACTIONINFO_STATUS_KEY_SUFFIX, results.getStateStatus(contingencyId, stateId).name()); - if ( results.getCause(contingencyId, stateId) != null ) - storedActionsInfosMap.put(stateId.toString() + STORED_RESULTS_ACTIONINFO_CAUSE_KEY_SUFFIX, results.getCause(contingencyId, stateId)); - if ( results.getActionPlan(contingencyId, stateId) != null ) - storedActionsInfosMap.put(stateId.toString() + STORED_RESULTS_ACTIONINFO_ACTIONPLAN_KEY_SUFFIX, results.getActionPlan(contingencyId, stateId)); - List actionsIds = results.getActionsIds(contingencyId, stateId); - if ( actionsIds != null ) { - for(String actionId : actionsIds) { - List equipmentsIds = results.getEquipmentsIds(contingencyId, stateId, actionId); - storedActionsEquipmentsMap.put(stateId + "_" + actionId, OnlineDbMVStoreUtils.actionsIdsToJson(equipmentsIds)); - for(String equipmentId : equipmentsIds) { - ActionParameters actionParameters = results.getParameters(contingencyId, stateId, actionId, equipmentId); - if ( actionParameters != null ) - storedActionsParametersMap.put(stateId + "_" + actionId + "_" + equipmentId, OnlineDbMVStoreUtils.actionParametersToJson(actionParameters)); - } - } - } else { - actionsIds = new ArrayList(); // I need anyway an empty list, for the getResults to work - } - storedActionsMap.put(stateId.toString(), OnlineDbMVStoreUtils.actionsIdsToJson(actionsIds)); - } - } - // store indexes for contingencies - for (String contingencyId : results.getUnsafeContingencies()) { - MVMap storedIndexesMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_INDEXES_MAP_SUFFIX, mapBuilder); - for (Integer stateId : results.getUnstableStates(contingencyId)) { - Map indexesData = results.getIndexesData(contingencyId, stateId); - storedIndexesMap.put(stateId.toString(), OnlineDbMVStoreUtils.indexesDataToJson(indexesData)); - } - } - wfMVStore.commit(); - } - - private void removeWfResults(String workflowId, MVStore wfMVStore) { - LOGGER.debug("Removing existing wf results for workflow {}", workflowId); - MVMap storedResultsMap = wfMVStore.openMap(STORED_RESULTS_MAP_NAME, mapBuilder); - // remove info about contingencies with action - Collection contingenciesWithAction = OnlineDbMVStoreUtils.jsonToContingenciesIds( - storedResultsMap.get(STORED_RESULTS_CONTINGENCIES_WITH_ACTIONS_KEY)); - for (String contingencyId : contingenciesWithAction) { - MVMap storedActionsMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONS_MAP_SUFFIX, mapBuilder); - wfMVStore.removeMap(storedActionsMap); - } - // remove info about unsafe contingencies - Collection unsafeContingencies = OnlineDbMVStoreUtils.jsonToContingenciesIds( - storedResultsMap.get(STORED_RESULTS_UNSAFE_CONTINGENCIES_KEY)); - for (String contingencyId : unsafeContingencies) { - MVMap storedIndexesMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_INDEXES_MAP_SUFFIX, mapBuilder); - wfMVStore.removeMap(storedIndexesMap); - } - // remove info about stored wf results - wfMVStore.removeMap(storedResultsMap); - // commit removal - wfMVStore.commit(); - } - - @Override - public OnlineWorkflowResults getResults(String workflowId) { - Objects.requireNonNull(workflowId, "workflow id is null"); - LOGGER.info("Getting results of wf {}", workflowId); - if ( isWorkflowStored(workflowId) ) { - MVStore wfMVStore = getStore(workflowId); - if ( wfMVStore.hasMap(STORED_RESULTS_MAP_NAME) ) { - MVMap storedResultsMap = wfMVStore.openMap(STORED_RESULTS_MAP_NAME, mapBuilder); - // create workflow results - OnlineWorkflowResultsImpl wfResults = new OnlineWorkflowResultsImpl( - workflowId, - TimeHorizon.valueOf(storedResultsMap.get(STORED_RESULTS_TIMEHORIZON_KEY))); - // add contingencies with actiions - Collection contingenciesWithAction = OnlineDbMVStoreUtils.jsonToContingenciesIds( - storedResultsMap.get(STORED_RESULTS_CONTINGENCIES_WITH_ACTIONS_KEY)); - for (String contingencyId : contingenciesWithAction) { - MVMap storedActionsMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONS_MAP_SUFFIX, mapBuilder); - MVMap storedActionsInfosMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONINFO_MAP_SUFFIX, mapBuilder); - MVMap storedActionsParametersMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONS_PARAMETERS_MAP_SUFFIX, mapBuilder); - MVMap storedActionsEquipmentsMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONS_EQUIPMENTS_MAP_SUFFIX, mapBuilder); - for (String stateId : storedActionsMap.keySet()) { - boolean actionsFound = true; - if ( storedActionsInfosMap.containsKey(stateId + STORED_RESULTS_ACTIONINFO_ACTIONSFOUND_KEY_SUFFIX) ) - actionsFound = Boolean.parseBoolean(storedActionsInfosMap.get(stateId + STORED_RESULTS_ACTIONINFO_ACTIONSFOUND_KEY_SUFFIX)); - CCOFinalStatus status = CCOFinalStatus.MANUAL_CORRECTIVE_ACTION_FOUND; - if ( storedActionsInfosMap.containsKey(stateId + STORED_RESULTS_ACTIONINFO_STATUS_KEY_SUFFIX) ) - status = CCOFinalStatus.valueOf(storedActionsInfosMap.get(stateId + STORED_RESULTS_ACTIONINFO_STATUS_KEY_SUFFIX)); - String cause = storedActionsInfosMap.get(stateId + STORED_RESULTS_ACTIONINFO_CAUSE_KEY_SUFFIX); - String actionPlan = storedActionsInfosMap.get(stateId + STORED_RESULTS_ACTIONINFO_ACTIONPLAN_KEY_SUFFIX); - Map> actions = null; - if ( storedActionsMap.containsKey(stateId) ) { - List actionsIds = OnlineDbMVStoreUtils.jsonToActionsIds(storedActionsMap.get(stateId)); - actions = new HashMap>(); - for(String actionId : actionsIds) { - Map equipments = new HashMap(); - List equipmentsIds = OnlineDbMVStoreUtils.jsonToActionsIds(storedActionsEquipmentsMap.get(stateId + "_" + actionId)); - if ( equipmentsIds != null ) { - for(String equipmentId : equipmentsIds) { - ActionParameters actionParameters = OnlineDbMVStoreUtils.jsonToActionParameters(storedActionsParametersMap.get(stateId + "_" + actionId + "_" + equipmentId)); - equipments.put(equipmentId, actionParameters); - } - } - actions.put(actionId, equipments); - } - } - wfResults.addContingenciesWithActions(contingencyId, Integer.parseInt(stateId), actionsFound, status, cause, actionPlan, actions); - } - } - // add unsafe contingencies - Collection unsafeContingencies = OnlineDbMVStoreUtils.jsonToContingenciesIds( - storedResultsMap.get(STORED_RESULTS_UNSAFE_CONTINGENCIES_KEY)); - for (String contingencyId : unsafeContingencies) { - MVMap storedIndexesMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_INDEXES_MAP_SUFFIX, mapBuilder); - for (String stateId : storedIndexesMap.keySet()) { - Map indexesData = OnlineDbMVStoreUtils.jsonToIndexesData(storedIndexesMap.get(stateId)); - wfResults.addUnsafeContingencies(contingencyId, Integer.parseInt(stateId), indexesData); - } - } - return wfResults; - } else { - LOGGER.warn("No results of wf {} stored in online db", workflowId); - return null; - } - } else { - LOGGER.warn("No data about wf {}", workflowId); - return null; - } - } - - @Override - public void storeRulesResults(String workflowId, OnlineWorkflowRulesResults results) { - Objects.requireNonNull(workflowId, "workflow id is null"); - Objects.requireNonNull(results, "online workflow rules results is null"); - LOGGER.info("Storing results of rules for workflow {}", workflowId); - MVStore wfMVStore = getStore(workflowId); - // check if the results for this wf have already been stored - if ( wfMVStore.hasMap(STORED_RULES_RESULTS_MAP_NAME) ) - removeWfRulesResults(workflowId, wfMVStore); - MVMap storedRulesResultsMap = wfMVStore.openMap(STORED_RULES_RESULTS_MAP_NAME, mapBuilder); - // store time horizon - storedRulesResultsMap.put(STORED_RESULTS_TIMEHORIZON_KEY, results.getTimeHorizon().getName()); - // store contingencies with security rules results - storedRulesResultsMap.put(STORED_RULES_RESULTS_CONTINGENCIES_WITH_RULES_KEY, - OnlineDbMVStoreUtils.contingenciesIdsToJson(results.getContingenciesWithSecurityRulesResults())); - // store rules results for contingencies - for (String contingencyId : results.getContingenciesWithSecurityRulesResults()) { - MVMap storedStateStatusMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_STATUS_MAP_SUFFIX, mapBuilder); - MVMap storedStateResultsMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_RESULTS_MAP_SUFFIX, mapBuilder); - for (Integer stateId : results.getStatesWithSecurityRulesResults(contingencyId)) { - // store state status - StateStatus status = results.getStateStatus(contingencyId, stateId); - storedStateStatusMap.put(stateId.toString(), status.name()); - // store state rules results - Map stateResults = results.getStateResults(contingencyId, stateId); - storedStateResultsMap.put(stateId.toString(), OnlineDbMVStoreUtils.indexesDataToJson(stateResults)); - } - } - wfMVStore.commit(); - } - - private void removeWfRulesResults(String workflowId, MVStore wfMVStore) { - LOGGER.debug("Removing existing rules results for workflow {}", workflowId); - MVMap storedRulesResultsMap = wfMVStore.openMap(STORED_RULES_RESULTS_MAP_NAME, mapBuilder); - // remove rules results - Collection rulesContingencies = OnlineDbMVStoreUtils.jsonToContingenciesIds( - storedRulesResultsMap.get(STORED_RULES_RESULTS_CONTINGENCIES_WITH_RULES_KEY)); - for (String contingencyId : rulesContingencies) { - MVMap storedStateStatusMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_STATUS_MAP_SUFFIX, mapBuilder); - wfMVStore.removeMap(storedStateStatusMap); - MVMap storedStateResultsMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_RESULTS_MAP_SUFFIX, mapBuilder); - wfMVStore.removeMap(storedStateResultsMap); - } - // remove info about stored rules results - wfMVStore.removeMap(storedRulesResultsMap); - // commit removal - wfMVStore.commit(); - } - - @Override - public OnlineWorkflowRulesResults getRulesResults(String workflowId) { - Objects.requireNonNull(workflowId, "workflow id is null"); - LOGGER.info("Getting rules results of wf {}", workflowId); - if ( isWorkflowStored(workflowId) ) { - MVStore wfMVStore = getStore(workflowId); - if ( wfMVStore.hasMap(STORED_RULES_RESULTS_MAP_NAME) ) { - MVMap storedRulesResultsMap = wfMVStore.openMap(STORED_RULES_RESULTS_MAP_NAME, mapBuilder); - // create workflow rules results - OnlineWorkflowRulesResultsImpl wfRulesResults = new OnlineWorkflowRulesResultsImpl( - workflowId, - TimeHorizon.valueOf(storedRulesResultsMap.get(STORED_RESULTS_TIMEHORIZON_KEY))); - // add contingencies with rules results - Collection contingenciesWithRules = OnlineDbMVStoreUtils.jsonToContingenciesIds( - storedRulesResultsMap.get(STORED_RULES_RESULTS_CONTINGENCIES_WITH_RULES_KEY)); - for (String contingencyId : contingenciesWithRules) { - MVMap storedStateStatusMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_STATUS_MAP_SUFFIX, mapBuilder); - MVMap storedStateResultsMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_RESULTS_MAP_SUFFIX, mapBuilder); - for (String stateId : storedStateStatusMap.keySet()) { - Map stateResults = OnlineDbMVStoreUtils.jsonToIndexesData(storedStateResultsMap.get(stateId)); - StateStatus stateStatus = StateStatus.valueOf(storedStateStatusMap.get(stateId)); - wfRulesResults.addContingencyWithSecurityRulesResults(contingencyId, Integer.parseInt(stateId), stateStatus, stateResults); - } - } - return wfRulesResults; - } else { - LOGGER.warn("No rules results of wf {} stored in online db", workflowId); - return null; - } - } else { - LOGGER.warn("No data about wf {}", workflowId); - return null; - } - } - - @Override - public void storeWcaResults(String workflowId, OnlineWorkflowWcaResults results) { - Objects.requireNonNull(workflowId, "workflow id is null"); - Objects.requireNonNull(results, "online workflow wca results is null"); - LOGGER.info("Storing results of WCA for workflow {}", workflowId); - MVStore wfMVStore = getStore(workflowId); - // check if the results for this wf have already been stored - if ( wfMVStore.hasMap(STORED_WCA_RESULTS_MAP_NAME) ) - removeWfWcaResults(workflowId, wfMVStore); - MVMap storedWcaResultsMap = wfMVStore.openMap(STORED_WCA_RESULTS_MAP_NAME, mapBuilder); - // store time horizon - storedWcaResultsMap.put(STORED_RESULTS_TIMEHORIZON_KEY, results.getTimeHorizon().getName()); - // store wca results for contingencies - MVMap storedClustersMap = wfMVStore.openMap(STORED_WCA_RESULTS_CLUSTERS_MAP_NAME, mapBuilder); - MVMap storedCausesMap = wfMVStore.openMap(STORED_WCA_RESULTS_CAUSES_MAP_NAME, mapBuilder); - for (String contingencyId : results.getContingencies()) { - storedClustersMap.put(contingencyId, Integer.toString(results.getClusterIndex(contingencyId))); - List causes = results.getCauses(contingencyId); - if (causes != null && causes.size() > 0) - storedCausesMap.put(contingencyId, causes.get(0)); - } - wfMVStore.commit(); - } - - private void removeWfWcaResults(String workflowId, MVStore wfMVStore) { - LOGGER.debug("Removing existing WCA results for workflow {}", workflowId); - MVMap storedWcaResultsMap = wfMVStore.openMap(STORED_WCA_RESULTS_MAP_NAME, mapBuilder); - // remove wca results - MVMap storedClustersMap = wfMVStore.openMap(STORED_WCA_RESULTS_CLUSTERS_MAP_NAME, mapBuilder); - wfMVStore.removeMap(storedClustersMap); - MVMap storedCausesMap = wfMVStore.openMap(STORED_WCA_RESULTS_CAUSES_MAP_NAME, mapBuilder); - wfMVStore.removeMap(storedCausesMap); - // remove info about stored wca results - wfMVStore.removeMap(storedWcaResultsMap); - // commit removal - wfMVStore.commit(); - } - - @Override - public OnlineWorkflowWcaResults getWcaResults(String workflowId) { - Objects.requireNonNull(workflowId, "workflow id is null"); - LOGGER.info("Getting WCA results of wf {}", workflowId); - if ( isWorkflowStored(workflowId) ) { - MVStore wfMVStore = getStore(workflowId); - if ( wfMVStore.hasMap(STORED_WCA_RESULTS_MAP_NAME) ) { - MVMap storedRulesResultsMap = wfMVStore.openMap(STORED_WCA_RESULTS_MAP_NAME, mapBuilder); - // create workflow rules results - OnlineWorkflowWcaResultsImpl wfWcaResults = new OnlineWorkflowWcaResultsImpl( - workflowId, - TimeHorizon.valueOf(storedRulesResultsMap.get(STORED_RESULTS_TIMEHORIZON_KEY))); - // add classification of contingencies in clusters - MVMap storedClustersMap = wfMVStore.openMap(STORED_WCA_RESULTS_CLUSTERS_MAP_NAME, mapBuilder); - MVMap storedCausesMap = wfMVStore.openMap(STORED_WCA_RESULTS_CAUSES_MAP_NAME, mapBuilder); - for(String contingencyId : storedClustersMap.keySet()) { - String cause = storedCausesMap.get(contingencyId); - wfWcaResults.addContingencyWithCluster(contingencyId, - Integer.valueOf(storedClustersMap.get(contingencyId)), - cause != null ? Arrays.asList(cause) : null); - } - return wfWcaResults; - } else { - LOGGER.warn("No WCA results of wf {} stored in online db", workflowId); - return null; - } - } else { - LOGGER.warn("No data about wf {}", workflowId); - return null; - } - } - - - @Override - public void storeWorkflowParameters(String workflowId, OnlineWorkflowParameters parameters) { - Objects.requireNonNull(workflowId, "workflow id is null"); - Objects.requireNonNull(parameters, "online workflow parameters is null"); - LOGGER.info("Storing configuration parameters for workflow {}", workflowId); - MVStore wfMVStore = getStore(workflowId); - // check if the parameters for this wf have already been stored - if ( wfMVStore.hasMap(STORED_PARAMETERS_MAP_NAME) ) - removeWfParameters(workflowId, wfMVStore); - MVMap storedParametersMap = wfMVStore.openMap(STORED_PARAMETERS_MAP_NAME, mapBuilder); - // store basecase - storedParametersMap.put(STORED_PARAMETERS_BASECASE_KEY, parameters.getBaseCaseDate().toString()); - // store number of states - storedParametersMap.put(STORED_PARAMETERS_STATE_NUMBER_KEY, Integer.toString(parameters.getStates())); - // store interval of historical data - storedParametersMap.put(STORED_PARAMETERS_HISTO_INTERVAL_KEY, parameters.getHistoInterval().toString()); - // store offline workflow id - storedParametersMap.put(STORED_PARAMETERS_OFFLINE_WF_ID_KEY, parameters.getOfflineWorkflowId()); - // store time horizon - storedParametersMap.put(STORED_RESULTS_TIMEHORIZON_KEY, parameters.getTimeHorizon().getName()); - // store forecast error analysis id - storedParametersMap.put(STORED_PARAMETERS_FEA_ID_KEY, parameters.getFeAnalysisId()); - // store rules purity threshold - storedParametersMap.put(STORED_PARAMETERS_RULES_PURITY_KEY, Double.toString(parameters.getRulesPurityThreshold())); - // store flag store states - storedParametersMap.put(STORED_PARAMETERS_STORE_STATES_KEY, Boolean.toString(parameters.storeStates())); - // store flag analyse basecase - storedParametersMap.put(STORED_PARAMETERS_ANALYSE_BASECASE_KEY, Boolean.toString(parameters.analyseBasecase())); - // store flag validation - storedParametersMap.put(STORED_PARAMETERS_VALIDATION_KEY, Boolean.toString(parameters.validation())); - // store security indexes - if ( parameters.getSecurityIndexes() != null ) - storedParametersMap.put(STORED_PARAMETERS_SECURITY_INDEXES_KEY, OnlineDbMVStoreUtils.indexesTypesToJson(parameters.getSecurityIndexes())); - // store case type - storedParametersMap.put(STORED_PARAMETERS_CASE_TYPE_KEY, parameters.getCaseType().name()); - // store countries - storedParametersMap.put(STORED_PARAMETERS_COUNTRIES_KEY, OnlineDbMVStoreUtils.countriesToJson(parameters.getCountries())); - // store merge optimized flag - storedParametersMap.put(STORED_PARAMETERS_MERGE_OPTIMIZED_KEY, Boolean.toString(parameters.isMergeOptimized())); - // store merge optimized flag - storedParametersMap.put(STORED_PARAMETERS_LIMIT_REDUCTION_KEY, Float.toString(parameters.getLimitReduction())); - - wfMVStore.commit(); - } - - private void removeWfParameters(String workflowId, MVStore wfMVStore) { - LOGGER.debug("Removing existing parameters for workflow {}", workflowId); - MVMap storedParametersMap = wfMVStore.openMap(STORED_PARAMETERS_MAP_NAME, mapBuilder); - // remove parameters - wfMVStore.removeMap(storedParametersMap); - // commit removal - wfMVStore.commit(); - } - - @Override - public OnlineWorkflowParameters getWorkflowParameters(String workflowId) { - Objects.requireNonNull(workflowId, "workflow id is null"); - LOGGER.info("Getting configuration parameters of wf {}", workflowId); - if ( isWorkflowStored(workflowId) ) { - MVStore wfMVStore = getStore(workflowId); - if ( wfMVStore.hasMap(STORED_PARAMETERS_MAP_NAME) ) { - MVMap storedParametersMap = wfMVStore.openMap(STORED_PARAMETERS_MAP_NAME, mapBuilder); - DateTime baseCaseDate = DateTime.parse(storedParametersMap.get(STORED_PARAMETERS_BASECASE_KEY)); - int states = Integer.parseInt(storedParametersMap.get(STORED_PARAMETERS_STATE_NUMBER_KEY)); - String offlineWorkflowId = storedParametersMap.get(STORED_PARAMETERS_OFFLINE_WF_ID_KEY); - TimeHorizon timeHorizon = TimeHorizon.fromName(storedParametersMap.get(STORED_RESULTS_TIMEHORIZON_KEY)); - Interval histoInterval = Interval.parse(storedParametersMap.get(STORED_PARAMETERS_HISTO_INTERVAL_KEY)); - String feAnalysisId = storedParametersMap.get(STORED_PARAMETERS_FEA_ID_KEY); - double rulesPurityThreshold = Double.parseDouble((storedParametersMap.get(STORED_PARAMETERS_RULES_PURITY_KEY) == null) ? "1" : storedParametersMap.get(STORED_PARAMETERS_RULES_PURITY_KEY)); - boolean storeStates = Boolean.parseBoolean(storedParametersMap.get(STORED_PARAMETERS_STORE_STATES_KEY)); - boolean analyseBasecase = Boolean.parseBoolean(storedParametersMap.get(STORED_PARAMETERS_ANALYSE_BASECASE_KEY)); - boolean validation = Boolean.parseBoolean(storedParametersMap.get(STORED_PARAMETERS_VALIDATION_KEY)); - Set securityIndexes = null; - if ( storedParametersMap.containsKey(STORED_PARAMETERS_SECURITY_INDEXES_KEY) ) - securityIndexes = OnlineDbMVStoreUtils.jsonToIndexesTypes(storedParametersMap.get(STORED_PARAMETERS_SECURITY_INDEXES_KEY)); - CaseType caseType = OnlineWorkflowParameters.DEFAULT_CASE_TYPE; - if ( storedParametersMap.containsKey(STORED_PARAMETERS_CASE_TYPE_KEY)) - caseType = CaseType.valueOf(storedParametersMap.get(STORED_PARAMETERS_CASE_TYPE_KEY)); - Set countries = new HashSet(OnlineWorkflowParameters.DEFAULT_COUNTRIES); - if ( storedParametersMap.containsKey(STORED_PARAMETERS_COUNTRIES_KEY)) - countries = OnlineDbMVStoreUtils.jsonToCountries(storedParametersMap.get(STORED_PARAMETERS_COUNTRIES_KEY)); - boolean mergeOptimized = OnlineWorkflowParameters.DAFAULT_MERGE_OPTIMIZED; - if ( storedParametersMap.containsKey(STORED_PARAMETERS_MERGE_OPTIMIZED_KEY)) - mergeOptimized = Boolean.parseBoolean(storedParametersMap.get(STORED_PARAMETERS_MERGE_OPTIMIZED_KEY)); - float limitReduction = OnlineWorkflowParameters.DEFAULT_LIMIT_REDUCTION; - if ( storedParametersMap.containsKey(STORED_PARAMETERS_LIMIT_REDUCTION_KEY)) - limitReduction = Float.parseFloat(storedParametersMap.get(STORED_PARAMETERS_LIMIT_REDUCTION_KEY)); - - return new OnlineWorkflowParameters(baseCaseDate, - states, - histoInterval, - offlineWorkflowId, - timeHorizon, - feAnalysisId, - rulesPurityThreshold, - storeStates, - analyseBasecase, - validation, - securityIndexes, - caseType, - countries, - mergeOptimized, - limitReduction - ); - } else { - LOGGER.warn("No configuration parameters of wf {} stored in online db", workflowId); - return null; - } - } else { - LOGGER.warn("No data about wf {}", workflowId); - return null; - } - } - - @Override - public void storeStatesProcessingStatus(String workflowId, Map statesProcessingStatus) { - Objects.requireNonNull(workflowId, "workflow id is null"); - Objects.requireNonNull(statesProcessingStatus, "online workflow states processing status is null"); - LOGGER.info("Storing states processing status for workflow {}", workflowId); - MVStore wfMVStore = getStore(workflowId); - // check if the states processing status for this wf have already been stored - if ( wfMVStore.hasMap(STORED_STATES_PROCESSING_STATUS_MAP_NAME) ) - removeStatesProcessingStatus(workflowId, wfMVStore); - MVMap statesProcessingStatusMap = wfMVStore.openMap(STORED_STATES_PROCESSING_STATUS_MAP_NAME, mapBuilder); - // store states with processing status - statesProcessingStatusMap.put(STORED_STATES_LIST_KEY, OnlineDbMVStoreUtils.stateIdsToJson(statesProcessingStatus.keySet())); - // store processing status for states - for (Integer stateId : statesProcessingStatus.keySet()) { - MVMap stateProcessingStatusMap = wfMVStore.openMap(stateId.toString() + STORED_STATE_PROCESSING_STATUS_MAP_SUFFIX, mapBuilder); - for (String step : statesProcessingStatus.get(stateId).getStatus().keySet()) { - // store processing status - stateProcessingStatusMap.put(step, statesProcessingStatus.get(stateId).getStatus().get(step)); - } - stateProcessingStatusMap.put(STORED_STATES_STATE_DETAILS_KEY, statesProcessingStatus.get(stateId).getDetail() == null ? "" : statesProcessingStatus.get(stateId).getDetail()); - } - wfMVStore.commit(); - } - - private void removeStatesProcessingStatus(String workflowId, MVStore wfMVStore) { - LOGGER.debug("Removing existing states processing status for workflow {}", workflowId); - MVMap statesProcessingStatusMap = wfMVStore.openMap(STORED_STATES_PROCESSING_STATUS_MAP_NAME, mapBuilder); - // remove processing status for states - Collection stateWithProcessingStatus = OnlineDbMVStoreUtils.jsonToStatesIds(statesProcessingStatusMap.get(STORED_STATES_LIST_KEY)); - for (Integer stateId : stateWithProcessingStatus) { - MVMap stateProcessingStatusMap = wfMVStore.openMap(stateId.toString() + STORED_STATE_PROCESSING_STATUS_MAP_SUFFIX, mapBuilder); - wfMVStore.removeMap(stateProcessingStatusMap); - } - // remove info about states with processing status - wfMVStore.removeMap(statesProcessingStatusMap); - // commit removal - wfMVStore.commit(); - - } - - @Override - public Map getStatesProcessingStatus(String workflowId) { - Objects.requireNonNull(workflowId, "workflow id is null"); - LOGGER.info("Getting states processing status of wf {}", workflowId); - if ( isWorkflowStored(workflowId) ) { - MVStore wfMVStore = getStore(workflowId); - if ( wfMVStore.hasMap(STORED_STATES_PROCESSING_STATUS_MAP_NAME) ) { - MVMap statesProcessingStatusMap = wfMVStore.openMap(STORED_STATES_PROCESSING_STATUS_MAP_NAME, mapBuilder); - // create states processing status - Map statesProcessingStatus = new HashMap(); - // add processing status for states - Collection stateWithProcessingStatus = OnlineDbMVStoreUtils.jsonToStatesIds(statesProcessingStatusMap.get(STORED_STATES_LIST_KEY)); - for (Integer stateId : stateWithProcessingStatus) { - MVMap stateProcessingStatusMap = wfMVStore.openMap(stateId + STORED_STATE_PROCESSING_STATUS_MAP_SUFFIX, mapBuilder); - Map processingStatus = new HashMap(); - for (String step : stateProcessingStatusMap.keySet()) { - if ( !step.equals(STORED_STATES_STATE_DETAILS_KEY) ) - processingStatus.put(step, stateProcessingStatusMap.get(step)); - } - statesProcessingStatus.put(stateId, new StateProcessingStatusImpl(processingStatus, stateProcessingStatusMap.get(STORED_STATES_STATE_DETAILS_KEY))); - } - return statesProcessingStatus; - } else { - LOGGER.warn("No states processing status of wf {} stored in online db", workflowId); - return null; - } - } else { - LOGGER.warn("No data about wf {}", workflowId); - return null; - } - } - - @Override - public void storeState(String workflowId, Integer stateId, Network network) { - String stateIdStr=String.valueOf(stateId); - LOGGER.info("Storing state {} of workflow {}", stateIdStr, workflowId); - if ( network.getStateManager().getStateIds().contains(stateIdStr) ) { - network.getStateManager().setWorkingState(stateIdStr); - Path workflowStatesFolder = getWorkflowStatesFolder(workflowId); - Path stateFolder = Paths.get(workflowStatesFolder.toString(), STORED_STATE_PREFIX + stateId); - if ( Files.exists(stateFolder) ) { - Path stateFile = Paths.get(stateFolder.toString(), network.getId() + ".xml"); - stateFile.toFile().delete(); - } else { - try { - Files.createDirectories(stateFolder); - } catch (IOException e) { - String errorMessage = "online db: folder " + workflowStatesFolder + " for workflow " + workflowId - + " and state " + stateIdStr + " cannot be created: " + e.getMessage(); - LOGGER.error(errorMessage); - throw new RuntimeException(errorMessage); - } - } - DataSource dataSource = new FileDataSource(stateFolder, network.getId()); - Properties parameters = new Properties(); - parameters.setProperty("iidm.export.xml.indent", "true"); - parameters.setProperty("iidm.export.xml.with-branch-state-variables", "true"); - parameters.setProperty("iidm.export.xml.with-breakers", "true"); - parameters.setProperty("iidm.export.xml.with-properties", "true"); - Exporters.export("XML", network, parameters, dataSource); - // store network state values, for later serialization - Map networkValues = IIDM2DB.extractCimValues(network, new IIDM2DB.Config(network.getId(), true, true)).getSingleValueMap(); - ConcurrentHashMap> workflowStates = new ConcurrentHashMap>(); - if ( workflowsStates.containsKey(workflowId) ) - workflowStates = workflowsStates.get(workflowId); - workflowStates.put(stateId, networkValues); - workflowsStates.put(workflowId, workflowStates); - } else { - String errorMessage = "online db: no state " + stateIdStr + " in network of workflow " + workflowId; - LOGGER.error(errorMessage); - throw new RuntimeException(errorMessage); - } - } - - private void serializeStoredWorkflowsStates() { - LOGGER.info("Serializing stored workflows states"); - for(String workflowId : workflowsStates.keySet()) { - if ( workflowStatesFolderExists(workflowId)) { - LOGGER.info("Serializing network data of workflow {}", workflowId); - ConcurrentHashMap> workflowStates = workflowsStates.get(workflowId); - Path workflowStatesFolder = getWorkflowStatesFolder(workflowId); - Path csvFile = Paths.get(workflowStatesFolder.toString(), SERIALIZED_STATES_FILENAME); - try(FileWriter fileWriter = new FileWriter(csvFile.toFile()); - CsvListWriter csvWriter = new CsvListWriter(fileWriter, new CsvPreference.Builder('"', ';', "\r\n").build())) { - boolean printHeaders = true; - for(Integer stateId : workflowStates.keySet()) { - Map networkValues = workflowStates.get(stateId); - if ( printHeaders ) { - List headers = new ArrayList<>(networkValues.size()); - for (HistoDbAttributeId attrId : networkValues.keySet()) { - headers.add(attrId.toString()); - } - ArrayList headersList = new ArrayList<>(); - headersList.add("workflow"); - headersList.add("state"); - headersList.addAll(Arrays.asList(headers.toArray(new String[] {}))); - csvWriter.writeHeader(headersList.toArray(new String[] {})); - printHeaders = false; - } - ArrayList valuesList = new ArrayList<>(); - valuesList.add(workflowId); - valuesList.add(stateId); - valuesList.addAll(Arrays.asList(networkValues.values().toArray())); - csvWriter.write(valuesList.toArray()); - } - } catch (IOException e) { - LOGGER.error("Error serializing network data for workflow {}", workflowId); - } - } - } - } - - @Override - public List listStoredStates(String workflowId) { - LOGGER.info("Getting list of stored states for workflow {}", workflowId); - List storedStates = new ArrayList(); - if ( workflowStatesFolderExists(workflowId)) { - Path workflowStatesFolder = getWorkflowStatesFolder(workflowId); - File[] files = workflowStatesFolder.toFile().listFiles(new FilenameFilter() { - public boolean accept(File dir, String name) { - return name.toLowerCase().startsWith(STORED_STATE_PREFIX); - } - }); - for (File file : files) { - if ( file.isDirectory() ) { - String stateId = file.getName().substring(STORED_STATE_PREFIX.length()); - storedStates.add(Integer.parseInt(stateId)); - } - } - Collections.sort(storedStates, new Comparator() { - public int compare(Integer o1, Integer o2) { - return o1.compareTo(o2); - } - }); - LOGGER.info("Found {} state(s) for workflow {}", storedStates.size(), workflowId); - } else { - LOGGER.info("Found no state(s) for workflow {}", workflowId); - } - return storedStates; - } - - @Override - public Network getState(String workflowId, Integer stateId) { - String stateIdStr=String.valueOf(stateId); - LOGGER.info("Getting state {} of workflow {}", stateIdStr, workflowId); - Path workflowStatesFolder = getWorkflowStatesFolder(workflowId); - Path stateFolder = Paths.get(workflowStatesFolder.toString(), STORED_STATE_PREFIX + stateIdStr); - if ( Files.exists(stateFolder) && Files.isDirectory(stateFolder) ) { - if ( stateFolder.toFile().list().length == 1 ) { - File stateFile = stateFolder.toFile().listFiles()[0]; - String stateFileName = stateFile.getName(); - if ( stateFileName.endsWith(".xml")); - String basename = stateFileName.substring(0, stateFileName.length()-4); - DataSource dataSource = new FileDataSource(stateFolder, basename); - //Network network = Importers.import_("XML", dataSource, null); - // with the new post processors configuration, the post processing is applied also to xml import - Importer xmlImporter = Importers.getImporter("XML"); - Importer noppImporter = Importers.removePostProcessors(xmlImporter); - Network network = noppImporter.import_(dataSource, null); - return network; - } - } - return null; - } - - @Override - public void exportState(String workflowId, Integer stateId, Path folder) { - LOGGER.info("Exporting network data of workflow {} and state {} to folder {}", workflowId, stateId, folder); - Network network = getState(workflowId, stateId); - NetworkData networkData = NetworkDataExtractor.extract(network); - NetworkDataExporter.export(networkData, folder); - } - - @Override - public boolean deleteWorkflow(String workflowId) { - LOGGER.info("Deleting workflow {}", workflowId); - boolean workflowDeleted = false; - boolean workflowStatesDeleted = true; - // if stored states for this workflow exist - if ( workflowStatesFolderExists(workflowId) ) - // delete them - workflowStatesDeleted = deleteStates(workflowId); - // if stored states have been deleted - if ( workflowStatesDeleted ) { - // store workflow results - Path workflowFile = Paths.get(config.getOnlineDbDir().toFile().toString(), STORED_WORKFLOW_PREFIX + workflowId); - if ( workflowFile.toFile().exists() && workflowFile.toFile().isFile() ) - try { - workflowDeleted = Files.deleteIfExists(workflowFile); - } catch (IOException e) { - LOGGER.error("Cannot delete workflow {} from online DB: {}", workflowId, e.getMessage()); - } - else - LOGGER.warn("No workflow {} stored in the online DB", workflowId); - } - return workflowDeleted; - } - - - @Override - public boolean deleteStates(String workflowId) { - LOGGER.info("Deleting stored states of workflow {}", workflowId); - boolean workflowStatesDeleted = false; - Path workflowStatesFolder = Paths.get(config.getOnlineDbDir().toFile().toString(), STORED_WORKFLOW_STATES_FOLDER_PREFIX + workflowId); - if ( workflowStatesFolder.toFile().exists() && workflowStatesFolder.toFile().isDirectory() ) - try { - FileUtils.deleteDirectory(workflowStatesFolder.toFile()); - workflowStatesDeleted = true; - } catch (IOException e) { - LOGGER.error("Cannot delete stored states of workflow {} from online DB: ", workflowId, e.getMessage()); - } - else - LOGGER.warn("No states of workflow {} stored in the online DB", workflowId); - return workflowStatesDeleted; - } - - - @Override - public void exportStates(String workflowId, Path file) { - if ( workflowStatesFolderExists(workflowId)) { - LOGGER.info("Exporting states for workflow {}", workflowId); - Path workflowStatesFolder = getWorkflowStatesFolder(workflowId); - Path csvFile = Paths.get(workflowStatesFolder.toString(), SERIALIZED_STATES_FILENAME); - if ( !csvFile.toFile().exists() ) { - LOGGER.info("Serializing network data of workflow {}", workflowId); - try(FileWriter fileWriter = new FileWriter(csvFile.toFile()); - CsvListWriter csvWriter = new CsvListWriter(fileWriter, new CsvPreference.Builder('"', ';', "\r\n").build())) { - boolean printHeaders = true; - for(Integer stateId : listStoredStates(workflowId)) { - Network network = getState(workflowId, stateId); - if ( network != null ) { - Map networkValues = IIDM2DB.extractCimValues(network, new IIDM2DB.Config(network.getId(), true, true)).getSingleValueMap(); - if ( printHeaders ) { - List headers = new ArrayList<>(networkValues.size()); - for (HistoDbAttributeId attrId : networkValues.keySet()) { - headers.add(attrId.toString()); - } - ArrayList headersList = new ArrayList<>(); - headersList.add("workflow"); - headersList.add("state"); - headersList.addAll(Arrays.asList(headers.toArray(new String[] {}))); - csvWriter.writeHeader(headersList.toArray(new String[] {})); - printHeaders = false; - } - ArrayList valuesList = new ArrayList<>(); - valuesList.add(workflowId); - valuesList.add(stateId); - valuesList.addAll(Arrays.asList(networkValues.values().toArray())); - csvWriter.write(valuesList.toArray()); - } - } - } catch (IOException e) { - LOGGER.error("Error serializing network data for workflow {}", workflowId); - } - } - try { - Files.copy(csvFile, file, StandardCopyOption.REPLACE_EXISTING); - } catch (IOException e) { - throw new RuntimeException(e); - } - } else - LOGGER.error("No stored states for workflow {}", workflowId); - } - - @Override - public void storeViolations(String workflowId, Integer stateId, OnlineStep step, List violations) { - String stateIdStr=String.valueOf(stateId); - LOGGER.info("Storing violations for wf {}, step {} and state {}", workflowId, step.name(), stateIdStr); - storeViolations(workflowId, STORED_VIOLATIONS_MAP_PREFIX + step.name() + "_" + stateIdStr, violations); - LOGGER.info("Storing violations metadata for wf {}, step {} and state {}", workflowId, step.name(), stateIdStr); - storeViolationsMetadata(workflowId, stateIdStr, step, violations); - } - - private void storeViolations(String workflowId, String mapName, List violations) { - try { - MVStore wfMVStore = getStore(workflowId); - Map metricsMap = wfMVStore.openMap(mapName, mapBuilder); - for ( LimitViolation limitViolation : violations ) { -// Violation violation = new Violation(limitViolation.getSubject().getId(), -// limitViolation.getLimitType(), -// limitViolation.getLimit(), -// limitViolation.getValue()); -// metricsMap.put(violation.getId(), OnlineDbMVStoreUtils.violationToJson(violation)); - String violationId = limitViolation.getSubject().getId(); - // there could be 2 violations on the same line, on both terminals: I need to store both - if ( metricsMap.containsKey(violationId) ) - violationId += "__1"; - metricsMap.put(violationId, OnlineDbMVStoreUtils.limitViolationToJson(limitViolation)); - } - wfMVStore.commit(); - } catch(Throwable e) { - String errorMessage = "Error storing violations for wf " + workflowId + " in map " + mapName + ": " + e.getMessage(); - LOGGER.error(errorMessage); - throw new RuntimeException(errorMessage); - } - } - - private void storeViolationsMetadata(String workflowId, String stateId, OnlineStep step, List violations) { - try { - MVStore wfMVStore = getStore(workflowId); - - // save info about stored wf steps - MVMap storedStepsMap = wfMVStore.openMap(STORED_VIOLATIONS_STEPS_MAP_NAME, mapBuilder); - storedStepsMap.putIfAbsent(step.name(), "1"); - // save info about stored states per step - MVMap stepStateMap = wfMVStore.openMap(step.name() + STORED_VIOLATIONS_STATES_MAP_SUFFIX, mapBuilder); - stepStateMap.putIfAbsent(stateId, ""); - - // save info about stored wf states - MVMap storedStatesMap = wfMVStore.openMap(STORED_VIOLATIONS_STATES_MAP_NAME, mapBuilder); - storedStatesMap.putIfAbsent(stateId, "1"); - // save info about stored steps per state - MVMap stepStepMap = wfMVStore.openMap(stateId + STORED_VIOLATIONS_STEPS_MAP_SUFFIX, mapBuilder); - stepStepMap.putIfAbsent(step.name(), ""); - - wfMVStore.commit(); - } catch(Throwable e) { - String errorMessage = "Error storing violations metadata for wf " + workflowId + ", step "+ step.name() + ", state " + stateId + ": " + e.getMessage(); - LOGGER.error(errorMessage); - throw new RuntimeException(errorMessage); - } - } - - @Override - public List getViolations(String workflowId, Integer stateId, OnlineStep step) { - String stateIdStr=String.valueOf(stateId); - LOGGER.info("Getting violations for wf {}, step {} and state {}", workflowId, step.name(), stateIdStr); - return getStoredViolations(workflowId, STORED_VIOLATIONS_MAP_PREFIX + step.name() + "_" + stateIdStr, null); - } - - private List getStoredViolations(String workflowId, String mapName, Network network) { - if ( isWorkflowStored(workflowId) ) { - MVStore wfMVStore = getStore(workflowId); - if ( wfMVStore.getMapNames().contains(mapName) ) { - if ( network==null ) - // load network: used to get equipment from equipment id, when creating limit violations - network = getState(workflowId, 0); - if ( network!=null ) { - List violations = new ArrayList(); - Map storedMap = wfMVStore.openMap(mapName, mapBuilder); - for ( String violationId : storedMap.keySet() ) { -// Violation violation = OnlineDbMVStoreUtils.jsonToViolation(storedMap.get(violationId)); -// Identifiable subject = network.getIdentifiable(violation.getSubject()); -// if ( subject!= null ) -// violations.add(new LimitViolation(subject, -// violation.getLimitType(), -// violation.getLimit(), -// violation.getValue())); - LimitViolation violation = OnlineDbMVStoreUtils.jsonToLimitViolation(storedMap.get(violationId), network); - if ( violation != null ) - violations.add(violation); - } - return violations; - } else { - LOGGER.warn("No network data (states) stored for wf {}, cannot get violations", workflowId); - return null; - } - } else { - LOGGER.warn("No map {} in wf {}", mapName, workflowId); - return null; - } - } else { - LOGGER.warn("No data about wf {}", workflowId); - return null; - } - } - - @Override - public Map> getViolations(String workflowId, Integer stateId) { - String stateIdStr = Integer.toString(stateId); - LOGGER.info("Getting violations for wf {} and state {}", workflowId, stateIdStr); - if ( isWorkflowStored(workflowId) ) { - MVStore wfMVStore = getStore(workflowId); - // check if there are stored violations - Map storedStatesMap = wfMVStore.openMap(STORED_VIOLATIONS_STATES_MAP_NAME, mapBuilder); - if ( storedStatesMap.containsKey(stateIdStr) ) { - // load network: used to get equipment from equipment id, when creating limit violations - Network network = getState(workflowId, 0); - if ( network!=null ) { - Map> stateViolations = new HashMap>(); - MVMap storedStepsMap = wfMVStore.openMap(stateIdStr + STORED_VIOLATIONS_STEPS_MAP_SUFFIX, mapBuilder); - for ( String stepName : storedStepsMap.keySet() ) { - OnlineStep step = OnlineStep.valueOf(stepName); - List violations = getStoredViolations(workflowId, STORED_VIOLATIONS_MAP_PREFIX + step.name() + "_" + stateId, network); - if ( violations!=null ) - stateViolations.put(step, violations); - } - return stateViolations; - } else { - LOGGER.warn("No network data (states) stored for wf {}, cannot get violations", workflowId); - return null; - } - } else { - LOGGER.warn("No violations for wf {} and state {}", workflowId, stateIdStr); - return null; - } - } else { - LOGGER.warn("No data about wf {}", workflowId); - return null; - } - } - - - @Override - public Map> getViolations(String workflowId, OnlineStep step) { - LOGGER.info("Getting violations for wf {} and step {}", workflowId, step.name()); - if ( isWorkflowStored(workflowId) ) { - MVStore wfMVStore = getStore(workflowId); - // check if there are stored violations - Map storedStepsMap = wfMVStore.openMap(STORED_VIOLATIONS_STEPS_MAP_NAME, mapBuilder); - if ( storedStepsMap.containsKey(step.name()) ) { - // load network: used to get equipment from equipment id, when creating limit violations - Network network = getState(workflowId, 0); - if ( network!=null ) { - Map> stepViolations = new HashMap>(); - MVMap storedStatesMap = wfMVStore.openMap(step.name() + STORED_VIOLATIONS_STATES_MAP_SUFFIX, mapBuilder); - for ( String stateId : storedStatesMap.keySet() ) { - List violations = getStoredViolations(workflowId, STORED_VIOLATIONS_MAP_PREFIX + step.name() + "_" + stateId, network); - if ( violations!=null ) - stepViolations.put(Integer.valueOf(stateId), violations); - } - return stepViolations; - } else { - LOGGER.warn("No network data (states) stored for wf {}, cannot get violations", workflowId); - return null; - } - } else { - LOGGER.warn("No violations for wf {} and step {}", workflowId, step.name()); - return null; - } - } else { - LOGGER.warn("No data for wf {}", workflowId); - return null; - } - } - - @Override - public Map>> getViolations(String workflowId) { - LOGGER.info("Getting violations for wf {}", workflowId); - if ( isWorkflowStored(workflowId) ) { - MVStore wfMVStore = getStore(workflowId); - // check if there are stored violations - Map storedStatesMap = wfMVStore.openMap(STORED_VIOLATIONS_STATES_MAP_NAME, mapBuilder); - if ( !storedStatesMap.isEmpty() ) { - // load network: used to get equipment from equipment id, when creating limit violations - Network network = getState(workflowId, 0); - if ( network!=null ) { - Map>> wfViolations = new HashMap>>(); - for(String stateIdStr : storedStatesMap.keySet()) { - Integer stateId = Integer.parseInt(stateIdStr); - Map> stateViolations = new HashMap>(); - MVMap storedStepsMap = wfMVStore.openMap(stateIdStr + STORED_VIOLATIONS_STEPS_MAP_SUFFIX, mapBuilder); - if ( !storedStepsMap.isEmpty() ) { - for ( String stepName : storedStepsMap.keySet() ) { - OnlineStep step = OnlineStep.valueOf(stepName); - List violations = getStoredViolations(workflowId, STORED_VIOLATIONS_MAP_PREFIX + step.name() + "_" + stateId, network); - if ( violations!=null ) - stateViolations.put(step, violations); - } - wfViolations.put(stateId, stateViolations); - } - } - return wfViolations; - } else { - LOGGER.warn("No network data (states) stored for wf {}, cannot get violations", workflowId); - return null; - } - } else { - LOGGER.warn("No violations for wf {}", workflowId); - return null; - } - } else { - LOGGER.warn("No data for wf {}", workflowId); - return null; - } - } - - @Override - public void storePostContingencyViolations(String workflowId, Integer stateId, String contingencyId, - boolean loadflowConverge, List violations) { - String stateIdStr=String.valueOf(stateId); - LOGGER.info("Storing post contingency violations for wf {}, contingency {} and state {}", workflowId, contingencyId, stateIdStr); - storeViolations(workflowId, STORED_PC_VIOLATIONS_MAP_PREFIX + contingencyId + "_" + stateIdStr, violations); - LOGGER.info("Storing post contingency violations metadata for wf {}, contingency {} and state {}", workflowId, contingencyId, stateIdStr); - storePCViolationsMetadata(workflowId, stateIdStr, contingencyId, violations); - LOGGER.info("Storing post contingency loadflow convergence for wf {}, contingency {} and state {}", workflowId, contingencyId, stateIdStr); - storePSLoadflowConvergence(workflowId, stateIdStr, contingencyId, loadflowConverge); - } - - private void storePCViolationsMetadata(String workflowId, String stateId, String contingencyId, List violations) { - try { - MVStore wfMVStore = getStore(workflowId); - - // save info about stored wf contingencies - MVMap storedContingenciesMap = wfMVStore.openMap(STORED_PC_VIOLATIONS_CONTINGENCIES_MAP_NAME, mapBuilder); - storedContingenciesMap.putIfAbsent(contingencyId, "1"); - // save info about stored states per contingency - MVMap contingencyStateMap = wfMVStore.openMap(contingencyId + STORED_PC_VIOLATIONS_STATES_MAP_SUFFIX, mapBuilder); - contingencyStateMap.putIfAbsent(stateId, ""); - - // save info about stored wf states - MVMap storedStatesMap = wfMVStore.openMap(STORED_PC_VIOLATIONS_STATES_MAP_NAME, mapBuilder); - storedStatesMap.putIfAbsent(stateId, "1"); - // save info about stored contingencies per state - MVMap stateContingencyMap = wfMVStore.openMap(stateId + STORED_PC_VIOLATIONS_CONTINGENCIES_MAP_SUFFIX, mapBuilder); - stateContingencyMap.putIfAbsent(contingencyId, ""); - - wfMVStore.commit(); - } catch(Throwable e) { - String errorMessage = "Error storing pc violations metadata for wf " + workflowId + ", contingency "+ contingencyId + ", state " + stateId + ": " + e.getMessage(); - LOGGER.error(errorMessage); - throw new RuntimeException(errorMessage); - } - } - - private void storePSLoadflowConvergence(String workflowId, String stateId, String contingencyId, boolean loadflowConverge) { - try { - MVStore wfMVStore = getStore(workflowId); - - // save info about stored wf contingencies - MVMap storedContingenciesMap = wfMVStore.openMap(STORED_PC_LOADFLOW_CONTINGENCIES_MAP_NAME, mapBuilder); - storedContingenciesMap.putIfAbsent(contingencyId, "1"); - // save info about stored states per contingency - MVMap contingencyStateMap = wfMVStore.openMap(contingencyId + STORED_PC_LOADFLOW_STATES_MAP_SUFFIX, mapBuilder); - contingencyStateMap.putIfAbsent(stateId, Boolean.toString(loadflowConverge)); - - // save info about stored wf states - MVMap storedStatesMap = wfMVStore.openMap(STORED_PC_LOADFLOW_STATES_MAP_NAME, mapBuilder); - storedStatesMap.putIfAbsent(stateId, "1"); - // save info about stored contingencies per state - MVMap stateContingencyMap = wfMVStore.openMap(stateId + STORED_PC_LOADFLOW_CONTINGENCIES_MAP_SUFFIX, mapBuilder); - stateContingencyMap.putIfAbsent(contingencyId, Boolean.toString(loadflowConverge)); - - wfMVStore.commit(); - } catch(Throwable e) { - String errorMessage = "Error storing pc loadflow convergence for wf " + workflowId + ", contingency "+ contingencyId + ", state " + stateId + ": " + e.getMessage(); - LOGGER.error(errorMessage); - throw new RuntimeException(errorMessage); - } - } - - @Override - public List getPostContingencyViolations(String workflowId, Integer stateId, String contingencyId) { - String stateIdStr=String.valueOf(stateId); - LOGGER.info("Getting post contingency violations for wf {}, contingency {} and state {}", workflowId, contingencyId, stateIdStr); - return getStoredViolations(workflowId, STORED_PC_VIOLATIONS_MAP_PREFIX + contingencyId + "_" + stateIdStr, null); - } - - @Override - public Map> getPostContingencyViolations(String workflowId, Integer stateId) { - String stateIdStr = Integer.toString(stateId); - LOGGER.info("Getting post contingency violations for wf {} and state {}", workflowId, stateIdStr); - if ( isWorkflowStored(workflowId) ) { - MVStore wfMVStore = getStore(workflowId); - // check if there are stored violations - Map storedStatesMap = wfMVStore.openMap(STORED_PC_VIOLATIONS_STATES_MAP_NAME, mapBuilder); - if ( storedStatesMap.containsKey(stateIdStr) ) { - // load network: used to get equipment from equipment id, when creating limit violations - Network network = getState(workflowId, 0); - if ( network!=null ) { - Map> stateViolations = new HashMap>(); - MVMap storedContingenciesMap = wfMVStore.openMap(stateIdStr + STORED_PC_VIOLATIONS_CONTINGENCIES_MAP_SUFFIX, mapBuilder); - for ( String contingencyId : storedContingenciesMap.keySet() ) { - List violations = getStoredViolations(workflowId, STORED_PC_VIOLATIONS_MAP_PREFIX + contingencyId + "_" + stateId, network); - if ( violations!=null ) - stateViolations.put(contingencyId, violations); - } - return stateViolations; - } else { - LOGGER.warn("No network data (states) stored for wf {}, cannot get post contingency violations", workflowId); - return null; - } - } else { - LOGGER.warn("No post contingency violations for wf {} and state {}", workflowId, stateIdStr); - return null; - } - } else { - LOGGER.warn("No data about wf {}", workflowId); - return null; - } - } - - @Override - public Map> getPostContingencyViolations(String workflowId, String contingencyId) { - LOGGER.info("Getting post contingency violations for wf {} and contingency {}", workflowId, contingencyId); - if ( isWorkflowStored(workflowId) ) { - MVStore wfMVStore = getStore(workflowId); - // check if there are stored violations - Map storedContingenciesMap = wfMVStore.openMap(STORED_PC_VIOLATIONS_CONTINGENCIES_MAP_NAME, mapBuilder); - if ( storedContingenciesMap.containsKey(contingencyId) ) { - // load network: used to get equipment from equipment id, when creating limit violations - Network network = getState(workflowId, 0); - if ( network!=null ) { - Map> contingencyViolations = new HashMap>(); - MVMap storedStatesMap = wfMVStore.openMap(contingencyId + STORED_PC_VIOLATIONS_STATES_MAP_SUFFIX, mapBuilder); - for ( String stateId : storedStatesMap.keySet() ) { - List violations = getStoredViolations(workflowId, STORED_PC_VIOLATIONS_MAP_PREFIX + contingencyId + "_" + stateId, network); - if ( violations!=null ) - contingencyViolations.put(Integer.valueOf(stateId), violations); - } - return contingencyViolations; - } else { - LOGGER.warn("No network data (states) stored for wf {}, cannot get post contingency violations", workflowId); - return null; - } - } else { - LOGGER.warn("No post contingency violations for wf {} and contingency {}", workflowId, contingencyId); - return null; - } - } else { - LOGGER.warn("No data for wf {}", workflowId); - return null; - } - } - - @Override - public Map>> getPostContingencyViolations(String workflowId) { - LOGGER.info("Getting post contingency violations for wf {}", workflowId); - if ( isWorkflowStored(workflowId) ) { - MVStore wfMVStore = getStore(workflowId); - // check if there are stored violations - Map storedStatesMap = wfMVStore.openMap(STORED_PC_VIOLATIONS_STATES_MAP_NAME, mapBuilder); - if ( !storedStatesMap.isEmpty() ) { - // load network: used to get equipment from equipment id, when creating limit violations - Network network = getState(workflowId, 0); - if ( network!=null ) { - Map>> wfViolations = new HashMap>>(); - for(String stateIdStr : storedStatesMap.keySet()) { - Integer stateId = Integer.parseInt(stateIdStr); - Map> stateViolations = new HashMap>(); - MVMap storedContingenciesMap = wfMVStore.openMap(stateIdStr + STORED_PC_VIOLATIONS_CONTINGENCIES_MAP_SUFFIX, mapBuilder); - if ( !storedContingenciesMap.isEmpty() ) { - for ( String contingencyId : storedContingenciesMap.keySet() ) { - List violations = getStoredViolations(workflowId, STORED_PC_VIOLATIONS_MAP_PREFIX + contingencyId + "_" + stateId, network); - if ( violations!=null ) - stateViolations.put(contingencyId, violations); - } - wfViolations.put(stateId, stateViolations); - } - } - return wfViolations; - } else { - LOGGER.warn("No network data (states) stored for wf {}, cannot get post contingency violations", workflowId); - return null; - } - } else { - LOGGER.warn("No post contingency violations for wf {}", workflowId); - return null; - } - } else { - LOGGER.warn("No data for wf {}", workflowId); - return null; - } - } - - @Override - public Map getPostContingencyLoadflowConvergence(String workflowId, Integer stateId) { - String stateIdStr = Integer.toString(stateId); - if ( isWorkflowStored(workflowId) ) { - Map loadflowConvergence = new HashMap(); - MVStore wfMVStore = getStore(workflowId); - if ( wfMVStore.getMapNames().contains(STORED_PC_LOADFLOW_STATES_MAP_NAME) ) { - Map storedStatesMap = wfMVStore.openMap(STORED_PC_LOADFLOW_STATES_MAP_NAME, mapBuilder); - if ( storedStatesMap.containsKey(stateIdStr)) { - MVMap stateContingencyMap = wfMVStore.openMap(stateIdStr + STORED_PC_LOADFLOW_CONTINGENCIES_MAP_SUFFIX, mapBuilder); - for ( String contingencyId : stateContingencyMap.keySet() ) { - loadflowConvergence.put(contingencyId, Boolean.valueOf(stateContingencyMap.get(contingencyId))); - } - return loadflowConvergence; - } else { - LOGGER.warn("No post contingency loadflow data for state {} in wf {}", stateIdStr, workflowId); - return null; - } - } else { - LOGGER.warn("No post contingency loadflow data in wf {}", workflowId); - return null; - } - } else { - LOGGER.warn("No data about wf {}", workflowId); - return null; - } - } - - @Override - public Map getPostContingencyLoadflowConvergence(String workflowId, String contingencyId) { - if ( isWorkflowStored(workflowId) ) { - Map loadflowConvergence = new HashMap(); - MVStore wfMVStore = getStore(workflowId); - if ( wfMVStore.getMapNames().contains(STORED_PC_LOADFLOW_CONTINGENCIES_MAP_NAME) ) { - Map storedStatesMap = wfMVStore.openMap(STORED_PC_LOADFLOW_CONTINGENCIES_MAP_NAME, mapBuilder); - if ( storedStatesMap.containsKey(contingencyId)) { - MVMap contingencyStateMap = wfMVStore.openMap(contingencyId + STORED_PC_LOADFLOW_STATES_MAP_SUFFIX, mapBuilder); - for ( String stateId : contingencyStateMap.keySet() ) { - loadflowConvergence.put(Integer.valueOf(stateId), Boolean.valueOf(contingencyStateMap.get(stateId))); - } - return loadflowConvergence; - } else { - LOGGER.warn("No post contingency loadflow data for contingency {} in wf {}", contingencyId, workflowId); - return null; - } - } else { - LOGGER.warn("No post contingency loadflow data in wf {}", workflowId); - return null; - } - } else { - LOGGER.warn("No data about wf {}", workflowId); - return null; - } - } - - @Override - public Map> getPostContingencyLoadflowConvergence(String workflowId) { - if ( isWorkflowStored(workflowId) ) { - Map> loadflowConvergence = new HashMap>(); - MVStore wfMVStore = getStore(workflowId); - if ( wfMVStore.getMapNames().contains(STORED_PC_LOADFLOW_STATES_MAP_NAME) ) { - Map storedStatesMap = wfMVStore.openMap(STORED_PC_LOADFLOW_STATES_MAP_NAME, mapBuilder); - for ( String stateId : storedStatesMap.keySet() ) { - MVMap stateContingencyMap = wfMVStore.openMap(stateId + STORED_PC_LOADFLOW_CONTINGENCIES_MAP_SUFFIX, mapBuilder); - HashMap stateLoadflowConvergence = new HashMap(); - for ( String contingencyId : stateContingencyMap.keySet() ) { - stateLoadflowConvergence.put(contingencyId, Boolean.valueOf(stateContingencyMap.get(contingencyId))); - } - loadflowConvergence.put(Integer.valueOf(stateId), stateLoadflowConvergence); - } - return loadflowConvergence; - } else { - LOGGER.warn("No post contingency loadflow data in wf {}", workflowId); - return null; - } - } else { - LOGGER.warn("No data about wf {}", workflowId); - return null; - } - } - - // these wca rules methods are similar to the mcla rules methods: refactoring could be a good idea - @Override - public void storeWcaRulesResults(String workflowId, OnlineWorkflowRulesResults results) { - Objects.requireNonNull(workflowId, "workflow id is null"); - Objects.requireNonNull(results, "online workflow wca rules results is null"); - LOGGER.info("Storing results of wca rules for workflow {}", workflowId); - MVStore wfMVStore = getStore(workflowId); - // check if the results for this wf have already been stored - if ( wfMVStore.hasMap(STORED_WCA_RULES_RESULTS_MAP_NAME) ) - removeWfWcaRulesResults(workflowId, wfMVStore); - MVMap storedRulesResultsMap = wfMVStore.openMap(STORED_WCA_RULES_RESULTS_MAP_NAME, mapBuilder); - // store time horizon - storedRulesResultsMap.put(STORED_RESULTS_TIMEHORIZON_KEY, results.getTimeHorizon().getName()); - // store contingencies with security rules results - storedRulesResultsMap.put(STORED_RULES_RESULTS_CONTINGENCIES_WITH_RULES_KEY, - OnlineDbMVStoreUtils.contingenciesIdsToJson(results.getContingenciesWithSecurityRulesResults())); - // store wca rules results for contingencies - for (String contingencyId : results.getContingenciesWithSecurityRulesResults()) { - MVMap storedStateStatusMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_STATUS_MAP_SUFFIX, mapBuilder); - MVMap storedStateResultsMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_RESULTS_MAP_SUFFIX, mapBuilder); - for (Integer stateId : results.getStatesWithSecurityRulesResults(contingencyId)) { - // store state status - StateStatus status = results.getStateStatus(contingencyId, stateId); - storedStateStatusMap.put(stateId.toString(), status.name()); - // store state rules results - Map stateResults = results.getStateResults(contingencyId, stateId); - storedStateResultsMap.put(stateId.toString(), OnlineDbMVStoreUtils.indexesDataToJson(stateResults)); - } - } - wfMVStore.commit(); - } - - private void removeWfWcaRulesResults(String workflowId, MVStore wfMVStore) { - LOGGER.debug("Removing existing wca rules results for workflow {}", workflowId); - MVMap storedRulesResultsMap = wfMVStore.openMap(STORED_WCA_RULES_RESULTS_MAP_NAME, mapBuilder); - // remove rules results - Collection rulesContingencies = OnlineDbMVStoreUtils.jsonToContingenciesIds( - storedRulesResultsMap.get(STORED_RULES_RESULTS_CONTINGENCIES_WITH_RULES_KEY)); - for (String contingencyId : rulesContingencies) { - MVMap storedStateStatusMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_STATUS_MAP_SUFFIX, mapBuilder); - wfMVStore.removeMap(storedStateStatusMap); - MVMap storedStateResultsMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_RESULTS_MAP_SUFFIX, mapBuilder); - wfMVStore.removeMap(storedStateResultsMap); - } - // remove info about stored rules results - wfMVStore.removeMap(storedRulesResultsMap); - // commit removal - wfMVStore.commit(); - } - - @Override - public OnlineWorkflowRulesResults getWcaRulesResults(String workflowId) { - Objects.requireNonNull(workflowId, "workflow id is null"); - LOGGER.info("Getting wca rules results of wf {}", workflowId); - if ( isWorkflowStored(workflowId) ) { - MVStore wfMVStore = getStore(workflowId); - if ( wfMVStore.hasMap(STORED_WCA_RULES_RESULTS_MAP_NAME) ) { - MVMap storedRulesResultsMap = wfMVStore.openMap(STORED_WCA_RULES_RESULTS_MAP_NAME, mapBuilder); - // create workflow rules results - OnlineWorkflowRulesResultsImpl wfRulesResults = new OnlineWorkflowRulesResultsImpl( - workflowId, - TimeHorizon.valueOf(storedRulesResultsMap.get(STORED_RESULTS_TIMEHORIZON_KEY))); - // add contingencies with rules results - Collection contingenciesWithRules = OnlineDbMVStoreUtils.jsonToContingenciesIds( - storedRulesResultsMap.get(STORED_RULES_RESULTS_CONTINGENCIES_WITH_RULES_KEY)); - for (String contingencyId : contingenciesWithRules) { - MVMap storedStateStatusMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_STATUS_MAP_SUFFIX, mapBuilder); - MVMap storedStateResultsMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_RESULTS_MAP_SUFFIX, mapBuilder); - for (String stateId : storedStateStatusMap.keySet()) { - Map stateResults = OnlineDbMVStoreUtils.jsonToIndexesData(storedStateResultsMap.get(stateId)); - StateStatus stateStatus = StateStatus.valueOf(storedStateStatusMap.get(stateId)); - wfRulesResults.addContingencyWithSecurityRulesResults(contingencyId, Integer.parseInt(stateId), stateStatus, stateResults); - } - } - return wfRulesResults; - } else { - LOGGER.warn("No wca rules results of wf {} stored in online db", workflowId); - return null; - } - } else { - LOGGER.warn("No data about wf {}", workflowId); - return null; - } - } - - - - - - - - - - @Override - public void close() throws Exception { - closeStores(); - serializeStoredWorkflowsStates(); - } - - private boolean isWorkflowStored(String workflowId) { - Path workflowFile = Paths.get(config.getOnlineDbDir().toString(), STORED_WORKFLOW_PREFIX + workflowId); - return Files.exists(workflowFile); - } - - private boolean workflowStatesFolderExists(String workflowId) { - Path workflowStatesFolder = Paths.get(config.getOnlineDbDir().toString(), STORED_WORKFLOW_STATES_FOLDER_PREFIX + workflowId); - return Files.exists(workflowStatesFolder) && Files.isDirectory(workflowStatesFolder); - } - - private Path getWorkflowStatesFolder(String workflowId) { - Path workflowStatesFolder = Paths.get(config.getOnlineDbDir().toString(), STORED_WORKFLOW_STATES_FOLDER_PREFIX + workflowId); - if ( !workflowStatesFolderExists(workflowId) ) - try { - Files.createDirectories(workflowStatesFolder); - } catch (IOException e) { - String errorMessage = "online db: folder " + workflowStatesFolder + " for workflow " + workflowId + " cannot be created: " + e.getMessage(); - LOGGER.error(errorMessage); - throw new RuntimeException(errorMessage); - } - - return workflowStatesFolder; - } - - /* - * support methods - * to inspect the content of the online db - */ - - public List getStoredMaps(String workflowId) { - Objects.requireNonNull(workflowId, "workflow id is null"); - LOGGER.info("Getting stored maps of wf {}", workflowId); - if ( isWorkflowStored(workflowId) ) { - MVStore wfMVStore = getStore(workflowId); - return new ArrayList(wfMVStore.getMapNames()); - } else { - LOGGER.warn("No data about wf {}", workflowId); - return null; - } - } - - public String exportStoredMapsList(String workflowId) { - Objects.requireNonNull(workflowId, "workflow id is null"); - LOGGER.info("Exporting list of stored maps of wf {}", workflowId); - StringBuffer storedMapList = new StringBuffer(); - List storedMaps = getStoredMaps(workflowId); - if ( storedMaps != null ) { - for (String map : storedMaps) { - storedMapList.append(map + "\n"); - } - } - return storedMapList.toString(); - } - - public String exportStoredMapContent(String workflowId, String mapName) { - Objects.requireNonNull(workflowId, "workflow id is null"); - Objects.requireNonNull(mapName, "map name id is null"); - LOGGER.info("Exporting content of stored map {} of wf {}", mapName, workflowId); - if ( isWorkflowStored(workflowId) ) { - MVStore wfMVStore = getStore(workflowId); - if ( wfMVStore.hasMap(mapName) ) { - StringBuffer storedMapContent = new StringBuffer(); - storedMapContent.append("Map " + mapName + "\n"); - MVMap storedMap = wfMVStore.openMap(mapName, mapBuilder); - for (String key : storedMap.keySet()) { - storedMapContent.append(key + " = " + storedMap.get(key) + "\n"); - } - return storedMapContent.toString(); - } else { - LOGGER.warn("No {} map in wf {}", mapName, workflowId); - return null; - } - } else { - LOGGER.warn("No data about wf {}", workflowId); - return null; - } - } - - public String exportStoredMapsContent(String workflowId) { - Objects.requireNonNull(workflowId, "workflow id is null"); - LOGGER.info("Exporting content of stored maps of wf {}", workflowId); - StringBuffer storedMapList = new StringBuffer(); - List storedMaps = getStoredMaps(workflowId); - if ( storedMaps != null ) { - for (String map : storedMaps) { - storedMapList.append(exportStoredMapContent(workflowId, map) + "\n"); - } - } - return storedMapList.toString(); - } + private static final String STORED_WORKFLOW_PREFIX = "wf-"; + private static final String STORED_METRICS_STEPS_MAP_NAME = "storedSteps"; + private static final String STORED_METRICS_STATES_MAP_SUFFIX = "_states"; + private static final String STORED_METRICS_PARAMS_MAP_SUFFIX = "_params"; + private static final String STORED_RESULTS_MAP_NAME = "wfResults"; + private static final String STORED_RESULTS_ACTIONS_MAP_SUFFIX = "_actions"; + private static final String STORED_RESULTS_ACTIONINFO_MAP_SUFFIX = "_actionplans"; // i do not change this, for backward compatibility + private static final String STORED_RESULTS_ACTIONINFO_ACTIONSFOUND_KEY_SUFFIX = "_actionsfound"; + private static final String STORED_RESULTS_ACTIONINFO_STATUS_KEY_SUFFIX = "_status"; + private static final String STORED_RESULTS_ACTIONINFO_CAUSE_KEY_SUFFIX = "_cause"; + private static final String STORED_RESULTS_ACTIONINFO_ACTIONPLAN_KEY_SUFFIX = "_actionplan"; + private static final String STORED_RESULTS_ACTIONS_EQUIPMENTS_MAP_SUFFIX = "_actionequipments"; + private static final String STORED_RESULTS_ACTIONS_PARAMETERS_MAP_SUFFIX = "_actionparameters"; + private static final String STORED_RESULTS_INDEXES_MAP_SUFFIX = "_indexes"; + private static final String STORED_RESULTS_TIMEHORIZON_KEY = "time_orizon"; + private static final String STORED_RESULTS_CONTINGENCIES_WITH_ACTIONS_KEY = "contingiencies_with_actions"; + private static final String STORED_RESULTS_UNSAFE_CONTINGENCIES_KEY = "unsafe_contingiencies"; + private static final String STORED_RULES_RESULTS_MAP_NAME = "wfRulesResults"; + private static final String STORED_RULES_RESULTS_STATE_RESULTS_MAP_SUFFIX = "_rulesresults"; + private static final String STORED_RULES_RESULTS_STATE_STATUS_MAP_SUFFIX = "_rulesstatus"; + private static final String STORED_RULES_RESULTS_STATE_RULES_AVAILABLE_MAP_SUFFIX = "_rulesavailable"; + private static final String STORED_RULES_RESULTS_STATE_INVALID_RULES_MAP_SUFFIX = "_rulesinvalid"; + private static final String STORED_RULES_RESULTS_CONTINGENCIES_WITH_RULES_KEY = "contingiencies_with_rules"; + private static final String STORED_WCA_RESULTS_MAP_NAME = "wfWcaResults"; + private static final String STORED_WCA_RESULTS_CLUSTERS_MAP_NAME = "contingencies_wcaclusters"; + private static final String STORED_WCA_RESULTS_CAUSES_MAP_NAME = "contingencies_wcacause"; + private static final String STORED_PARAMETERS_MAP_NAME = "wfParameters"; + private static final String STORED_PARAMETERS_BASECASE_KEY = "basecase"; + private static final String STORED_PARAMETERS_STATE_NUMBER_KEY = "state_number"; + private static final String STORED_PARAMETERS_HISTO_INTERVAL_KEY = "histo_interval"; + private static final String STORED_PARAMETERS_OFFLINE_WF_ID_KEY = "offline_wf"; + private static final String STORED_PARAMETERS_FEA_ID_KEY = "fe_analysis"; + private static final String STORED_PARAMETERS_RULES_PURITY_KEY = "rules_purity"; + private static final String STORED_PARAMETERS_STORE_STATES_KEY = "store_states"; + private static final String STORED_PARAMETERS_ANALYSE_BASECASE_KEY = "analyse_basecase"; + private static final String STORED_PARAMETERS_VALIDATION_KEY = "validation"; + private static final String STORED_PARAMETERS_SECURITY_INDEXES_KEY = "security_indexes"; + private static final String STORED_PARAMETERS_CASE_TYPE_KEY = "case_type"; + private static final String STORED_PARAMETERS_COUNTRIES_KEY = "countries"; + private static final String STORED_PARAMETERS_MERGE_OPTIMIZED_KEY = "merge_optimized"; + private static final String STORED_PARAMETERS_LIMIT_REDUCTION_KEY = "limit_reduction"; + private static final String STORED_PARAMETERS_HANDLE_VIOLATIONS_KEY = "handle_violations"; + private static final String STORED_PARAMETERS_CONSTRAINT_MARGIN_KEY = "constraint_margin"; + private static final String STORED_STATES_PROCESSING_STATUS_MAP_NAME = "statesProcessingStatus"; + private static final String STORED_STATES_LIST_KEY = "states"; + private static final String STORED_STATES_STATE_DETAILS_KEY = "stateStatusDetails"; + private static final String STORED_STATE_PROCESSING_STATUS_MAP_SUFFIX = "_processingstatus"; + private static final String STORED_WORKFLOW_STATES_FOLDER_PREFIX = "states-wf-"; + private static final String STORED_STATE_PREFIX = "state-"; + private static final String STORED_VIOLATIONS_STEPS_MAP_NAME = "storedViolationsSteps"; + private static final String STORED_VIOLATIONS_STATES_MAP_SUFFIX = "_violationsstates"; + private static final String STORED_VIOLATIONS_STATES_MAP_NAME = "storedViolationsStates"; + private static final String STORED_VIOLATIONS_STEPS_MAP_SUFFIX = "_violationssteps"; + private static final String STORED_VIOLATIONS_MAP_PREFIX = "violations_"; + private static final String STORED_PC_VIOLATIONS_CONTINGENCIES_MAP_NAME = "storedPCViolationsContingencies"; + private static final String STORED_PC_VIOLATIONS_STATES_MAP_SUFFIX = "_pcviolationsstates"; + private static final String STORED_PC_VIOLATIONS_STATES_MAP_NAME = "storedPCViolationsStates"; + private static final String STORED_PC_VIOLATIONS_CONTINGENCIES_MAP_SUFFIX = "_pcviolationscontigencies"; + private static final String STORED_PC_VIOLATIONS_MAP_PREFIX = "pcviolations_"; + private static final String STORED_PC_LOADFLOW_CONTINGENCIES_MAP_NAME = "storedPCLoadflowContingencies"; + private static final String STORED_PC_LOADFLOW_STATES_MAP_SUFFIX = "_pcloadflowstates";; + private static final String STORED_PC_LOADFLOW_STATES_MAP_NAME = "storedPCLoadflowStates"; + private static final String STORED_PC_LOADFLOW_CONTINGENCIES_MAP_SUFFIX = "_pcloadflowcontigencies"; + private static final String STORED_WCA_RULES_RESULTS_MAP_NAME = "wfWcaRulesResults"; + private static final String STORED_WCA_RULES_RESULTS_STATE_RESULTS_MAP_SUFFIX = "_wcarulesresults"; + private static final String STORED_WCA_RULES_RESULTS_STATE_STATUS_MAP_SUFFIX = "_wcarulesstatus"; + private static final String STORED_WCA_RULES_RESULTS_STATE_RULES_AVAILABLE_MAP_SUFFIX = "_wcarulesavailable"; + private static final String STORED_WCA_RULES_RESULTS_STATE_INVALID_RULES_MAP_SUFFIX = "_wcarulesinvalid"; + private static final String SERIALIZED_STATES_FILENAME = "network-states.csv"; + + + private static final Logger LOGGER = LoggerFactory.getLogger(OnlineDbMVStore.class); + + + private OnlineDbMVStoreConfig config = null; + + HashMap storedWFMetrics = new HashMap(); + ConcurrentHashMap>> workflowsStates = new ConcurrentHashMap>>(); + + MVMapConcurrent.Builder mapBuilder; + + + public OnlineDbMVStore(OnlineDbMVStoreConfig config) { + this.config = config; + LOGGER.info(config.toString()); + Path storageFolder = config.getOnlineDbDir(); + if ( !Files.exists(storageFolder) ) { + try { + Files.createDirectories(storageFolder); + } catch (IOException e) { + String errorMessage = "online db folder " + storageFolder + " does not exist and cannot be created: " + e.getMessage(); + LOGGER.error(errorMessage); + throw new RuntimeException(errorMessage); + } + } + mapBuilder = new MVMapConcurrent.Builder(); + } + + public OnlineDbMVStore() { + this(OnlineDbMVStoreConfig.load()); + } + + private synchronized void closeStores() { + ArrayList workflowIds = new ArrayList(); + for (String storedWorkflowId : storedWFMetrics.keySet()) { + MVStore wfMVStore = storedWFMetrics.get(storedWorkflowId); + wfMVStore.close(); + workflowIds.add(storedWorkflowId); + } + for (String workflowId : workflowIds) { + storedWFMetrics.remove(workflowId); + } + } + + private synchronized MVStore getStore(String workflowId) { + MVStore wfMVStore; + if ( storedWFMetrics.containsKey(workflowId)) + wfMVStore = storedWFMetrics.get(workflowId); + else { + LOGGER.debug("Opening file for workflow {}", workflowId); + wfMVStore = MVStore.open(config.getOnlineDbDir().toString() + File.separator + STORED_WORKFLOW_PREFIX + workflowId); + storedWFMetrics.put(workflowId, wfMVStore); + } + return wfMVStore; + } + + @Override + public void storeMetrics(String workflowId, OnlineStep step, Map metrics) { + LOGGER.info("Storing metrics for wf {} and step {}", workflowId, step.name()); + storeMetrics(workflowId, step.name() + "__", metrics); + LOGGER.info("Storing metadata for wf {} and step {}", workflowId, step.name()); + storeStepMetadata(workflowId, "_", step, metrics); + + } + + @Override + public void storeMetrics(String workflowId, Integer stateId, OnlineStep step, Map metrics) { + String stateIdStr=String.valueOf(stateId); + LOGGER.info("Storing metrics for wf {}, step {} and state {}", workflowId, step.name(), stateIdStr); + storeMetrics(workflowId, step.name() + "_" + stateIdStr, metrics); + LOGGER.info("Storing metadata for wf {}, step {} and state {}", workflowId, step.name(), stateIdStr); + storeStepMetadata(workflowId, stateIdStr, step, metrics); + } + + private void storeMetrics(String workflowId, String mapName, Map metrics) { + try { + MVStore wfMVStore = getStore(workflowId); + Map metricsMap = wfMVStore.openMap(mapName, mapBuilder); + for ( String parameter : metrics.keySet() ) { + metricsMap.put(parameter, metrics.get(parameter)); + } + wfMVStore.commit(); + } catch(Throwable e) { + String errorMessage = "Error storing metrics for wf " + workflowId + " in map " + mapName + ": " + e.getMessage(); + LOGGER.error(errorMessage); + throw new RuntimeException(errorMessage); + } + } + + private void storeStepMetadata(String workflowId, String stateId, OnlineStep step, Map metrics) { + try { + MVStore wfMVStore = getStore(workflowId); + // save info about stored wf steps + MVMap storedStepsMap = wfMVStore.openMap(STORED_METRICS_STEPS_MAP_NAME, mapBuilder); + storedStepsMap.putIfAbsent(step.name(), "1"); + // save info about stored states per step + MVMap stepStatesMap = wfMVStore.openMap(step.name() + STORED_METRICS_STATES_MAP_SUFFIX, mapBuilder); + stepStatesMap.putIfAbsent(stateId, ""); + // save info about stored params per step + MVMap stepParamsMap = wfMVStore.openMap(step.name() + STORED_METRICS_PARAMS_MAP_SUFFIX, mapBuilder); + for ( String parameter : metrics.keySet() ) { + stepParamsMap.putIfAbsent(parameter, ""); + } + wfMVStore.commit(); + } catch(Throwable e) { + String errorMessage = "Error storing metadata for wf " + workflowId + ", step "+ step.name() + ", state " + stateId + ": " + e.getMessage(); + LOGGER.error(errorMessage); + throw new RuntimeException(errorMessage); + } + } + + @Override + public Map getMetrics(String workflowId, OnlineStep step) { + LOGGER.info("Getting metrics from wf {} and step {}", workflowId, step.name()); + return getMetrics(workflowId, step.name() + "__"); + } + + @Override + public Map getMetrics(String workflowId, Integer stateId, OnlineStep step) { + String stateIdStr=String.valueOf(stateId); + LOGGER.info("Getting metrics from wf {}, step {} and state {}", workflowId, step.name(), stateIdStr); + return getMetrics(workflowId, step.name() + "_" + stateIdStr); + } + + private Map getMetrics(String workflowId, String mapName) { + if ( isWorkflowStored(workflowId) ) { + HashMap metrics = new HashMap(); + MVStore wfMVStore = getStore(workflowId); + if ( wfMVStore.getMapNames().contains(mapName) ) { + Map storedMap = wfMVStore.openMap(mapName, mapBuilder); + for ( String parameter : storedMap.keySet() ) { + metrics.put(parameter, storedMap.get(parameter)); + } + } + return metrics; + } else { + LOGGER.warn("No data about wf {}", workflowId); + return null; + } + } + + @Override + public String getCsvMetrics(String workflowId, OnlineStep step) { + LOGGER.info("Preparing CSV data for wf {} and step {}", workflowId, step.name()); + if ( isWorkflowStored(workflowId) ) { + StringWriter content = new StringWriter(); + CsvWriter cvsWriter = new CsvWriter(content, ','); + try { + MVStore wfMVStore = getStore(workflowId); + // check if there are stored metrics + Map storedStepsMap = wfMVStore.openMap(STORED_METRICS_STEPS_MAP_NAME, mapBuilder); + if ( storedStepsMap.containsKey(step.name()) ) { + MVMap stepParamsMap = wfMVStore.openMap(step.name() + STORED_METRICS_PARAMS_MAP_SUFFIX, mapBuilder); + MVMap stepStatesMap = wfMVStore.openMap(step.name() + STORED_METRICS_STATES_MAP_SUFFIX, mapBuilder); + // write headers + //LOGGER.debug("Preparing CSV headers for wf {} and step {}", workflowId, step.name()); + String[] headers = new String[stepParamsMap.keySet().size()+1]; + headers[0] = "state"; + HashMap paramsIndexes = new HashMap<>(); + int i = 1; + for ( String parameter : stepParamsMap.keySet() ) { + headers[i] = parameter; + paramsIndexes.put(parameter, i); + i++; + } + cvsWriter.writeRecord(headers); + // write step general metrics, if stored + if ( stepStatesMap.containsKey("_") ) { + //LOGGER.debug("Preparing CSV data for wf {} and step {} - general step metrics", workflowId, step.name()); + String[] values = getStoredMapValues(wfMVStore, "_", step, stepParamsMap.keySet().size(), paramsIndexes); + cvsWriter.writeRecord(values); + } + // write step metrics for each state, if stored + for ( String stateId : stepStatesMap.keySet() ) { + if (!"_".equals(stateId) ) { + //LOGGER.debug("Preparing CSV data for wf {} and step {} - state {} metrics", workflowId, step.name(), stateId); + String[] values = getStoredMapValues(wfMVStore, stateId, step, stepParamsMap.keySet().size(), paramsIndexes); + cvsWriter.writeRecord(values); + } + } + } + } catch (IOException e) { + String errorMessage = "error getting cvs data for step " + step.name() + " and wf id " + workflowId; + LOGGER.error(errorMessage); + throw new RuntimeException(errorMessage); + } + cvsWriter.flush(); + return content.toString(); + } else { + LOGGER.warn("No data about wf {}", workflowId); + return null; + } + } + + private String[] getStoredMapValues(MVStore wfMVStore, String stateId, OnlineStep step, int paramsN, HashMap paramsIndexes) { + String[] values = new String[paramsN+1]; + values[0] = stateId; + Map storedMap = wfMVStore.openMap(step.name() + "_" + stateId, mapBuilder); + for ( String parameter : storedMap.keySet() ) { + int index = paramsIndexes.get(parameter); + values[index] = storedMap.get(parameter); + } + return values; + } + + @Override + public List listWorkflows() { + LOGGER.info("Getting list of stored workflows"); + List workflowIds = new ArrayList(); + File[] files = config.getOnlineDbDir().toFile().listFiles(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.toLowerCase().startsWith(STORED_WORKFLOW_PREFIX); + } + }); + Arrays.sort(files, new Comparator(){ + public int compare(File f1, File f2) + { + return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); + } }); + for (File file : files) { + if ( file.isFile() ) { + OnlineWorkflowDetails workflowDetails = new OnlineWorkflowDetails(file.getName().substring(STORED_WORKFLOW_PREFIX.length())); + workflowDetails.setWorkflowDate(new DateTime(file.lastModified())); + workflowIds.add(workflowDetails); + } + } + LOGGER.info("Found {} workflow(s)", workflowIds.size()); + return workflowIds; + } + + @Override + public List listWorkflows(DateTime basecaseDate) { + LOGGER.info("Getting list of stored workflows run on basecase {}", basecaseDate); + String wfNamePrefix = DateTimeFormat.forPattern("yyyyMMdd_HHmm_").print(basecaseDate); + List workflowIds = new ArrayList(); + File[] files = config.getOnlineDbDir().toFile().listFiles(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.toLowerCase().startsWith(STORED_WORKFLOW_PREFIX+wfNamePrefix); + } + }); + Arrays.sort(files, new Comparator(){ + public int compare(File f1, File f2) + { + return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); + } }); + for (File file : files) { + if ( file.isFile() ) { + OnlineWorkflowDetails workflowDetails = new OnlineWorkflowDetails(file.getName().substring(STORED_WORKFLOW_PREFIX.length())); + workflowDetails.setWorkflowDate(new DateTime(file.lastModified())); + workflowIds.add(workflowDetails); + } + } + LOGGER.info("Found {} workflow(s)", workflowIds.size()); + return workflowIds; + } + + @Override + public List listWorkflows(Interval basecaseInterval) { + LOGGER.info("Getting list of stored workflows run on basecases within the interval {}", basecaseInterval); + String dateFormatPattern = "yyyyMMdd_HHmm"; + DateTimeFormatter formatter = DateTimeFormat.forPattern(dateFormatPattern); + List workflowIds = new ArrayList(); + File[] files = config.getOnlineDbDir().toFile().listFiles(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.toLowerCase().startsWith(STORED_WORKFLOW_PREFIX); + } + }); + Arrays.sort(files, new Comparator(){ + public int compare(File f1, File f2) + { + return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); + } }); + for (File file : files) { + if ( file.isFile() ) { + String wfId = file.getName().substring(STORED_WORKFLOW_PREFIX.length()); + if ( wfId.length() > dateFormatPattern.length() && wfId.substring(dateFormatPattern.length(),dateFormatPattern.length()+1).equals("_")) { + String basecaseName = wfId.substring(0, dateFormatPattern.length()-1); + DateTime basecaseDate = DateTime.parse(basecaseName, formatter); + if ( basecaseInterval.contains(basecaseDate.getMillis())) { + OnlineWorkflowDetails workflowDetails = new OnlineWorkflowDetails(wfId); + workflowDetails.setWorkflowDate(new DateTime(file.lastModified())); + workflowIds.add(workflowDetails); + } + } + } + } + LOGGER.info("Found {} workflow(s)", workflowIds.size()); + return workflowIds; + } + + @Override + public void storeResults(String workflowId, OnlineWorkflowResults results) { + Objects.requireNonNull(workflowId, "workflow id is null"); + Objects.requireNonNull(results, "online workflow results is null"); + LOGGER.info("Storing results for workflow {}", workflowId); + MVStore wfMVStore = getStore(workflowId); + // check if the results for this wf have already been stored + if ( wfMVStore.hasMap(STORED_RESULTS_MAP_NAME) ) + removeWfResults(workflowId, wfMVStore); + MVMap storedResultsMap = wfMVStore.openMap(STORED_RESULTS_MAP_NAME, mapBuilder); + // store time horizon + storedResultsMap.put(STORED_RESULTS_TIMEHORIZON_KEY, results.getTimeHorizon().getName()); + // store contingencies with actions + storedResultsMap.put(STORED_RESULTS_CONTINGENCIES_WITH_ACTIONS_KEY, OnlineDbMVStoreUtils.contingenciesIdsToJson(results.getContingenciesWithActions())); + // store contingencies with actions + storedResultsMap.put(STORED_RESULTS_UNSAFE_CONTINGENCIES_KEY, OnlineDbMVStoreUtils.contingenciesIdsToJson(results.getUnsafeContingencies())); + // store actions for contingencies + for (String contingencyId : results.getContingenciesWithActions()) { + MVMap storedActionsInfosMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONINFO_MAP_SUFFIX, mapBuilder); + MVMap storedActionsMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONS_MAP_SUFFIX, mapBuilder); + MVMap storedActionsEquipmentsMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONS_EQUIPMENTS_MAP_SUFFIX, mapBuilder); + MVMap storedActionsParametersMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONS_PARAMETERS_MAP_SUFFIX, mapBuilder); + for (Integer stateId : results.getUnsafeStatesWithActions(contingencyId).keySet()) { + storedActionsInfosMap.put(stateId.toString() + STORED_RESULTS_ACTIONINFO_ACTIONSFOUND_KEY_SUFFIX, + Boolean.toString(results.getUnsafeStatesWithActions(contingencyId).get(stateId))); + storedActionsInfosMap.put(stateId.toString() + STORED_RESULTS_ACTIONINFO_STATUS_KEY_SUFFIX, results.getStateStatus(contingencyId, stateId).name()); + if ( results.getCause(contingencyId, stateId) != null ) + storedActionsInfosMap.put(stateId.toString() + STORED_RESULTS_ACTIONINFO_CAUSE_KEY_SUFFIX, results.getCause(contingencyId, stateId)); + if ( results.getActionPlan(contingencyId, stateId) != null ) + storedActionsInfosMap.put(stateId.toString() + STORED_RESULTS_ACTIONINFO_ACTIONPLAN_KEY_SUFFIX, results.getActionPlan(contingencyId, stateId)); + List actionsIds = results.getActionsIds(contingencyId, stateId); + if ( actionsIds != null ) { + for(String actionId : actionsIds) { + List equipmentsIds = results.getEquipmentsIds(contingencyId, stateId, actionId); + storedActionsEquipmentsMap.put(stateId + "_" + actionId, OnlineDbMVStoreUtils.actionsIdsToJson(equipmentsIds)); + for(String equipmentId : equipmentsIds) { + ActionParameters actionParameters = results.getParameters(contingencyId, stateId, actionId, equipmentId); + if ( actionParameters != null ) + storedActionsParametersMap.put(stateId + "_" + actionId + "_" + equipmentId, OnlineDbMVStoreUtils.actionParametersToJson(actionParameters)); + } + } + } else { + actionsIds = new ArrayList(); // I need anyway an empty list, for the getResults to work + } + storedActionsMap.put(stateId.toString(), OnlineDbMVStoreUtils.actionsIdsToJson(actionsIds)); + } + } + // store indexes for contingencies + for (String contingencyId : results.getUnsafeContingencies()) { + MVMap storedIndexesMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_INDEXES_MAP_SUFFIX, mapBuilder); + for (Integer stateId : results.getUnstableStates(contingencyId)) { + Map indexesData = results.getIndexesData(contingencyId, stateId); + storedIndexesMap.put(stateId.toString(), OnlineDbMVStoreUtils.indexesDataToJson(indexesData)); + } + } + wfMVStore.commit(); + } + + private void removeWfResults(String workflowId, MVStore wfMVStore) { + LOGGER.debug("Removing existing wf results for workflow {}", workflowId); + MVMap storedResultsMap = wfMVStore.openMap(STORED_RESULTS_MAP_NAME, mapBuilder); + // remove info about contingencies with action + Collection contingenciesWithAction = OnlineDbMVStoreUtils.jsonToContingenciesIds( + storedResultsMap.get(STORED_RESULTS_CONTINGENCIES_WITH_ACTIONS_KEY)); + for (String contingencyId : contingenciesWithAction) { + MVMap storedActionsMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONS_MAP_SUFFIX, mapBuilder); + wfMVStore.removeMap(storedActionsMap); + } + // remove info about unsafe contingencies + Collection unsafeContingencies = OnlineDbMVStoreUtils.jsonToContingenciesIds( + storedResultsMap.get(STORED_RESULTS_UNSAFE_CONTINGENCIES_KEY)); + for (String contingencyId : unsafeContingencies) { + MVMap storedIndexesMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_INDEXES_MAP_SUFFIX, mapBuilder); + wfMVStore.removeMap(storedIndexesMap); + } + // remove info about stored wf results + wfMVStore.removeMap(storedResultsMap); + // commit removal + wfMVStore.commit(); + } + + @Override + public OnlineWorkflowResults getResults(String workflowId) { + Objects.requireNonNull(workflowId, "workflow id is null"); + LOGGER.info("Getting results of wf {}", workflowId); + if ( isWorkflowStored(workflowId) ) { + MVStore wfMVStore = getStore(workflowId); + if ( wfMVStore.hasMap(STORED_RESULTS_MAP_NAME) ) { + MVMap storedResultsMap = wfMVStore.openMap(STORED_RESULTS_MAP_NAME, mapBuilder); + // create workflow results + OnlineWorkflowResultsImpl wfResults = new OnlineWorkflowResultsImpl( + workflowId, + TimeHorizon.valueOf(storedResultsMap.get(STORED_RESULTS_TIMEHORIZON_KEY))); + // add contingencies with actiions + Collection contingenciesWithAction = OnlineDbMVStoreUtils.jsonToContingenciesIds( + storedResultsMap.get(STORED_RESULTS_CONTINGENCIES_WITH_ACTIONS_KEY)); + for (String contingencyId : contingenciesWithAction) { + MVMap storedActionsMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONS_MAP_SUFFIX, mapBuilder); + MVMap storedActionsInfosMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONINFO_MAP_SUFFIX, mapBuilder); + MVMap storedActionsParametersMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONS_PARAMETERS_MAP_SUFFIX, mapBuilder); + MVMap storedActionsEquipmentsMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_ACTIONS_EQUIPMENTS_MAP_SUFFIX, mapBuilder); + for (String stateId : storedActionsMap.keySet()) { + boolean actionsFound = true; + if ( storedActionsInfosMap.containsKey(stateId + STORED_RESULTS_ACTIONINFO_ACTIONSFOUND_KEY_SUFFIX) ) + actionsFound = Boolean.parseBoolean(storedActionsInfosMap.get(stateId + STORED_RESULTS_ACTIONINFO_ACTIONSFOUND_KEY_SUFFIX)); + CCOFinalStatus status = CCOFinalStatus.MANUAL_CORRECTIVE_ACTION_FOUND; + if ( storedActionsInfosMap.containsKey(stateId + STORED_RESULTS_ACTIONINFO_STATUS_KEY_SUFFIX) ) + status = CCOFinalStatus.valueOf(storedActionsInfosMap.get(stateId + STORED_RESULTS_ACTIONINFO_STATUS_KEY_SUFFIX)); + String cause = storedActionsInfosMap.get(stateId + STORED_RESULTS_ACTIONINFO_CAUSE_KEY_SUFFIX); + String actionPlan = storedActionsInfosMap.get(stateId + STORED_RESULTS_ACTIONINFO_ACTIONPLAN_KEY_SUFFIX); + Map> actions = null; + if ( storedActionsMap.containsKey(stateId) ) { + List actionsIds = OnlineDbMVStoreUtils.jsonToActionsIds(storedActionsMap.get(stateId)); + actions = new HashMap>(); + for(String actionId : actionsIds) { + Map equipments = new HashMap(); + List equipmentsIds = OnlineDbMVStoreUtils.jsonToActionsIds(storedActionsEquipmentsMap.get(stateId + "_" + actionId)); + if ( equipmentsIds != null ) { + for(String equipmentId : equipmentsIds) { + ActionParameters actionParameters = OnlineDbMVStoreUtils.jsonToActionParameters(storedActionsParametersMap.get(stateId + "_" + actionId + "_" + equipmentId)); + equipments.put(equipmentId, actionParameters); + } + } + actions.put(actionId, equipments); + } + } + wfResults.addContingenciesWithActions(contingencyId, Integer.parseInt(stateId), actionsFound, status, cause, actionPlan, actions); + } + } + // add unsafe contingencies + Collection unsafeContingencies = OnlineDbMVStoreUtils.jsonToContingenciesIds( + storedResultsMap.get(STORED_RESULTS_UNSAFE_CONTINGENCIES_KEY)); + for (String contingencyId : unsafeContingencies) { + MVMap storedIndexesMap = wfMVStore.openMap(contingencyId + STORED_RESULTS_INDEXES_MAP_SUFFIX, mapBuilder); + for (String stateId : storedIndexesMap.keySet()) { + Map indexesData = OnlineDbMVStoreUtils.jsonToIndexesData(storedIndexesMap.get(stateId)); + wfResults.addUnsafeContingencies(contingencyId, Integer.parseInt(stateId), indexesData); + } + } + return wfResults; + } else { + LOGGER.warn("No results of wf {} stored in online db", workflowId); + return null; + } + } else { + LOGGER.warn("No data about wf {}", workflowId); + return null; + } + } + + @Override + public void storeRulesResults(String workflowId, OnlineWorkflowRulesResults results) { + Objects.requireNonNull(workflowId, "workflow id is null"); + Objects.requireNonNull(results, "online workflow rules results is null"); + LOGGER.info("Storing results of rules for workflow {}", workflowId); + MVStore wfMVStore = getStore(workflowId); + // check if the results for this wf have already been stored + if ( wfMVStore.hasMap(STORED_RULES_RESULTS_MAP_NAME) ) + removeWfRulesResults(workflowId, wfMVStore); + MVMap storedRulesResultsMap = wfMVStore.openMap(STORED_RULES_RESULTS_MAP_NAME, mapBuilder); + // store time horizon + storedRulesResultsMap.put(STORED_RESULTS_TIMEHORIZON_KEY, results.getTimeHorizon().getName()); + // store contingencies with security rules results + storedRulesResultsMap.put(STORED_RULES_RESULTS_CONTINGENCIES_WITH_RULES_KEY, + OnlineDbMVStoreUtils.contingenciesIdsToJson(results.getContingenciesWithSecurityRulesResults())); + // store rules results for contingencies + for (String contingencyId : results.getContingenciesWithSecurityRulesResults()) { + MVMap storedStateStatusMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_STATUS_MAP_SUFFIX, mapBuilder); + MVMap storedStateResultsMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_RESULTS_MAP_SUFFIX, mapBuilder); + MVMap storedStateAvailableRulesMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_RULES_AVAILABLE_MAP_SUFFIX, mapBuilder); + MVMap storedStateInvalidRulesMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_INVALID_RULES_MAP_SUFFIX, mapBuilder); + for (Integer stateId : results.getStatesWithSecurityRulesResults(contingencyId)) { + // store state status + StateStatus status = results.getStateStatus(contingencyId, stateId); + storedStateStatusMap.put(stateId.toString(), status.name()); + // store state rules results + Map stateResults = results.getStateResults(contingencyId, stateId); + storedStateResultsMap.put(stateId.toString(), OnlineDbMVStoreUtils.indexesDataToJson(stateResults)); + // store state rules available flag + boolean rulesAvalable = results.areValidRulesAvailable(contingencyId, stateId); + storedStateAvailableRulesMap.put(stateId.toString(), Boolean.toString(rulesAvalable)); + // store state invalid rules + List invalidRules = results.getInvalidRules(contingencyId, stateId); + storedStateInvalidRulesMap.put(stateId.toString(), OnlineDbMVStoreUtils.indexesTypesToJson(new HashSet(invalidRules))); + } + } + wfMVStore.commit(); + } + + private void removeWfRulesResults(String workflowId, MVStore wfMVStore) { + LOGGER.debug("Removing existing rules results for workflow {}", workflowId); + MVMap storedRulesResultsMap = wfMVStore.openMap(STORED_RULES_RESULTS_MAP_NAME, mapBuilder); + // remove rules results + Collection rulesContingencies = OnlineDbMVStoreUtils.jsonToContingenciesIds( + storedRulesResultsMap.get(STORED_RULES_RESULTS_CONTINGENCIES_WITH_RULES_KEY)); + for (String contingencyId : rulesContingencies) { + MVMap storedStateStatusMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_STATUS_MAP_SUFFIX, mapBuilder); + wfMVStore.removeMap(storedStateStatusMap); + MVMap storedStateResultsMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_RESULTS_MAP_SUFFIX, mapBuilder); + wfMVStore.removeMap(storedStateResultsMap); + MVMap storedStateAvailableRulesMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_RULES_AVAILABLE_MAP_SUFFIX, mapBuilder); + wfMVStore.removeMap(storedStateAvailableRulesMap); + MVMap storedStateInvalidRulesMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_INVALID_RULES_MAP_SUFFIX, mapBuilder); + wfMVStore.removeMap(storedStateInvalidRulesMap); + } + // remove info about stored rules results + wfMVStore.removeMap(storedRulesResultsMap); + // commit removal + wfMVStore.commit(); + } + + @Override + public OnlineWorkflowRulesResults getRulesResults(String workflowId) { + Objects.requireNonNull(workflowId, "workflow id is null"); + LOGGER.info("Getting rules results of wf {}", workflowId); + if ( isWorkflowStored(workflowId) ) { + MVStore wfMVStore = getStore(workflowId); + if ( wfMVStore.hasMap(STORED_RULES_RESULTS_MAP_NAME) ) { + MVMap storedRulesResultsMap = wfMVStore.openMap(STORED_RULES_RESULTS_MAP_NAME, mapBuilder); + // create workflow rules results + OnlineWorkflowRulesResultsImpl wfRulesResults = new OnlineWorkflowRulesResultsImpl( + workflowId, + TimeHorizon.valueOf(storedRulesResultsMap.get(STORED_RESULTS_TIMEHORIZON_KEY))); + // add contingencies with rules results + Collection contingenciesWithRules = OnlineDbMVStoreUtils.jsonToContingenciesIds( + storedRulesResultsMap.get(STORED_RULES_RESULTS_CONTINGENCIES_WITH_RULES_KEY)); + for (String contingencyId : contingenciesWithRules) { + MVMap storedStateStatusMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_STATUS_MAP_SUFFIX, mapBuilder); + MVMap storedStateResultsMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_RESULTS_MAP_SUFFIX, mapBuilder); + MVMap storedStateAvailableRulesMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_RULES_AVAILABLE_MAP_SUFFIX, mapBuilder); + MVMap storedStateInvalidRulesMap = wfMVStore.openMap(contingencyId + STORED_RULES_RESULTS_STATE_INVALID_RULES_MAP_SUFFIX, mapBuilder); + for (String stateId : storedStateStatusMap.keySet()) { + Map stateResults = OnlineDbMVStoreUtils.jsonToIndexesData(storedStateResultsMap.get(stateId)); + StateStatus stateStatus = StateStatus.valueOf(storedStateStatusMap.get(stateId)); + boolean rulesAvailable = true; + if ( storedStateAvailableRulesMap.containsKey(stateId) ) + rulesAvailable = Boolean.parseBoolean(storedStateAvailableRulesMap.get(stateId)); + List invalidRules = new ArrayList(); + if ( storedStateInvalidRulesMap.containsKey(stateId) ) + invalidRules.addAll(OnlineDbMVStoreUtils.jsonToIndexesTypes(storedStateInvalidRulesMap.get(stateId))); + wfRulesResults.addContingencyWithSecurityRulesResults(contingencyId, Integer.parseInt(stateId), stateStatus, stateResults, + rulesAvailable, invalidRules); + } + } + return wfRulesResults; + } else { + LOGGER.warn("No rules results of wf {} stored in online db", workflowId); + return null; + } + } else { + LOGGER.warn("No data about wf {}", workflowId); + return null; + } + } + + @Override + public void storeWcaResults(String workflowId, OnlineWorkflowWcaResults results) { + Objects.requireNonNull(workflowId, "workflow id is null"); + Objects.requireNonNull(results, "online workflow wca results is null"); + LOGGER.info("Storing results of WCA for workflow {}", workflowId); + MVStore wfMVStore = getStore(workflowId); + // check if the results for this wf have already been stored + if ( wfMVStore.hasMap(STORED_WCA_RESULTS_MAP_NAME) ) + removeWfWcaResults(workflowId, wfMVStore); + MVMap storedWcaResultsMap = wfMVStore.openMap(STORED_WCA_RESULTS_MAP_NAME, mapBuilder); + // store time horizon + storedWcaResultsMap.put(STORED_RESULTS_TIMEHORIZON_KEY, results.getTimeHorizon().getName()); + // store wca results for contingencies + MVMap storedClustersMap = wfMVStore.openMap(STORED_WCA_RESULTS_CLUSTERS_MAP_NAME, mapBuilder); + MVMap storedCausesMap = wfMVStore.openMap(STORED_WCA_RESULTS_CAUSES_MAP_NAME, mapBuilder); + for (String contingencyId : results.getContingencies()) { + storedClustersMap.put(contingencyId, Integer.toString(results.getClusterIndex(contingencyId))); + List causes = results.getCauses(contingencyId); + if (causes != null && causes.size() > 0) + storedCausesMap.put(contingencyId, causes.get(0)); + } + wfMVStore.commit(); + } + + private void removeWfWcaResults(String workflowId, MVStore wfMVStore) { + LOGGER.debug("Removing existing WCA results for workflow {}", workflowId); + MVMap storedWcaResultsMap = wfMVStore.openMap(STORED_WCA_RESULTS_MAP_NAME, mapBuilder); + // remove wca results + MVMap storedClustersMap = wfMVStore.openMap(STORED_WCA_RESULTS_CLUSTERS_MAP_NAME, mapBuilder); + wfMVStore.removeMap(storedClustersMap); + MVMap storedCausesMap = wfMVStore.openMap(STORED_WCA_RESULTS_CAUSES_MAP_NAME, mapBuilder); + wfMVStore.removeMap(storedCausesMap); + // remove info about stored wca results + wfMVStore.removeMap(storedWcaResultsMap); + // commit removal + wfMVStore.commit(); + } + + @Override + public OnlineWorkflowWcaResults getWcaResults(String workflowId) { + Objects.requireNonNull(workflowId, "workflow id is null"); + LOGGER.info("Getting WCA results of wf {}", workflowId); + if ( isWorkflowStored(workflowId) ) { + MVStore wfMVStore = getStore(workflowId); + if ( wfMVStore.hasMap(STORED_WCA_RESULTS_MAP_NAME) ) { + MVMap storedRulesResultsMap = wfMVStore.openMap(STORED_WCA_RESULTS_MAP_NAME, mapBuilder); + // create workflow rules results + OnlineWorkflowWcaResultsImpl wfWcaResults = new OnlineWorkflowWcaResultsImpl( + workflowId, + TimeHorizon.valueOf(storedRulesResultsMap.get(STORED_RESULTS_TIMEHORIZON_KEY))); + // add classification of contingencies in clusters + MVMap storedClustersMap = wfMVStore.openMap(STORED_WCA_RESULTS_CLUSTERS_MAP_NAME, mapBuilder); + MVMap storedCausesMap = wfMVStore.openMap(STORED_WCA_RESULTS_CAUSES_MAP_NAME, mapBuilder); + for(String contingencyId : storedClustersMap.keySet()) { + String cause = storedCausesMap.get(contingencyId); + wfWcaResults.addContingencyWithCluster(contingencyId, + Integer.valueOf(storedClustersMap.get(contingencyId)), + cause != null ? Arrays.asList(cause) : null); + } + return wfWcaResults; + } else { + LOGGER.warn("No WCA results of wf {} stored in online db", workflowId); + return null; + } + } else { + LOGGER.warn("No data about wf {}", workflowId); + return null; + } + } + + + @Override + public void storeWorkflowParameters(String workflowId, OnlineWorkflowParameters parameters) { + Objects.requireNonNull(workflowId, "workflow id is null"); + Objects.requireNonNull(parameters, "online workflow parameters is null"); + LOGGER.info("Storing configuration parameters for workflow {}", workflowId); + MVStore wfMVStore = getStore(workflowId); + // check if the parameters for this wf have already been stored + if ( wfMVStore.hasMap(STORED_PARAMETERS_MAP_NAME) ) + removeWfParameters(workflowId, wfMVStore); + MVMap storedParametersMap = wfMVStore.openMap(STORED_PARAMETERS_MAP_NAME, mapBuilder); + // store basecase + storedParametersMap.put(STORED_PARAMETERS_BASECASE_KEY, parameters.getBaseCaseDate().toString()); + // store number of states + storedParametersMap.put(STORED_PARAMETERS_STATE_NUMBER_KEY, Integer.toString(parameters.getStates())); + // store interval of historical data + storedParametersMap.put(STORED_PARAMETERS_HISTO_INTERVAL_KEY, parameters.getHistoInterval().toString()); + // store offline workflow id + storedParametersMap.put(STORED_PARAMETERS_OFFLINE_WF_ID_KEY, parameters.getOfflineWorkflowId()); + // store time horizon + storedParametersMap.put(STORED_RESULTS_TIMEHORIZON_KEY, parameters.getTimeHorizon().getName()); + // store forecast error analysis id + storedParametersMap.put(STORED_PARAMETERS_FEA_ID_KEY, parameters.getFeAnalysisId()); + // store rules purity threshold + storedParametersMap.put(STORED_PARAMETERS_RULES_PURITY_KEY, Double.toString(parameters.getRulesPurityThreshold())); + // store flag store states + storedParametersMap.put(STORED_PARAMETERS_STORE_STATES_KEY, Boolean.toString(parameters.storeStates())); + // store flag analyse basecase + storedParametersMap.put(STORED_PARAMETERS_ANALYSE_BASECASE_KEY, Boolean.toString(parameters.analyseBasecase())); + // store flag validation + storedParametersMap.put(STORED_PARAMETERS_VALIDATION_KEY, Boolean.toString(parameters.validation())); + // store security indexes + if ( parameters.getSecurityIndexes() != null ) + storedParametersMap.put(STORED_PARAMETERS_SECURITY_INDEXES_KEY, OnlineDbMVStoreUtils.indexesTypesToJson(parameters.getSecurityIndexes())); + // store case type + storedParametersMap.put(STORED_PARAMETERS_CASE_TYPE_KEY, parameters.getCaseType().name()); + // store countries + storedParametersMap.put(STORED_PARAMETERS_COUNTRIES_KEY, OnlineDbMVStoreUtils.countriesToJson(parameters.getCountries())); + // store merge optimized flag + storedParametersMap.put(STORED_PARAMETERS_MERGE_OPTIMIZED_KEY, Boolean.toString(parameters.isMergeOptimized())); + // store merge optimized flag + storedParametersMap.put(STORED_PARAMETERS_LIMIT_REDUCTION_KEY, Float.toString(parameters.getLimitReduction())); + // store handle violations in N flag + storedParametersMap.put(STORED_PARAMETERS_HANDLE_VIOLATIONS_KEY, Boolean.toString(parameters.isHandleViolationsInN())); + // store merge constraint margin + storedParametersMap.put(STORED_PARAMETERS_CONSTRAINT_MARGIN_KEY, Float.toString(parameters.getConstraintMargin())); + + wfMVStore.commit(); + } + + private void removeWfParameters(String workflowId, MVStore wfMVStore) { + LOGGER.debug("Removing existing parameters for workflow {}", workflowId); + MVMap storedParametersMap = wfMVStore.openMap(STORED_PARAMETERS_MAP_NAME, mapBuilder); + // remove parameters + wfMVStore.removeMap(storedParametersMap); + // commit removal + wfMVStore.commit(); + } + + @Override + public OnlineWorkflowParameters getWorkflowParameters(String workflowId) { + Objects.requireNonNull(workflowId, "workflow id is null"); + LOGGER.info("Getting configuration parameters of wf {}", workflowId); + if ( isWorkflowStored(workflowId) ) { + MVStore wfMVStore = getStore(workflowId); + if ( wfMVStore.hasMap(STORED_PARAMETERS_MAP_NAME) ) { + MVMap storedParametersMap = wfMVStore.openMap(STORED_PARAMETERS_MAP_NAME, mapBuilder); + DateTime baseCaseDate = DateTime.parse(storedParametersMap.get(STORED_PARAMETERS_BASECASE_KEY)); + int states = Integer.parseInt(storedParametersMap.get(STORED_PARAMETERS_STATE_NUMBER_KEY)); + String offlineWorkflowId = storedParametersMap.get(STORED_PARAMETERS_OFFLINE_WF_ID_KEY); + TimeHorizon timeHorizon = TimeHorizon.fromName(storedParametersMap.get(STORED_RESULTS_TIMEHORIZON_KEY)); + Interval histoInterval = Interval.parse(storedParametersMap.get(STORED_PARAMETERS_HISTO_INTERVAL_KEY)); + String feAnalysisId = storedParametersMap.get(STORED_PARAMETERS_FEA_ID_KEY); + double rulesPurityThreshold = Double.parseDouble((storedParametersMap.get(STORED_PARAMETERS_RULES_PURITY_KEY) == null) ? "1" : storedParametersMap.get(STORED_PARAMETERS_RULES_PURITY_KEY)); + boolean storeStates = Boolean.parseBoolean(storedParametersMap.get(STORED_PARAMETERS_STORE_STATES_KEY)); + boolean analyseBasecase = Boolean.parseBoolean(storedParametersMap.get(STORED_PARAMETERS_ANALYSE_BASECASE_KEY)); + boolean validation = Boolean.parseBoolean(storedParametersMap.get(STORED_PARAMETERS_VALIDATION_KEY)); + Set securityIndexes = null; + if ( storedParametersMap.containsKey(STORED_PARAMETERS_SECURITY_INDEXES_KEY) ) + securityIndexes = OnlineDbMVStoreUtils.jsonToIndexesTypes(storedParametersMap.get(STORED_PARAMETERS_SECURITY_INDEXES_KEY)); + CaseType caseType = OnlineWorkflowParameters.DEFAULT_CASE_TYPE; + if ( storedParametersMap.containsKey(STORED_PARAMETERS_CASE_TYPE_KEY)) + caseType = CaseType.valueOf(storedParametersMap.get(STORED_PARAMETERS_CASE_TYPE_KEY)); + Set countries = new HashSet(OnlineWorkflowParameters.DEFAULT_COUNTRIES); + if ( storedParametersMap.containsKey(STORED_PARAMETERS_COUNTRIES_KEY)) + countries = OnlineDbMVStoreUtils.jsonToCountries(storedParametersMap.get(STORED_PARAMETERS_COUNTRIES_KEY)); + boolean mergeOptimized = OnlineWorkflowParameters.DAFAULT_MERGE_OPTIMIZED; + if ( storedParametersMap.containsKey(STORED_PARAMETERS_MERGE_OPTIMIZED_KEY)) + mergeOptimized = Boolean.parseBoolean(storedParametersMap.get(STORED_PARAMETERS_MERGE_OPTIMIZED_KEY)); + float limitReduction = OnlineWorkflowParameters.DEFAULT_LIMIT_REDUCTION; + if ( storedParametersMap.containsKey(STORED_PARAMETERS_LIMIT_REDUCTION_KEY)) + limitReduction = Float.parseFloat(storedParametersMap.get(STORED_PARAMETERS_LIMIT_REDUCTION_KEY)); + boolean handleViolations = OnlineWorkflowParameters.DAFAULT_HANDLE_VIOLATIONS_IN_N; + if ( storedParametersMap.containsKey(STORED_PARAMETERS_HANDLE_VIOLATIONS_KEY)) + handleViolations = Boolean.parseBoolean(storedParametersMap.get(STORED_PARAMETERS_HANDLE_VIOLATIONS_KEY)); + float constraintMargin = OnlineWorkflowParameters.DEFAULT_CONSTRAINT_MARGIN; + if ( storedParametersMap.containsKey(STORED_PARAMETERS_CONSTRAINT_MARGIN_KEY)) + constraintMargin = Float.parseFloat(storedParametersMap.get(STORED_PARAMETERS_CONSTRAINT_MARGIN_KEY)); + + return new OnlineWorkflowParameters(baseCaseDate, + states, + histoInterval, + offlineWorkflowId, + timeHorizon, + feAnalysisId, + rulesPurityThreshold, + storeStates, + analyseBasecase, + validation, + securityIndexes, + caseType, + countries, + mergeOptimized, + limitReduction, + handleViolations, + constraintMargin + ); + } else { + LOGGER.warn("No configuration parameters of wf {} stored in online db", workflowId); + return null; + } + } else { + LOGGER.warn("No data about wf {}", workflowId); + return null; + } + } + + @Override + public void storeStatesProcessingStatus(String workflowId, Map statesProcessingStatus) { + Objects.requireNonNull(workflowId, "workflow id is null"); + Objects.requireNonNull(statesProcessingStatus, "online workflow states processing status is null"); + LOGGER.info("Storing states processing status for workflow {}", workflowId); + MVStore wfMVStore = getStore(workflowId); + // check if the states processing status for this wf have already been stored + if ( wfMVStore.hasMap(STORED_STATES_PROCESSING_STATUS_MAP_NAME) ) + removeStatesProcessingStatus(workflowId, wfMVStore); + MVMap statesProcessingStatusMap = wfMVStore.openMap(STORED_STATES_PROCESSING_STATUS_MAP_NAME, mapBuilder); + // store states with processing status + statesProcessingStatusMap.put(STORED_STATES_LIST_KEY, OnlineDbMVStoreUtils.stateIdsToJson(statesProcessingStatus.keySet())); + // store processing status for states + for (Integer stateId : statesProcessingStatus.keySet()) { + MVMap stateProcessingStatusMap = wfMVStore.openMap(stateId.toString() + STORED_STATE_PROCESSING_STATUS_MAP_SUFFIX, mapBuilder); + for (String step : statesProcessingStatus.get(stateId).getStatus().keySet()) { + // store processing status + stateProcessingStatusMap.put(step, statesProcessingStatus.get(stateId).getStatus().get(step)); + } + stateProcessingStatusMap.put(STORED_STATES_STATE_DETAILS_KEY, statesProcessingStatus.get(stateId).getDetail() == null ? "" : statesProcessingStatus.get(stateId).getDetail()); + } + wfMVStore.commit(); + } + + private void removeStatesProcessingStatus(String workflowId, MVStore wfMVStore) { + LOGGER.debug("Removing existing states processing status for workflow {}", workflowId); + MVMap statesProcessingStatusMap = wfMVStore.openMap(STORED_STATES_PROCESSING_STATUS_MAP_NAME, mapBuilder); + // remove processing status for states + Collection stateWithProcessingStatus = OnlineDbMVStoreUtils.jsonToStatesIds(statesProcessingStatusMap.get(STORED_STATES_LIST_KEY)); + for (Integer stateId : stateWithProcessingStatus) { + MVMap stateProcessingStatusMap = wfMVStore.openMap(stateId.toString() + STORED_STATE_PROCESSING_STATUS_MAP_SUFFIX, mapBuilder); + wfMVStore.removeMap(stateProcessingStatusMap); + } + // remove info about states with processing status + wfMVStore.removeMap(statesProcessingStatusMap); + // commit removal + wfMVStore.commit(); + + } + + @Override + public Map getStatesProcessingStatus(String workflowId) { + Objects.requireNonNull(workflowId, "workflow id is null"); + LOGGER.info("Getting states processing status of wf {}", workflowId); + if ( isWorkflowStored(workflowId) ) { + MVStore wfMVStore = getStore(workflowId); + if ( wfMVStore.hasMap(STORED_STATES_PROCESSING_STATUS_MAP_NAME) ) { + MVMap statesProcessingStatusMap = wfMVStore.openMap(STORED_STATES_PROCESSING_STATUS_MAP_NAME, mapBuilder); + // create states processing status + Map statesProcessingStatus = new HashMap(); + // add processing status for states + Collection stateWithProcessingStatus = OnlineDbMVStoreUtils.jsonToStatesIds(statesProcessingStatusMap.get(STORED_STATES_LIST_KEY)); + for (Integer stateId : stateWithProcessingStatus) { + MVMap stateProcessingStatusMap = wfMVStore.openMap(stateId + STORED_STATE_PROCESSING_STATUS_MAP_SUFFIX, mapBuilder); + Map processingStatus = new HashMap(); + for (String step : stateProcessingStatusMap.keySet()) { + if ( !step.equals(STORED_STATES_STATE_DETAILS_KEY) ) + processingStatus.put(step, stateProcessingStatusMap.get(step)); + } + statesProcessingStatus.put(stateId, new StateProcessingStatusImpl(processingStatus, stateProcessingStatusMap.get(STORED_STATES_STATE_DETAILS_KEY))); + } + return statesProcessingStatus; + } else { + LOGGER.warn("No states processing status of wf {} stored in online db", workflowId); + return null; + } + } else { + LOGGER.warn("No data about wf {}", workflowId); + return null; + } + } + + @Override + public void storeState(String workflowId, Integer stateId, Network network) { + String stateIdStr=String.valueOf(stateId); + LOGGER.info("Storing state {} of workflow {}", stateIdStr, workflowId); + if ( network.getStateManager().getStateIds().contains(stateIdStr) ) { + network.getStateManager().setWorkingState(stateIdStr); + Path workflowStatesFolder = getWorkflowStatesFolder(workflowId); + Path stateFolder = Paths.get(workflowStatesFolder.toString(), STORED_STATE_PREFIX + stateId); + if ( Files.exists(stateFolder) ) { + Path stateFile = Paths.get(stateFolder.toString(), network.getId() + ".xml"); + stateFile.toFile().delete(); + } else { + try { + Files.createDirectories(stateFolder); + } catch (IOException e) { + String errorMessage = "online db: folder " + workflowStatesFolder + " for workflow " + workflowId + + " and state " + stateIdStr + " cannot be created: " + e.getMessage(); + LOGGER.error(errorMessage); + throw new RuntimeException(errorMessage); + } + } + DataSource dataSource = new FileDataSource(stateFolder, network.getId()); + Properties parameters = new Properties(); + parameters.setProperty("iidm.export.xml.indent", "true"); + parameters.setProperty("iidm.export.xml.with-branch-state-variables", "true"); + parameters.setProperty("iidm.export.xml.with-breakers", "true"); + parameters.setProperty("iidm.export.xml.with-properties", "true"); + Exporters.export("XML", network, parameters, dataSource); + // store network state values, for later serialization + Map networkValues = IIDM2DB.extractCimValues(network, new IIDM2DB.Config(network.getId(), true, true)).getSingleValueMap(); + ConcurrentHashMap> workflowStates = new ConcurrentHashMap>(); + if ( workflowsStates.containsKey(workflowId) ) + workflowStates = workflowsStates.get(workflowId); + workflowStates.put(stateId, networkValues); + workflowsStates.put(workflowId, workflowStates); + } else { + String errorMessage = "online db: no state " + stateIdStr + " in network of workflow " + workflowId; + LOGGER.error(errorMessage); + throw new RuntimeException(errorMessage); + } + } + + private void serializeStoredWorkflowsStates() { + LOGGER.info("Serializing stored workflows states"); + for(String workflowId : workflowsStates.keySet()) { + if ( workflowStatesFolderExists(workflowId)) { + LOGGER.info("Serializing network data of workflow {}", workflowId); + ConcurrentHashMap> workflowStates = workflowsStates.get(workflowId); + Path workflowStatesFolder = getWorkflowStatesFolder(workflowId); + Path csvFile = Paths.get(workflowStatesFolder.toString(), SERIALIZED_STATES_FILENAME); + try(FileWriter fileWriter = new FileWriter(csvFile.toFile()); + CsvListWriter csvWriter = new CsvListWriter(fileWriter, new CsvPreference.Builder('"', ';', "\r\n").build())) { + boolean printHeaders = true; + for(Integer stateId : workflowStates.keySet()) { + Map networkValues = workflowStates.get(stateId); + if ( printHeaders ) { + List headers = new ArrayList<>(networkValues.size()); + for (HistoDbAttributeId attrId : networkValues.keySet()) { + headers.add(attrId.toString()); + } + ArrayList headersList = new ArrayList<>(); + headersList.add("workflow"); + headersList.add("state"); + headersList.addAll(Arrays.asList(headers.toArray(new String[] {}))); + csvWriter.writeHeader(headersList.toArray(new String[] {})); + printHeaders = false; + } + ArrayList valuesList = new ArrayList<>(); + valuesList.add(workflowId); + valuesList.add(stateId); + valuesList.addAll(Arrays.asList(networkValues.values().toArray())); + csvWriter.write(valuesList.toArray()); + } + } catch (IOException e) { + LOGGER.error("Error serializing network data for workflow {}", workflowId); + } + } + } + } + + @Override + public List listStoredStates(String workflowId) { + LOGGER.info("Getting list of stored states for workflow {}", workflowId); + List storedStates = new ArrayList(); + if ( workflowStatesFolderExists(workflowId)) { + Path workflowStatesFolder = getWorkflowStatesFolder(workflowId); + File[] files = workflowStatesFolder.toFile().listFiles(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.toLowerCase().startsWith(STORED_STATE_PREFIX); + } + }); + for (File file : files) { + if ( file.isDirectory() ) { + String stateId = file.getName().substring(STORED_STATE_PREFIX.length()); + storedStates.add(Integer.parseInt(stateId)); + } + } + Collections.sort(storedStates, new Comparator() { + public int compare(Integer o1, Integer o2) { + return o1.compareTo(o2); + } + }); + LOGGER.info("Found {} state(s) for workflow {}", storedStates.size(), workflowId); + } else { + LOGGER.info("Found no state(s) for workflow {}", workflowId); + } + return storedStates; + } + + @Override + public Network getState(String workflowId, Integer stateId) { + String stateIdStr=String.valueOf(stateId); + LOGGER.info("Getting state {} of workflow {}", stateIdStr, workflowId); + Path workflowStatesFolder = getWorkflowStatesFolder(workflowId); + Path stateFolder = Paths.get(workflowStatesFolder.toString(), STORED_STATE_PREFIX + stateIdStr); + if ( Files.exists(stateFolder) && Files.isDirectory(stateFolder) ) { + if ( stateFolder.toFile().list().length == 1 ) { + File stateFile = stateFolder.toFile().listFiles()[0]; + String stateFileName = stateFile.getName(); + if ( stateFileName.endsWith(".xml")); + String basename = stateFileName.substring(0, stateFileName.length()-4); + DataSource dataSource = new FileDataSource(stateFolder, basename); + //Network network = Importers.import_("XML", dataSource, null); + // with the new post processors configuration, the post processing is applied also to xml import + Importer xmlImporter = Importers.getImporter("XML"); + Importer noppImporter = Importers.removePostProcessors(xmlImporter); + Network network = noppImporter.import_(dataSource, null); + return network; + } + } + return null; + } + + @Override + public void exportState(String workflowId, Integer stateId, Path folder) { + LOGGER.info("Exporting network data of workflow {} and state {} to folder {}", workflowId, stateId, folder); + Network network = getState(workflowId, stateId); + NetworkData networkData = NetworkDataExtractor.extract(network); + NetworkDataExporter.export(networkData, folder); + } + + @Override + public boolean deleteWorkflow(String workflowId) { + LOGGER.info("Deleting workflow {}", workflowId); + boolean workflowDeleted = false; + boolean workflowStatesDeleted = true; + // if stored states for this workflow exist + if ( workflowStatesFolderExists(workflowId) ) + // delete them + workflowStatesDeleted = deleteStates(workflowId); + // if stored states have been deleted + if ( workflowStatesDeleted ) { + // store workflow results + Path workflowFile = Paths.get(config.getOnlineDbDir().toFile().toString(), STORED_WORKFLOW_PREFIX + workflowId); + if ( workflowFile.toFile().exists() && workflowFile.toFile().isFile() ) + try { + workflowDeleted = Files.deleteIfExists(workflowFile); + } catch (IOException e) { + LOGGER.error("Cannot delete workflow {} from online DB: {}", workflowId, e.getMessage()); + } + else + LOGGER.warn("No workflow {} stored in the online DB", workflowId); + } + return workflowDeleted; + } + + + @Override + public boolean deleteStates(String workflowId) { + LOGGER.info("Deleting stored states of workflow {}", workflowId); + boolean workflowStatesDeleted = false; + Path workflowStatesFolder = Paths.get(config.getOnlineDbDir().toFile().toString(), STORED_WORKFLOW_STATES_FOLDER_PREFIX + workflowId); + if ( workflowStatesFolder.toFile().exists() && workflowStatesFolder.toFile().isDirectory() ) + try { + FileUtils.deleteDirectory(workflowStatesFolder.toFile()); + workflowStatesDeleted = true; + } catch (IOException e) { + LOGGER.error("Cannot delete stored states of workflow {} from online DB: ", workflowId, e.getMessage()); + } + else + LOGGER.warn("No states of workflow {} stored in the online DB", workflowId); + return workflowStatesDeleted; + } + + + @Override + public void exportStates(String workflowId, Path file) { + if ( workflowStatesFolderExists(workflowId)) { + LOGGER.info("Exporting states for workflow {}", workflowId); + Path workflowStatesFolder = getWorkflowStatesFolder(workflowId); + Path csvFile = Paths.get(workflowStatesFolder.toString(), SERIALIZED_STATES_FILENAME); + if ( !csvFile.toFile().exists() ) { + LOGGER.info("Serializing network data of workflow {}", workflowId); + try(FileWriter fileWriter = new FileWriter(csvFile.toFile()); + CsvListWriter csvWriter = new CsvListWriter(fileWriter, new CsvPreference.Builder('"', ';', "\r\n").build())) { + boolean printHeaders = true; + for(Integer stateId : listStoredStates(workflowId)) { + Network network = getState(workflowId, stateId); + if ( network != null ) { + Map networkValues = IIDM2DB.extractCimValues(network, new IIDM2DB.Config(network.getId(), true, true)).getSingleValueMap(); + if ( printHeaders ) { + List headers = new ArrayList<>(networkValues.size()); + for (HistoDbAttributeId attrId : networkValues.keySet()) { + headers.add(attrId.toString()); + } + ArrayList headersList = new ArrayList<>(); + headersList.add("workflow"); + headersList.add("state"); + headersList.addAll(Arrays.asList(headers.toArray(new String[] {}))); + csvWriter.writeHeader(headersList.toArray(new String[] {})); + printHeaders = false; + } + ArrayList valuesList = new ArrayList<>(); + valuesList.add(workflowId); + valuesList.add(stateId); + valuesList.addAll(Arrays.asList(networkValues.values().toArray())); + csvWriter.write(valuesList.toArray()); + } + } + } catch (IOException e) { + LOGGER.error("Error serializing network data for workflow {}", workflowId); + } + } + try { + Files.copy(csvFile, file, StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else + LOGGER.error("No stored states for workflow {}", workflowId); + } + + @Override + public void storeViolations(String workflowId, Integer stateId, OnlineStep step, List violations) { + String stateIdStr=String.valueOf(stateId); + LOGGER.info("Storing violations for wf {}, step {} and state {}", workflowId, step.name(), stateIdStr); + storeViolations(workflowId, STORED_VIOLATIONS_MAP_PREFIX + step.name() + "_" + stateIdStr, violations); + LOGGER.info("Storing violations metadata for wf {}, step {} and state {}", workflowId, step.name(), stateIdStr); + storeViolationsMetadata(workflowId, stateIdStr, step, violations); + } + + private void storeViolations(String workflowId, String mapName, List violations) { + try { + MVStore wfMVStore = getStore(workflowId); + Map metricsMap = wfMVStore.openMap(mapName, mapBuilder); + int violationIndex = 0; + for ( LimitViolation limitViolation : violations ) { + String violationId = limitViolation.getSubject().getId() + "_" + violationIndex; + metricsMap.put(violationId, OnlineDbMVStoreUtils.limitViolationToJson(limitViolation)); + violationIndex++; + } + wfMVStore.commit(); + } catch(Throwable e) { + String errorMessage = "Error storing violations for wf " + workflowId + " in map " + mapName + ": " + e.getMessage(); + LOGGER.error(errorMessage); + throw new RuntimeException(errorMessage); + } + } + + private void storeViolationsMetadata(String workflowId, String stateId, OnlineStep step, List violations) { + try { + MVStore wfMVStore = getStore(workflowId); + + // save info about stored wf steps + MVMap storedStepsMap = wfMVStore.openMap(STORED_VIOLATIONS_STEPS_MAP_NAME, mapBuilder); + storedStepsMap.putIfAbsent(step.name(), "1"); + // save info about stored states per step + MVMap stepStateMap = wfMVStore.openMap(step.name() + STORED_VIOLATIONS_STATES_MAP_SUFFIX, mapBuilder); + stepStateMap.putIfAbsent(stateId, ""); + + // save info about stored wf states + MVMap storedStatesMap = wfMVStore.openMap(STORED_VIOLATIONS_STATES_MAP_NAME, mapBuilder); + storedStatesMap.putIfAbsent(stateId, "1"); + // save info about stored steps per state + MVMap stepStepMap = wfMVStore.openMap(stateId + STORED_VIOLATIONS_STEPS_MAP_SUFFIX, mapBuilder); + stepStepMap.putIfAbsent(step.name(), ""); + + wfMVStore.commit(); + } catch(Throwable e) { + String errorMessage = "Error storing violations metadata for wf " + workflowId + ", step "+ step.name() + ", state " + stateId + ": " + e.getMessage(); + LOGGER.error(errorMessage); + throw new RuntimeException(errorMessage); + } + } + + @Override + public List getViolations(String workflowId, Integer stateId, OnlineStep step) { + String stateIdStr=String.valueOf(stateId); + LOGGER.info("Getting violations for wf {}, step {} and state {}", workflowId, step.name(), stateIdStr); + return getStoredViolations(workflowId, STORED_VIOLATIONS_MAP_PREFIX + step.name() + "_" + stateIdStr, null); + } + + private List getStoredViolations(String workflowId, String mapName, Network network) { + if ( isWorkflowStored(workflowId) ) { + MVStore wfMVStore = getStore(workflowId); + if ( wfMVStore.getMapNames().contains(mapName) ) { + if ( network==null ) + // load network: used to get equipment from equipment id, when creating limit violations + network = getState(workflowId, 0); + if ( network!=null ) { + List violations = new ArrayList(); + Map storedMap = wfMVStore.openMap(mapName, mapBuilder); + for ( String violationId : storedMap.keySet() ) { + LimitViolation violation = OnlineDbMVStoreUtils.jsonToLimitViolation(storedMap.get(violationId), network); + if ( violation != null ) + violations.add(violation); + } + return violations; + } else { + LOGGER.warn("No network data (states) stored for wf {}, cannot get violations", workflowId); + return null; + } + } else { + LOGGER.warn("No map {} in wf {}", mapName, workflowId); + return null; + } + } else { + LOGGER.warn("No data about wf {}", workflowId); + return null; + } + } + + @Override + public Map> getViolations(String workflowId, Integer stateId) { + String stateIdStr = Integer.toString(stateId); + LOGGER.info("Getting violations for wf {} and state {}", workflowId, stateIdStr); + if ( isWorkflowStored(workflowId) ) { + MVStore wfMVStore = getStore(workflowId); + // check if there are stored violations + Map storedStatesMap = wfMVStore.openMap(STORED_VIOLATIONS_STATES_MAP_NAME, mapBuilder); + if ( storedStatesMap.containsKey(stateIdStr) ) { + // load network: used to get equipment from equipment id, when creating limit violations + Network network = getState(workflowId, 0); + if ( network!=null ) { + Map> stateViolations = new HashMap>(); + MVMap storedStepsMap = wfMVStore.openMap(stateIdStr + STORED_VIOLATIONS_STEPS_MAP_SUFFIX, mapBuilder); + for ( String stepName : storedStepsMap.keySet() ) { + OnlineStep step = OnlineStep.valueOf(stepName); + List violations = getStoredViolations(workflowId, STORED_VIOLATIONS_MAP_PREFIX + step.name() + "_" + stateId, network); + if ( violations!=null ) + stateViolations.put(step, violations); + } + return stateViolations; + } else { + LOGGER.warn("No network data (states) stored for wf {}, cannot get violations", workflowId); + return null; + } + } else { + LOGGER.warn("No violations for wf {} and state {}", workflowId, stateIdStr); + return null; + } + } else { + LOGGER.warn("No data about wf {}", workflowId); + return null; + } + } + + + @Override + public Map> getViolations(String workflowId, OnlineStep step) { + LOGGER.info("Getting violations for wf {} and step {}", workflowId, step.name()); + if ( isWorkflowStored(workflowId) ) { + MVStore wfMVStore = getStore(workflowId); + // check if there are stored violations + Map storedStepsMap = wfMVStore.openMap(STORED_VIOLATIONS_STEPS_MAP_NAME, mapBuilder); + if ( storedStepsMap.containsKey(step.name()) ) { + // load network: used to get equipment from equipment id, when creating limit violations + Network network = getState(workflowId, 0); + if ( network!=null ) { + Map> stepViolations = new HashMap>(); + MVMap storedStatesMap = wfMVStore.openMap(step.name() + STORED_VIOLATIONS_STATES_MAP_SUFFIX, mapBuilder); + for ( String stateId : storedStatesMap.keySet() ) { + List violations = getStoredViolations(workflowId, STORED_VIOLATIONS_MAP_PREFIX + step.name() + "_" + stateId, network); + if ( violations!=null ) + stepViolations.put(Integer.valueOf(stateId), violations); + } + return stepViolations; + } else { + LOGGER.warn("No network data (states) stored for wf {}, cannot get violations", workflowId); + return null; + } + } else { + LOGGER.warn("No violations for wf {} and step {}", workflowId, step.name()); + return null; + } + } else { + LOGGER.warn("No data for wf {}", workflowId); + return null; + } + } + + @Override + public Map>> getViolations(String workflowId) { + LOGGER.info("Getting violations for wf {}", workflowId); + if ( isWorkflowStored(workflowId) ) { + MVStore wfMVStore = getStore(workflowId); + // check if there are stored violations + Map storedStatesMap = wfMVStore.openMap(STORED_VIOLATIONS_STATES_MAP_NAME, mapBuilder); + if ( !storedStatesMap.isEmpty() ) { + // load network: used to get equipment from equipment id, when creating limit violations + Network network = getState(workflowId, 0); + if ( network!=null ) { + Map>> wfViolations = new HashMap>>(); + for(String stateIdStr : storedStatesMap.keySet()) { + Integer stateId = Integer.parseInt(stateIdStr); + Map> stateViolations = new HashMap>(); + MVMap storedStepsMap = wfMVStore.openMap(stateIdStr + STORED_VIOLATIONS_STEPS_MAP_SUFFIX, mapBuilder); + if ( !storedStepsMap.isEmpty() ) { + for ( String stepName : storedStepsMap.keySet() ) { + OnlineStep step = OnlineStep.valueOf(stepName); + List violations = getStoredViolations(workflowId, STORED_VIOLATIONS_MAP_PREFIX + step.name() + "_" + stateId, network); + if ( violations!=null ) + stateViolations.put(step, violations); + } + wfViolations.put(stateId, stateViolations); + } + } + return wfViolations; + } else { + LOGGER.warn("No network data (states) stored for wf {}, cannot get violations", workflowId); + return null; + } + } else { + LOGGER.warn("No violations for wf {}", workflowId); + return null; + } + } else { + LOGGER.warn("No data for wf {}", workflowId); + return null; + } + } + + @Override + public void storePostContingencyViolations(String workflowId, Integer stateId, String contingencyId, + boolean loadflowConverge, List violations) { + String stateIdStr=String.valueOf(stateId); + LOGGER.info("Storing post contingency violations for wf {}, contingency {} and state {}", workflowId, contingencyId, stateIdStr); + storeViolations(workflowId, STORED_PC_VIOLATIONS_MAP_PREFIX + contingencyId + "_" + stateIdStr, violations); + LOGGER.info("Storing post contingency violations metadata for wf {}, contingency {} and state {}", workflowId, contingencyId, stateIdStr); + storePCViolationsMetadata(workflowId, stateIdStr, contingencyId, violations); + LOGGER.info("Storing post contingency loadflow convergence for wf {}, contingency {} and state {}", workflowId, contingencyId, stateIdStr); + storePSLoadflowConvergence(workflowId, stateIdStr, contingencyId, loadflowConverge); + } + + private synchronized void storePCViolationsMetadata(String workflowId, String stateId, String contingencyId, List violations) { + try { + MVStore wfMVStore = getStore(workflowId); + + // save info about stored wf contingencies + MVMap storedContingenciesMap = wfMVStore.openMap(STORED_PC_VIOLATIONS_CONTINGENCIES_MAP_NAME, mapBuilder); + storedContingenciesMap.putIfAbsent(contingencyId, "1"); + // save info about stored states per contingency + MVMap contingencyStateMap = wfMVStore.openMap(contingencyId + STORED_PC_VIOLATIONS_STATES_MAP_SUFFIX, mapBuilder); + contingencyStateMap.putIfAbsent(stateId, ""); + + // save info about stored wf states + MVMap storedStatesMap = wfMVStore.openMap(STORED_PC_VIOLATIONS_STATES_MAP_NAME, mapBuilder); + storedStatesMap.putIfAbsent(stateId, "1"); + // save info about stored contingencies per state + MVMap stateContingencyMap = wfMVStore.openMap(stateId + STORED_PC_VIOLATIONS_CONTINGENCIES_MAP_SUFFIX, mapBuilder); + LOGGER.info("storePCViolationsMetadata: Adding contingency {} to map {} for workflow {}, state {}", + contingencyId, + stateId + STORED_PC_VIOLATIONS_CONTINGENCIES_MAP_SUFFIX, + workflowId, + stateId + ); + //stateContingencyMap.putIfAbsent(contingencyId, ""); + stateContingencyMap.put(contingencyId, ""); + + wfMVStore.commit(); + } catch(Throwable e) { + String errorMessage = "Error storing pc violations metadata for wf " + workflowId + ", contingency "+ contingencyId + ", state " + stateId + ": " + e.getMessage(); + LOGGER.error(errorMessage); + throw new RuntimeException(errorMessage); + } + } + + private synchronized void storePSLoadflowConvergence(String workflowId, String stateId, String contingencyId, boolean loadflowConverge) { + try { + MVStore wfMVStore = getStore(workflowId); + + // save info about stored wf contingencies + MVMap storedContingenciesMap = wfMVStore.openMap(STORED_PC_LOADFLOW_CONTINGENCIES_MAP_NAME, mapBuilder); + storedContingenciesMap.putIfAbsent(contingencyId, "1"); + // save info about stored states per contingency + MVMap contingencyStateMap = wfMVStore.openMap(contingencyId + STORED_PC_LOADFLOW_STATES_MAP_SUFFIX, mapBuilder); + contingencyStateMap.putIfAbsent(stateId, Boolean.toString(loadflowConverge)); + + // save info about stored wf states + MVMap storedStatesMap = wfMVStore.openMap(STORED_PC_LOADFLOW_STATES_MAP_NAME, mapBuilder); + storedStatesMap.putIfAbsent(stateId, "1"); + // save info about stored contingencies per state + MVMap stateContingencyMap = wfMVStore.openMap(stateId + STORED_PC_LOADFLOW_CONTINGENCIES_MAP_SUFFIX, mapBuilder); + LOGGER.info("storePSLoadflowConvergence: Adding contingency {} to map {} for workflow {}, state {}", + contingencyId, + stateId + STORED_PC_LOADFLOW_CONTINGENCIES_MAP_SUFFIX, + workflowId, + stateId + ); + //stateContingencyMap.putIfAbsent(contingencyId, Boolean.toString(loadflowConverge)); + stateContingencyMap.put(contingencyId, Boolean.toString(loadflowConverge)); + + wfMVStore.commit(); + } catch(Throwable e) { + String errorMessage = "Error storing pc loadflow convergence for wf " + workflowId + ", contingency "+ contingencyId + ", state " + stateId + ": " + e.getMessage(); + LOGGER.error(errorMessage); + throw new RuntimeException(errorMessage); + } + } + + @Override + public List getPostContingencyViolations(String workflowId, Integer stateId, String contingencyId) { + String stateIdStr=String.valueOf(stateId); + LOGGER.info("Getting post contingency violations for wf {}, contingency {} and state {}", workflowId, contingencyId, stateIdStr); + return getStoredViolations(workflowId, STORED_PC_VIOLATIONS_MAP_PREFIX + contingencyId + "_" + stateIdStr, null); + } + + @Override + public Map> getPostContingencyViolations(String workflowId, Integer stateId) { + String stateIdStr = Integer.toString(stateId); + LOGGER.info("Getting post contingency violations for wf {} and state {}", workflowId, stateIdStr); + if ( isWorkflowStored(workflowId) ) { + MVStore wfMVStore = getStore(workflowId); + // check if there are stored violations + Map storedStatesMap = wfMVStore.openMap(STORED_PC_VIOLATIONS_STATES_MAP_NAME, mapBuilder); + if ( storedStatesMap.containsKey(stateIdStr) ) { + // load network: used to get equipment from equipment id, when creating limit violations + Network network = getState(workflowId, 0); + if ( network!=null ) { + Map> stateViolations = new HashMap>(); + MVMap storedContingenciesMap = wfMVStore.openMap(stateIdStr + STORED_PC_VIOLATIONS_CONTINGENCIES_MAP_SUFFIX, mapBuilder); + for ( String contingencyId : storedContingenciesMap.keySet() ) { + List violations = getStoredViolations(workflowId, STORED_PC_VIOLATIONS_MAP_PREFIX + contingencyId + "_" + stateId, network); + if ( violations!=null ) + stateViolations.put(contingencyId, violations); + } + return stateViolations; + } else { + LOGGER.warn("No network data (states) stored for wf {}, cannot get post contingency violations", workflowId); + return null; + } + } else { + LOGGER.warn("No post contingency violations for wf {} and state {}", workflowId, stateIdStr); + return null; + } + } else { + LOGGER.warn("No data about wf {}", workflowId); + return null; + } + } + + @Override + public Map> getPostContingencyViolations(String workflowId, String contingencyId) { + LOGGER.info("Getting post contingency violations for wf {} and contingency {}", workflowId, contingencyId); + if ( isWorkflowStored(workflowId) ) { + MVStore wfMVStore = getStore(workflowId); + // check if there are stored violations + Map storedContingenciesMap = wfMVStore.openMap(STORED_PC_VIOLATIONS_CONTINGENCIES_MAP_NAME, mapBuilder); + if ( storedContingenciesMap.containsKey(contingencyId) ) { + // load network: used to get equipment from equipment id, when creating limit violations + Network network = getState(workflowId, 0); + if ( network!=null ) { + Map> contingencyViolations = new HashMap>(); + MVMap storedStatesMap = wfMVStore.openMap(contingencyId + STORED_PC_VIOLATIONS_STATES_MAP_SUFFIX, mapBuilder); + for ( String stateId : storedStatesMap.keySet() ) { + List violations = getStoredViolations(workflowId, STORED_PC_VIOLATIONS_MAP_PREFIX + contingencyId + "_" + stateId, network); + if ( violations!=null ) + contingencyViolations.put(Integer.valueOf(stateId), violations); + } + return contingencyViolations; + } else { + LOGGER.warn("No network data (states) stored for wf {}, cannot get post contingency violations", workflowId); + return null; + } + } else { + LOGGER.warn("No post contingency violations for wf {} and contingency {}", workflowId, contingencyId); + return null; + } + } else { + LOGGER.warn("No data for wf {}", workflowId); + return null; + } + } + + @Override + public Map>> getPostContingencyViolations(String workflowId) { + LOGGER.info("Getting post contingency violations for wf {}", workflowId); + if ( isWorkflowStored(workflowId) ) { + MVStore wfMVStore = getStore(workflowId); + // check if there are stored violations + Map storedStatesMap = wfMVStore.openMap(STORED_PC_VIOLATIONS_STATES_MAP_NAME, mapBuilder); + if ( !storedStatesMap.isEmpty() ) { + // load network: used to get equipment from equipment id, when creating limit violations + Network network = getState(workflowId, 0); + if ( network!=null ) { + Map>> wfViolations = new HashMap>>(); + for(String stateIdStr : storedStatesMap.keySet()) { + Integer stateId = Integer.parseInt(stateIdStr); + Map> stateViolations = new HashMap>(); + MVMap storedContingenciesMap = wfMVStore.openMap(stateIdStr + STORED_PC_VIOLATIONS_CONTINGENCIES_MAP_SUFFIX, mapBuilder); + if ( !storedContingenciesMap.isEmpty() ) { + for ( String contingencyId : storedContingenciesMap.keySet() ) { + List violations = getStoredViolations(workflowId, STORED_PC_VIOLATIONS_MAP_PREFIX + contingencyId + "_" + stateId, network); + if ( violations!=null ) + stateViolations.put(contingencyId, violations); + } + wfViolations.put(stateId, stateViolations); + } + } + return wfViolations; + } else { + LOGGER.warn("No network data (states) stored for wf {}, cannot get post contingency violations", workflowId); + return null; + } + } else { + LOGGER.warn("No post contingency violations for wf {}", workflowId); + return null; + } + } else { + LOGGER.warn("No data for wf {}", workflowId); + return null; + } + } + + @Override + public Map getPostContingencyLoadflowConvergence(String workflowId, Integer stateId) { + String stateIdStr = Integer.toString(stateId); + if ( isWorkflowStored(workflowId) ) { + Map loadflowConvergence = new HashMap(); + MVStore wfMVStore = getStore(workflowId); + if ( wfMVStore.getMapNames().contains(STORED_PC_LOADFLOW_STATES_MAP_NAME) ) { + Map storedStatesMap = wfMVStore.openMap(STORED_PC_LOADFLOW_STATES_MAP_NAME, mapBuilder); + if ( storedStatesMap.containsKey(stateIdStr)) { + MVMap stateContingencyMap = wfMVStore.openMap(stateIdStr + STORED_PC_LOADFLOW_CONTINGENCIES_MAP_SUFFIX, mapBuilder); + for ( String contingencyId : stateContingencyMap.keySet() ) { + loadflowConvergence.put(contingencyId, Boolean.valueOf(stateContingencyMap.get(contingencyId))); + } + return loadflowConvergence; + } else { + LOGGER.warn("No post contingency loadflow data for state {} in wf {}", stateIdStr, workflowId); + return null; + } + } else { + LOGGER.warn("No post contingency loadflow data in wf {}", workflowId); + return null; + } + } else { + LOGGER.warn("No data about wf {}", workflowId); + return null; + } + } + + @Override + public Map getPostContingencyLoadflowConvergence(String workflowId, String contingencyId) { + if ( isWorkflowStored(workflowId) ) { + Map loadflowConvergence = new HashMap(); + MVStore wfMVStore = getStore(workflowId); + if ( wfMVStore.getMapNames().contains(STORED_PC_LOADFLOW_CONTINGENCIES_MAP_NAME) ) { + Map storedStatesMap = wfMVStore.openMap(STORED_PC_LOADFLOW_CONTINGENCIES_MAP_NAME, mapBuilder); + if ( storedStatesMap.containsKey(contingencyId)) { + MVMap contingencyStateMap = wfMVStore.openMap(contingencyId + STORED_PC_LOADFLOW_STATES_MAP_SUFFIX, mapBuilder); + for ( String stateId : contingencyStateMap.keySet() ) { + loadflowConvergence.put(Integer.valueOf(stateId), Boolean.valueOf(contingencyStateMap.get(stateId))); + } + return loadflowConvergence; + } else { + LOGGER.warn("No post contingency loadflow data for contingency {} in wf {}", contingencyId, workflowId); + return null; + } + } else { + LOGGER.warn("No post contingency loadflow data in wf {}", workflowId); + return null; + } + } else { + LOGGER.warn("No data about wf {}", workflowId); + return null; + } + } + + @Override + public Map> getPostContingencyLoadflowConvergence(String workflowId) { + if ( isWorkflowStored(workflowId) ) { + Map> loadflowConvergence = new HashMap>(); + MVStore wfMVStore = getStore(workflowId); + if ( wfMVStore.getMapNames().contains(STORED_PC_LOADFLOW_STATES_MAP_NAME) ) { + Map storedStatesMap = wfMVStore.openMap(STORED_PC_LOADFLOW_STATES_MAP_NAME, mapBuilder); + for ( String stateId : storedStatesMap.keySet() ) { + MVMap stateContingencyMap = wfMVStore.openMap(stateId + STORED_PC_LOADFLOW_CONTINGENCIES_MAP_SUFFIX, mapBuilder); + HashMap stateLoadflowConvergence = new HashMap(); + for ( String contingencyId : stateContingencyMap.keySet() ) { + stateLoadflowConvergence.put(contingencyId, Boolean.valueOf(stateContingencyMap.get(contingencyId))); + } + loadflowConvergence.put(Integer.valueOf(stateId), stateLoadflowConvergence); + } + return loadflowConvergence; + } else { + LOGGER.warn("No post contingency loadflow data in wf {}", workflowId); + return null; + } + } else { + LOGGER.warn("No data about wf {}", workflowId); + return null; + } + } + + // these wca rules methods are similar to the mcla rules methods: refactoring could be a good idea + @Override + public void storeWcaRulesResults(String workflowId, OnlineWorkflowRulesResults results) { + Objects.requireNonNull(workflowId, "workflow id is null"); + Objects.requireNonNull(results, "online workflow wca rules results is null"); + LOGGER.info("Storing results of wca rules for workflow {}", workflowId); + MVStore wfMVStore = getStore(workflowId); + // check if the results for this wf have already been stored + if ( wfMVStore.hasMap(STORED_WCA_RULES_RESULTS_MAP_NAME) ) + removeWfWcaRulesResults(workflowId, wfMVStore); + MVMap storedRulesResultsMap = wfMVStore.openMap(STORED_WCA_RULES_RESULTS_MAP_NAME, mapBuilder); + // store time horizon + storedRulesResultsMap.put(STORED_RESULTS_TIMEHORIZON_KEY, results.getTimeHorizon().getName()); + // store contingencies with security rules results + storedRulesResultsMap.put(STORED_RULES_RESULTS_CONTINGENCIES_WITH_RULES_KEY, + OnlineDbMVStoreUtils.contingenciesIdsToJson(results.getContingenciesWithSecurityRulesResults())); + // store wca rules results for contingencies + for (String contingencyId : results.getContingenciesWithSecurityRulesResults()) { + MVMap storedStateStatusMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_STATUS_MAP_SUFFIX, mapBuilder); + MVMap storedStateResultsMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_RESULTS_MAP_SUFFIX, mapBuilder); + MVMap storedStateAvailableRulesMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_RULES_AVAILABLE_MAP_SUFFIX, mapBuilder); + MVMap storedStateInvalidRulesMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_INVALID_RULES_MAP_SUFFIX, mapBuilder); + for (Integer stateId : results.getStatesWithSecurityRulesResults(contingencyId)) { + // store state status + StateStatus status = results.getStateStatus(contingencyId, stateId); + storedStateStatusMap.put(stateId.toString(), status.name()); + // store state rules results + Map stateResults = results.getStateResults(contingencyId, stateId); + storedStateResultsMap.put(stateId.toString(), OnlineDbMVStoreUtils.indexesDataToJson(stateResults)); + // store state rules available flag + boolean rulesAvalable = results.areValidRulesAvailable(contingencyId, stateId); + storedStateAvailableRulesMap.put(stateId.toString(), Boolean.toString(rulesAvalable)); + // store state invalid rules + List invalidRules = results.getInvalidRules(contingencyId, stateId); + storedStateInvalidRulesMap.put(stateId.toString(), OnlineDbMVStoreUtils.indexesTypesToJson(new HashSet(invalidRules))); + } + } + wfMVStore.commit(); + } + + private void removeWfWcaRulesResults(String workflowId, MVStore wfMVStore) { + LOGGER.debug("Removing existing wca rules results for workflow {}", workflowId); + MVMap storedRulesResultsMap = wfMVStore.openMap(STORED_WCA_RULES_RESULTS_MAP_NAME, mapBuilder); + // remove rules results + Collection rulesContingencies = OnlineDbMVStoreUtils.jsonToContingenciesIds( + storedRulesResultsMap.get(STORED_RULES_RESULTS_CONTINGENCIES_WITH_RULES_KEY)); + for (String contingencyId : rulesContingencies) { + MVMap storedStateStatusMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_STATUS_MAP_SUFFIX, mapBuilder); + wfMVStore.removeMap(storedStateStatusMap); + MVMap storedStateResultsMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_RESULTS_MAP_SUFFIX, mapBuilder); + wfMVStore.removeMap(storedStateResultsMap); + MVMap storedStateAvailableRulesMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_RULES_AVAILABLE_MAP_SUFFIX, mapBuilder); + wfMVStore.removeMap(storedStateAvailableRulesMap); + MVMap storedStateInvalidRulesMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_INVALID_RULES_MAP_SUFFIX, mapBuilder); + wfMVStore.removeMap(storedStateInvalidRulesMap); + } + // remove info about stored rules results + wfMVStore.removeMap(storedRulesResultsMap); + // commit removal + wfMVStore.commit(); + } + + @Override + public OnlineWorkflowRulesResults getWcaRulesResults(String workflowId) { + Objects.requireNonNull(workflowId, "workflow id is null"); + LOGGER.info("Getting wca rules results of wf {}", workflowId); + if ( isWorkflowStored(workflowId) ) { + MVStore wfMVStore = getStore(workflowId); + if ( wfMVStore.hasMap(STORED_WCA_RULES_RESULTS_MAP_NAME) ) { + MVMap storedRulesResultsMap = wfMVStore.openMap(STORED_WCA_RULES_RESULTS_MAP_NAME, mapBuilder); + // create workflow rules results + OnlineWorkflowRulesResultsImpl wfRulesResults = new OnlineWorkflowRulesResultsImpl( + workflowId, + TimeHorizon.valueOf(storedRulesResultsMap.get(STORED_RESULTS_TIMEHORIZON_KEY))); + // add contingencies with rules results + Collection contingenciesWithRules = OnlineDbMVStoreUtils.jsonToContingenciesIds( + storedRulesResultsMap.get(STORED_RULES_RESULTS_CONTINGENCIES_WITH_RULES_KEY)); + for (String contingencyId : contingenciesWithRules) { + MVMap storedStateStatusMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_STATUS_MAP_SUFFIX, mapBuilder); + MVMap storedStateResultsMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_RESULTS_MAP_SUFFIX, mapBuilder); + MVMap storedStateAvailableRulesMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_RULES_AVAILABLE_MAP_SUFFIX, mapBuilder); + MVMap storedStateInvalidRulesMap = wfMVStore.openMap(contingencyId + STORED_WCA_RULES_RESULTS_STATE_INVALID_RULES_MAP_SUFFIX, mapBuilder); + for (String stateId : storedStateStatusMap.keySet()) { + Map stateResults = OnlineDbMVStoreUtils.jsonToIndexesData(storedStateResultsMap.get(stateId)); + StateStatus stateStatus = StateStatus.valueOf(storedStateStatusMap.get(stateId)); + boolean rulesAvailable = true; + if ( storedStateAvailableRulesMap.containsKey(stateId) ) + rulesAvailable = Boolean.parseBoolean(storedStateAvailableRulesMap.get(stateId)); + List invalidRules = new ArrayList(); + if ( storedStateInvalidRulesMap.containsKey(stateId) ) + invalidRules.addAll(OnlineDbMVStoreUtils.jsonToIndexesTypes(storedStateInvalidRulesMap.get(stateId))); + wfRulesResults.addContingencyWithSecurityRulesResults(contingencyId, Integer.parseInt(stateId), stateStatus, stateResults, + rulesAvailable, invalidRules); + } + } + return wfRulesResults; + } else { + LOGGER.warn("No wca rules results of wf {} stored in online db", workflowId); + return null; + } + } else { + LOGGER.warn("No data about wf {}", workflowId); + return null; + } + } + + @Override + public void close() throws Exception { + closeStores(); + serializeStoredWorkflowsStates(); + } + + private boolean isWorkflowStored(String workflowId) { + Path workflowFile = Paths.get(config.getOnlineDbDir().toString(), STORED_WORKFLOW_PREFIX + workflowId); + return Files.exists(workflowFile); + } + + private boolean workflowStatesFolderExists(String workflowId) { + Path workflowStatesFolder = Paths.get(config.getOnlineDbDir().toString(), STORED_WORKFLOW_STATES_FOLDER_PREFIX + workflowId); + return Files.exists(workflowStatesFolder) && Files.isDirectory(workflowStatesFolder); + } + + private Path getWorkflowStatesFolder(String workflowId) { + Path workflowStatesFolder = Paths.get(config.getOnlineDbDir().toString(), STORED_WORKFLOW_STATES_FOLDER_PREFIX + workflowId); + if ( !workflowStatesFolderExists(workflowId) ) + try { + Files.createDirectories(workflowStatesFolder); + } catch (IOException e) { + String errorMessage = "online db: folder " + workflowStatesFolder + " for workflow " + workflowId + " cannot be created: " + e.getMessage(); + LOGGER.error(errorMessage); + throw new RuntimeException(errorMessage); + } + + return workflowStatesFolder; + } + + /* + * support methods + * to inspect the content of the online db + */ + + public List getStoredMaps(String workflowId) { + Objects.requireNonNull(workflowId, "workflow id is null"); + LOGGER.info("Getting stored maps of wf {}", workflowId); + if ( isWorkflowStored(workflowId) ) { + MVStore wfMVStore = getStore(workflowId); + return new ArrayList(wfMVStore.getMapNames()); + } else { + LOGGER.warn("No data about wf {}", workflowId); + return null; + } + } + + public String exportStoredMapsList(String workflowId) { + Objects.requireNonNull(workflowId, "workflow id is null"); + LOGGER.info("Exporting list of stored maps of wf {}", workflowId); + StringBuffer storedMapList = new StringBuffer(); + List storedMaps = getStoredMaps(workflowId); + if ( storedMaps != null ) { + for (String map : storedMaps) { + storedMapList.append(map + "\n"); + } + } + return storedMapList.toString(); + } + + public String exportStoredMapContent(String workflowId, String mapName) { + Objects.requireNonNull(workflowId, "workflow id is null"); + Objects.requireNonNull(mapName, "map name id is null"); + LOGGER.info("Exporting content of stored map {} of wf {}", mapName, workflowId); + if ( isWorkflowStored(workflowId) ) { + MVStore wfMVStore = getStore(workflowId); + if ( wfMVStore.hasMap(mapName) ) { + StringBuffer storedMapContent = new StringBuffer(); + storedMapContent.append("Map " + mapName + "\n"); + MVMap storedMap = wfMVStore.openMap(mapName, mapBuilder); + for (String key : storedMap.keySet()) { + storedMapContent.append(key + " = " + storedMap.get(key) + "\n"); + } + return storedMapContent.toString(); + } else { + LOGGER.warn("No {} map in wf {}", mapName, workflowId); + return null; + } + } else { + LOGGER.warn("No data about wf {}", workflowId); + return null; + } + } + + public String exportStoredMapsContent(String workflowId) { + Objects.requireNonNull(workflowId, "workflow id is null"); + LOGGER.info("Exporting content of stored maps of wf {}", workflowId); + StringBuffer storedMapList = new StringBuffer(); + List storedMaps = getStoredMaps(workflowId); + if ( storedMaps != null ) { + for (String map : storedMaps) { + storedMapList.append(exportStoredMapContent(workflowId, map) + "\n"); + } + } + return storedMapList.toString(); + } } diff --git a/online-workflow/src/main/java/eu/itesla_project/online/db/OnlineWorkflowRulesResultsImpl.java b/online-workflow/src/main/java/eu/itesla_project/online/db/OnlineWorkflowRulesResultsImpl.java index 2e7a8561..c2eb5b82 100644 --- a/online-workflow/src/main/java/eu/itesla_project/online/db/OnlineWorkflowRulesResultsImpl.java +++ b/online-workflow/src/main/java/eu/itesla_project/online/db/OnlineWorkflowRulesResultsImpl.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) + * Copyright (c) 2016, 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/. @@ -15,75 +16,112 @@ import eu.itesla_project.modules.online.OnlineWorkflowRulesResults; import eu.itesla_project.modules.online.StateStatus; import eu.itesla_project.modules.online.TimeHorizon; +import eu.itesla_project.modules.securityindexes.SecurityIndexType; /** * * @author Quinary */ class OnlineWorkflowRulesResultsImpl implements OnlineWorkflowRulesResults { - - // the id of the workflow where the rules have been applied - private final String workflowId; - // the time horizon used for the workflow where the rules have been applied - private final TimeHorizon timeHorizon; - // > - private Map>> contingenciesWithRulesResults = new HashMap>>(); - // - private Map> contingenciesWithRulesStatus = new HashMap>(); - - OnlineWorkflowRulesResultsImpl(String workflowId, TimeHorizon timeHorizon) { - this.workflowId = workflowId; - this.timeHorizon = timeHorizon; - } - - @Override - public String getWorkflowId() { - return workflowId; - } - - @Override - public TimeHorizon getTimeHorizon() { - return timeHorizon; - } - - @Override - public Collection getContingenciesWithSecurityRulesResults() { - return contingenciesWithRulesResults.keySet(); - } - - @Override - public List getStatesWithSecurityRulesResults(String contingencyId) { - List statesWithRulesResults = new ArrayList(); - statesWithRulesResults.addAll(contingenciesWithRulesResults.get(contingencyId).keySet()); - return statesWithRulesResults; - } - - @Override - public StateStatus getStateStatus(String contingencyId, Integer stateId) { - return contingenciesWithRulesStatus.get(contingencyId).get(stateId); - } - - @Override - public Map getStateResults(String contingencyId, Integer stateId) { - return contingenciesWithRulesResults.get(contingencyId).get(stateId); - } - - void addContingencyWithSecurityRulesResults(String contingencyId, Integer stateId, StateStatus stateStatus, - Map stateResults) { - // save state results - Map> statesWithRulesResults = new HashMap>(); - if ( contingenciesWithRulesResults.containsKey(contingencyId) ) { - statesWithRulesResults = contingenciesWithRulesResults.get(contingencyId); - } - statesWithRulesResults.put(stateId, stateResults); - contingenciesWithRulesResults.put(contingencyId, statesWithRulesResults); - // save state status - Map statesWithRulesStatus = new HashMap(); - if ( contingenciesWithRulesStatus.containsKey(contingencyId) ) { - statesWithRulesStatus = contingenciesWithRulesStatus.get(contingencyId); - } - statesWithRulesStatus.put(stateId, stateStatus); - contingenciesWithRulesStatus.put(contingencyId, statesWithRulesStatus); - } + + // the id of the workflow where the rules have been applied + private final String workflowId; + // the time horizon used for the workflow where the rules have been applied + private final TimeHorizon timeHorizon; + // > + private Map>> contingenciesWithRulesResults = new HashMap>>(); + // + private Map> contingenciesWithRulesStatus = new HashMap>(); + // contingencies, map of + private Map> contingenciesWithRules = new HashMap>(); + // contingencies, map of + private Map>> contingenciesWithInvalidRules = new HashMap>>(); + + + OnlineWorkflowRulesResultsImpl(String workflowId, TimeHorizon timeHorizon) { + this.workflowId = workflowId; + this.timeHorizon = timeHorizon; + } + + @Override + public String getWorkflowId() { + return workflowId; + } + + @Override + public TimeHorizon getTimeHorizon() { + return timeHorizon; + } + + @Override + public Collection getContingenciesWithSecurityRulesResults() { + return contingenciesWithRulesResults.keySet(); + } + + @Override + public List getStatesWithSecurityRulesResults(String contingencyId) { + List statesWithRulesResults = new ArrayList(); + statesWithRulesResults.addAll(contingenciesWithRulesResults.get(contingencyId).keySet()); + return statesWithRulesResults; + } + + @Override + public StateStatus getStateStatus(String contingencyId, Integer stateId) { + return contingenciesWithRulesStatus.get(contingencyId).get(stateId); + } + + @Override + public Map getStateResults(String contingencyId, Integer stateId) { + return contingenciesWithRulesResults.get(contingencyId).get(stateId); + } + + void addContingencyWithSecurityRulesResults(String contingencyId, Integer stateId, StateStatus stateStatus, Map stateResults, + boolean rulesAvailable, List invalidRules) { + // save state results + Map> statesWithRulesResults = new HashMap>(); + if ( contingenciesWithRulesResults.containsKey(contingencyId) ) { + statesWithRulesResults = contingenciesWithRulesResults.get(contingencyId); + } + statesWithRulesResults.put(stateId, stateResults); + contingenciesWithRulesResults.put(contingencyId, statesWithRulesResults); + + // save state status + Map statesWithRulesStatus = new HashMap(); + if ( contingenciesWithRulesStatus.containsKey(contingencyId) ) { + statesWithRulesStatus = contingenciesWithRulesStatus.get(contingencyId); + } + statesWithRulesStatus.put(stateId, stateStatus); + contingenciesWithRulesStatus.put(contingencyId, statesWithRulesStatus); + + Map statesWithRules = new HashMap(); + if ( contingenciesWithRules.containsKey(contingencyId) ) { + statesWithRules = contingenciesWithRules.get(contingencyId); + } + statesWithRules.put(stateId, rulesAvailable); + contingenciesWithRules.put(contingencyId, statesWithRules); + + Map> statesWithInvalidRules = new HashMap>(); + if ( contingenciesWithInvalidRules.containsKey(contingencyId) ) { + statesWithInvalidRules = contingenciesWithInvalidRules.get(contingencyId); + } + statesWithInvalidRules.put(stateId, invalidRules); + contingenciesWithInvalidRules.put(contingencyId, statesWithInvalidRules); + } + + @Override + public boolean areValidRulesAvailable(String contingencyId, Integer stateId) { + boolean rulesAvailable = false; + if ( contingenciesWithRules.containsKey(contingencyId) && contingenciesWithRules.get(contingencyId).containsKey(stateId) ) + rulesAvailable = contingenciesWithRules.get(contingencyId).get(stateId); + return rulesAvailable; + } + + @Override + public List getInvalidRules(String contingencyId, Integer stateId) { + List invalidRules = new ArrayList(); + if ( contingenciesWithInvalidRules.containsKey(contingencyId) && contingenciesWithInvalidRules.get(contingencyId).containsKey(stateId) ) + invalidRules = contingenciesWithInvalidRules.get(contingencyId).get(stateId); + return invalidRules; + } } diff --git a/online-workflow/src/main/java/eu/itesla_project/online/modules/mock/RulesFacadeMock.java b/online-workflow/src/main/java/eu/itesla_project/online/modules/mock/RulesFacadeMock.java index 5ed73dc9..d2dd5c85 100644 --- a/online-workflow/src/main/java/eu/itesla_project/online/modules/mock/RulesFacadeMock.java +++ b/online-workflow/src/main/java/eu/itesla_project/online/modules/mock/RulesFacadeMock.java @@ -6,10 +6,13 @@ */ package eu.itesla_project.online.modules.mock; +import java.util.ArrayList; import java.util.EnumMap; import java.util.Map; import java.util.Objects; +import eu.itesla_project.commons.io.ModuleConfig; +import eu.itesla_project.commons.io.PlatformConfig; import eu.itesla_project.iidm.network.Network; import eu.itesla_project.modules.contingencies.Contingency; import eu.itesla_project.modules.online.OnlineRulesFacade; @@ -19,40 +22,52 @@ import eu.itesla_project.modules.securityindexes.SecurityIndexType; /** -* -* @author Quinary -*/ + * + * @author Quinary + */ public class RulesFacadeMock implements OnlineRulesFacade { - RulesFacadeParameters parameters; - - @Override - public void init(RulesFacadeParameters parameters) throws Exception { - this.parameters = parameters; - } - - @Override - public RulesFacadeResults evaluate(Contingency contingency, Network network) { - Objects.requireNonNull(contingency, "contingency is null"); - Objects.requireNonNull(network, "network is null"); - return getMockResults(contingency, network); - } - - @Override - public RulesFacadeResults wcaEvaluate(Contingency contingency, Network network) { - Objects.requireNonNull(contingency, "contingency is null"); - Objects.requireNonNull(network, "network is null"); - return getMockResults(contingency, network); - } - - private RulesFacadeResults getMockResults(Contingency contingency, Network network) { - Map indexesResults = new EnumMap<>(SecurityIndexType.class); - SecurityIndexType[] securityIndexTypes = parameters.getSecurityIndexTypes() == null ? SecurityIndexType.values() + RulesFacadeParameters parameters; + SecurityIndexType[] securityIndexTypes; + StateStatus rulesResults = StateStatus.SAFE; + + @Override + public void init(RulesFacadeParameters parameters) throws Exception { + this.parameters = parameters; + securityIndexTypes = parameters.getSecurityIndexTypes() == null ? SecurityIndexType.values() : parameters.getSecurityIndexTypes().toArray(new SecurityIndexType[parameters.getSecurityIndexTypes().size()]); - for (SecurityIndexType indexType : securityIndexTypes) { - indexesResults.put(indexType, StateStatus.SAFE); - } - return new RulesFacadeResults(network.getStateManager().getWorkingStateId(), contingency.getId(), StateStatus.SAFE, indexesResults); - } + readConfig(); + } + + @Override + public RulesFacadeResults evaluate(Contingency contingency, Network network) { + Objects.requireNonNull(contingency, "contingency is null"); + Objects.requireNonNull(network, "network is null"); + return getMockResults(contingency, network); + } + + @Override + public RulesFacadeResults wcaEvaluate(Contingency contingency, Network network) { + Objects.requireNonNull(contingency, "contingency is null"); + Objects.requireNonNull(network, "network is null"); + return getMockResults(contingency, network); + } + + private RulesFacadeResults getMockResults(Contingency contingency, Network network) { + Map indexesResults = new EnumMap<>(SecurityIndexType.class); + for (SecurityIndexType indexType : securityIndexTypes) { + StateStatus ruleResults = (rulesResults == StateStatus.SAFE) ? StateStatus.SAFE : StateStatus.UNSAFE; + indexesResults.put(indexType, ruleResults); + } + return new RulesFacadeResults(network.getStateManager().getWorkingStateId(), contingency.getId(), rulesResults, indexesResults, + new ArrayList<>(), true); + } + + private void readConfig() { + if (PlatformConfig.defaultConfig().moduleExists("rulesFacadeMock")) { + ModuleConfig config = PlatformConfig.defaultConfig().getModuleConfig("rulesFacadeMock"); + rulesResults = config.getEnumProperty("rulesResults", StateStatus.class, StateStatus.SAFE); + } + } } diff --git a/online-workflow/src/main/java/eu/itesla_project/online/security_rules/ContingencyEvaluator.java b/online-workflow/src/main/java/eu/itesla_project/online/security_rules/ContingencyEvaluator.java index 3b595a50..3a693d75 100644 --- a/online-workflow/src/main/java/eu/itesla_project/online/security_rules/ContingencyEvaluator.java +++ b/online-workflow/src/main/java/eu/itesla_project/online/security_rules/ContingencyEvaluator.java @@ -7,6 +7,16 @@ */ package eu.itesla_project.online.security_rules; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import eu.itesla_project.iidm.network.Network; import eu.itesla_project.modules.contingencies.Contingency; import eu.itesla_project.modules.histo.HistoDbAttributeId; @@ -16,97 +26,118 @@ import eu.itesla_project.modules.rules.SecurityRule; import eu.itesla_project.modules.securityindexes.SecurityIndexType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.*; - /** * * @author Quinary */ public class ContingencyEvaluator { - private static final Logger LOGGER = LoggerFactory.getLogger(ContingencyEvaluator.class); - - private final Contingency contingency; - private final List mcRules; - private final double purityThreshold; - private List wcaRules = new ArrayList(); - - public ContingencyEvaluator(Contingency contingency, List mcRules, double purityThreshold) { - Objects.requireNonNull(contingency, "contingency is null"); - Objects.requireNonNull(mcRules, "mc rules is null"); - this.contingency = contingency; - this.mcRules = mcRules; - this.purityThreshold = purityThreshold; - } - - public ContingencyEvaluator(Contingency contingency, List mcRules, List wcaRules, double purityThreshold) { - Objects.requireNonNull(contingency, "contingency is null"); - Objects.requireNonNull(mcRules, "mc rules is null"); - Objects.requireNonNull(wcaRules, "wca rules is null"); - this.contingency = contingency; - this.mcRules = mcRules; - this.wcaRules = wcaRules; - this.purityThreshold = purityThreshold; - } - - public Contingency getContingency() { - return contingency; - } - - public RulesFacadeResults evaluate(Network network) { - return evaluate(network, mcRules); - } - - public RulesFacadeResults evaluate(String networkId, String stateId, Map networkValues) { - return evaluate(networkId, stateId, networkValues, mcRules); - } - - public RulesFacadeResults wcaEvaluate(Network network) { - return evaluate(network, wcaRules); - } - - public RulesFacadeResults wcaEvaluate(String networkId, String stateId, Map networkValues) { - return evaluate(networkId, stateId, networkValues, wcaRules); - } - - private RulesFacadeResults evaluate(Network network, List rules) { - Objects.requireNonNull(network, "network is null"); - HashMap networkValues = IIDM2DB.extractCimValues(network, new IIDM2DB.Config(null, true)).getSingleValueMap(); - return evaluate(network.getId(), network.getStateManager().getWorkingStateId(), networkValues, rules); - } - - private RulesFacadeResults evaluate(String networkId, String stateId, Map networkValues, List rules) { - Objects.requireNonNull(networkValues, "networkValues is null"); - LOGGER.info("Evaluating {} network, {} state, {} contingency", networkId, stateId, contingency.getId()); - StateStatus stateStatus = StateStatus.SAFE; - boolean staticIndexUnsafe = false; - boolean dynamicIndexUnsafe = false; - Map indexesResults = new EnumMap<>(SecurityIndexType.class); - for (SecurityRule rule : rules) { - boolean safe = rule.toExpression(purityThreshold).check(networkValues).isSafe(); - LOGGER.debug("{}: Result on {} network, {} state, {} contingency, {} index: safe = {}", - rule.getId(), networkId, stateId, contingency.getId(), rule.getId().getSecurityIndexId().getSecurityIndexType(), safe); - if ( safe ) { - indexesResults.put(rule.getId().getSecurityIndexId().getSecurityIndexType(), StateStatus.SAFE); - } else { // one index unsafe -> state-contingency unsafe - indexesResults.put(rule.getId().getSecurityIndexId().getSecurityIndexType(), StateStatus.UNSAFE); + private static final Logger LOGGER = LoggerFactory.getLogger(ContingencyEvaluator.class); + + private final Contingency contingency; + private final List mcRules; + private final double purityThreshold; + private List wcaRules = new ArrayList(); + private Map> mcViolatedEquipment = new HashMap<>(); + private Map> wcaViolatedEquipment = new HashMap<>(); + private final boolean checkRules; + private List bacecaseInvalidMcRulesIndexes = new ArrayList(); + private List bacecaseInvalidWcaRulesIndexes = new ArrayList(); + + public ContingencyEvaluator(Contingency contingency, List mcRules, double purityThreshold, Map> mcViolatedEquipment, boolean checkRules) { + Objects.requireNonNull(contingency, "contingency is null"); + Objects.requireNonNull(mcRules, "mc rules is null"); + this.contingency = contingency; + this.mcRules = mcRules; + this.purityThreshold = purityThreshold; + this.mcViolatedEquipment = mcViolatedEquipment; + this.checkRules = checkRules; + } + + public ContingencyEvaluator(Contingency contingency, List mcRules, List wcaRules, double purityThreshold, + Map> mcViolatedEquipment, Map> wcaViolatedEquipment, + boolean checkRules) { + Objects.requireNonNull(contingency, "contingency is null"); + Objects.requireNonNull(mcRules, "mc rules is null"); + Objects.requireNonNull(wcaRules, "wca rules is null"); + this.contingency = contingency; + this.mcRules = mcRules; + this.wcaRules = wcaRules; + this.purityThreshold = purityThreshold; + this.mcViolatedEquipment = mcViolatedEquipment; + this.wcaViolatedEquipment = wcaViolatedEquipment; + this.checkRules = checkRules; + } + + public Contingency getContingency() { + return contingency; + } + + public RulesFacadeResults evaluate(Network network) { + return evaluate(network, mcRules, bacecaseInvalidMcRulesIndexes); + } + + public RulesFacadeResults evaluate(String networkId, String stateId, Map networkValues) { + return evaluate(networkId, stateId, networkValues, mcRules, bacecaseInvalidMcRulesIndexes); + } + + public RulesFacadeResults wcaEvaluate(Network network) { + return evaluate(network, wcaRules, bacecaseInvalidWcaRulesIndexes); + } + + public RulesFacadeResults wcaEvaluate(String networkId, String stateId, Map networkValues) { + return evaluate(networkId, stateId, networkValues, wcaRules, bacecaseInvalidWcaRulesIndexes); + } + + private RulesFacadeResults evaluate(Network network, List rules, List bacecaseInvalidRulesIndexes) { + Objects.requireNonNull(network, "network is null"); + HashMap networkValues = IIDM2DB.extractCimValues(network, new IIDM2DB.Config(null, true)).getSingleValueMap(); + return evaluate(network.getId(), network.getStateManager().getWorkingStateId(), networkValues, rules, bacecaseInvalidRulesIndexes); + } + + private RulesFacadeResults evaluate(String networkId, String stateId, Map networkValues, List rules, + List bacecaseInvalidRulesIndexes) { + Objects.requireNonNull(networkValues, "networkValues is null"); + LOGGER.info("Evaluating {} network, {} state, {} contingency", networkId, stateId, contingency.getId()); + StateStatus stateStatus = StateStatus.SAFE; + List invalidRulesIndexes = new ArrayList(); + boolean staticIndexUnsafe = false; + boolean dynamicIndexUnsafe = false; + if ( checkRules ) { + checkRules(rules, invalidRulesIndexes, bacecaseInvalidRulesIndexes); + if ( "0".equals(stateId) ) + bacecaseInvalidRulesIndexes = invalidRulesIndexes; // keep for samples evaluation -> rules invalid on basecase are invalid for all samples + } + Map indexesResults = new EnumMap<>(SecurityIndexType.class); + for (SecurityRule rule : rules) { + boolean safe = rule.toExpression(purityThreshold).check(networkValues).isSafe(); + LOGGER.debug("{}: Result on {} network, {} state, {} contingency, {} index: safe = {}", + rule.getId(), networkId, stateId, contingency.getId(), rule.getId().getSecurityIndexId().getSecurityIndexType(), safe); + if ( safe ) { + indexesResults.put(rule.getId().getSecurityIndexId().getSecurityIndexType(), StateStatus.SAFE); + } else { // one index unsafe -> state-contingency unsafe + indexesResults.put(rule.getId().getSecurityIndexId().getSecurityIndexType(), StateStatus.UNSAFE); if (rule.getId().getSecurityIndexId().getSecurityIndexType().isDynamic()) { dynamicIndexUnsafe = true; } else { staticIndexUnsafe = true; } - } - } - if (dynamicIndexUnsafe) { // at least one dynamic index unsafe -> status unsafe - stateStatus = StateStatus.UNSAFE; + } + } + if (dynamicIndexUnsafe) { // at least one dynamic index unsafe -> status unsafe + stateStatus = StateStatus.UNSAFE; } else if (staticIndexUnsafe) { // all dynamic indexes safe, at least one static index unsafe -> status safe with corrective action - stateStatus = StateStatus.SAFE_WITH_CORRECTIVE_ACTIONS; + stateStatus = StateStatus.SAFE_WITH_CORRECTIVE_ACTIONS; } - LOGGER.info("Result on {} network, {} state, {} contingency: {}", networkId, stateId, contingency.getId(), stateStatus); - return new RulesFacadeResults(stateId, contingency.getId(), stateStatus, indexesResults); - } + LOGGER.info("Result on {} network, {} state, {} contingency: {}", networkId, stateId, contingency.getId(), stateStatus); + return new RulesFacadeResults(stateId, contingency.getId(), stateStatus, indexesResults, invalidRulesIndexes, !rules.isEmpty()); + } + + private void checkRules(List rules, List invalidRulesIndexes, + List bacecaseInvalidRulesIndexes) { + // TODO: check if the rules are still valid, using the violations + // and keeping into account the rules invalid on basecase + } } diff --git a/online-workflow/src/main/java/eu/itesla_project/online/security_rules/SecurityRulesFacade.java b/online-workflow/src/main/java/eu/itesla_project/online/security_rules/SecurityRulesFacade.java index 7a04d16e..97332043 100644 --- a/online-workflow/src/main/java/eu/itesla_project/online/security_rules/SecurityRulesFacade.java +++ b/online-workflow/src/main/java/eu/itesla_project/online/security_rules/SecurityRulesFacade.java @@ -32,59 +32,64 @@ */ public class SecurityRulesFacade implements OnlineRulesFacade { - private static final Logger LOGGER = LoggerFactory.getLogger(SecurityRulesFacade.class); + private static final Logger LOGGER = LoggerFactory.getLogger(SecurityRulesFacade.class); - private final RulesDbClient rulesDbClient; + private final RulesDbClient rulesDbClient; - private final Map evaluators = new HashMap<>(); + private final Map evaluators = new HashMap<>(); - public SecurityRulesFacade(RulesDbClient rulesDbClient) { - this.rulesDbClient = rulesDbClient; - } + public SecurityRulesFacade(RulesDbClient rulesDbClient) { + this.rulesDbClient = rulesDbClient; + } - @Override - public void init(RulesFacadeParameters parameters) throws Exception { - Objects.requireNonNull(parameters, "parameters is null"); + @Override + public void init(RulesFacadeParameters parameters) throws Exception { + Objects.requireNonNull(parameters, "parameters is null"); // preload security rules - SecurityIndexType[] securityIndexTypes = parameters.getSecurityIndexTypes() == null ? SecurityIndexType.values() + SecurityIndexType[] securityIndexTypes = parameters.getSecurityIndexTypes() == null ? SecurityIndexType.values() : parameters.getSecurityIndexTypes().toArray(new SecurityIndexType[parameters.getSecurityIndexTypes().size()]); for (Contingency contingency : parameters.getContingencies()) { List mcRules = new ArrayList<>(); // rules for the current contingency List wcaRules = new ArrayList<>(); // wca rules for the current contingency + Map> mcViolatedEquipmentForContingency = new HashMap<>(); + Map> wcaViolatedEquipmentForContingency = new HashMap<>(); for (SecurityIndexType securityIndexType :securityIndexTypes) { LOGGER.info("Getting mc security rule for {} contingency and {} index", contingency.getId(), securityIndexType); mcRules.addAll(rulesDbClient.getRules(parameters.getOfflineWorkflowId(), RuleAttributeSet.MONTE_CARLO, contingency.getId(), securityIndexType)); + mcViolatedEquipmentForContingency.put(securityIndexType, new ArrayList()); // so far we do not have the violated components for a rule/index if ( parameters.wcaRules() ) { // get wca rules for validation - LOGGER.info("Getting wca security rule for {} contingency and {} index", contingency.getId(), securityIndexType); - wcaRules.addAll(rulesDbClient.getRules(parameters.getOfflineWorkflowId(), RuleAttributeSet.WORST_CASE, contingency.getId(), securityIndexType)); + LOGGER.info("Getting wca security rule for {} contingency and {} index", contingency.getId(), securityIndexType); + wcaRules.addAll(rulesDbClient.getRules(parameters.getOfflineWorkflowId(), RuleAttributeSet.WORST_CASE, contingency.getId(), securityIndexType)); + wcaViolatedEquipmentForContingency.put(securityIndexType, new ArrayList()); // so far we do not have the violated components for a rule/index } } if ( parameters.wcaRules() ) // store wca rules for validation - evaluators.put(contingency.getId(), new ContingencyEvaluator(contingency, mcRules, wcaRules, parameters.getPurityThreshold())); + evaluators.put(contingency.getId(), new ContingencyEvaluator(contingency, mcRules, wcaRules, parameters.getPurityThreshold(), + mcViolatedEquipmentForContingency, wcaViolatedEquipmentForContingency, + parameters.isCheckRules())); else - evaluators.put(contingency.getId(), new ContingencyEvaluator(contingency, mcRules, parameters.getPurityThreshold())); + evaluators.put(contingency.getId(), new ContingencyEvaluator(contingency, mcRules, parameters.getPurityThreshold(), + mcViolatedEquipmentForContingency, parameters.isCheckRules())); } - } + } - public ContingencyEvaluator getContingencyEvaluator(Contingency contingency) { - Objects.requireNonNull(contingency, "contingency is null"); + public ContingencyEvaluator getContingencyEvaluator(Contingency contingency) { + Objects.requireNonNull(contingency, "contingency is null"); ContingencyEvaluator evaluator = evaluators.get(contingency.getId()); if (evaluator == null) { throw new RuntimeException("Security rules for contingency {} has not been preloaded"); } return evaluator; - } - - @Override - public RulesFacadeResults evaluate(Contingency contingency, Network network) { - return getContingencyEvaluator(contingency).evaluate(network); - } - - @Override - public RulesFacadeResults wcaEvaluate(Contingency contingency, Network network) { - return getContingencyEvaluator(contingency).wcaEvaluate(network); - } + } + @Override + public RulesFacadeResults evaluate(Contingency contingency, Network network) { + return getContingencyEvaluator(contingency).evaluate(network); + } + @Override + public RulesFacadeResults wcaEvaluate(Contingency contingency, Network network) { + return getContingencyEvaluator(contingency).wcaEvaluate(network); + } } diff --git a/online-workflow/src/main/java/eu/itesla_project/online/tools/ListOnlineWorkflowsTool.java b/online-workflow/src/main/java/eu/itesla_project/online/tools/ListOnlineWorkflowsTool.java index 7c48efcd..94a3848e 100644 --- a/online-workflow/src/main/java/eu/itesla_project/online/tools/ListOnlineWorkflowsTool.java +++ b/online-workflow/src/main/java/eu/itesla_project/online/tools/ListOnlineWorkflowsTool.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) + * Copyright (c) 2016, 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/. @@ -32,131 +33,137 @@ */ @AutoService(Tool.class) public class ListOnlineWorkflowsTool implements Tool { - - private static Command COMMAND = new Command() { - - @Override - public String getName() { - return "list-online-workflows"; - } - @Override - public String getTheme() { - return Themes.ONLINE_WORKFLOW; - } + private static Command COMMAND = new Command() { - @Override - public String getDescription() { - return "list stored online workflows"; - } + @Override + public String getName() { + return "list-online-workflows"; + } - @Override - public Options getOptions() { - Options options = new Options(); - options.addOption(Option.builder().longOpt("basecase") - .desc("Base case") - .hasArg() - .argName("BASECASE") - .build()); - options.addOption(Option.builder().longOpt("basecases-interval") - .desc("Base cases interval") - .hasArg() - .argName("INTERVAL") - .build()); - options.addOption(Option.builder().longOpt("parameters") - .desc("print the workflow parameters") - .build()); - return options; - } + @Override + public String getTheme() { + return Themes.ONLINE_WORKFLOW; + } - @Override - public String getUsageFooter() { - return null; - } - - }; + @Override + public String getDescription() { + return "list stored online workflows"; + } - @Override - public Command getCommand() { - return COMMAND; - } + @Override + public Options getOptions() { + Options options = new Options(); + options.addOption(Option.builder().longOpt("basecase") + .desc("Base case") + .hasArg() + .argName("BASECASE") + .build()); + options.addOption(Option.builder().longOpt("basecases-interval") + .desc("Base cases interval") + .hasArg() + .argName("INTERVAL") + .build()); + options.addOption(Option.builder().longOpt("parameters") + .desc("print the workflow parameters") + .build()); + return options; + } - @Override - public void run(CommandLine line) throws Exception { - OnlineConfig config = OnlineConfig.load(); - OnlineDb onlinedb = config.getOnlineDbFactoryClass().newInstance().create(); - List workflows = null; - if ( line.hasOption("basecase") ) { - DateTime basecaseDate = DateTime.parse(line.getOptionValue("basecase")); - workflows = onlinedb.listWorkflows(basecaseDate); - } else if ( line.hasOption("basecases-interval") ) { - Interval basecasesInterval = Interval.parse(line.getOptionValue("basecases-interval")); - workflows = onlinedb.listWorkflows(basecasesInterval); - } else - workflows = onlinedb.listWorkflows(); - boolean printParameters = line.hasOption("parameters"); - DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"); - Table table = new Table(2, BorderStyle.CLASSIC_WIDE); - if ( printParameters ) - table = new Table(3, BorderStyle.CLASSIC_WIDE); + @Override + public String getUsageFooter() { + return null; + } + + }; + + @Override + public Command getCommand() { + return COMMAND; + } + + @Override + public void run(CommandLine line) throws Exception { + OnlineConfig config = OnlineConfig.load(); + OnlineDb onlinedb = config.getOnlineDbFactoryClass().newInstance().create(); + List workflows = null; + if ( line.hasOption("basecase") ) { + DateTime basecaseDate = DateTime.parse(line.getOptionValue("basecase")); + workflows = onlinedb.listWorkflows(basecaseDate); + } else if ( line.hasOption("basecases-interval") ) { + Interval basecasesInterval = Interval.parse(line.getOptionValue("basecases-interval")); + workflows = onlinedb.listWorkflows(basecasesInterval); + } else + workflows = onlinedb.listWorkflows(); + boolean printParameters = line.hasOption("parameters"); + DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"); + Table table = new Table(2, BorderStyle.CLASSIC_WIDE); + if ( printParameters ) + table = new Table(3, BorderStyle.CLASSIC_WIDE); table.addCell("ID", new CellStyle(CellStyle.HorizontalAlign.center)); table.addCell("Date", new CellStyle(CellStyle.HorizontalAlign.center)); if ( printParameters ) - table.addCell("Parameters", new CellStyle(CellStyle.HorizontalAlign.center)); + table.addCell("Parameters", new CellStyle(CellStyle.HorizontalAlign.center)); for (OnlineWorkflowDetails workflow : workflows) { table.addCell(workflow.getWorkflowId()); table.addCell(formatter.print(workflow.getWorkflowDate())); if ( printParameters ) { - OnlineWorkflowParameters parameters = onlinedb.getWorkflowParameters(workflow.getWorkflowId()); - if ( parameters != null ) { - table.addCell("Basecase = "+parameters.getBaseCaseDate().toString()); - table.addCell(" "); - table.addCell(" "); - table.addCell("Time Horizon = "+parameters.getTimeHorizon().getName()); - table.addCell(" "); - table.addCell(" "); - table.addCell("FE Analysis Id = "+parameters.getFeAnalysisId()); - table.addCell(" "); - table.addCell(" "); - table.addCell("Offline Workflow Id = "+parameters.getOfflineWorkflowId()); - table.addCell(" "); - table.addCell(" "); - table.addCell("Historical Interval = "+parameters.getHistoInterval().toString()); - table.addCell(" "); - table.addCell(" "); - table.addCell("States = "+Integer.toString(parameters.getStates())); - table.addCell(" "); - table.addCell(" "); - table.addCell("Rules Purity Threshold = "+Double.toString(parameters.getRulesPurityThreshold())); - table.addCell(" "); - table.addCell(" "); - table.addCell("Store States = "+Boolean.toString(parameters.storeStates())); - table.addCell(" "); - table.addCell(" "); - table.addCell("Analyse Basecase = "+Boolean.toString(parameters.analyseBasecase())); - table.addCell(" "); - table.addCell(" "); - table.addCell("Validation = "+Boolean.toString(parameters.validation())); - table.addCell(" "); - table.addCell(" "); - String securityRulesString = parameters.getSecurityIndexes()==null ? "ALL" : parameters.getSecurityIndexes().toString(); - table.addCell("Security Rules = "+securityRulesString); - table.addCell(" "); - table.addCell(" "); - table.addCell("Case Type = "+parameters.getCaseType()); - table.addCell(" "); - table.addCell(" "); - table.addCell("Countries = "+parameters.getCountries().toString()); - table.addCell(" "); - table.addCell(" "); - table.addCell("Limits Reduction = "+Float.toString(parameters.getLimitReduction())); - } else { - table.addCell("-"); - } + OnlineWorkflowParameters parameters = onlinedb.getWorkflowParameters(workflow.getWorkflowId()); + if ( parameters != null ) { + table.addCell("Basecase = "+parameters.getBaseCaseDate().toString()); + table.addCell(" "); + table.addCell(" "); + table.addCell("Time Horizon = "+parameters.getTimeHorizon().getName()); + table.addCell(" "); + table.addCell(" "); + table.addCell("FE Analysis Id = "+parameters.getFeAnalysisId()); + table.addCell(" "); + table.addCell(" "); + table.addCell("Offline Workflow Id = "+parameters.getOfflineWorkflowId()); + table.addCell(" "); + table.addCell(" "); + table.addCell("Historical Interval = "+parameters.getHistoInterval().toString()); + table.addCell(" "); + table.addCell(" "); + table.addCell("States = "+Integer.toString(parameters.getStates())); + table.addCell(" "); + table.addCell(" "); + table.addCell("Rules Purity Threshold = "+Double.toString(parameters.getRulesPurityThreshold())); + table.addCell(" "); + table.addCell(" "); + table.addCell("Store States = "+Boolean.toString(parameters.storeStates())); + table.addCell(" "); + table.addCell(" "); + table.addCell("Analyse Basecase = "+Boolean.toString(parameters.analyseBasecase())); + table.addCell(" "); + table.addCell(" "); + table.addCell("Validation = "+Boolean.toString(parameters.validation())); + table.addCell(" "); + table.addCell(" "); + String securityRulesString = parameters.getSecurityIndexes()==null ? "ALL" : parameters.getSecurityIndexes().toString(); + table.addCell("Security Rules = "+securityRulesString); + table.addCell(" "); + table.addCell(" "); + table.addCell("Case Type = "+parameters.getCaseType()); + table.addCell(" "); + table.addCell(" "); + table.addCell("Countries = "+parameters.getCountries().toString()); + table.addCell(" "); + table.addCell(" "); + table.addCell("Limits Reduction = "+Float.toString(parameters.getLimitReduction())); + table.addCell(" "); + table.addCell(" "); + table.addCell("Handle Violations in N = "+Boolean.toString(parameters.isHandleViolationsInN())); + table.addCell(" "); + table.addCell(" "); + table.addCell("Constrain Margin = "+Float.toString(parameters.getConstraintMargin())); + } else { + table.addCell("-"); + } } } System.out.println(table.render()); onlinedb.close(); - } + } } diff --git a/online-workflow/src/main/java/eu/itesla_project/online/tools/OnlineWorkflowCommand.java b/online-workflow/src/main/java/eu/itesla_project/online/tools/OnlineWorkflowCommand.java index 9619da85..9ae0bb42 100644 --- a/online-workflow/src/main/java/eu/itesla_project/online/tools/OnlineWorkflowCommand.java +++ b/online-workflow/src/main/java/eu/itesla_project/online/tools/OnlineWorkflowCommand.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) + * Copyright (c) 2016, 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/. @@ -16,204 +17,192 @@ * @author Quinary */ public class OnlineWorkflowCommand implements Command { - - public static final OnlineWorkflowCommand INSTANCE =new OnlineWorkflowCommand(); - - public static final String HOST="host"; - public static final String PORT="port"; - public static final String START_CMD="start-workflow"; - public static final String SHUTDOWN_CMD="shutdown"; - public static final String BASE_CASE="base-case"; - public static final String TIME_HORIZON = "time-horizon"; - public static final String STATES = "states"; - public static final String WORKFLOW_ID = "workflow"; - public static final String HISTODB_INTERVAL = "histodb-interval"; - public static final String THREADS = "threads"; - public static final String FEANALYSIS_ID ="fe-analysis-id"; - public static final String RULES_PURITY ="rules-purity"; - public static final String STORE_STATES ="store-states"; - public static final String ANALYSE_BASECASE ="analyse-basecase"; - public static final String VALIDATION ="validation"; - public static final String SECURITY_INDEXES ="security-indexes"; - public static final String BASECASES_INTERVAL = "basecases-interval"; - public static final String CASE_TYPE = "case-type"; - public static final String COUNTRIES = "countries"; - public static final String MERGE_OPTIMIZED = "merge-optimized"; - public static final String LIMIT_REDUCTION = "limits-reduction"; - - @Override - public String getName() { - return "online-workflow-control"; - } - - @Override - public String getTheme() { - return Themes.ONLINE_WORKFLOW; - } - - @Override - public String getDescription() { - return "Online workflow application control"; - } - - @Override - public Options getOptions() { - Options opts = new Options(); - - OptionGroup og = new OptionGroup(); - og.setRequired(true); - - og.addOption(Option.builder().longOpt(START_CMD) - .desc("start new online workflow") - .build()); - og.addOption(Option.builder().longOpt(SHUTDOWN_CMD) - .desc("shutdown online workflow application") - .build()); - opts.addOptionGroup(og); - - - opts.addOption(Option.builder().longOpt(HOST) - .desc("jmx host") - .hasArg() - .argName("HOST") - .build()); - opts.addOption(Option.builder().longOpt(PORT) - .desc("jmx port") - .hasArg() - .argName("PORT") - .build()); - - - - - opts.addOption(Option.builder().longOpt(BASE_CASE) + + public static final OnlineWorkflowCommand INSTANCE =new OnlineWorkflowCommand(); + + public static final String HOST="host"; + public static final String PORT="port"; + public static final String START_CMD="start-workflow"; + public static final String SHUTDOWN_CMD="shutdown"; + public static final String BASE_CASE="base-case"; + public static final String TIME_HORIZON = "time-horizon"; + public static final String STATES = "states"; + public static final String WORKFLOW_ID = "workflow"; + public static final String HISTODB_INTERVAL = "histodb-interval"; + public static final String THREADS = "threads"; + public static final String FEANALYSIS_ID ="fe-analysis-id"; + public static final String RULES_PURITY ="rules-purity"; + public static final String STORE_STATES ="store-states"; + public static final String ANALYSE_BASECASE ="analyse-basecase"; + public static final String VALIDATION ="validation"; + public static final String SECURITY_INDEXES ="security-indexes"; + public static final String BASECASES_INTERVAL = "basecases-interval"; + public static final String CASE_TYPE = "case-type"; + public static final String COUNTRIES = "countries"; + public static final String MERGE_OPTIMIZED = "merge-optimized"; + public static final String LIMIT_REDUCTION = "limits-reduction"; + public static final String HANDLE_VIOLATION_IN_N = "handle-violations"; + public static final String CONSTRAINT_MARGIN = "constraint-margin"; + + @Override + public String getName() { + return "online-workflow-control"; + } + + @Override + public String getTheme() { + return Themes.ONLINE_WORKFLOW; + } + + @Override + public String getDescription() { + return "Online workflow application control"; + } + + @Override + public Options getOptions() { + Options opts = new Options(); + + OptionGroup og = new OptionGroup(); + og.setRequired(true); + + og.addOption(Option.builder().longOpt(START_CMD) + .desc("start new online workflow") + .build()); + + og.addOption(Option.builder().longOpt(SHUTDOWN_CMD) + .desc("shutdown online workflow application") + .build()); + opts.addOptionGroup(og); + + opts.addOption(Option.builder().longOpt(HOST) + .desc("jmx host") + .hasArg() + .argName("HOST") + .build()); + opts.addOption(Option.builder().longOpt(PORT) + .desc("jmx port") + .hasArg() + .argName("PORT") + .build()); + + opts.addOption(Option.builder().longOpt(BASE_CASE) .desc("Base case") - .hasArg() - .argName(BASE_CASE) + .hasArg() + .argName(BASE_CASE) .build()); - - opts.addOption(Option.builder().longOpt(TIME_HORIZON) + + opts.addOption(Option.builder().longOpt(TIME_HORIZON) .desc("time horizon for the online analysis") - .hasArg() - .argName(TIME_HORIZON) + .hasArg() + .argName(TIME_HORIZON) .build()); - - opts.addOption(Option.builder().longOpt(BASE_CASE) + + opts.addOption(Option.builder().longOpt(BASE_CASE) .desc("Basecase to be analyzed") - .hasArg() - .argName(BASE_CASE) + .hasArg() + .argName(BASE_CASE) .build()); - - opts.addOption(Option.builder().longOpt(STATES) + + opts.addOption(Option.builder().longOpt(STATES) .desc("States number") - .hasArg() - .argName(STATES) + .hasArg() + .argName(STATES) .build()); - - opts.addOption(Option.builder().longOpt(WORKFLOW_ID) + + opts.addOption(Option.builder().longOpt(WORKFLOW_ID) .desc("offline workflow id that produced the security rules") - .hasArg() - .argName(WORKFLOW_ID) + .hasArg() + .argName(WORKFLOW_ID) .build()); - - opts.addOption(Option.builder().longOpt(HISTODB_INTERVAL) + + opts.addOption(Option.builder().longOpt(HISTODB_INTERVAL) .desc("interval of historical data to be used for WCA") - .hasArg() - .argName(HISTODB_INTERVAL) + .hasArg() + .argName(HISTODB_INTERVAL) .build()); - - opts.addOption(Option.builder().longOpt(THREADS) + + opts.addOption(Option.builder().longOpt(THREADS) .desc("Executing threads number") - .hasArg() - .argName(THREADS) + .hasArg() + .argName(THREADS) .build()); - - opts.addOption(Option.builder().longOpt(FEANALYSIS_ID) + + opts.addOption(Option.builder().longOpt(FEANALYSIS_ID) .desc("id of the forecast error analysis") - .hasArg() - .argName(FEANALYSIS_ID) + .hasArg() + .argName(FEANALYSIS_ID) .build()); - - opts.addOption(Option.builder().longOpt(RULES_PURITY) + + opts.addOption(Option.builder().longOpt(RULES_PURITY) .desc("purity threshold for the security rules") - .hasArg() - .argName(RULES_PURITY) + .hasArg() + .argName(RULES_PURITY) .build()); - - opts.addOption(Option.builder().longOpt(STORE_STATES) + + opts.addOption(Option.builder().longOpt(STORE_STATES) .desc("store states") .build()); - - opts.addOption(Option.builder().longOpt(ANALYSE_BASECASE) + + opts.addOption(Option.builder().longOpt(ANALYSE_BASECASE) .desc("analyse basecase") .build()); - - opts.addOption(Option.builder().longOpt(VALIDATION) + + opts.addOption(Option.builder().longOpt(VALIDATION) .desc("validation") .build()); - - opts.addOption(Option.builder().longOpt(SECURITY_INDEXES) + + opts.addOption(Option.builder().longOpt(SECURITY_INDEXES) .desc("sub list of security index types to use, use ALL for using all of them") .hasArg() .argName("INDEX_TYPE,INDEX_TYPE,...") .build()); - opts.addOption(Option.builder().longOpt(BASECASES_INTERVAL) - .desc("interval for basecases to be considered; when set, overrides base-case parameter") - .hasArg() - .argName(BASECASES_INTERVAL) - .build()); - - opts.addOption(Option.builder().longOpt(CASE_TYPE) - .desc("the type (FO/SN) of the base case") - .hasArg() - .argName(CASE_TYPE) - .build()); - - opts.addOption(Option.builder().longOpt(COUNTRIES) - .desc("the countries of the base case, separated by comma") - .hasArg() - .argName("COUNTRY,COUNTRY,...") - .build()); - - opts.addOption(Option.builder().longOpt(MERGE_OPTIMIZED) - .desc("merge optimized") - .build()); - - - opts.addOption(Option.builder().longOpt(LIMIT_REDUCTION) + opts.addOption(Option.builder().longOpt(BASECASES_INTERVAL) + .desc("interval for basecases to be considered; when set, overrides base-case parameter") + .hasArg() + .argName(BASECASES_INTERVAL) + .build()); + + opts.addOption(Option.builder().longOpt(CASE_TYPE) + .desc("the type (FO/SN) of the base case") + .hasArg() + .argName(CASE_TYPE) + .build()); + + opts.addOption(Option.builder().longOpt(COUNTRIES) + .desc("the countries of the base case, separated by comma") + .hasArg() + .argName("COUNTRY,COUNTRY,...") + .build()); + + opts.addOption(Option.builder().longOpt(MERGE_OPTIMIZED) + .desc("merge optimized") + .build()); + + opts.addOption(Option.builder().longOpt(LIMIT_REDUCTION) .desc("limits reduction") - .hasArg() - .argName(LIMIT_REDUCTION) - .build()); - - /* - Option opt = new Option("host",true,": jmx host"); - opt.setRequired(true); - opts.addOption(opt); - - opt = new Option("port",true,": jmx port"); - opt.setRequired(true); - opts.addOption(opt); - - OptionGroup og = new OptionGroup(); - og.setRequired(true); - - opt = new Option("startWorkflow",false,": start new online workflow"); - opt.setRequired(false); - og.addOption(opt); - opt = new Option("shutdown",false,": shutdown online workflow application"); - opt.setRequired(false); - og.addOption(opt); - opts.addOptionGroup(og); - */ - return opts; - } - - @Override - public String getUsageFooter() { - - return null; - } + .hasArg() + .argName(LIMIT_REDUCTION) + .build()); + + opts.addOption(Option.builder().longOpt(HANDLE_VIOLATION_IN_N) + .desc("handle violation in n") + .build()); + + opts.addOption(Option.builder().longOpt(CONSTRAINT_MARGIN) + .desc("constraint margin") + .hasArg() + .argName(CONSTRAINT_MARGIN) + .build()); + + return opts; + } + + @Override + public String getUsageFooter() { + + return null; + } } diff --git a/online-workflow/src/main/java/eu/itesla_project/online/tools/OnlineWorkflowTool.java b/online-workflow/src/main/java/eu/itesla_project/online/tools/OnlineWorkflowTool.java index 76322a58..112b0aa7 100644 --- a/online-workflow/src/main/java/eu/itesla_project/online/tools/OnlineWorkflowTool.java +++ b/online-workflow/src/main/java/eu/itesla_project/online/tools/OnlineWorkflowTool.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) + * Copyright (c) 2016, 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/. @@ -39,141 +40,145 @@ @AutoService(Tool.class) public class OnlineWorkflowTool implements Tool { - @Override - public Command getCommand() { - return OnlineWorkflowCommand.INSTANCE; - } - - @Override - public void run(CommandLine line) throws Exception { - - OnlineWorkflowStartParameters startconfig=OnlineWorkflowStartParameters.loadDefault(); - - String host=line.getOptionValue(OnlineWorkflowCommand.HOST); - String port=line.getOptionValue(OnlineWorkflowCommand.PORT); - String threads=line.getOptionValue(OnlineWorkflowCommand.THREADS); - if(host!=null) - startconfig.setJmxHost(host); - if(port!=null) - startconfig.setJmxPort(port); - if(threads!=null) - startconfig.setThreads(Integer.valueOf(threads)); - - OnlineWorkflowParameters params=OnlineWorkflowParameters.loadDefault(); - + @Override + public Command getCommand() { + return OnlineWorkflowCommand.INSTANCE; + } + + @Override + public void run(CommandLine line) throws Exception { + + OnlineWorkflowStartParameters startconfig=OnlineWorkflowStartParameters.loadDefault(); + + String host=line.getOptionValue(OnlineWorkflowCommand.HOST); + String port=line.getOptionValue(OnlineWorkflowCommand.PORT); + String threads=line.getOptionValue(OnlineWorkflowCommand.THREADS); + if(host!=null) + startconfig.setJmxHost(host); + if(port!=null) + startconfig.setJmxPort(port); + if(threads!=null) + startconfig.setThreads(Integer.valueOf(threads)); + + OnlineWorkflowParameters params=OnlineWorkflowParameters.loadDefault(); + if(line.hasOption(OnlineWorkflowCommand.CASE_TYPE)) - params.setCaseType(CaseType.valueOf(line.getOptionValue(OnlineWorkflowCommand.CASE_TYPE))); - + params.setCaseType(CaseType.valueOf(line.getOptionValue(OnlineWorkflowCommand.CASE_TYPE))); + Set countries = null; if (line.hasOption(OnlineWorkflowCommand.COUNTRIES)) { - countries = Arrays.stream(line.getOptionValue(OnlineWorkflowCommand.COUNTRIES).split(",")) + countries = Arrays.stream(line.getOptionValue(OnlineWorkflowCommand.COUNTRIES).split(",")) .map(Country::valueOf) .collect(Collectors.toSet()); params.setCountries(countries);; } - - Set baseCasesSet=null; - if(line.hasOption(OnlineWorkflowCommand.BASECASES_INTERVAL)) { - Interval basecasesInterval=Interval.parse(line.getOptionValue(OnlineWorkflowCommand.BASECASES_INTERVAL)); - OnlineConfig oConfig=OnlineConfig.load(); - CaseRepository caseRepo=oConfig.getCaseRepositoryFactoryClass().newInstance().create(new LocalComputationManager()); - baseCasesSet=caseRepo.dataAvailable(params.getCaseType(), params.getCountries(), basecasesInterval); - System.out.println("Base cases available for interval " + basecasesInterval.toString() ); - baseCasesSet.forEach(x -> { - System.out.println(" " + x); - }); - } - -// String base=line.getOptionValue(OnlineWorkflowCommand.BASE_CASE); -// if(base!=null) -// params.setBaseCaseDate(DateTime.parse(base)); - - if (baseCasesSet==null) { - baseCasesSet=new HashSet(); - String base=line.getOptionValue(OnlineWorkflowCommand.BASE_CASE); - if (base!=null) { - baseCasesSet.add(DateTime.parse(base)); - } else { - baseCasesSet.add(params.getBaseCaseDate()); - } - } - - String histo=line.getOptionValue(OnlineWorkflowCommand.HISTODB_INTERVAL); - if(histo!=null) - params.setHistoInterval(Interval.parse(histo)); - - String states=line.getOptionValue(OnlineWorkflowCommand.STATES); - if(states!=null) - params.setStates(Integer.parseInt(states)); - - String timeHorizon=line.getOptionValue(OnlineWorkflowCommand.TIME_HORIZON); - if(timeHorizon!=null) - params.setTimeHorizon(TimeHorizon.fromName(timeHorizon)); - - String workflowid = line.getOptionValue(OnlineWorkflowCommand.WORKFLOW_ID); - if(workflowid!=null) - params.setOfflineWorkflowId(workflowid); - - String feAnalysisId = line.getOptionValue(OnlineWorkflowCommand.FEANALYSIS_ID); - if(feAnalysisId!=null) - params.setFeAnalysisId(feAnalysisId); - - String rulesPurity=line.getOptionValue(OnlineWorkflowCommand.RULES_PURITY); - if(rulesPurity!=null) - params.setRulesPurityThreshold(Double.parseDouble(rulesPurity)); - - if(line.hasOption(OnlineWorkflowCommand.STORE_STATES)) - params.setStoreStates(true); - - if(line.hasOption(OnlineWorkflowCommand.ANALYSE_BASECASE)) - params.setAnalyseBasecase(true); - - if(line.hasOption(OnlineWorkflowCommand.VALIDATION)) { - params.setValidation(true); - params.setStoreStates(true); // if validation then store states - params.setAnalyseBasecase(true); // if validation then analyze base case - } - - Set securityIndexes = null; + + Set baseCasesSet=null; + if(line.hasOption(OnlineWorkflowCommand.BASECASES_INTERVAL)) { + Interval basecasesInterval=Interval.parse(line.getOptionValue(OnlineWorkflowCommand.BASECASES_INTERVAL)); + OnlineConfig oConfig=OnlineConfig.load(); + CaseRepository caseRepo=oConfig.getCaseRepositoryFactoryClass().newInstance().create(new LocalComputationManager()); + baseCasesSet=caseRepo.dataAvailable(params.getCaseType(), params.getCountries(), basecasesInterval); + System.out.println("Base cases available for interval " + basecasesInterval.toString() ); + baseCasesSet.forEach(x -> { + System.out.println(" " + x); + }); + } + + if (baseCasesSet==null) { + baseCasesSet=new HashSet(); + String base=line.getOptionValue(OnlineWorkflowCommand.BASE_CASE); + if (base!=null) { + baseCasesSet.add(DateTime.parse(base)); + } else { + baseCasesSet.add(params.getBaseCaseDate()); + } + } + + String histo=line.getOptionValue(OnlineWorkflowCommand.HISTODB_INTERVAL); + if(histo!=null) + params.setHistoInterval(Interval.parse(histo)); + + String states=line.getOptionValue(OnlineWorkflowCommand.STATES); + if(states!=null) + params.setStates(Integer.parseInt(states)); + + String timeHorizon=line.getOptionValue(OnlineWorkflowCommand.TIME_HORIZON); + if(timeHorizon!=null) + params.setTimeHorizon(TimeHorizon.fromName(timeHorizon)); + + String workflowid = line.getOptionValue(OnlineWorkflowCommand.WORKFLOW_ID); + if(workflowid!=null) + params.setOfflineWorkflowId(workflowid); + + String feAnalysisId = line.getOptionValue(OnlineWorkflowCommand.FEANALYSIS_ID); + if(feAnalysisId!=null) + params.setFeAnalysisId(feAnalysisId); + + String rulesPurity=line.getOptionValue(OnlineWorkflowCommand.RULES_PURITY); + if(rulesPurity!=null) + params.setRulesPurityThreshold(Double.parseDouble(rulesPurity)); + + if(line.hasOption(OnlineWorkflowCommand.STORE_STATES)) + params.setStoreStates(true); + + if(line.hasOption(OnlineWorkflowCommand.ANALYSE_BASECASE)) + params.setAnalyseBasecase(true); + + if(line.hasOption(OnlineWorkflowCommand.VALIDATION)) { + params.setValidation(true); + params.setStoreStates(true); // if validation then store states + params.setAnalyseBasecase(true); // if validation then analyze base case + } + + Set securityIndexes = null; if (line.hasOption(OnlineWorkflowCommand.SECURITY_INDEXES)) { - if ( !"ALL".equals(line.getOptionValue(OnlineWorkflowCommand.SECURITY_INDEXES)) ) - securityIndexes = Arrays.stream(line.getOptionValue(OnlineWorkflowCommand.SECURITY_INDEXES).split(",")) - .map(SecurityIndexType::valueOf) - .collect(Collectors.toSet()); + if ( !"ALL".equals(line.getOptionValue(OnlineWorkflowCommand.SECURITY_INDEXES)) ) + securityIndexes = Arrays.stream(line.getOptionValue(OnlineWorkflowCommand.SECURITY_INDEXES).split(",")) + .map(SecurityIndexType::valueOf) + .collect(Collectors.toSet()); params.setSecurityIndexes(securityIndexes); } - + if(line.hasOption(OnlineWorkflowCommand.MERGE_OPTIMIZED)) - params.setMergeOptimized(true); - + params.setMergeOptimized(true); + String limitReduction=line.getOptionValue(OnlineWorkflowCommand.LIMIT_REDUCTION); - if(limitReduction!=null) - params.setLimitReduction(Float.parseFloat(limitReduction)); - - String urlString = "service:jmx:rmi:///jndi/rmi://"+startconfig.getJmxHost()+":"+startconfig.getJmxPort()+"/jmxrmi"; - //System.out.println("urlString="+urlString); - - JMXServiceURL serviceURL = new JMXServiceURL(urlString); - Map jmxEnv = new HashMap<>(); - JMXConnector connector = JMXConnectorFactory.connect(serviceURL, jmxEnv) ; - MBeanServerConnection mbsc = connector.getMBeanServerConnection(); - - ObjectName name = new ObjectName(LocalOnlineApplicationMBean.BEAN_NAME); - LocalOnlineApplicationMBean application = MBeanServerInvocationHandler.newProxyInstance(mbsc, name, LocalOnlineApplicationMBean.class, false); - - if( line.hasOption(OnlineWorkflowCommand.START_CMD)) - { - for (DateTime basecase:baseCasesSet) { - params.setBaseCaseDate(basecase); - System.out.println("starting Online Workflow, basecase " + basecase.toString()); - application.startWorkflow(startconfig, params); - } - } - else if(line.hasOption(OnlineWorkflowCommand.SHUTDOWN_CMD)) - { - application.shutdown(); - } - - } + if(limitReduction!=null) + params.setLimitReduction(Float.parseFloat(limitReduction)); + + if(line.hasOption(OnlineWorkflowCommand.HANDLE_VIOLATION_IN_N)) { + params.setHandleViolationsInN(true); + params.setAnalyseBasecase(true); // if I need to handle violations in N, I need to analyze base case + } + + String constraintMargin=line.getOptionValue(OnlineWorkflowCommand.CONSTRAINT_MARGIN); + if(constraintMargin!=null) + params.setConstraintMargin(Float.parseFloat(constraintMargin)); + + String urlString = "service:jmx:rmi:///jndi/rmi://"+startconfig.getJmxHost()+":"+startconfig.getJmxPort()+"/jmxrmi"; + + JMXServiceURL serviceURL = new JMXServiceURL(urlString); + Map jmxEnv = new HashMap<>(); + JMXConnector connector = JMXConnectorFactory.connect(serviceURL, jmxEnv) ; + MBeanServerConnection mbsc = connector.getMBeanServerConnection(); + + ObjectName name = new ObjectName(LocalOnlineApplicationMBean.BEAN_NAME); + LocalOnlineApplicationMBean application = MBeanServerInvocationHandler.newProxyInstance(mbsc, name, LocalOnlineApplicationMBean.class, false); + + if( line.hasOption(OnlineWorkflowCommand.START_CMD)) + { + for (DateTime basecase:baseCasesSet) { + params.setBaseCaseDate(basecase); + System.out.println("starting Online Workflow, basecase " + basecase.toString()); + application.startWorkflow(startconfig, params); + } + } + else if(line.hasOption(OnlineWorkflowCommand.SHUTDOWN_CMD)) + { + application.shutdown(); + } + + } } diff --git a/online-workflow/src/main/java/eu/itesla_project/online/tools/PrintOnlineWorkflowPostContingencyViolationsTool.java b/online-workflow/src/main/java/eu/itesla_project/online/tools/PrintOnlineWorkflowPostContingencyViolationsTool.java index 8e21d780..4a530cb6 100644 --- a/online-workflow/src/main/java/eu/itesla_project/online/tools/PrintOnlineWorkflowPostContingencyViolationsTool.java +++ b/online-workflow/src/main/java/eu/itesla_project/online/tools/PrintOnlineWorkflowPostContingencyViolationsTool.java @@ -1,19 +1,21 @@ /** * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) + * Copyright (c) 2016, 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/. */ package eu.itesla_project.online.tools; -import com.csvreader.CsvWriter; -import com.google.auto.service.AutoService; - -import eu.itesla_project.commons.tools.Command; -import eu.itesla_project.commons.tools.Tool; -import eu.itesla_project.modules.online.OnlineConfig; -import eu.itesla_project.modules.online.OnlineDb; -import eu.itesla_project.modules.security.LimitViolation; +import java.io.IOException; +import java.io.StringWriter; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; @@ -22,9 +24,16 @@ import org.nocrala.tools.texttablefmt.CellStyle; import org.nocrala.tools.texttablefmt.Table; -import java.io.IOException; -import java.io.StringWriter; -import java.util.*; +import com.csvreader.CsvWriter; +import com.google.auto.service.AutoService; + +import eu.itesla_project.commons.tools.Command; +import eu.itesla_project.commons.tools.Tool; +import eu.itesla_project.modules.online.OnlineConfig; +import eu.itesla_project.modules.online.OnlineDb; +import eu.itesla_project.modules.security.LimitViolation; +import eu.itesla_project.modules.security.LimitViolationFilter; +import eu.itesla_project.modules.security.LimitViolationType; /** * @@ -33,155 +42,167 @@ @AutoService(Tool.class) public class PrintOnlineWorkflowPostContingencyViolationsTool implements Tool { - private static Command COMMAND = new Command() { - - @Override - public String getName() { - return "print-online-workflow-postcontingency-violations"; - } - - @Override - public String getTheme() { - return Themes.ONLINE_WORKFLOW; - } - - @Override - public String getDescription() { - return "Print post contingency violations in the network data of an online workflow"; - } - - @Override - public Options getOptions() { - Options options = new Options(); - options.addOption(Option.builder().longOpt("workflow") - .desc("the workflow id") - .hasArg() - .required() - .argName("ID") - .build()); - options.addOption(Option.builder().longOpt("state") - .desc("the state id") - .hasArg() - .argName("STATE") - .build()); - options.addOption(Option.builder().longOpt("contingency") - .desc("the contingency id") - .hasArg() - .argName("CONTINGENCY") - .build()); - options.addOption(Option.builder().longOpt("csv") - .desc("export in csv format") - .build()); - return options; - } - - @Override - public String getUsageFooter() { - return null; - } - - }; - - @Override - public Command getCommand() { - return COMMAND; - } - - @Override - public void run(CommandLine line) throws Exception { - OnlineConfig config = OnlineConfig.load(); - OnlineDb onlinedb = config.getOnlineDbFactoryClass().newInstance().create(); - String workflowId = line.getOptionValue("workflow"); - if ( line.hasOption("state") && line.hasOption("contingency")) { - Integer stateId = Integer.parseInt(line.getOptionValue("state")); - String contingencyId = line.getOptionValue("contingency"); - List violations = onlinedb.getPostContingencyViolations(workflowId, stateId, contingencyId); - if ( violations != null && !violations.isEmpty() ) { - Table table = new Table(7, BorderStyle.CLASSIC_WIDE); - StringWriter content = new StringWriter(); - CsvWriter cvsWriter = new CsvWriter(content, ','); - printHeaders(table, cvsWriter); - printValues(table, cvsWriter, stateId, contingencyId, violations); - printOutput(table, content, line.hasOption("csv")); - cvsWriter.close(); - } else - System.out.println("\nNo post contingency violations for workflow "+workflowId+", contingency "+contingencyId+" and state "+stateId); - } else if ( line.hasOption("state") ) { - Integer stateId = Integer.parseInt(line.getOptionValue("state")); - Map> stateViolations = onlinedb.getPostContingencyViolations(workflowId, stateId); - if ( stateViolations != null && !stateViolations.keySet().isEmpty() ) { - Table table = new Table(7, BorderStyle.CLASSIC_WIDE); - StringWriter content = new StringWriter(); - CsvWriter cvsWriter = new CsvWriter(content, ','); - printHeaders(table, cvsWriter); - String[] contingencyIds = stateViolations.keySet().toArray(new String[stateViolations.keySet().size()]); - Arrays.sort(contingencyIds); - for(String contingencyId : contingencyIds) { - List violations = stateViolations.get(contingencyId); - if ( violations != null && !violations.isEmpty() ) { - printValues(table, cvsWriter, stateId, contingencyId, violations); - } - } - cvsWriter.flush(); - printOutput(table, content, line.hasOption("csv")); - cvsWriter.close(); - } else - System.out.println("\nNo post contingency violations for workflow "+workflowId+" and state "+stateId); - } else if ( line.hasOption("contingency") ) { - String contingencyId = line.getOptionValue("contingency"); - Map> contingencyViolations = onlinedb.getPostContingencyViolations(workflowId, contingencyId); - if ( contingencyViolations != null && !contingencyViolations.keySet().isEmpty() ) { - Table table = new Table(7, BorderStyle.CLASSIC_WIDE); - StringWriter content = new StringWriter(); - CsvWriter cvsWriter = new CsvWriter(content, ','); - printHeaders(table, cvsWriter); - Integer[] stateIds = contingencyViolations.keySet().toArray(new Integer[contingencyViolations.keySet().size()]); - Arrays.sort(stateIds); - for(Integer stateId : stateIds) { - List violations = contingencyViolations.get(stateId); - if ( violations != null && !violations.isEmpty() ) { - printValues(table, cvsWriter, stateId, contingencyId, violations); - } - } - cvsWriter.flush(); - printOutput(table, content, line.hasOption("csv")); - cvsWriter.close(); - } else - System.out.println("\nNo post contingency violations for workflow "+workflowId+" and contingency "+contingencyId); - } else { - Map>> wfViolations = onlinedb.getPostContingencyViolations(workflowId); - if ( wfViolations != null && !wfViolations.keySet().isEmpty() ) { - Table table = new Table(7, BorderStyle.CLASSIC_WIDE); - StringWriter content = new StringWriter(); - CsvWriter cvsWriter = new CsvWriter(content, ','); - printHeaders(table, cvsWriter); - Integer[] stateIds = wfViolations.keySet().toArray(new Integer[wfViolations.keySet().size()]); - Arrays.sort(stateIds); - for(Integer stateId : stateIds) { - Map> stateViolations = wfViolations.get(stateId); - if ( stateViolations != null && !stateViolations.keySet().isEmpty() ) { - String[] contingencyIds = stateViolations.keySet().toArray(new String[stateViolations.keySet().size()]); - Arrays.sort(contingencyIds); - for(String contingencyId : contingencyIds) { - List violations = stateViolations.get(contingencyId); - if ( violations != null && !violations.isEmpty() ) { - printValues(table, cvsWriter, stateId, contingencyId, violations); - } - } - } - } - cvsWriter.flush(); - printOutput(table, content, line.hasOption("csv")); - cvsWriter.close(); - } else - System.out.println("\nNo post contingency violations for workflow "+workflowId); - } - onlinedb.close(); - } - - private void printHeaders(Table table, CsvWriter cvsWriter) throws IOException { - String[] headers = new String[7]; - int i = 0; + private static Command COMMAND = new Command() { + + @Override + public String getName() { + return "print-online-workflow-postcontingency-violations"; + } + + @Override + public String getTheme() { + return Themes.ONLINE_WORKFLOW; + } + + @Override + public String getDescription() { + return "Print post contingency violations in the network data of an online workflow"; + } + + @Override + public Options getOptions() { + Options options = new Options(); + options.addOption(Option.builder().longOpt("workflow") + .desc("the workflow id") + .hasArg() + .required() + .argName("ID") + .build()); + options.addOption(Option.builder().longOpt("state") + .desc("the state id") + .hasArg() + .argName("STATE") + .build()); + options.addOption(Option.builder().longOpt("contingency") + .desc("the contingency id") + .hasArg() + .argName("CONTINGENCY") + .build()); + options.addOption(Option.builder().longOpt("type") + .desc("sub list of violations types (CURRENT, HIGH_VOLTAGE, LOW_VOLTAGE) to use") + .hasArg() + .argName("VIOLATION_TYPE,VIOLATION_TYPE,...") + .build()); + options.addOption(Option.builder().longOpt("csv") + .desc("export in csv format") + .build()); + return options; + } + + @Override + public String getUsageFooter() { + return null; + } + + }; + + @Override + public Command getCommand() { + return COMMAND; + } + + @Override + public void run(CommandLine line) throws Exception { + OnlineConfig config = OnlineConfig.load(); + OnlineDb onlinedb = config.getOnlineDbFactoryClass().newInstance().create(); + String workflowId = line.getOptionValue("workflow"); + LimitViolationFilter violationsFilter = null; + if (line.hasOption("type")) { + Set limitViolationTypes = Arrays.stream(line.getOptionValue("type").split(",")) + .map(LimitViolationType::valueOf) + .collect(Collectors.toSet()); + violationsFilter = new LimitViolationFilter(limitViolationTypes, 0); + } + if ( line.hasOption("state") && line.hasOption("contingency")) { + Integer stateId = Integer.parseInt(line.getOptionValue("state")); + String contingencyId = line.getOptionValue("contingency"); + List violations = onlinedb.getPostContingencyViolations(workflowId, stateId, contingencyId); + if ( violations != null && !violations.isEmpty() ) { + Table table = new Table(8, BorderStyle.CLASSIC_WIDE); + StringWriter content = new StringWriter(); + CsvWriter cvsWriter = new CsvWriter(content, ','); + printHeaders(table, cvsWriter); + printValues(table, cvsWriter, stateId, contingencyId, violations, violationsFilter); + printOutput(table, content, line.hasOption("csv")); + cvsWriter.close(); + } else + System.out.println("\nNo post contingency violations for workflow "+workflowId+", contingency "+contingencyId+" and state "+stateId); + } else if ( line.hasOption("state") ) { + Integer stateId = Integer.parseInt(line.getOptionValue("state")); + Map> stateViolations = onlinedb.getPostContingencyViolations(workflowId, stateId); + if ( stateViolations != null && !stateViolations.keySet().isEmpty() ) { + Table table = new Table(8, BorderStyle.CLASSIC_WIDE); + StringWriter content = new StringWriter(); + CsvWriter cvsWriter = new CsvWriter(content, ','); + printHeaders(table, cvsWriter); + String[] contingencyIds = stateViolations.keySet().toArray(new String[stateViolations.keySet().size()]); + Arrays.sort(contingencyIds); + for(String contingencyId : contingencyIds) { + List violations = stateViolations.get(contingencyId); + if ( violations != null && !violations.isEmpty() ) { + printValues(table, cvsWriter, stateId, contingencyId, violations, violationsFilter); + } + } + cvsWriter.flush(); + printOutput(table, content, line.hasOption("csv")); + cvsWriter.close(); + } else + System.out.println("\nNo post contingency violations for workflow "+workflowId+" and state "+stateId); + } else if ( line.hasOption("contingency") ) { + String contingencyId = line.getOptionValue("contingency"); + Map> contingencyViolations = onlinedb.getPostContingencyViolations(workflowId, contingencyId); + if ( contingencyViolations != null && !contingencyViolations.keySet().isEmpty() ) { + Table table = new Table(8, BorderStyle.CLASSIC_WIDE); + StringWriter content = new StringWriter(); + CsvWriter cvsWriter = new CsvWriter(content, ','); + printHeaders(table, cvsWriter); + Integer[] stateIds = contingencyViolations.keySet().toArray(new Integer[contingencyViolations.keySet().size()]); + Arrays.sort(stateIds); + for(Integer stateId : stateIds) { + List violations = contingencyViolations.get(stateId); + if ( violations != null && !violations.isEmpty() ) { + printValues(table, cvsWriter, stateId, contingencyId, violations, violationsFilter); + } + } + cvsWriter.flush(); + printOutput(table, content, line.hasOption("csv")); + cvsWriter.close(); + } else + System.out.println("\nNo post contingency violations for workflow "+workflowId+" and contingency "+contingencyId); + } else { + Map>> wfViolations = onlinedb.getPostContingencyViolations(workflowId); + if ( wfViolations != null && !wfViolations.keySet().isEmpty() ) { + Table table = new Table(8, BorderStyle.CLASSIC_WIDE); + StringWriter content = new StringWriter(); + CsvWriter cvsWriter = new CsvWriter(content, ','); + printHeaders(table, cvsWriter); + Integer[] stateIds = wfViolations.keySet().toArray(new Integer[wfViolations.keySet().size()]); + Arrays.sort(stateIds); + for(Integer stateId : stateIds) { + Map> stateViolations = wfViolations.get(stateId); + if ( stateViolations != null && !stateViolations.keySet().isEmpty() ) { + String[] contingencyIds = stateViolations.keySet().toArray(new String[stateViolations.keySet().size()]); + Arrays.sort(contingencyIds); + for(String contingencyId : contingencyIds) { + List violations = stateViolations.get(contingencyId); + if ( violations != null && !violations.isEmpty() ) { + printValues(table, cvsWriter, stateId, contingencyId, violations, violationsFilter); + } + } + } + } + cvsWriter.flush(); + printOutput(table, content, line.hasOption("csv")); + cvsWriter.close(); + } else + System.out.println("\nNo post contingency violations for workflow "+workflowId); + } + onlinedb.close(); + } + + private void printHeaders(Table table, CsvWriter cvsWriter) throws IOException { + String[] headers = new String[8]; + int i = 0; table.addCell("State", new CellStyle(CellStyle.HorizontalAlign.center)); headers[i++] = "State"; table.addCell("Contingency", new CellStyle(CellStyle.HorizontalAlign.center)); @@ -196,41 +217,48 @@ private void printHeaders(Table table, CsvWriter cvsWriter) throws IOException { headers[i++] = "Limit"; table.addCell("Limit Reduction", new CellStyle(CellStyle.HorizontalAlign.center)); headers[i++] = "Limit Reduction"; + table.addCell("Voltage Level", new CellStyle(CellStyle.HorizontalAlign.center)); + headers[i++] = "Voltage Level"; cvsWriter.writeRecord(headers); - } - - private void printValues(Table table, CsvWriter cvsWriter, Integer stateId, String contingencyId, List violations) throws IOException { - Collections.sort(violations, new Comparator() { - public int compare(LimitViolation o1, LimitViolation o2) { - return o1.getSubject().getId().compareTo(o2.getSubject().getId()); - } - }); - for (LimitViolation violation : violations) { - String[] values = new String[7]; - int i = 0; - table.addCell(Integer.toString(stateId), new CellStyle(CellStyle.HorizontalAlign.right)); - values[i++] = Integer.toString(stateId); - table.addCell(contingencyId, new CellStyle(CellStyle.HorizontalAlign.left)); - values[i++] = contingencyId; - table.addCell(violation.getSubject().getId(), new CellStyle(CellStyle.HorizontalAlign.left)); - values[i++] = violation.getSubject().getId(); - table.addCell(violation.getLimitType().name(), new CellStyle(CellStyle.HorizontalAlign.left)); - values[i++] = violation.getLimitType().name(); - table.addCell(Float.toString(violation.getValue()), new CellStyle(CellStyle.HorizontalAlign.right)); - values[i++] = Float.toString(violation.getValue()); - table.addCell(Float.toString(violation.getLimit()), new CellStyle(CellStyle.HorizontalAlign.right)); - values[i++] = Float.toString(violation.getLimit()); - table.addCell(Float.toString(violation.getLimitReduction()), new CellStyle(CellStyle.HorizontalAlign.right)); - values[i++] = Float.toString(violation.getLimitReduction()); - cvsWriter.writeRecord(values); - } - } - - private void printOutput(Table table, StringWriter content, boolean csv) { - if ( csv ) - System.out.println(content.toString()); - else - System.out.println(table.render()); - } - + } + + private void printValues(Table table, CsvWriter cvsWriter, Integer stateId, String contingencyId, List violations, + LimitViolationFilter violationsFilter) throws IOException { + if ( violationsFilter != null ) + violations = violationsFilter.apply(violations); + Collections.sort(violations, new Comparator() { + public int compare(LimitViolation o1, LimitViolation o2) { + return o1.getSubject().getId().compareTo(o2.getSubject().getId()); + } + }); + for (LimitViolation violation : violations) { + String[] values = new String[8]; + int i = 0; + table.addCell(Integer.toString(stateId), new CellStyle(CellStyle.HorizontalAlign.right)); + values[i++] = Integer.toString(stateId); + table.addCell(contingencyId, new CellStyle(CellStyle.HorizontalAlign.left)); + values[i++] = contingencyId; + table.addCell(violation.getSubject().getId(), new CellStyle(CellStyle.HorizontalAlign.left)); + values[i++] = violation.getSubject().getId(); + table.addCell(violation.getLimitType().name(), new CellStyle(CellStyle.HorizontalAlign.left)); + values[i++] = violation.getLimitType().name(); + table.addCell(Float.toString(violation.getValue()), new CellStyle(CellStyle.HorizontalAlign.right)); + values[i++] = Float.toString(violation.getValue()); + table.addCell(Float.toString(violation.getLimit()), new CellStyle(CellStyle.HorizontalAlign.right)); + values[i++] = Float.toString(violation.getLimit()); + table.addCell(Float.toString(violation.getLimitReduction()), new CellStyle(CellStyle.HorizontalAlign.right)); + values[i++] = Float.toString(violation.getLimitReduction()); + table.addCell(Float.toString(violation.getBaseVoltage()), new CellStyle(CellStyle.HorizontalAlign.right)); + values[i++] = Float.toString(violation.getBaseVoltage()); + cvsWriter.writeRecord(values); + } + } + + private void printOutput(Table table, StringWriter content, boolean csv) { + if ( csv ) + System.out.println(content.toString()); + else + System.out.println(table.render()); + } + } diff --git a/online-workflow/src/main/java/eu/itesla_project/online/tools/PrintOnlineWorkflowRulesResultsTool.java b/online-workflow/src/main/java/eu/itesla_project/online/tools/PrintOnlineWorkflowRulesResultsTool.java index 992b21f6..4b467e82 100644 --- a/online-workflow/src/main/java/eu/itesla_project/online/tools/PrintOnlineWorkflowRulesResultsTool.java +++ b/online-workflow/src/main/java/eu/itesla_project/online/tools/PrintOnlineWorkflowRulesResultsTool.java @@ -1,13 +1,27 @@ /** * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) + * Copyright (c) 2016, 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/. */ package eu.itesla_project.online.tools; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.nocrala.tools.texttablefmt.BorderStyle; +import org.nocrala.tools.texttablefmt.CellStyle; +import org.nocrala.tools.texttablefmt.Table; + import com.csvreader.CsvWriter; import com.google.auto.service.AutoService; + import eu.itesla_project.commons.tools.Command; import eu.itesla_project.commons.tools.Tool; import eu.itesla_project.modules.online.OnlineConfig; @@ -15,16 +29,6 @@ import eu.itesla_project.modules.online.OnlineWorkflowParameters; import eu.itesla_project.modules.online.OnlineWorkflowRulesResults; import eu.itesla_project.modules.securityindexes.SecurityIndexType; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.Options; -import org.nocrala.tools.texttablefmt.BorderStyle; -import org.nocrala.tools.texttablefmt.CellStyle; -import org.nocrala.tools.texttablefmt.Table; - -import java.io.StringWriter; -import java.util.HashMap; -import java.util.Map; /** * @@ -32,123 +36,134 @@ */ @AutoService(Tool.class) public class PrintOnlineWorkflowRulesResultsTool implements Tool { - - private static Command COMMAND = new Command() { - - @Override - public String getName() { - return "print-online-workflow-rules-results"; - } - - @Override - public String getTheme() { - return Themes.ONLINE_WORKFLOW; - } - - @Override - public String getDescription() { - return "Print stored results of security rules application for an online workflow"; - } - - @Override - public Options getOptions() { - Options options = new Options(); - options.addOption(Option.builder().longOpt("workflow") - .desc("the workflow id") - .hasArg() - .required() - .argName("ID") - .build()); - options.addOption(Option.builder().longOpt("wca") - .desc("get results of wca rules (monte_carlo if not specified)") - .build()); - options.addOption(Option.builder().longOpt("csv") - .desc("export in csv format") - .build()); - return options; - } - - @Override - public String getUsageFooter() { - return null; - } - - }; - - @Override - public Command getCommand() { - return COMMAND; - } - - @Override - public void run(CommandLine line) throws Exception { - OnlineConfig config = OnlineConfig.load(); - OnlineDb onlinedb = config.getOnlineDbFactoryClass().newInstance().create(); - String workflowId = line.getOptionValue("workflow"); - OnlineWorkflowRulesResults wfRulesResults = onlinedb.getRulesResults(workflowId); - if ( line.hasOption("wca")) - wfRulesResults = onlinedb.getWcaRulesResults(workflowId); - if ( wfRulesResults != null ) { - if ( !wfRulesResults.getContingenciesWithSecurityRulesResults().isEmpty() ) { - OnlineWorkflowParameters parameters = onlinedb.getWorkflowParameters(workflowId); - SecurityIndexType[] securityIndexTypes = parameters.getSecurityIndexes() == null ? SecurityIndexType.values() - : parameters.getSecurityIndexes().toArray(new SecurityIndexType[parameters.getSecurityIndexes().size()]); - Table table = new Table(securityIndexTypes.length+3, BorderStyle.CLASSIC_WIDE); - StringWriter content = new StringWriter(); - CsvWriter cvsWriter = new CsvWriter(content, ','); - String[] headers = new String[securityIndexTypes.length+3]; - int i = 0; - table.addCell("Contingency", new CellStyle(CellStyle.HorizontalAlign.center)); - headers[i++] = "Contingency"; - table.addCell("State", new CellStyle(CellStyle.HorizontalAlign.center)); - headers[i++] = "State"; - table.addCell("Status", new CellStyle(CellStyle.HorizontalAlign.center)); - headers[i++] = "Status"; - for (SecurityIndexType securityIndexType : securityIndexTypes) { - table.addCell(securityIndexType.getLabel(), new CellStyle(CellStyle.HorizontalAlign.center)); - headers[i++] = securityIndexType.getLabel(); - } - cvsWriter.writeRecord(headers); - for (String contingencyId : wfRulesResults.getContingenciesWithSecurityRulesResults()) { - for (Integer stateId : wfRulesResults.getStatesWithSecurityRulesResults(contingencyId)) { - String[] values = new String[securityIndexTypes.length+3]; - i = 0; - table.addCell(contingencyId); - values[i++] = contingencyId; - table.addCell(stateId.toString(), new CellStyle(CellStyle.HorizontalAlign.right)); - values[i++] = stateId.toString(); - table.addCell(wfRulesResults.getStateStatus(contingencyId, stateId).name()); - values[i++] = wfRulesResults.getStateStatus(contingencyId, stateId).name(); - HashMap rulesResults = getRulesResults(wfRulesResults.getStateResults(contingencyId, stateId), securityIndexTypes); - for (SecurityIndexType securityIndexType : securityIndexTypes) { - table.addCell(rulesResults.get(securityIndexType.getLabel()), new CellStyle(CellStyle.HorizontalAlign.center)); - values[i++] = rulesResults.get(securityIndexType.getLabel()); - } - cvsWriter.writeRecord(values); - } - } - cvsWriter.flush(); - if ( line.hasOption("csv")) - System.out.println(content.toString()); - else - System.out.println(table.render()); - cvsWriter.close(); - } else - System.out.println("\nNo results of security rules applications for this workflow"); - } else - System.out.println("No results for this workflow"); - onlinedb.close(); - } - private HashMap getRulesResults(Map stateResults, SecurityIndexType[] securityIndexTypes) { - HashMap rulesResults = new HashMap(); - for (SecurityIndexType securityIndexType : securityIndexTypes) { - if ( stateResults.containsKey(securityIndexType.getLabel()) ) - rulesResults.put(securityIndexType.getLabel(), stateResults.get(securityIndexType.getLabel()) ? "Safe" : "Unsafe"); - else - rulesResults.put(securityIndexType.getLabel(), "-"); - } - return rulesResults; - } + private static String NO_RULES_AVAILABLE = "NO_RULES_AVAILABLE"; + private static String INVALID_RULE = "Invalid Rule"; + + private static Command COMMAND = new Command() { + + @Override + public String getName() { + return "print-online-workflow-rules-results"; + } + + @Override + public String getTheme() { + return Themes.ONLINE_WORKFLOW; + } + + @Override + public String getDescription() { + return "Print stored results of security rules application for an online workflow"; + } + + @Override + public Options getOptions() { + Options options = new Options(); + options.addOption(Option.builder().longOpt("workflow") + .desc("the workflow id") + .hasArg() + .required() + .argName("ID") + .build()); + options.addOption(Option.builder().longOpt("wca") + .desc("get results of wca rules (monte_carlo if not specified)") + .build()); + options.addOption(Option.builder().longOpt("csv") + .desc("export in csv format") + .build()); + return options; + } + + @Override + public String getUsageFooter() { + return null; + } + + }; + + @Override + public Command getCommand() { + return COMMAND; + } + + @Override + public void run(CommandLine line) throws Exception { + OnlineConfig config = OnlineConfig.load(); + OnlineDb onlinedb = config.getOnlineDbFactoryClass().newInstance().create(); + String workflowId = line.getOptionValue("workflow"); + OnlineWorkflowRulesResults wfRulesResults = onlinedb.getRulesResults(workflowId); + if ( line.hasOption("wca")) + wfRulesResults = onlinedb.getWcaRulesResults(workflowId); + if ( wfRulesResults != null ) { + if ( !wfRulesResults.getContingenciesWithSecurityRulesResults().isEmpty() ) { + OnlineWorkflowParameters parameters = onlinedb.getWorkflowParameters(workflowId); + SecurityIndexType[] securityIndexTypes = parameters.getSecurityIndexes() == null ? SecurityIndexType.values() + : parameters.getSecurityIndexes().toArray(new SecurityIndexType[parameters.getSecurityIndexes().size()]); + Table table = new Table(securityIndexTypes.length+3, BorderStyle.CLASSIC_WIDE); + StringWriter content = new StringWriter(); + CsvWriter cvsWriter = new CsvWriter(content, ','); + String[] headers = new String[securityIndexTypes.length+3]; + int i = 0; + table.addCell("Contingency", new CellStyle(CellStyle.HorizontalAlign.center)); + headers[i++] = "Contingency"; + table.addCell("State", new CellStyle(CellStyle.HorizontalAlign.center)); + headers[i++] = "State"; + table.addCell("Status", new CellStyle(CellStyle.HorizontalAlign.center)); + headers[i++] = "Status"; + for (SecurityIndexType securityIndexType : securityIndexTypes) { + table.addCell(securityIndexType.getLabel(), new CellStyle(CellStyle.HorizontalAlign.center)); + headers[i++] = securityIndexType.getLabel(); + } + cvsWriter.writeRecord(headers); + for (String contingencyId : wfRulesResults.getContingenciesWithSecurityRulesResults()) { + for (Integer stateId : wfRulesResults.getStatesWithSecurityRulesResults(contingencyId)) { + String[] values = new String[securityIndexTypes.length+3]; + i = 0; + table.addCell(contingencyId); + values[i++] = contingencyId; + table.addCell(stateId.toString(), new CellStyle(CellStyle.HorizontalAlign.right)); + values[i++] = stateId.toString(); + if ( wfRulesResults.areValidRulesAvailable(contingencyId, stateId) ) { + table.addCell(wfRulesResults.getStateStatus(contingencyId, stateId).name()); + values[i++] = wfRulesResults.getStateStatus(contingencyId, stateId).name(); + } else { + table.addCell(NO_RULES_AVAILABLE); + values[i++] = NO_RULES_AVAILABLE; + } + HashMap rulesResults = getRulesResults(wfRulesResults.getStateResults(contingencyId, stateId), securityIndexTypes, + wfRulesResults.getInvalidRules(contingencyId, stateId)); + for (SecurityIndexType securityIndexType : securityIndexTypes) { + table.addCell(rulesResults.get(securityIndexType.getLabel()), new CellStyle(CellStyle.HorizontalAlign.center)); + values[i++] = rulesResults.get(securityIndexType.getLabel()); + } + cvsWriter.writeRecord(values); + } + } + cvsWriter.flush(); + if ( line.hasOption("csv")) + System.out.println(content.toString()); + else + System.out.println(table.render()); + cvsWriter.close(); + } else + System.out.println("\nNo results of security rules applications for this workflow"); + } else + System.out.println("No results for this workflow"); + onlinedb.close(); + } + + private HashMap getRulesResults(Map stateResults, SecurityIndexType[] securityIndexTypes, List invalidRules) { + HashMap rulesResults = new HashMap(); + for (SecurityIndexType securityIndexType : securityIndexTypes) { + if ( stateResults.containsKey(securityIndexType.getLabel()) ) + rulesResults.put(securityIndexType.getLabel(), stateResults.get(securityIndexType.getLabel()) ? "Safe" : "Unsafe"); + else if ( invalidRules.contains(securityIndexType) ) + rulesResults.put(securityIndexType.getLabel(), INVALID_RULE); + else + rulesResults.put(securityIndexType.getLabel(), "-"); + } + return rulesResults; + } } diff --git a/online-workflow/src/main/java/eu/itesla_project/online/tools/PrintOnlineWorkflowViolationsTool.java b/online-workflow/src/main/java/eu/itesla_project/online/tools/PrintOnlineWorkflowViolationsTool.java index d59a4633..8fcc9f7a 100644 --- a/online-workflow/src/main/java/eu/itesla_project/online/tools/PrintOnlineWorkflowViolationsTool.java +++ b/online-workflow/src/main/java/eu/itesla_project/online/tools/PrintOnlineWorkflowViolationsTool.java @@ -1,29 +1,40 @@ /** * Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium) + * Copyright (c) 2016, 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/. */ package eu.itesla_project.online.tools; +import java.io.IOException; +import java.io.StringWriter; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.nocrala.tools.texttablefmt.BorderStyle; +import org.nocrala.tools.texttablefmt.CellStyle; +import org.nocrala.tools.texttablefmt.Table; + import com.csvreader.CsvWriter; import com.google.auto.service.AutoService; + import eu.itesla_project.commons.tools.Command; import eu.itesla_project.commons.tools.Tool; import eu.itesla_project.modules.online.OnlineConfig; import eu.itesla_project.modules.online.OnlineDb; import eu.itesla_project.modules.online.OnlineStep; import eu.itesla_project.modules.security.LimitViolation; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.Options; -import org.nocrala.tools.texttablefmt.BorderStyle; -import org.nocrala.tools.texttablefmt.CellStyle; -import org.nocrala.tools.texttablefmt.Table; - -import java.io.IOException; -import java.io.StringWriter; -import java.util.*; +import eu.itesla_project.modules.security.LimitViolationFilter; +import eu.itesla_project.modules.security.LimitViolationType; /** * @@ -32,155 +43,167 @@ @AutoService(Tool.class) public class PrintOnlineWorkflowViolationsTool implements Tool { - private static Command COMMAND = new Command() { - - @Override - public String getName() { - return "print-online-workflow-violations"; - } - - @Override - public String getTheme() { - return Themes.ONLINE_WORKFLOW; - } - - @Override - public String getDescription() { - return "Print violations in the network data of an online workflow"; - } - - @Override - public Options getOptions() { - Options options = new Options(); - options.addOption(Option.builder().longOpt("workflow") - .desc("the workflow id") - .hasArg() - .required() - .argName("ID") - .build()); - options.addOption(Option.builder().longOpt("state") - .desc("the state id") - .hasArg() - .argName("STATE") - .build()); - options.addOption(Option.builder().longOpt("step") - .desc("the online step (FORECAST_ERRORS_ANALYSIS,MERGING,WORST_CASE_APPROACH,MONTE_CARLO_SAMPLING,LOAD_FLOW,SECURITY_RULES_ASSESSMENT,CONTROL_ACTION_OPTIMIZATION,TIME_DOMAIN_SIMULATION)") - .hasArg() - .argName("STEP") - .build()); - options.addOption(Option.builder().longOpt("csv") - .desc("export in csv format") - .build()); - return options; - } - - @Override - public String getUsageFooter() { - return null; - } - - }; - - @Override - public Command getCommand() { - return COMMAND; - } - - @Override - public void run(CommandLine line) throws Exception { - OnlineConfig config = OnlineConfig.load(); - OnlineDb onlinedb = config.getOnlineDbFactoryClass().newInstance().create(); - String workflowId = line.getOptionValue("workflow"); - if ( line.hasOption("state") && line.hasOption("step")) { - Integer stateId = Integer.parseInt(line.getOptionValue("state")); - OnlineStep step = OnlineStep.valueOf(line.getOptionValue("step")); - List violations = onlinedb.getViolations(workflowId, stateId, step); - if ( violations != null && !violations.isEmpty() ) { - Table table = new Table(7, BorderStyle.CLASSIC_WIDE); - StringWriter content = new StringWriter(); - CsvWriter cvsWriter = new CsvWriter(content, ','); - printHeaders(table, cvsWriter); - printValues(table, cvsWriter, stateId, step, violations); - printOutput(table, content, line.hasOption("csv")); - cvsWriter.close(); - } else - System.out.println("\nNo violations for workflow "+workflowId+", step "+step.name()+" and state "+stateId); - } else if ( line.hasOption("state") ) { - Integer stateId = Integer.parseInt(line.getOptionValue("state")); - Map> stateViolations = onlinedb.getViolations(workflowId, stateId); - if ( stateViolations != null && !stateViolations.keySet().isEmpty() ) { - Table table = new Table(7, BorderStyle.CLASSIC_WIDE); - StringWriter content = new StringWriter(); - CsvWriter cvsWriter = new CsvWriter(content, ','); - printHeaders(table, cvsWriter); - OnlineStep[] steps = stateViolations.keySet().toArray(new OnlineStep[stateViolations.keySet().size()]); - Arrays.sort(steps); - for(OnlineStep step : steps) { - List violations = stateViolations.get(step); - if ( violations != null && !violations.isEmpty() ) { - printValues(table, cvsWriter, stateId, step, violations); - } - } - cvsWriter.flush(); - printOutput(table, content, line.hasOption("csv")); - cvsWriter.close(); - } else - System.out.println("\nNo violations for workflow "+workflowId+" and state "+stateId); - } else if ( line.hasOption("step") ) { - OnlineStep step = OnlineStep.valueOf(line.getOptionValue("step")); - Map> stepViolations = onlinedb.getViolations(workflowId, step); - if ( stepViolations != null && !stepViolations.keySet().isEmpty() ) { - Table table = new Table(7, BorderStyle.CLASSIC_WIDE); - StringWriter content = new StringWriter(); - CsvWriter cvsWriter = new CsvWriter(content, ','); - printHeaders(table, cvsWriter); - Integer[] stateIds = stepViolations.keySet().toArray(new Integer[stepViolations.keySet().size()]); - Arrays.sort(stateIds); - for(Integer stateId : stateIds) { - List violations = stepViolations.get(stateId); - if ( violations != null && !violations.isEmpty() ) { - printValues(table, cvsWriter, stateId, step, violations); - } - } - cvsWriter.flush(); - printOutput(table, content, line.hasOption("csv")); - cvsWriter.close(); - } else - System.out.println("\nNo violations for workflow "+workflowId+" and step "+step); - } else { - Map>> wfViolations = onlinedb.getViolations(workflowId); - if ( wfViolations != null && !wfViolations.keySet().isEmpty() ) { - Table table = new Table(7, BorderStyle.CLASSIC_WIDE); - StringWriter content = new StringWriter(); - CsvWriter cvsWriter = new CsvWriter(content, ','); - printHeaders(table, cvsWriter); - Integer[] stateIds = wfViolations.keySet().toArray(new Integer[wfViolations.keySet().size()]); - Arrays.sort(stateIds); - for(Integer stateId : stateIds) { - Map> stateViolations = wfViolations.get(stateId); - if ( stateViolations != null && !stateViolations.keySet().isEmpty() ) { - OnlineStep[] steps = stateViolations.keySet().toArray(new OnlineStep[stateViolations.keySet().size()]); - Arrays.sort(steps); - for(OnlineStep step : steps) { - List violations = stateViolations.get(step); - if ( violations != null && !violations.isEmpty() ) { - printValues(table, cvsWriter, stateId, step, violations); - } - } - } - } - cvsWriter.flush(); - printOutput(table, content, line.hasOption("csv")); - cvsWriter.close(); - } else - System.out.println("\nNo violations for workflow "+workflowId); - } - onlinedb.close(); - } - - private void printHeaders(Table table, CsvWriter cvsWriter) throws IOException { - String[] headers = new String[7]; - int i = 0; + private static Command COMMAND = new Command() { + + @Override + public String getName() { + return "print-online-workflow-violations"; + } + + @Override + public String getTheme() { + return Themes.ONLINE_WORKFLOW; + } + + @Override + public String getDescription() { + return "Print violations in the network data of an online workflow"; + } + + @Override + public Options getOptions() { + Options options = new Options(); + options.addOption(Option.builder().longOpt("workflow") + .desc("the workflow id") + .hasArg() + .required() + .argName("ID") + .build()); + options.addOption(Option.builder().longOpt("state") + .desc("the state id") + .hasArg() + .argName("STATE") + .build()); + options.addOption(Option.builder().longOpt("step") + .desc("the online step (FORECAST_ERRORS_ANALYSIS,MERGING,WORST_CASE_APPROACH,MONTE_CARLO_SAMPLING,LOAD_FLOW,SECURITY_RULES_ASSESSMENT,CONTROL_ACTION_OPTIMIZATION,TIME_DOMAIN_SIMULATION)") + .hasArg() + .argName("STEP") + .build()); + options.addOption(Option.builder().longOpt("type") + .desc("sub list of violations types (CURRENT, HIGH_VOLTAGE, LOW_VOLTAGE) to use") + .hasArg() + .argName("VIOLATION_TYPE,VIOLATION_TYPE,...") + .build()); + options.addOption(Option.builder().longOpt("csv") + .desc("export in csv format") + .build()); + return options; + } + + @Override + public String getUsageFooter() { + return null; + } + + }; + + @Override + public Command getCommand() { + return COMMAND; + } + + @Override + public void run(CommandLine line) throws Exception { + OnlineConfig config = OnlineConfig.load(); + OnlineDb onlinedb = config.getOnlineDbFactoryClass().newInstance().create(); + String workflowId = line.getOptionValue("workflow"); + LimitViolationFilter violationsFilter = null; + if (line.hasOption("type")) { + Set limitViolationTypes = Arrays.stream(line.getOptionValue("type").split(",")) + .map(LimitViolationType::valueOf) + .collect(Collectors.toSet()); + violationsFilter = new LimitViolationFilter(limitViolationTypes, 0); + } + if ( line.hasOption("state") && line.hasOption("step")) { + Integer stateId = Integer.parseInt(line.getOptionValue("state")); + OnlineStep step = OnlineStep.valueOf(line.getOptionValue("step")); + List violations = onlinedb.getViolations(workflowId, stateId, step); + if ( violations != null && !violations.isEmpty() ) { + Table table = new Table(8, BorderStyle.CLASSIC_WIDE); + StringWriter content = new StringWriter(); + CsvWriter cvsWriter = new CsvWriter(content, ','); + printHeaders(table, cvsWriter); + printValues(table, cvsWriter, stateId, step, violations, violationsFilter); + printOutput(table, content, line.hasOption("csv")); + cvsWriter.close(); + } else + System.out.println("\nNo violations for workflow "+workflowId+", step "+step.name()+" and state "+stateId); + } else if ( line.hasOption("state") ) { + Integer stateId = Integer.parseInt(line.getOptionValue("state")); + Map> stateViolations = onlinedb.getViolations(workflowId, stateId); + if ( stateViolations != null && !stateViolations.keySet().isEmpty() ) { + Table table = new Table(8, BorderStyle.CLASSIC_WIDE); + StringWriter content = new StringWriter(); + CsvWriter cvsWriter = new CsvWriter(content, ','); + printHeaders(table, cvsWriter); + OnlineStep[] steps = stateViolations.keySet().toArray(new OnlineStep[stateViolations.keySet().size()]); + Arrays.sort(steps); + for(OnlineStep step : steps) { + List violations = stateViolations.get(step); + if ( violations != null && !violations.isEmpty() ) { + printValues(table, cvsWriter, stateId, step, violations, violationsFilter); + } + } + cvsWriter.flush(); + printOutput(table, content, line.hasOption("csv")); + cvsWriter.close(); + } else + System.out.println("\nNo violations for workflow "+workflowId+" and state "+stateId); + } else if ( line.hasOption("step") ) { + OnlineStep step = OnlineStep.valueOf(line.getOptionValue("step")); + Map> stepViolations = onlinedb.getViolations(workflowId, step); + if ( stepViolations != null && !stepViolations.keySet().isEmpty() ) { + Table table = new Table(8, BorderStyle.CLASSIC_WIDE); + StringWriter content = new StringWriter(); + CsvWriter cvsWriter = new CsvWriter(content, ','); + printHeaders(table, cvsWriter); + Integer[] stateIds = stepViolations.keySet().toArray(new Integer[stepViolations.keySet().size()]); + Arrays.sort(stateIds); + for(Integer stateId : stateIds) { + List violations = stepViolations.get(stateId); + if ( violations != null && !violations.isEmpty() ) { + printValues(table, cvsWriter, stateId, step, violations, violationsFilter); + } + } + cvsWriter.flush(); + printOutput(table, content, line.hasOption("csv")); + cvsWriter.close(); + } else + System.out.println("\nNo violations for workflow "+workflowId+" and step "+step); + } else { + Map>> wfViolations = onlinedb.getViolations(workflowId); + if ( wfViolations != null && !wfViolations.keySet().isEmpty() ) { + Table table = new Table(8, BorderStyle.CLASSIC_WIDE); + StringWriter content = new StringWriter(); + CsvWriter cvsWriter = new CsvWriter(content, ','); + printHeaders(table, cvsWriter); + Integer[] stateIds = wfViolations.keySet().toArray(new Integer[wfViolations.keySet().size()]); + Arrays.sort(stateIds); + for(Integer stateId : stateIds) { + Map> stateViolations = wfViolations.get(stateId); + if ( stateViolations != null && !stateViolations.keySet().isEmpty() ) { + OnlineStep[] steps = stateViolations.keySet().toArray(new OnlineStep[stateViolations.keySet().size()]); + Arrays.sort(steps); + for(OnlineStep step : steps) { + List violations = stateViolations.get(step); + if ( violations != null && !violations.isEmpty() ) { + printValues(table, cvsWriter, stateId, step, violations, violationsFilter); + } + } + } + } + cvsWriter.flush(); + printOutput(table, content, line.hasOption("csv")); + cvsWriter.close(); + } else + System.out.println("\nNo violations for workflow "+workflowId); + } + onlinedb.close(); + } + + private void printHeaders(Table table, CsvWriter cvsWriter) throws IOException { + String[] headers = new String[8]; + int i = 0; table.addCell("State", new CellStyle(CellStyle.HorizontalAlign.center)); headers[i++] = "State"; table.addCell("Step", new CellStyle(CellStyle.HorizontalAlign.center)); @@ -195,41 +218,48 @@ private void printHeaders(Table table, CsvWriter cvsWriter) throws IOException { headers[i++] = "Limit"; table.addCell("Limit Reduction", new CellStyle(CellStyle.HorizontalAlign.center)); headers[i++] = "Limit Reduction"; + table.addCell("Voltage Level", new CellStyle(CellStyle.HorizontalAlign.center)); + headers[i++] = "Voltage Level"; cvsWriter.writeRecord(headers); - } - - private void printValues(Table table, CsvWriter cvsWriter, Integer stateId, OnlineStep step, List violations) throws IOException { - Collections.sort(violations, new Comparator() { - public int compare(LimitViolation o1, LimitViolation o2) { - return o1.getSubject().getId().compareTo(o2.getSubject().getId()); - } - }); - for (LimitViolation violation : violations) { - String[] values = new String[7]; - int i = 0; - table.addCell(Integer.toString(stateId), new CellStyle(CellStyle.HorizontalAlign.right)); - values[i++] = Integer.toString(stateId); - table.addCell(step.name(), new CellStyle(CellStyle.HorizontalAlign.left)); - values[i++] = step.name(); - table.addCell(violation.getSubject().getId(), new CellStyle(CellStyle.HorizontalAlign.left)); - values[i++] = violation.getSubject().getId(); - table.addCell(violation.getLimitType().name(), new CellStyle(CellStyle.HorizontalAlign.left)); - values[i++] = violation.getLimitType().name(); - table.addCell(Float.toString(violation.getValue()), new CellStyle(CellStyle.HorizontalAlign.right)); - values[i++] = Float.toString(violation.getValue()); - table.addCell(Float.toString(violation.getLimit()), new CellStyle(CellStyle.HorizontalAlign.right)); - values[i++] = Float.toString(violation.getLimit()); - table.addCell(Float.toString(violation.getLimitReduction()), new CellStyle(CellStyle.HorizontalAlign.right)); - values[i++] = Float.toString(violation.getLimitReduction()); - cvsWriter.writeRecord(values); - } - } - - private void printOutput(Table table, StringWriter content, boolean csv) { - if ( csv ) - System.out.println(content.toString()); - else - System.out.println(table.render()); - } - + } + + private void printValues(Table table, CsvWriter cvsWriter, Integer stateId, OnlineStep step, List violations, + LimitViolationFilter violationsFilter) throws IOException { + if ( violationsFilter != null ) + violations = violationsFilter.apply(violations); + Collections.sort(violations, new Comparator() { + public int compare(LimitViolation o1, LimitViolation o2) { + return o1.getSubject().getId().compareTo(o2.getSubject().getId()); + } + }); + for (LimitViolation violation : violations) { + String[] values = new String[8]; + int i = 0; + table.addCell(Integer.toString(stateId), new CellStyle(CellStyle.HorizontalAlign.right)); + values[i++] = Integer.toString(stateId); + table.addCell(step.name(), new CellStyle(CellStyle.HorizontalAlign.left)); + values[i++] = step.name(); + table.addCell(violation.getSubject().getId(), new CellStyle(CellStyle.HorizontalAlign.left)); + values[i++] = violation.getSubject().getId(); + table.addCell(violation.getLimitType().name(), new CellStyle(CellStyle.HorizontalAlign.left)); + values[i++] = violation.getLimitType().name(); + table.addCell(Float.toString(violation.getValue()), new CellStyle(CellStyle.HorizontalAlign.right)); + values[i++] = Float.toString(violation.getValue()); + table.addCell(Float.toString(violation.getLimit()), new CellStyle(CellStyle.HorizontalAlign.right)); + values[i++] = Float.toString(violation.getLimit()); + table.addCell(Float.toString(violation.getLimitReduction()), new CellStyle(CellStyle.HorizontalAlign.right)); + values[i++] = Float.toString(violation.getLimitReduction()); + table.addCell(Float.toString(violation.getBaseVoltage()), new CellStyle(CellStyle.HorizontalAlign.right)); + values[i++] = Float.toString(violation.getBaseVoltage()); + cvsWriter.writeRecord(values); + } + } + + private void printOutput(Table table, StringWriter content, boolean csv) { + if ( csv ) + System.out.println(content.toString()); + else + System.out.println(table.render()); + } + } diff --git a/pom.xml b/pom.xml index be495beb..602e9094 100644 --- a/pom.xml +++ b/pom.xml @@ -127,8 +127,9 @@ - scm:git:https://bitbucket.org/itesla/itesla.git - https://bitbucket.org/itesla/itesla.git + scm:git:https://github.com/itesla/ipst.git + scm:git:https://github.com/itesla/ipst.git + https://github.com/itesla/ipst