Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalize extensions #23

Merged
merged 10 commits into from
Apr 10, 2024
Merged
5 changes: 5 additions & 0 deletions network-store-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@
<artifactId>lombok</artifactId>
</dependency>
<!-- runtime scope -->
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-network-store-iidm-impl</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-config-classic</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
/**
* Copyright (c) 2024, 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 com.powsybl.network.store.server;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.powsybl.network.store.model.ExtensionAttributes;
import com.powsybl.network.store.model.IdentifiableAttributes;
import com.powsybl.network.store.model.Resource;
import com.powsybl.network.store.model.ResourceType;
import com.powsybl.network.store.server.dto.OwnerInfo;
import com.powsybl.network.store.server.exceptions.UncheckedSqlException;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.io.UncheckedIOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

import static com.powsybl.network.store.server.NetworkStoreRepository.BATCH_SIZE;
import static com.powsybl.network.store.server.Utils.bindValues;

/**
* @author Antoine Bouhours <antoine.bouhours at rte-france.com>
*/
@Component
public class ExtensionHandler {
private final DataSource dataSource;
private final ObjectMapper mapper;

public ExtensionHandler(DataSource dataSource, ObjectMapper mapper) {
this.dataSource = dataSource;
this.mapper = mapper;
}

public void insertExtensions(Map<OwnerInfo, Map<String, ExtensionAttributes>> extensions) {
try (var connection = dataSource.getConnection()) {
try (var preparedStmt = connection.prepareStatement(QueryExtensionCatalog.buildInsertExtensionsQuery())) {
List<Object> values = new ArrayList<>(6);
List<Map.Entry<OwnerInfo, Map<String, ExtensionAttributes>>> list = new ArrayList<>(extensions.entrySet());
for (List<Map.Entry<OwnerInfo, Map<String, ExtensionAttributes>>> subExtensions : Lists.partition(list, BATCH_SIZE)) {
for (Map.Entry<OwnerInfo, Map<String, ExtensionAttributes>> entry : subExtensions) {
for (Map.Entry<String, ExtensionAttributes> extension : entry.getValue().entrySet()) {
values.clear();
values.add(entry.getKey().getEquipmentId());
values.add(entry.getKey().getEquipmentType().toString());
values.add(entry.getKey().getNetworkUuid());
values.add(entry.getKey().getVariantNum());
values.add(extension.getKey());
values.add(extension.getValue());
bindValues(preparedStmt, values, mapper);
preparedStmt.addBatch();
}
}
preparedStmt.executeBatch();
}
}
} catch (SQLException e) {
throw new UncheckedSqlException(e);
}
}

public Map<OwnerInfo, Map<String, ExtensionAttributes>> getExtensionsWithInClause(UUID networkUuid, int variantNum, String columnNameForWhereClause, List<String> valuesForInClause) {
if (valuesForInClause.isEmpty()) {
return Collections.emptyMap();
}
try (var connection = dataSource.getConnection()) {
var preparedStmt = connection.prepareStatement(QueryExtensionCatalog.buildExtensionsWithInClauseQuery(columnNameForWhereClause, valuesForInClause.size()));
preparedStmt.setObject(1, networkUuid);
preparedStmt.setInt(2, variantNum);
for (int i = 0; i < valuesForInClause.size(); i++) {
preparedStmt.setString(3 + i, valuesForInClause.get(i));
}

return innerGetExtensions(preparedStmt);
} catch (SQLException e) {
throw new UncheckedSqlException(e);
}
}

public Map<OwnerInfo, Map<String, ExtensionAttributes>> getExtensions(UUID networkUuid, int variantNum, String columnNameForWhereClause, String valueForWhereClause) {
try (var connection = dataSource.getConnection()) {
var preparedStmt = connection.prepareStatement(QueryExtensionCatalog.buildExtensionsQuery(columnNameForWhereClause));
preparedStmt.setObject(1, networkUuid);
preparedStmt.setInt(2, variantNum);
preparedStmt.setString(3, valueForWhereClause);

return innerGetExtensions(preparedStmt);
} catch (SQLException e) {
throw new UncheckedSqlException(e);
}
}

private Map<OwnerInfo, Map<String, ExtensionAttributes>> innerGetExtensions(PreparedStatement preparedStmt) throws SQLException {
try (ResultSet resultSet = preparedStmt.executeQuery()) {
Map<OwnerInfo, Map<String, ExtensionAttributes>> map = new HashMap<>();
while (resultSet.next()) {

OwnerInfo owner = new OwnerInfo();
owner.setEquipmentId(resultSet.getString(1));
owner.setEquipmentType(ResourceType.valueOf(resultSet.getString(2)));
owner.setNetworkUuid(UUID.fromString(resultSet.getString(3)));
owner.setVariantNum(resultSet.getInt(4));

String extensionName = resultSet.getString(5);
ExtensionAttributes extensionValue = mapper.readValue(resultSet.getString(6), ExtensionAttributes.class);

map.computeIfAbsent(owner, k -> new HashMap<>());
map.get(owner).put(extensionName, extensionValue);
}
return map;
} catch (JsonProcessingException e) {
throw new UncheckedIOException(e);
}
}

public <T extends IdentifiableAttributes> Map<OwnerInfo, Map<String, ExtensionAttributes>> getExtensionsFromEquipments(UUID networkUuid, List<Resource<T>> resources) {
Map<OwnerInfo, Map<String, ExtensionAttributes>> map = new HashMap<>();

if (!resources.isEmpty()) {
for (Resource<T> resource : resources) {
Map<String, ExtensionAttributes> extensions = resource.getAttributes().getExtensionAttributes();
if (extensions != null && !extensions.isEmpty()) {
OwnerInfo info = new OwnerInfo(
resource.getId(),
resource.getType(),
networkUuid,
resource.getVariantNum()
);
map.put(info, extensions);
}
}
}
return map;
}

public <T extends IdentifiableAttributes> void insertExtensionsInEquipments(UUID networkUuid, List<Resource<T>> equipments, Map<OwnerInfo, Map<String, ExtensionAttributes>> extensions) {
if (!extensions.isEmpty() && !equipments.isEmpty()) {
for (Resource<T> equipmentAttributesResource : equipments) {
OwnerInfo owner = new OwnerInfo(
equipmentAttributesResource.getId(),
equipmentAttributesResource.getType(),
networkUuid,
equipmentAttributesResource.getVariantNum()
);
if (extensions.containsKey(owner)) {
T attributes = equipmentAttributesResource.getAttributes();
extensions.get(owner).forEach((key, value) -> {
if (attributes != null && attributes.getExtensionAttributes() != null) {
attributes.getExtensionAttributes().put(key, value);
}
});
}
}
}
}

public void deleteExtensions(UUID networkUuid, int variantNum, String equipmentId) {
deleteExtensions(networkUuid, variantNum, List.of(equipmentId));
}

public void deleteExtensions(UUID networkUuid, int variantNum, List<String> equipmentIds) {
try (var connection = dataSource.getConnection()) {
try (var preparedStmt = connection.prepareStatement(QueryExtensionCatalog.buildDeleteExtensionsVariantEquipmentINQuery(equipmentIds.size()))) {
preparedStmt.setObject(1, networkUuid);
preparedStmt.setInt(2, variantNum);
for (int i = 0; i < equipmentIds.size(); i++) {
preparedStmt.setString(3 + i, equipmentIds.get(i));
}
preparedStmt.executeUpdate();
}
} catch (SQLException e) {
throw new UncheckedSqlException(e);
}
}

public <T extends IdentifiableAttributes> void deleteExtensions(UUID networkUuid, List<Resource<T>> resources) {
Map<Integer, List<String>> resourceIdsByVariant = new HashMap<>();
for (Resource<T> resource : resources) {
List<String> resourceIds = resourceIdsByVariant.get(resource.getVariantNum());
if (resourceIds != null) {
resourceIds.add(resource.getId());
} else {
resourceIds = new ArrayList<>();
resourceIds.add(resource.getId());
}
resourceIdsByVariant.put(resource.getVariantNum(), resourceIds);
}
resourceIdsByVariant.forEach((k, v) -> deleteExtensions(networkUuid, k, v));
}

/**
* Extensions do not always exist in the variant and can be added by a
* modification for example. Instead of implementing an UPSERT, we delete then insert
* the extensions.
*/
public <T extends IdentifiableAttributes> void updateExtensions(UUID networkUuid, List<Resource<T>> resources) {
deleteExtensions(networkUuid, resources);
insertExtensions(getExtensionsFromEquipments(networkUuid, resources));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ public class Mappings {
private static final String CONNECTABLE_BUS = "connectableBus";
private static final String CONNECTABLE_BUS_1 = "connectableBus1";
private static final String CONNECTABLE_BUS_2 = "connectableBus2";
private static final String OPERATING_STATUS = "operatingStatus";
private static final String FICTITIOUS = "fictitious";
private static final String NODE = "node";
private static final String NODE_1 = "node1";
Expand Down Expand Up @@ -154,7 +153,6 @@ private void createLineMappings() {
lineMappings.addColumnMapping("bus2", new ColumnMapping<>(String.class, LineAttributes::getBus2, LineAttributes::setBus2));
lineMappings.addColumnMapping(CONNECTABLE_BUS_1, new ColumnMapping<>(String.class, LineAttributes::getConnectableBus1, LineAttributes::setConnectableBus1));
lineMappings.addColumnMapping(CONNECTABLE_BUS_2, new ColumnMapping<>(String.class, LineAttributes::getConnectableBus2, LineAttributes::setConnectableBus2));
lineMappings.addColumnMapping(OPERATING_STATUS, new ColumnMapping<>(String.class, LineAttributes::getOperatingStatus, LineAttributes::setOperatingStatus));
lineMappings.addColumnMapping("r", new ColumnMapping<>(Double.class, LineAttributes::getR, LineAttributes::setR));
lineMappings.addColumnMapping("x", new ColumnMapping<>(Double.class, LineAttributes::getX, LineAttributes::setX));
lineMappings.addColumnMapping("g1", new ColumnMapping<>(Double.class, LineAttributes::getG1, LineAttributes::setG1));
Expand Down Expand Up @@ -238,7 +236,6 @@ private void createGeneratorMappings() {
}
((MinMaxReactiveLimitsAttributes) attributes.getReactiveLimits()).setMaxQ(value);
}));
generatorMappings.addColumnMapping("activePowerControl", new ColumnMapping<>(ActivePowerControlAttributes.class, GeneratorAttributes::getActivePowerControl, GeneratorAttributes::setActivePowerControl));
generatorMappings.addColumnMapping(REGULATION_TERMINAL, new ColumnMapping<>(TerminalRefAttributes.class, GeneratorAttributes::getRegulatingTerminal, GeneratorAttributes::setRegulatingTerminal));
generatorMappings.addColumnMapping("coordinatedReactiveControl", new ColumnMapping<>(CoordinatedReactiveControlAttributes.class, GeneratorAttributes::getCoordinatedReactiveControl, GeneratorAttributes::setCoordinatedReactiveControl));
generatorMappings.addColumnMapping("remoteReactivePowerControl", new ColumnMapping<>(RemoteReactivePowerControlAttributes.class, GeneratorAttributes::getRemoteReactivePowerControl, GeneratorAttributes::setRemoteReactivePowerControl));
Expand All @@ -248,7 +245,6 @@ private void createGeneratorMappings() {
generatorMappings.addColumnMapping(ALIAS_BY_TYPE, new ColumnMapping<>(Map.class, GeneratorAttributes::getAliasByType, GeneratorAttributes::setAliasByType));
generatorMappings.addColumnMapping(ALIASES_WITHOUT_TYPE, new ColumnMapping<>(Set.class, GeneratorAttributes::getAliasesWithoutType, GeneratorAttributes::setAliasesWithoutType));
generatorMappings.addColumnMapping(POSITION, new ColumnMapping<>(ConnectablePositionAttributes.class, GeneratorAttributes::getPosition, GeneratorAttributes::setPosition));
generatorMappings.addColumnMapping("generatorStartup", new ColumnMapping<>(GeneratorStartupAttributes.class, GeneratorAttributes::getGeneratorStartupAttributes, GeneratorAttributes::setGeneratorStartupAttributes));
generatorMappings.addColumnMapping("generatorShortCircuit", new ColumnMapping<>(GeneratorShortCircuitAttributes.class, GeneratorAttributes::getGeneratorShortCircuitAttributes, GeneratorAttributes::setGeneratorShortCircuitAttributes));
}

Expand Down Expand Up @@ -373,7 +369,6 @@ private void createBatteryMappings() {
}
((MinMaxReactiveLimitsAttributes) attributes.getReactiveLimits()).setMaxQ(value);
}));
batteryMappings.addColumnMapping("activePowerControl", new ColumnMapping<>(ActivePowerControlAttributes.class, BatteryAttributes::getActivePowerControl, BatteryAttributes::setActivePowerControl));
batteryMappings.addColumnMapping("node", new ColumnMapping<>(Integer.class, BatteryAttributes::getNode, BatteryAttributes::setNode));
batteryMappings.addColumnMapping(PROPERTIES, new ColumnMapping<>(Map.class, BatteryAttributes::getProperties, BatteryAttributes::setProperties));
batteryMappings.addColumnMapping(ALIAS_BY_TYPE, new ColumnMapping<>(Map.class, BatteryAttributes::getAliasByType, BatteryAttributes::setAliasByType));
Expand Down Expand Up @@ -438,14 +433,12 @@ private void createDanglingLineMappings() {
danglingLineMappings.addColumnMapping(POSITION, new ColumnMapping<>(ConnectablePositionAttributes.class, DanglingLineAttributes::getPosition, DanglingLineAttributes::setPosition));
danglingLineMappings.addColumnMapping(SELECTED_OPERATIONAL_LIMITS_GROUP_ID_COLUMN, new ColumnMapping<>(String.class, DanglingLineAttributes::getSelectedOperationalLimitsGroupId, DanglingLineAttributes::setSelectedOperationalLimitsGroupId));
danglingLineMappings.addColumnMapping(TIE_LINE_ID, new ColumnMapping<>(String.class, DanglingLineAttributes::getTieLineId, DanglingLineAttributes::setTieLineId));
danglingLineMappings.addColumnMapping(OPERATING_STATUS, new ColumnMapping<>(String.class, DanglingLineAttributes::getOperatingStatus, DanglingLineAttributes::setOperatingStatus));
}

private void createTieLineMappings() {
tieLineMappings.addColumnMapping("name", new ColumnMapping<>(String.class, TieLineAttributes::getName, TieLineAttributes::setName));
tieLineMappings.addColumnMapping("danglingLine1Id", new ColumnMapping<>(String.class, TieLineAttributes::getDanglingLine1Id, TieLineAttributes::setDanglingLine1Id));
tieLineMappings.addColumnMapping("danglingLine2Id", new ColumnMapping<>(String.class, TieLineAttributes::getDanglingLine2Id, TieLineAttributes::setDanglingLine2Id));
tieLineMappings.addColumnMapping(OPERATING_STATUS, new ColumnMapping<>(String.class, TieLineAttributes::getOperatingStatus, TieLineAttributes::setOperatingStatus));
}

public TableMapping getTieLineMappings() {
Expand Down Expand Up @@ -596,7 +589,6 @@ private void createHvdcLineMappings() {
hvdcLineMappings.addColumnMapping("converterStationId2", new ColumnMapping<>(String.class, HvdcLineAttributes::getConverterStationId2, HvdcLineAttributes::setConverterStationId2));
hvdcLineMappings.addColumnMapping("hvdcAngleDroopActivePowerControl", new ColumnMapping<>(HvdcAngleDroopActivePowerControlAttributes.class, HvdcLineAttributes::getHvdcAngleDroopActivePowerControl, HvdcLineAttributes::setHvdcAngleDroopActivePowerControl));
hvdcLineMappings.addColumnMapping("hvdcOperatorActivePowerRange", new ColumnMapping<>(HvdcOperatorActivePowerRangeAttributes.class, HvdcLineAttributes::getHvdcOperatorActivePowerRange, HvdcLineAttributes::setHvdcOperatorActivePowerRange));
hvdcLineMappings.addColumnMapping(OPERATING_STATUS, new ColumnMapping<>(String.class, HvdcLineAttributes::getOperatingStatus, HvdcLineAttributes::setOperatingStatus));
}

public TableMapping getTwoWindingsTransformerMappings() {
Expand All @@ -611,7 +603,6 @@ private void createTwoWindingsTransformerMappings() {
twoWindingsTransformerMappings.addColumnMapping("bus2", new ColumnMapping<>(String.class, TwoWindingsTransformerAttributes::getBus2, TwoWindingsTransformerAttributes::setBus2));
twoWindingsTransformerMappings.addColumnMapping(CONNECTABLE_BUS_1, new ColumnMapping<>(String.class, TwoWindingsTransformerAttributes::getConnectableBus1, TwoWindingsTransformerAttributes::setConnectableBus1));
twoWindingsTransformerMappings.addColumnMapping(CONNECTABLE_BUS_2, new ColumnMapping<>(String.class, TwoWindingsTransformerAttributes::getConnectableBus2, TwoWindingsTransformerAttributes::setConnectableBus2));
twoWindingsTransformerMappings.addColumnMapping(OPERATING_STATUS, new ColumnMapping<>(String.class, TwoWindingsTransformerAttributes::getOperatingStatus, TwoWindingsTransformerAttributes::setOperatingStatus));
twoWindingsTransformerMappings.addColumnMapping("r", new ColumnMapping<>(Double.class, TwoWindingsTransformerAttributes::getR, TwoWindingsTransformerAttributes::setR));
twoWindingsTransformerMappings.addColumnMapping("x", new ColumnMapping<>(Double.class, TwoWindingsTransformerAttributes::getX, TwoWindingsTransformerAttributes::setX));
twoWindingsTransformerMappings.addColumnMapping("g", new ColumnMapping<>(Double.class, TwoWindingsTransformerAttributes::getG, TwoWindingsTransformerAttributes::setG));
Expand Down Expand Up @@ -814,7 +805,6 @@ public TableMapping getThreeWindingsTransformerMappings() {

private void createThreeWindingsTransformerMappings() {
threeWindingsTransformerMappings.addColumnMapping("name", new ColumnMapping<>(String.class, ThreeWindingsTransformerAttributes::getName, ThreeWindingsTransformerAttributes::setName));
threeWindingsTransformerMappings.addColumnMapping(OPERATING_STATUS, new ColumnMapping<>(String.class, ThreeWindingsTransformerAttributes::getOperatingStatus, ThreeWindingsTransformerAttributes::setOperatingStatus));
threeWindingsTransformerMappings.addColumnMapping("p1", new ColumnMapping<>(Double.class, ThreeWindingsTransformerAttributes::getP1, ThreeWindingsTransformerAttributes::setP1));
threeWindingsTransformerMappings.addColumnMapping("q1", new ColumnMapping<>(Double.class, ThreeWindingsTransformerAttributes::getQ1, ThreeWindingsTransformerAttributes::setQ1));
threeWindingsTransformerMappings.addColumnMapping("p2", new ColumnMapping<>(Double.class, ThreeWindingsTransformerAttributes::getP2, ThreeWindingsTransformerAttributes::setP2));
Expand Down
Loading
Loading