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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Extend `GermanVoltageLevelUtils` with more synonymousIds [#143](https://github.com/ie3-institute/PowerSystemDataModel/issues/143)
- Change spotless to use googleJavaFormat('1.28.0') [#1409](https://github.com/ie3-institute/PowerSystemDataModel/issues/1409)
- Change `TimeSeries` to no longer extend `UniqueEntity` [#1441](https://github.com/ie3-institute/PowerSystemDataModel/issues/1441)
- Refactor CSV handling into shared file-based infrastructure. [#1450](https://github.com/ie3-institute/PowerSystemDataModel/issues/1445)

## [8.1.0] - 2025-07-25

Expand Down
57 changes: 22 additions & 35 deletions src/main/java/edu/ie3/datamodel/io/connectors/CsvFileConnector.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,19 @@
* @version 0.1
* @since 19.03.20
*/
public class CsvFileConnector implements DataConnector {
public class CsvFileConnector extends FileConnector {
private static final Logger log = LoggerFactory.getLogger(CsvFileConnector.class);

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

public CsvFileConnector(Path baseDirectory) {
this.baseDirectory = baseDirectory;
this.customInputStream = Optional.empty();
super(baseDirectory);
}

public CsvFileConnector(Path baseDirectory, Function<String, InputStream> inputStreamSupplier) {
this.baseDirectory = baseDirectory;
this.customInputStream = Optional.ofNullable(inputStreamSupplier);
}

/** Returns the base directory of this connector. */
public Path getBaseDirectory() {
return baseDirectory;
public CsvFileConnector(Path baseDirectory, Function<String, InputStream> customInputStream) {
super(baseDirectory, customInputStream);
}

public synchronized BufferedCsvWriter getOrInitWriter(
Expand Down Expand Up @@ -94,6 +85,19 @@ BufferedCsvWriter getOrInitWriter(T timeSeries, CsvFileDefinition fileDefinition
}
}

/**
* Initializes a reader for the given file name.
*
* @param filePath path of file starting from base folder, including file name but not file
* extension
* @return the reader that contains information about the file to be read in
* @throws FileNotFoundException if no file with the provided file name can be found
*/
public BufferedReader initReader(Path filePath) throws FileNotFoundException {
InputStream inputStream = openInputStream(filePath);
return new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8), 16384);
}

/**
* Initializes a writer with the given base folder and file definition
*
Expand Down Expand Up @@ -158,28 +162,6 @@ public synchronized <C extends Entity> void closeEntityWriter(Class<C> clz) thro
}
}

/**
* Initializes a file reader for the given file name.
*
* @param filePath path of file starting from base folder, including file name but not file
* extension
* @return the reader that contains information about the file to be read in
* @throws FileNotFoundException if no file with the provided file name can be found
*/
public BufferedReader initReader(Path filePath) throws FileNotFoundException {
Path fullPath = baseDirectory.resolve(filePath.toString() + FILE_ENDING);

InputStream inputStream;

if (customInputStream.isPresent()) {
inputStream = customInputStream.get().apply(fullPath.toString());
} else {
inputStream = new FileInputStream(fullPath.toFile());
}

return new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8), 16384);
}

@Override
public void shutdown() {
Stream.of(entityWriters.values(), timeSeriesWriters.values())
Expand All @@ -193,4 +175,9 @@ public void shutdown() {
}
});
}

@Override
protected String getFileEnding() {
return FILE_ENDING;
}
}
64 changes: 64 additions & 0 deletions src/main/java/edu/ie3/datamodel/io/connectors/FileConnector.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* © 2025. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/
package edu.ie3.datamodel.io.connectors;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.function.Function;

/** Base connector for file-based sources and sinks. */
public abstract class FileConnector implements DataConnector {

protected final Path baseDirectory;

/**
* Optional factory for custom input streams; may be {@code null} when using the default handling.
*/
private final Function<String, InputStream> customInputStream;

protected FileConnector(Path baseDirectory) {
this(baseDirectory, null);
}

protected FileConnector(Path baseDirectory, Function<String, InputStream> customInputStream) {
this.baseDirectory = baseDirectory;
this.customInputStream = customInputStream;
}

/** Returns the base directory backing this connector. */
public Path getBaseDirectory() {
return baseDirectory;
}

/**
* Open an {@link InputStream} to the given file path (without file ending) relative to the base
* directory.
*/
protected InputStream openInputStream(Path filePath) throws FileNotFoundException {
Path fullPath = resolveFilePath(filePath);
if (customInputStream != null) {
return customInputStream.apply(fullPath.toString());
}
return new FileInputStream(fullPath.toFile());
}

/** Resolve the path including the file ending relative to the base directory. */
protected Path resolveFilePath(Path filePath) {
String relativePath = filePath.toString();
if (!relativePath.endsWith(getFileEnding())) {
relativePath = relativePath + getFileEnding();
}
return baseDirectory.resolve(relativePath);
}

/** Returns the file ending (including the dot) handled by this connector. */
protected abstract String getFileEnding();

@Override
public void shutdown() {}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

import edu.ie3.datamodel.io.factory.EntityData;
import edu.ie3.datamodel.io.factory.EntityFactory;
import edu.ie3.datamodel.io.naming.TimeSeriesMetaInformation;
import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme;
import edu.ie3.datamodel.io.naming.timeseries.IndividualTimeSeriesMetaInformation;
import edu.ie3.datamodel.io.naming.timeseries.LoadProfileMetaInformation;
import edu.ie3.datamodel.io.naming.timeseries.TimeSeriesMetaInformation;
import java.util.Collections;
import java.util.List;
import java.util.Set;
Expand Down
36 changes: 36 additions & 0 deletions src/main/java/edu/ie3/datamodel/io/file/FileType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* © 2025. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/
package edu.ie3.datamodel.io.file;

import edu.ie3.datamodel.exceptions.ParsingException;
import java.util.Arrays;
import java.util.stream.Collectors;

public enum FileType {
CSV(".csv");

public final String fileEnding;

FileType(String fileEnding) {
this.fileEnding = fileEnding;
}

public static FileType getFileType(String fileName) throws ParsingException {
FileType[] fileTypes = FileType.values();
return Arrays.stream(fileTypes)
.filter(f -> fileName.endsWith(f.fileEnding))
.findFirst()
.orElseThrow(
() ->
new ParsingException(
"No file ending found for file '"
+ fileName
+ "'. Only supports file types: "
+ Arrays.stream(fileTypes)
.map(t -> t.fileEnding)
.collect(Collectors.joining(", "))));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import edu.ie3.datamodel.io.IoUtil;
import edu.ie3.datamodel.io.naming.timeseries.IndividualTimeSeriesMetaInformation;
import edu.ie3.datamodel.io.naming.timeseries.LoadProfileMetaInformation;
import edu.ie3.datamodel.io.naming.timeseries.TimeSeriesMetaInformation;
import edu.ie3.datamodel.models.Entity;
import edu.ie3.datamodel.models.timeseries.TimeSeries;
import edu.ie3.datamodel.models.timeseries.TimeSeriesEntry;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,49 @@
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/
package edu.ie3.datamodel.io.csv;
package edu.ie3.datamodel.io.naming.timeseries;

import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme;
import edu.ie3.datamodel.io.naming.timeseries.IndividualTimeSeriesMetaInformation;
import edu.ie3.datamodel.io.file.FileType;
import java.nio.file.Path;
import java.util.Objects;
import java.util.UUID;

/** Enhancing the {@link IndividualTimeSeriesMetaInformation} with the full path to csv file */
public class CsvIndividualTimeSeriesMetaInformation extends IndividualTimeSeriesMetaInformation {
public class FileIndividualTimeSeriesMetaInformation extends IndividualTimeSeriesMetaInformation {
private final Path fullFilePath;
private final FileType fileType;

public CsvIndividualTimeSeriesMetaInformation(
UUID uuid, ColumnScheme columnScheme, Path fullFilePath) {
public FileIndividualTimeSeriesMetaInformation(
UUID uuid, ColumnScheme columnScheme, Path fullFilePath, FileType fileType) {
super(uuid, columnScheme);
this.fullFilePath = fullFilePath;
this.fileType = fileType;
}

public CsvIndividualTimeSeriesMetaInformation(
IndividualTimeSeriesMetaInformation metaInformation, Path fullFilePath) {
this(metaInformation.getUuid(), metaInformation.getColumnScheme(), fullFilePath);
public FileIndividualTimeSeriesMetaInformation(
IndividualTimeSeriesMetaInformation metaInformation, Path fullFilePath, FileType fileType) {
this(metaInformation.getUuid(), metaInformation.getColumnScheme(), fullFilePath, fileType);
}

public Path getFullFilePath() {
return fullFilePath;
}

public FileType getFileType() {
return fileType;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CsvIndividualTimeSeriesMetaInformation that)) return false;
if (!(o instanceof FileIndividualTimeSeriesMetaInformation that)) return false;
if (!super.equals(o)) return false;
return fullFilePath.equals(that.fullFilePath);
return fullFilePath.equals(that.fullFilePath) && fileType.equals(that.fileType);
}

@Override
public int hashCode() {
return Objects.hash(super.hashCode(), fullFilePath);
return Objects.hash(super.hashCode(), fullFilePath, fileType);
}

@Override
Expand All @@ -53,6 +58,8 @@ public String toString() {
+ ", fullFilePath='"
+ fullFilePath
+ '\''
+ ", fileType="
+ fileType
+ '}';
}
}
Loading