Skip to content

Commit 3f9926b

Browse files
Merge pull request #1450 from ie3-institute/ps/#1445-CsvToFile
Generalize CSV->File
2 parents 07ee1b6 + f5467c3 commit 3f9926b

24 files changed

+480
-322
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2525
- Extend `GermanVoltageLevelUtils` with more synonymousIds [#143](https://github.com/ie3-institute/PowerSystemDataModel/issues/143)
2626
- Change spotless to use googleJavaFormat('1.28.0') [#1409](https://github.com/ie3-institute/PowerSystemDataModel/issues/1409)
2727
- Change `TimeSeries` to no longer extend `UniqueEntity` [#1441](https://github.com/ie3-institute/PowerSystemDataModel/issues/1441)
28+
- Refactor CSV handling into shared file-based infrastructure. [#1450](https://github.com/ie3-institute/PowerSystemDataModel/issues/1445)
2829

2930
## [8.1.0] - 2025-07-25
3031

src/main/java/edu/ie3/datamodel/io/connectors/CsvFileConnector.java

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -29,28 +29,19 @@
2929
* @version 0.1
3030
* @since 19.03.20
3131
*/
32-
public class CsvFileConnector implements DataConnector {
32+
public class CsvFileConnector extends FileConnector {
3333
private static final Logger log = LoggerFactory.getLogger(CsvFileConnector.class);
3434

3535
private final Map<Class<? extends Entity>, BufferedCsvWriter> entityWriters = new HashMap<>();
3636
private final Map<UUID, BufferedCsvWriter> timeSeriesWriters = new HashMap<>();
37-
private final Path baseDirectory;
38-
private final Optional<Function<String, InputStream>> customInputStream;
3937
private static final String FILE_ENDING = ".csv";
4038

4139
public CsvFileConnector(Path baseDirectory) {
42-
this.baseDirectory = baseDirectory;
43-
this.customInputStream = Optional.empty();
40+
super(baseDirectory);
4441
}
4542

46-
public CsvFileConnector(Path baseDirectory, Function<String, InputStream> inputStreamSupplier) {
47-
this.baseDirectory = baseDirectory;
48-
this.customInputStream = Optional.ofNullable(inputStreamSupplier);
49-
}
50-
51-
/** Returns the base directory of this connector. */
52-
public Path getBaseDirectory() {
53-
return baseDirectory;
43+
public CsvFileConnector(Path baseDirectory, Function<String, InputStream> customInputStream) {
44+
super(baseDirectory, customInputStream);
5445
}
5546

5647
public synchronized BufferedCsvWriter getOrInitWriter(
@@ -94,6 +85,19 @@ BufferedCsvWriter getOrInitWriter(T timeSeries, CsvFileDefinition fileDefinition
9485
}
9586
}
9687

88+
/**
89+
* Initializes a reader for the given file name.
90+
*
91+
* @param filePath path of file starting from base folder, including file name but not file
92+
* extension
93+
* @return the reader that contains information about the file to be read in
94+
* @throws FileNotFoundException if no file with the provided file name can be found
95+
*/
96+
public BufferedReader initReader(Path filePath) throws FileNotFoundException {
97+
InputStream inputStream = openInputStream(filePath);
98+
return new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8), 16384);
99+
}
100+
97101
/**
98102
* Initializes a writer with the given base folder and file definition
99103
*
@@ -158,28 +162,6 @@ public synchronized <C extends Entity> void closeEntityWriter(Class<C> clz) thro
158162
}
159163
}
160164

161-
/**
162-
* Initializes a file reader for the given file name.
163-
*
164-
* @param filePath path of file starting from base folder, including file name but not file
165-
* extension
166-
* @return the reader that contains information about the file to be read in
167-
* @throws FileNotFoundException if no file with the provided file name can be found
168-
*/
169-
public BufferedReader initReader(Path filePath) throws FileNotFoundException {
170-
Path fullPath = baseDirectory.resolve(filePath.toString() + FILE_ENDING);
171-
172-
InputStream inputStream;
173-
174-
if (customInputStream.isPresent()) {
175-
inputStream = customInputStream.get().apply(fullPath.toString());
176-
} else {
177-
inputStream = new FileInputStream(fullPath.toFile());
178-
}
179-
180-
return new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8), 16384);
181-
}
182-
183165
@Override
184166
public void shutdown() {
185167
Stream.of(entityWriters.values(), timeSeriesWriters.values())
@@ -193,4 +175,9 @@ public void shutdown() {
193175
}
194176
});
195177
}
178+
179+
@Override
180+
protected String getFileEnding() {
181+
return FILE_ENDING;
182+
}
196183
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* © 2025. TU Dortmund University,
3+
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
4+
* Research group Distribution grid planning and operation
5+
*/
6+
package edu.ie3.datamodel.io.connectors;
7+
8+
import java.io.FileInputStream;
9+
import java.io.FileNotFoundException;
10+
import java.io.InputStream;
11+
import java.nio.file.Path;
12+
import java.util.function.Function;
13+
14+
/** Base connector for file-based sources and sinks. */
15+
public abstract class FileConnector implements DataConnector {
16+
17+
protected final Path baseDirectory;
18+
19+
/**
20+
* Optional factory for custom input streams; may be {@code null} when using the default handling.
21+
*/
22+
private final Function<String, InputStream> customInputStream;
23+
24+
protected FileConnector(Path baseDirectory) {
25+
this(baseDirectory, null);
26+
}
27+
28+
protected FileConnector(Path baseDirectory, Function<String, InputStream> customInputStream) {
29+
this.baseDirectory = baseDirectory;
30+
this.customInputStream = customInputStream;
31+
}
32+
33+
/** Returns the base directory backing this connector. */
34+
public Path getBaseDirectory() {
35+
return baseDirectory;
36+
}
37+
38+
/**
39+
* Open an {@link InputStream} to the given file path (without file ending) relative to the base
40+
* directory.
41+
*/
42+
protected InputStream openInputStream(Path filePath) throws FileNotFoundException {
43+
Path fullPath = resolveFilePath(filePath);
44+
if (customInputStream != null) {
45+
return customInputStream.apply(fullPath.toString());
46+
}
47+
return new FileInputStream(fullPath.toFile());
48+
}
49+
50+
/** Resolve the path including the file ending relative to the base directory. */
51+
protected Path resolveFilePath(Path filePath) {
52+
String relativePath = filePath.toString();
53+
if (!relativePath.endsWith(getFileEnding())) {
54+
relativePath = relativePath + getFileEnding();
55+
}
56+
return baseDirectory.resolve(relativePath);
57+
}
58+
59+
/** Returns the file ending (including the dot) handled by this connector. */
60+
protected abstract String getFileEnding();
61+
62+
@Override
63+
public void shutdown() {}
64+
}

src/main/java/edu/ie3/datamodel/io/csv/CsvLoadProfileMetaInformation.java

Lines changed: 0 additions & 55 deletions
This file was deleted.

src/main/java/edu/ie3/datamodel/io/factory/timeseries/TimeSeriesMetaInformationFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77

88
import edu.ie3.datamodel.io.factory.EntityData;
99
import edu.ie3.datamodel.io.factory.EntityFactory;
10-
import edu.ie3.datamodel.io.naming.TimeSeriesMetaInformation;
1110
import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme;
1211
import edu.ie3.datamodel.io.naming.timeseries.IndividualTimeSeriesMetaInformation;
1312
import edu.ie3.datamodel.io.naming.timeseries.LoadProfileMetaInformation;
13+
import edu.ie3.datamodel.io.naming.timeseries.TimeSeriesMetaInformation;
1414
import java.util.Collections;
1515
import java.util.List;
1616
import java.util.Set;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* © 2025. TU Dortmund University,
3+
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
4+
* Research group Distribution grid planning and operation
5+
*/
6+
package edu.ie3.datamodel.io.file;
7+
8+
import edu.ie3.datamodel.exceptions.ParsingException;
9+
import java.util.Arrays;
10+
import java.util.stream.Collectors;
11+
12+
public enum FileType {
13+
CSV(".csv");
14+
15+
public final String fileEnding;
16+
17+
FileType(String fileEnding) {
18+
this.fileEnding = fileEnding;
19+
}
20+
21+
public static FileType getFileType(String fileName) throws ParsingException {
22+
FileType[] fileTypes = FileType.values();
23+
return Arrays.stream(fileTypes)
24+
.filter(f -> fileName.endsWith(f.fileEnding))
25+
.findFirst()
26+
.orElseThrow(
27+
() ->
28+
new ParsingException(
29+
"No file ending found for file '"
30+
+ fileName
31+
+ "'. Only supports file types: "
32+
+ Arrays.stream(fileTypes)
33+
.map(t -> t.fileEnding)
34+
.collect(Collectors.joining(", "))));
35+
}
36+
}

src/main/java/edu/ie3/datamodel/io/naming/FileNamingStrategy.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import edu.ie3.datamodel.io.IoUtil;
99
import edu.ie3.datamodel.io.naming.timeseries.IndividualTimeSeriesMetaInformation;
1010
import edu.ie3.datamodel.io.naming.timeseries.LoadProfileMetaInformation;
11+
import edu.ie3.datamodel.io.naming.timeseries.TimeSeriesMetaInformation;
1112
import edu.ie3.datamodel.models.Entity;
1213
import edu.ie3.datamodel.models.timeseries.TimeSeries;
1314
import edu.ie3.datamodel.models.timeseries.TimeSeriesEntry;

src/main/java/edu/ie3/datamodel/io/csv/CsvIndividualTimeSeriesMetaInformation.java renamed to src/main/java/edu/ie3/datamodel/io/naming/timeseries/FileIndividualTimeSeriesMetaInformation.java

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,49 @@
33
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
44
* Research group Distribution grid planning and operation
55
*/
6-
package edu.ie3.datamodel.io.csv;
6+
package edu.ie3.datamodel.io.naming.timeseries;
77

8-
import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme;
9-
import edu.ie3.datamodel.io.naming.timeseries.IndividualTimeSeriesMetaInformation;
8+
import edu.ie3.datamodel.io.file.FileType;
109
import java.nio.file.Path;
1110
import java.util.Objects;
1211
import java.util.UUID;
1312

1413
/** Enhancing the {@link IndividualTimeSeriesMetaInformation} with the full path to csv file */
15-
public class CsvIndividualTimeSeriesMetaInformation extends IndividualTimeSeriesMetaInformation {
14+
public class FileIndividualTimeSeriesMetaInformation extends IndividualTimeSeriesMetaInformation {
1615
private final Path fullFilePath;
16+
private final FileType fileType;
1717

18-
public CsvIndividualTimeSeriesMetaInformation(
19-
UUID uuid, ColumnScheme columnScheme, Path fullFilePath) {
18+
public FileIndividualTimeSeriesMetaInformation(
19+
UUID uuid, ColumnScheme columnScheme, Path fullFilePath, FileType fileType) {
2020
super(uuid, columnScheme);
2121
this.fullFilePath = fullFilePath;
22+
this.fileType = fileType;
2223
}
2324

24-
public CsvIndividualTimeSeriesMetaInformation(
25-
IndividualTimeSeriesMetaInformation metaInformation, Path fullFilePath) {
26-
this(metaInformation.getUuid(), metaInformation.getColumnScheme(), fullFilePath);
25+
public FileIndividualTimeSeriesMetaInformation(
26+
IndividualTimeSeriesMetaInformation metaInformation, Path fullFilePath, FileType fileType) {
27+
this(metaInformation.getUuid(), metaInformation.getColumnScheme(), fullFilePath, fileType);
2728
}
2829

2930
public Path getFullFilePath() {
3031
return fullFilePath;
3132
}
3233

34+
public FileType getFileType() {
35+
return fileType;
36+
}
37+
3338
@Override
3439
public boolean equals(Object o) {
3540
if (this == o) return true;
36-
if (!(o instanceof CsvIndividualTimeSeriesMetaInformation that)) return false;
41+
if (!(o instanceof FileIndividualTimeSeriesMetaInformation that)) return false;
3742
if (!super.equals(o)) return false;
38-
return fullFilePath.equals(that.fullFilePath);
43+
return fullFilePath.equals(that.fullFilePath) && fileType.equals(that.fileType);
3944
}
4045

4146
@Override
4247
public int hashCode() {
43-
return Objects.hash(super.hashCode(), fullFilePath);
48+
return Objects.hash(super.hashCode(), fullFilePath, fileType);
4449
}
4550

4651
@Override
@@ -53,6 +58,8 @@ public String toString() {
5358
+ ", fullFilePath='"
5459
+ fullFilePath
5560
+ '\''
61+
+ ", fileType="
62+
+ fileType
5663
+ '}';
5764
}
5865
}

0 commit comments

Comments
 (0)