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

CGMES metadata models extension #2898

Merged
merged 30 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
39b04b0
CGMES metadata models extension
zamarrenolm Feb 13, 2024
5348e0f
checkstyle: whitespace
zamarrenolm Feb 13, 2024
01dd060
Merge branch 'main' into cgmes_metadata_models
zamarrenolm Feb 19, 2024
53f5051
Merge branch 'main' into cgmes_metadata_models
zamarrenolm Mar 7, 2024
10c32b9
Merge branch 'main' into cgmes_metadata_models
zamarrenolm Mar 7, 2024
c1dfc40
remove previous sv, ssh extensions and replace with new generic exten…
zamarrenolm Mar 7, 2024
04d3863
fixes from failing unit tests
zamarrenolm Mar 8, 2024
db2bb00
names in extension
zamarrenolm Mar 8, 2024
d43c1ae
always export models sorted; adjust names in test expected data
zamarrenolm Mar 8, 2024
fc6defd
remove debug code
zamarrenolm Mar 8, 2024
88d7f50
Merge branch 'main' into cgmes_metadata_models
zamarrenolm Mar 8, 2024
8b85452
add source of model (import or export); use enum for part (cgmes subset)
zamarrenolm Mar 11, 2024
3a8ba5e
Merge branch 'main' into cgmes_metadata_models
zamarrenolm Mar 11, 2024
7510cb1
ignore unknown subset in test
zamarrenolm Mar 11, 2024
0ca3f24
Merge branch 'main' into cgmes_metadata_models
zamarrenolm Mar 12, 2024
f8d998a
remove source of metadata model
zamarrenolm Mar 12, 2024
5bd9507
use a single class for storing CGMES metadata model information
zamarrenolm Mar 13, 2024
54fe16e
Merge branch 'main' into cgmes_metadata_models
zamarrenolm Mar 13, 2024
9d39929
Merge branch 'main' into cgmes_metadata_models
zamarrenolm Mar 14, 2024
705e84c
we do not need to store multiple identifiers in a metadata model
zamarrenolm Mar 14, 2024
17a2425
query fullModel for profile replace by fullModels
zamarrenolm Mar 15, 2024
9759a96
fix license data
zamarrenolm Mar 15, 2024
e1707e4
Merge branch 'main' into cgmes_metadata_models
zamarrenolm Mar 15, 2024
3c80f77
Merge branch 'main' into cgmes_metadata_models
zamarrenolm Mar 18, 2024
feeef19
Model part is an enum
zamarrenolm Mar 18, 2024
7ebd5c0
Merge branch 'main' into cgmes_metadata_models
zamarrenolm Mar 19, 2024
6e535d4
naming: uniform use of cgmes "subset" instead of "part"
zamarrenolm Mar 22, 2024
78e0c49
Merge branch 'main' into cgmes_metadata_models
zamarrenolm Mar 22, 2024
514e137
Add javadoc
rcourtier Mar 26, 2024
d27b2bd
Merge branch 'main' into cgmes_metadata_models
rcourtier Mar 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ private static void writeHeader(Network network, XMLStreamWriter writer, CgmesEx
String euNamespace = context.getCim().getEuNamespace();
CgmesExportUtil.writeRdfRoot(cimNamespace, context.getCim().getEuPrefix(), euNamespace, writer);
if (context.getCimVersion() >= 16) {
CgmesExportUtil.writeModelDescription(network, CgmesSubset.EQUIPMENT, writer, context.getEqModelDescription(), context);
CgmesExportUtil.writeModelDescription(network, CgmesSubset.EQUIPMENT, writer, context.getExportedEQModel(), context);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.powsybl.cgmes.conversion.export.*;
import com.powsybl.cgmes.conversion.naming.NamingStrategy;
import com.powsybl.cgmes.conversion.naming.NamingStrategyFactory;
import com.powsybl.cgmes.model.CgmesMetadataModel;
import com.powsybl.cgmes.model.CgmesNamespace;
import com.powsybl.commons.config.PlatformConfig;
import com.powsybl.commons.datasource.DataSource;
Expand Down Expand Up @@ -116,16 +117,16 @@ public void export(Network network, Properties params, DataSource ds, ReportNode
masUri = sourcingActor.get("masUri");
}

context.getEqModelDescription().setModelingAuthoritySet(masUri);
context.getTpModelDescription().setModelingAuthoritySet(masUri);
context.getSshModelDescription().setModelingAuthoritySet(masUri);
context.getSvModelDescription().setModelingAuthoritySet(masUri);
context.getExportedEQModel().setModelingAuthoritySet(masUri);
context.getExportedTPModel().setModelingAuthoritySet(masUri);
context.getExportedSSHModel().setModelingAuthoritySet(masUri);
context.getExportedSVModel().setModelingAuthoritySet(masUri);
String modelDescription = Parameter.readString(getFormat(), params, MODEL_DESCRIPTION_PARAMETER, defaultValueConfig);
if (modelDescription != null) {
context.getEqModelDescription().setDescription(modelDescription);
context.getTpModelDescription().setDescription(modelDescription);
context.getSshModelDescription().setDescription(modelDescription);
context.getSvModelDescription().setDescription(modelDescription);
context.getExportedEQModel().setDescription(modelDescription);
context.getExportedTPModel().setDescription(modelDescription);
context.getExportedSSHModel().setDescription(modelDescription);
context.getExportedSVModel().setDescription(modelDescription);
}
String cimVersionParam = Parameter.readString(getFormat(), params, CIM_VERSION_PARAMETER, defaultValueConfig);
if (cimVersionParam != null) {
Expand All @@ -134,10 +135,10 @@ public void export(Network network, Properties params, DataSource ds, ReportNode

String modelVersion = Parameter.readString(getFormat(), params, MODEL_VERSION_PARAMETER, defaultValueConfig);
if (modelVersion != null) {
context.getEqModelDescription().setVersion(Integer.parseInt(modelVersion));
context.getTpModelDescription().setVersion(Integer.parseInt(modelVersion));
context.getSshModelDescription().setVersion(Integer.parseInt(modelVersion));
context.getSvModelDescription().setVersion(Integer.parseInt(modelVersion));
context.getExportedEQModel().setVersion(Integer.parseInt(modelVersion));
context.getExportedTPModel().setVersion(Integer.parseInt(modelVersion));
context.getExportedSSHModel().setVersion(Integer.parseInt(modelVersion));
context.getExportedSVModel().setVersion(Integer.parseInt(modelVersion));
}

try {
Expand All @@ -149,24 +150,24 @@ public void export(Network network, Properties params, DataSource ds, ReportNode
EquipmentExport.write(network, writer, context);
}
} else {
addProfilesIdentifiers(network, "EQ", context.getEqModelDescription());
context.getEqModelDescription().addId(context.getNamingStrategy().getCgmesId(network));
addSubsetIdentifiers(network, "EQ", context.getExportedEQModel());
context.getExportedEQModel().setId(context.getNamingStrategy().getCgmesId(network));
}
if (profiles.contains("TP")) {
try (OutputStream out = new BufferedOutputStream(ds.newOutputStream(filenameTp, false))) {
XMLStreamWriter writer = XmlUtil.initializeWriter(true, INDENT, out);
TopologyExport.write(network, writer, context);
}
} else {
addProfilesIdentifiers(network, "TP", context.getTpModelDescription());
addSubsetIdentifiers(network, "TP", context.getExportedTPModel());
}
if (profiles.contains("SSH")) {
try (OutputStream out = new BufferedOutputStream(ds.newOutputStream(filenameSsh, false))) {
XMLStreamWriter writer = XmlUtil.initializeWriter(true, INDENT, out);
SteadyStateHypothesisExport.write(network, writer, context);
}
} else {
addProfilesIdentifiers(network, "SSH", context.getSshModelDescription());
addSubsetIdentifiers(network, "SSH", context.getExportedSSHModel());
}
if (profiles.contains("SV")) {
try (OutputStream out = new BufferedOutputStream(ds.newOutputStream(filenameSv, false))) {
Expand Down Expand Up @@ -198,8 +199,8 @@ private String getBoundaryId(String profile, Network network, Properties params,
return id;
}

private static void addProfilesIdentifiers(Network network, String profile, CgmesExportContext.ModelDescription description) {
description.setIds(network.getPropertyNames().stream()
private static void addSubsetIdentifiers(Network network, String profile, CgmesMetadataModel description) {
description.addDependentOn(network.getPropertyNames().stream()
.filter(p -> p.startsWith(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + profile + "_ID"))
.map(network::getProperty)
.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;

import static com.powsybl.cgmes.conversion.CgmesReports.importedCgmesNetworkReport;
import static com.powsybl.cgmes.conversion.Conversion.Config.StateProfile.SSH;
Expand Down Expand Up @@ -156,8 +157,7 @@ public Network convert(ReportNode reportNode) {
Network network = createNetwork();
Context context = createContext(network, reportNode);
assignNetworkProperties(context);
addCgmesSvMetadata(network, context);
addCgmesSshMetadata(network, context);
addMetadataModels(network, context);
addCimCharacteristics(network);
BaseVoltageMappingAdder bvAdder = network.newExtension(BaseVoltageMappingAdder.class);
cgmes.baseVoltages().forEach(bv -> bvAdder.addBaseVoltage(bv.getId("BaseVoltage"), bv.asDouble("nominalVoltage"), isBoundaryBaseVoltage(bv.getLocal("graph"))));
Expand Down Expand Up @@ -439,36 +439,72 @@ private void assignNetworkProperties(Context context) {
LOG.info("network forecastDistance : {}", context.network().getForecastDistance());
}

private void addCgmesSvMetadata(Network network, Context context) {
PropertyBags svDescription = cgmes.fullModel(CgmesSubset.STATE_VARIABLES.getProfile());
if (svDescription != null && !svDescription.isEmpty()) {
CgmesSvMetadataAdder adder = network.newExtension(CgmesSvMetadataAdder.class)
.setDescription(svDescription.get(0).get("description"))
.setSvVersion(readVersion(svDescription, context))
.setModelingAuthoritySet(svDescription.get(0).get("modelingAuthoritySet"));
svDescription.pluckLocals("DependentOn").forEach(adder::addDependency);
adder.add();
/**
* Read the model header (the FullModel node) that holds metadata information.
* The metadata will be stored in the {@link CgmesMetadataModels} extension.
* @param network The network described by the model header and that will hold the extension.
* @param context The conversion context.
*/
private void addMetadataModels(Network network, Context context) {
PropertyBags ps = cgmes.fullModels();
if (ps.isEmpty()) {
return;
}
CgmesMetadataModelsAdder modelsAdder = network.newExtension(CgmesMetadataModelsAdder.class);
for (PropertyBag p : ps) {
CgmesMetadataModelsAdder.ModelAdder modelAdder = modelsAdder.newModel()
.setId(p.getId("FullModel"))
.setSubset(subsetFromGraph(p.getLocal("graph")))
.setDescription(p.getId("description"))
.setVersion(readVersion(p, context))
.setModelingAuthoritySet(p.getId("modelingAuthoritySet"));
addMetadataModelReferences(p, "profileList", modelAdder::addProfile);
addMetadataModelReferences(p, "dependentOnList", modelAdder::addDependentOn);
addMetadataModelReferences(p, "supersedesList", modelAdder::addSupersedes);
modelAdder.add();
}
modelsAdder.add();
}

private void addCgmesSshMetadata(Network network, Context context) {
PropertyBags sshDescription = cgmes.fullModel(CgmesSubset.STEADY_STATE_HYPOTHESIS.getProfile());
if (sshDescription != null && !sshDescription.isEmpty()) {
CgmesSshMetadataAdder adder = network.newExtension(CgmesSshMetadataAdder.class)
.setId(sshDescription.get(0).get("FullModel"))
.setDescription(sshDescription.get(0).get("description"))
.setSshVersion(readVersion(sshDescription, context))
.setModelingAuthoritySet(sshDescription.get(0).get("modelingAuthoritySet"));
sshDescription.pluckLocals("DependentOn").forEach(adder::addDependency);
adder.add();
/**
* Add references (profiles, dependencies, supersedes) to the {@link CgmesMetadataModel} being created by the adder.
* @param p The property bag holding the references.
* @param refsProperty The property name to look for in the property bag.
* The property value must be split to retrieve the complete list of references.
* @param adder The method in the adder that will add the references to the model.
*/
private void addMetadataModelReferences(PropertyBag p, String refsProperty, Function<String, CgmesMetadataModelsAdder.ModelAdder> adder) {
String refs = p.get(refsProperty);
if (refs != null && !refs.isEmpty()) {
for (String ref : refs.split(" ")) {
adder.apply(ref);
}
}
}

private int readVersion(PropertyBags propertyBags, Context context) {
/**
* Retrieve the subset from the graph.
* @param graph The file name. It shall contain the subset identifier.
* @return The {@link CgmesSubset} corresponding to the graph.
*/
private CgmesSubset subsetFromGraph(String graph) {
return Stream.of(CgmesSubset.values())
.filter(subset -> subset.isValidName(graph))
.findFirst()
.orElse(CgmesSubset.UNKNOWN);
}

/**
* Retrieve the version number from the property bag.
* @param propertyBag The bag where to look for a version property.
* @param context The conversion context.
* @return The version number if found and is a proper integer, else the default value: 1.
*/
private int readVersion(PropertyBag propertyBag, Context context) {
try {
return propertyBags.get(0).asInt("version");
return propertyBag.asInt("version");
} catch (NumberFormatException e) {
context.fixed("Version", "The version is expected to be an integer: " + propertyBags.get(0).get("version") + ". Fixed to 1");
context.fixed("Version", "The version is expected to be an integer: " + propertyBag.get("version") + ". Fixed to 1");
return 1;
}
}
Expand Down
Loading