Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -17,6 +17,9 @@
import com.powsybl.commons.parameters.ParameterDefaultValueConfig;
import com.powsybl.commons.parameters.ParameterType;
import com.powsybl.ieeecdf.model.*;
import com.powsybl.ieeecdf.model.elements.IeeeCdfBranch;
import com.powsybl.ieeecdf.model.elements.IeeeCdfBus;
import com.powsybl.ieeecdf.model.elements.IeeeCdfTitle;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.extensions.SlackTerminal;
import com.powsybl.iidm.network.util.ContainersMapping;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
import com.powsybl.commons.PowsyblException;
import com.powsybl.commons.datasource.ResourceDataSource;
import com.powsybl.commons.datasource.ResourceSet;
import com.powsybl.ieeecdf.model.IeeeCdfBranch;
import com.powsybl.ieeecdf.model.IeeeCdfBus;
import com.powsybl.ieeecdf.model.elements.IeeeCdfBranch;
import com.powsybl.ieeecdf.model.elements.IeeeCdfBus;
import com.powsybl.ieeecdf.model.IeeeCdfModel;
import com.powsybl.ieeecdf.model.IeeeCdfTitle;
import com.powsybl.ieeecdf.model.elements.IeeeCdfTitle;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.NetworkFactory;
import com.univocity.parsers.csv.CsvParser;
Expand Down
9 changes: 5 additions & 4 deletions ieee-cdf/ieee-cdf-model/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.univocity</groupId>
<artifactId>univocity-parsers</artifactId>
</dependency>

<dependency>
<groupId>${project.groupId}</groupId>
Expand All @@ -69,6 +65,11 @@
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>

</dependencies>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
*/
package com.powsybl.ieeecdf.model;

import com.powsybl.ieeecdf.model.elements.IeeeCdfBranch;
import com.powsybl.ieeecdf.model.elements.IeeeCdfBus;
import com.powsybl.ieeecdf.model.elements.IeeeCdfInterchangeData;
import com.powsybl.ieeecdf.model.elements.IeeeCdfLossZone;
import com.powsybl.ieeecdf.model.elements.IeeeCdfTieLine;
import com.powsybl.ieeecdf.model.elements.IeeeCdfTitle;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,100 +7,70 @@
*/
package com.powsybl.ieeecdf.model;

import com.univocity.parsers.common.processor.BeanListProcessor;
import com.univocity.parsers.fixed.FixedWidthParser;
import com.univocity.parsers.fixed.FixedWidthParserSettings;
import com.google.re2j.Matcher;
import com.google.re2j.Pattern;
import com.powsybl.commons.PowsyblException;
import com.powsybl.ieeecdf.model.elements.IeeeCdfTitle;
import com.powsybl.ieeecdf.model.reader.IeeeCdfBranchReader;
import com.powsybl.ieeecdf.model.reader.IeeeCdfBusReader;
import com.powsybl.ieeecdf.model.reader.IeeeCdfInterchangeDataReader;
import com.powsybl.ieeecdf.model.reader.IeeeCdfLossZoneReader;
import com.powsybl.ieeecdf.model.reader.IeeeCdfTieLineReader;
import com.powsybl.ieeecdf.model.reader.IeeeCdfTitleReader;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
*/
public class IeeeCdfReader {

enum IeeeCdfSection {
BUS,
BRANCH,
LOSS_ZONES,
INTERCHANGE_DATA,
TIE_LINES
}
private static final Pattern PATTERN_BUS = Pattern.compile("BUS DATA FOLLOWS\\s+(\\d+)\\s+ITEMS");
private static final Pattern PATTERN_BRANCH = Pattern.compile("BRANCH DATA FOLLOWS\\s+(\\d+)\\s+ITEMS");
private static final Pattern PATTERN_LOSS_ZONE = Pattern.compile("LOSS ZONES FOLLOWS\\s+(\\d+)\\s+ITEMS");
private static final Pattern PATTERN_INTERCHANGE = Pattern.compile("INTERCHANGE DATA FOLLOWS\\s+(\\d+)\\s+ITEMS");
private static final Pattern PATTERN_TIE_LINE = Pattern.compile("TIE LINES FOLLOWS\\s+(\\d+)\\s+ITEMS");

public IeeeCdfModel read(BufferedReader reader) throws IOException {
String line = reader.readLine();
String line;

// Ensure malformed input does not trigger unexpected ArrayIndexOutOfBoundException
List<IeeeCdfTitle> parsedLines = parseLines(Collections.singletonList(line), IeeeCdfTitle.class);
if (parsedLines.isEmpty()) {
IeeeCdfTitle title = IeeeCdfTitleReader.parseTitle(reader);
if (title == null) {
throw new IllegalArgumentException("Failed to parse the IeeeCdfModel");
}

IeeeCdfTitle title = parsedLines.get(0);
IeeeCdfModel model = new IeeeCdfModel(title);

IeeeCdfSection section = null;
List<String> lines = new ArrayList<>();
while ((line = reader.readLine()) != null) {
if (line.startsWith("BUS DATA FOLLOWS")) {
section = IeeeCdfSection.BUS;
int expectedItemsNumber = getExpectedItemsNumber(line, PATTERN_BUS);
model.getBuses().addAll(IeeeCdfBusReader.parseBuses(reader, expectedItemsNumber));
} else if (line.startsWith("BRANCH DATA FOLLOWS")) {
section = IeeeCdfSection.BRANCH;
int expectedItemsNumber = getExpectedItemsNumber(line, PATTERN_BRANCH);
model.getBranches().addAll(IeeeCdfBranchReader.parseBranches(reader, expectedItemsNumber));
} else if (line.startsWith("LOSS ZONES FOLLOWS")) {
section = IeeeCdfSection.LOSS_ZONES;
int expectedItemsNumber = getExpectedItemsNumber(line, PATTERN_LOSS_ZONE);
model.getLossZones().addAll(IeeeCdfLossZoneReader.parseLossZones(reader, expectedItemsNumber));
} else if (line.startsWith("INTERCHANGE DATA FOLLOWS")) {
section = IeeeCdfSection.INTERCHANGE_DATA;
int expectedItemsNumber = getExpectedItemsNumber(line, PATTERN_INTERCHANGE);
model.getInterchangeData().addAll(IeeeCdfInterchangeDataReader.parseInterchangeData(reader, expectedItemsNumber));
} else if (line.startsWith("TIE LINES FOLLOWS ")) {
section = IeeeCdfSection.TIE_LINES;
} else if (line.startsWith("-9")) {
if (section != null) {
parseLines(lines, model, section);
lines.clear();
section = null;
}
} else {
if (section != null) {
lines.add(line);
}
int expectedItemsNumber = getExpectedItemsNumber(line, PATTERN_TIE_LINE);
model.getTieLines().addAll(IeeeCdfTieLineReader.parseTieLine(reader, expectedItemsNumber));
}
}

return model;
}

private static <T> List<T> parseLines(List<String> lines, Class<T> aClass) {
FixedWidthParserSettings settings = new FixedWidthParserSettings();
BeanListProcessor<T> processor = new BeanListProcessor<>(aClass);
settings.setProcessor(processor);
FixedWidthParser parser = new FixedWidthParser(settings);
for (String line : lines) {
parser.parseLine(line);
}
return processor.getBeans();
}

private void parseLines(List<String> lines, IeeeCdfModel model, IeeeCdfSection section) {
switch (section) {
case BUS:
model.getBuses().addAll(parseLines(lines, IeeeCdfBus.class));
break;
case BRANCH:
model.getBranches().addAll(parseLines(lines, IeeeCdfBranch.class));
break;
case LOSS_ZONES:
model.getLossZones().addAll(parseLines(lines, IeeeCdfLossZone.class));
break;
case INTERCHANGE_DATA:
model.getInterchangeData().addAll(parseLines(lines, IeeeCdfInterchangeData.class));
break;
case TIE_LINES:
model.getTieLines().addAll(parseLines(lines, IeeeCdfTieLine.class));
break;
default:
throw new IllegalStateException("Section unknown: " + section);
private static int getExpectedItemsNumber(String line, Pattern pattern) {
Matcher m = pattern.matcher(line);
if (m.matches()) {
return Integer.parseInt(m.group(1));
} else {
throw new PowsyblException("Failed to parse the expected number of IEEE-CDF items in:" + line);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
*/
package com.powsybl.ieeecdf.model;

import com.univocity.parsers.common.processor.BeanWriterProcessor;
import com.univocity.parsers.fixed.FixedWidthWriter;
import com.univocity.parsers.fixed.FixedWidthWriterSettings;
import com.powsybl.ieeecdf.model.writer.IeeeCdfBranchWriter;
import com.powsybl.ieeecdf.model.writer.IeeeCdfBusWriter;
import com.powsybl.ieeecdf.model.writer.IeeeCdfInterchangeDataWriter;
import com.powsybl.ieeecdf.model.writer.IeeeCdfLossZoneWriter;
import com.powsybl.ieeecdf.model.writer.IeeeCdfTieLineWriter;
import com.powsybl.ieeecdf.model.writer.IeeeCdfTitleWriter;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
Expand All @@ -29,47 +29,14 @@ public IeeeCdfWriter(IeeeCdfModel model) {
this.model = Objects.requireNonNull(model);
}

private static <T> void writeRecords(Writer writer, List<T> beans, Class<T> aClass) {
FixedWidthWriterSettings settings = new FixedWidthWriterSettings();
settings.setWriteLineSeparatorAfterRecord(true);
BeanWriterProcessor<T> processor = new BeanWriterProcessor<>(aClass);
settings.setRowWriterProcessor(processor);
new FixedWidthWriter(writer, settings).processRecords(beans);
}

public void write(BufferedWriter writer) throws IOException {

writeRecords(writer, Collections.singletonList(model.getTitle()), IeeeCdfTitle.class);

writer.write(String.format("BUS DATA FOLLOWS %d ITEMS", model.getBuses().size()));
writer.newLine();
writeRecords(writer, model.getBuses(), IeeeCdfBus.class);
writer.write("-999");
writer.newLine();

writer.write(String.format("BRANCH DATA FOLLOWS %d ITEMS", model.getBranches().size()));
writer.newLine();
writeRecords(writer, model.getBranches(), IeeeCdfBranch.class);
writer.write("-999");
writer.newLine();

writer.write(String.format("LOSS ZONES FOLLOWS %d ITEMS", model.getLossZones().size()));
writer.newLine();
writeRecords(writer, model.getLossZones(), IeeeCdfLossZone.class);
writer.write("-99");
writer.newLine();

writer.write(String.format("INTERCHANGE DATA FOLLOWS %d ITEMS", model.getInterchangeData().size()));
writer.newLine();
writeRecords(writer, model.getInterchangeData(), IeeeCdfInterchangeData.class);
writer.write("-9");
writer.newLine();

writer.write(String.format("TIE LINES FOLLOWS %d ITEMS", model.getTieLines().size()));
writer.newLine();
writeRecords(writer, model.getTieLines(), IeeeCdfTieLine.class);
writer.write("-999");
writer.newLine();
IeeeCdfTitleWriter.writeTitle(writer, model.getTitle());
IeeeCdfBusWriter.writeBuses(writer, model.getBuses());
IeeeCdfBranchWriter.writeBranches(writer, model.getBranches());
IeeeCdfLossZoneWriter.writeLossZone(writer, model.getLossZones());
IeeeCdfInterchangeDataWriter.writeInterchangeData(writer, model.getInterchangeData());
IeeeCdfTieLineWriter.writeTieLines(writer, model.getTieLines());

writer.write("END OF DATA");
writer.newLine();
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
/**
* Copyright (c) 2019, RTE (http://www.rte-france.com)
/*
* Copyright (c) 2019-2025, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.ieeecdf.model;
package com.powsybl.ieeecdf.model.conversion;

import com.univocity.parsers.conversions.ObjectConversion;
import com.powsybl.ieeecdf.model.elements.IeeeCdfBranch;

/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
*/
public class BranchSideConversion extends ObjectConversion<IeeeCdfBranch.Side> {
public final class BranchSideConversion {

private BranchSideConversion() {
// Utility class
}

@Override
protected IeeeCdfBranch.Side fromString(String str) {
public static IeeeCdfBranch.Side fromString(String str) {
return IeeeCdfBranch.Side.values()[Integer.parseInt(str.trim())];
}

@Override
public String revert(IeeeCdfBranch.Side side) {
public static String revert(IeeeCdfBranch.Side side) {
return side == null ? "" : Integer.toString(side.ordinal());
}
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
/**
* Copyright (c) 2019, RTE (http://www.rte-france.com)
/*
* Copyright (c) 2019-2025, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.ieeecdf.model;
package com.powsybl.ieeecdf.model.conversion;

import com.univocity.parsers.conversions.ObjectConversion;
import com.powsybl.ieeecdf.model.elements.IeeeCdfBranch;

/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
*/
public class BranchTypeConversion extends ObjectConversion<IeeeCdfBranch.Type> {
public final class BranchTypeConversion {

private BranchTypeConversion() {
// Utility class
}

@Override
protected IeeeCdfBranch.Type fromString(String str) {
public static IeeeCdfBranch.Type fromString(String str) {
String trimmedStr = str.trim();
return trimmedStr.isEmpty() ? null : IeeeCdfBranch.Type.values()[Integer.parseInt(trimmedStr)];
}

@Override
public String revert(IeeeCdfBranch.Type type) {
public static String revert(IeeeCdfBranch.Type type) {
return type == null ? "" : Integer.toString(type.ordinal());
}
}
Loading