Skip to content

Refactoring TimeSeriesTypeSource and cleaning up CsvFileConnector #566

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

Merged
merged 17 commits into from
Jul 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
d01bda5
Refactoring TimeSeriesTypeSource to TimeSeriesMetaInformationSource
sebastian-peter Mar 16, 2022
3b09288
Merge branch 'dev' into sp/#565-restructure-timeseries-meta-information
sebastian-peter Mar 17, 2022
0ee55fc
Cleaning up CsvFileConnector and friends regarding time series meta i…
sebastian-peter Mar 17, 2022
dae2b16
Adapting CHANGELOG.md
sebastian-peter Mar 17, 2022
3214828
Adding comments to SQL schemata
sebastian-peter Mar 18, 2022
8da958f
Improving comment in test SQL files
sebastian-peter Apr 5, 2022
3912107
Merge branch 'dev' into sp/#565-restructure-timeseries-meta-information
sebastian-peter Apr 5, 2022
c388589
Removing deprecated SQL test files
sebastian-peter Apr 5, 2022
36f065b
Adapting CsvFileConnectorTest because resource has been moved
sebastian-peter Apr 5, 2022
165914a
Merge branch 'dev' into sp/#565-restructure-timeseries-meta-information
sebastian-peter Apr 8, 2022
5faa8b2
Merge branch 'dev' into sp/#565-restructure-timeseries-meta-information
sebastian-peter May 2, 2022
6648fea
Merge branch 'dev' into sp/#565-restructure-timeseries-meta-information
sebastian-peter May 4, 2022
191b088
Merge branch 'dev' into sp/#565-restructure-timeseries-meta-information
sebastian-peter May 25, 2022
57a0747
Merge branch 'dev' into sp/#565-restructure-timeseries-meta-information
sebastian-peter May 29, 2022
a4b4b65
Merge branch 'dev' into sp/#565-restructure-timeseries-meta-information
sebastian-peter Jun 27, 2022
4a9ee65
Merge branch 'dev' into sp/#565-restructure-timeseries-meta-information
sebastian-peter Jul 10, 2022
37db9b0
Merge branch 'dev' into sp/#565-restructure-timeseries-meta-information
danielfeismann Jul 30, 2022
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- SQL time series sources (`SqlTimeSeriesSource` and `SqlTimeSeriesMappingSource`) [#467](https://github.com/ie3-institute/PowerSystemDataModel/issues/467)
- SQL time series have a different structure than CSV counterparts [#545](https://github.com/ie3-institute/PowerSystemDataModel/issues/545)
- Graph with impedance weighted edges including facilities to create it [#440](https://github.com/ie3-institute/PowerSystemDataModel/issues/440)
- `TimeSeriesTypeSource` providing a source for the mapping of time series uuids to column schemes (previously provided by `TimeSeriesMappingSource`) [#515](https://github.com/ie3-institute/PowerSystemDataModel/issues/515)
- `TimeSeriesMetaInformationSource` providing a source for the mapping of time series uuids to column schemes (previously provided by `TimeSeriesMappingSource`) [#515](https://github.com/ie3-institute/PowerSystemDataModel/issues/515)
- `TemperatureDependantLoadProfile`s for depiction of profile behavior of night storage heating and heat pumps [#601](https://github.com/ie3-institute/PowerSystemDataModel/issues/601)
- `ThermalUnits` as a container to hold all thermal units [#134](https://github.com/ie3-institute/PowerSystemDataModel/issues/134)
- `ThermalInput` as a distinct abstract class for all thermal models
Expand All @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Create JavaDoc with java 17 instead of java 8
- Let JavDoc pass, if there are warnings **ATTENTION:** Should be removed, when JavaDoc is fixed! (cf. Issue [#494](https://github.com/ie3-institute/PowerSystemDataModel/issues/494))
- `BufferedCsvWriter` writes columns in the order, that the headline elements are defined [#434](https://github.com/ie3-institute/PowerSystemDataModel/issues/393)
- Cleaned up `IndividualTimeSeriesMetaInformation`-related methods in `CsvFileConnector` [#544](https://github.com/ie3-institute/PowerSystemDataModel/issues/544)

### Changed
- BREAKING: PvInput Model parameter name height changed to elevationAngle [#393](https://github.com/ie3-institute/PowerSystemDataModel/issues/393) :warning:
Expand Down
132 changes: 22 additions & 110 deletions src/main/java/edu/ie3/datamodel/io/connectors/CsvFileConnector.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.io.FilenameUtils;
Expand All @@ -42,8 +43,10 @@ public class CsvFileConnector implements DataConnector {
new HashMap<>();
private final Map<UUID, BufferedCsvWriter> timeSeriesWriters = new HashMap<>();
// ATTENTION: Do not finalize. It's meant for lazy evaluation.
@Deprecated(since = "3.0", forRemoval = true)
private Map<UUID, edu.ie3.datamodel.io.csv.CsvIndividualTimeSeriesMetaInformation>
individualTimeSeriesMetaInformation;

private final FileNamingStrategy fileNamingStrategy;
private final String baseDirectoryName;

Expand Down Expand Up @@ -221,87 +224,45 @@ public BufferedReader initReader(String filePath) throws FileNotFoundException {
*
* @param timeSeriesUuid The time series in question
* @return An option on the queried information
* @deprecated since 3.0. Use {@link #getIndividualTimeSeriesMetaInformation()} instead
* @deprecated since 3.0. Use {@link #getCsvIndividualTimeSeriesMetaInformation(ColumnScheme...)}
* instead
*/
@Deprecated(since = "3.0", forRemoval = true)
public Optional<edu.ie3.datamodel.io.csv.timeseries.IndividualTimeSeriesMetaInformation>
getIndividualTimeSeriesMetaInformation(UUID timeSeriesUuid) {
if (Objects.isNull(individualTimeSeriesMetaInformation))
individualTimeSeriesMetaInformation = buildIndividualTimeSeriesMetaInformation();
individualTimeSeriesMetaInformation = getCsvIndividualTimeSeriesMetaInformation();

return Optional.ofNullable(individualTimeSeriesMetaInformation.get(timeSeriesUuid))
.map(edu.ie3.datamodel.io.csv.timeseries.IndividualTimeSeriesMetaInformation::new);
}

/**
* Get time series meta information
*
* <p>This method lazily evaluates the mapping from <i>all</i> time series files to their meta
* information.
* Receive the information for specific time series. They are given back filtered by the column
* scheme in order to allow for accounting the different content types.
*
* @return All time series meta information
* @param columnSchemes the column schemes to initialize readers for. If no scheme is given, all
* possible readers will be initialized.
* @return A mapping from column scheme to the individual time series meta information
*/
public Map<UUID, edu.ie3.datamodel.io.csv.CsvIndividualTimeSeriesMetaInformation>
getIndividualTimeSeriesMetaInformation() {
if (Objects.isNull(individualTimeSeriesMetaInformation))
individualTimeSeriesMetaInformation = buildIndividualTimeSeriesMetaInformation();

return individualTimeSeriesMetaInformation;
}

/**
* This method creates a map from time series uuid to it's meta information.
*
* @return Mapping from time series uuid to it's meta information.
*/
private Map<UUID, edu.ie3.datamodel.io.csv.CsvIndividualTimeSeriesMetaInformation>
buildIndividualTimeSeriesMetaInformation() {
getCsvIndividualTimeSeriesMetaInformation(final ColumnScheme... columnSchemes) {
return getIndividualTimeSeriesFilePaths().parallelStream()
.map(
filePath -> {
/* Extract meta information from file path and enhance it with the file path itself */
String filePathWithoutEnding = removeFileEnding(filePath);
IndividualTimeSeriesMetaInformation metaInformation =
(IndividualTimeSeriesMetaInformation)
fileNamingStrategy.timeSeriesMetaInformation(filePathWithoutEnding);
fileNamingStrategy.individualTimeSeriesMetaInformation(filePath);
return new edu.ie3.datamodel.io.csv.CsvIndividualTimeSeriesMetaInformation(
metaInformation, filePathWithoutEnding);
})
.collect(Collectors.toMap(TimeSeriesMetaInformation::getUuid, v -> v));
}

/**
* Receive the information for specific time series. They are given back grouped by the column
* scheme in order to allow for accounting the different content types.
*
* @param columnSchemes the column schemes to initialize readers for. If no scheme is given, all
* possible readers will be initialized.
* @return A mapping from column scheme to the individual time series meta information
*/
public Map<ColumnScheme, Set<edu.ie3.datamodel.io.csv.CsvIndividualTimeSeriesMetaInformation>>
getCsvIndividualTimeSeriesMetaInformation(ColumnScheme... columnSchemes) {
return getIndividualTimeSeriesFilePaths().parallelStream()
.map(
pathString -> {
String filePathWithoutEnding = removeFileEnding(pathString);
return buildCsvTimeSeriesMetaInformation(filePathWithoutEnding, columnSchemes);
metaInformation, FileNamingStrategy.removeFileNameEnding(filePath));
})
.filter(Optional::isPresent)
.map(Optional::get)
.collect(
Collectors.groupingBy(
edu.ie3.datamodel.io.csv.CsvIndividualTimeSeriesMetaInformation::getColumnScheme,
Collectors.toSet()));
}

/**
* Removes the file ending from input string
*
* @param input String to manipulate
* @return input without possible ending
*/
private String removeFileEnding(String input) {
return input.replaceAll(FILE_ENDING + "$", "");
.filter(
metaInformation ->
columnSchemes == null
|| columnSchemes.length == 0
|| Stream.of(columnSchemes)
.anyMatch(scheme -> scheme.equals(metaInformation.getColumnScheme())))
.collect(Collectors.toMap(TimeSeriesMetaInformation::getUuid, Function.identity()));
}

/**
Expand All @@ -320,7 +281,7 @@ private Set<String> getIndividualTimeSeriesFilePaths() {
.map(baseDirectoryPath::relativize)
.filter(
path -> {
String withoutEnding = removeFileEnding(path.toString());
String withoutEnding = FileNamingStrategy.removeFileNameEnding(path.toString());
return fileNamingStrategy
.getIndividualTimeSeriesPattern()
.matcher(withoutEnding)
Expand All @@ -334,55 +295,6 @@ private Set<String> getIndividualTimeSeriesFilePaths() {
}
}

/**
* Compose the needed information for reading in a single time series. If the file points to a
* non-individual time series or a time series of a column scheme other than the specified ones,
* or the initialisation of the reader does not work, an empty {@link Optional} is given back
*
* @param filePathString String describing the path to the time series file
* @param columnSchemes the allowed column schemes. If no scheme is specified, all schemes are
* allowed.
* @return An {@link Optional} to {@link IndividualTimeSeriesMetaInformation}
*/
private Optional<edu.ie3.datamodel.io.csv.CsvIndividualTimeSeriesMetaInformation>
buildCsvTimeSeriesMetaInformation(String filePathString, ColumnScheme... columnSchemes) {
try {
TimeSeriesMetaInformation metaInformation =
fileNamingStrategy.timeSeriesMetaInformation(filePathString);
if (!IndividualTimeSeriesMetaInformation.class.isAssignableFrom(metaInformation.getClass())) {
log.error(
"The time series file '{}' does not represent an individual time series.",
filePathString);
return Optional.empty();
}

IndividualTimeSeriesMetaInformation individualMetaInformation =
(IndividualTimeSeriesMetaInformation) metaInformation;

// If no column schemes are specified, we will include all. If there a specified schemes, we
// check if the file's column scheme matches any of them
if (columnSchemes != null
&& columnSchemes.length > 0
&& Stream.of(columnSchemes)
.noneMatch(scheme -> scheme.equals(individualMetaInformation.getColumnScheme()))) {
log.warn(
"The column scheme of the time series file {} does not match any of the specified column schemes ({}), so it will not be processed.",
filePathString,
columnSchemes);
return Optional.empty();
}
return Optional.of(
new edu.ie3.datamodel.io.csv.CsvIndividualTimeSeriesMetaInformation(
individualMetaInformation.getUuid(),
individualMetaInformation.getColumnScheme(),
filePathString));
} catch (IllegalArgumentException e) {
log.error(
"Error during extraction of meta information from file name '{}'.", filePathString, e);
return Optional.empty();
}
}

/**
* Initialises a reader to get grip on the file that contains mapping information between
* coordinate id and actual coordinate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import edu.ie3.datamodel.io.factory.EntityFactory;
import edu.ie3.datamodel.io.factory.SimpleEntityData;
import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme;
import edu.ie3.datamodel.io.source.TimeSeriesTypeSource;
import edu.ie3.datamodel.io.naming.timeseries.IndividualTimeSeriesMetaInformation;
import java.util.Collections;
import java.util.List;
import java.util.Set;
Expand All @@ -17,15 +17,16 @@
import java.util.stream.Stream;

/**
* Factory that creates {@link TimeSeriesTypeSource.TypeEntry} entities from source field mappings
* Factory that creates {@link IndividualTimeSeriesMetaInformation} entities from source field
* mappings
*/
public class TimeSeriesTypeFactory
extends EntityFactory<TimeSeriesTypeSource.TypeEntry, SimpleEntityData> {
public class TimeSeriesMetaInformationFactory
extends EntityFactory<IndividualTimeSeriesMetaInformation, SimpleEntityData> {
private static final String TIME_SERIES = "timeSeries";
private static final String COLUMN_SCHEME = "columnScheme";

public TimeSeriesTypeFactory() {
super(TimeSeriesTypeSource.TypeEntry.class);
public TimeSeriesMetaInformationFactory() {
super(IndividualTimeSeriesMetaInformation.class);
}

@Override
Expand All @@ -35,9 +36,9 @@ protected List<Set<String>> getFields(SimpleEntityData data) {
}

@Override
protected TimeSeriesTypeSource.TypeEntry buildModel(SimpleEntityData data) {
protected IndividualTimeSeriesMetaInformation buildModel(SimpleEntityData data) {
UUID timeSeries = data.getUUID(TIME_SERIES);
ColumnScheme columnScheme = ColumnScheme.parse(data.getField(COLUMN_SCHEME)).orElseThrow();
return new TimeSeriesTypeSource.TypeEntry(timeSeries, columnScheme);
return new IndividualTimeSeriesMetaInformation(timeSeries, columnScheme);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ public FileNameMetaInformation extractTimeSeriesMetaInformation(String fileName)
*/
public TimeSeriesMetaInformation timeSeriesMetaInformation(String fileName) {
/* Remove the file ending (ending limited to 255 chars, which is the max file name allowed in NTFS and ext4) */
String withoutEnding = fileName.replaceAll("(?:\\.[^\\\\/\\s]{1,255}){1,2}$", "");
String withoutEnding = removeFileNameEnding(fileName);

if (getIndividualTimeSeriesPattern().matcher(withoutEnding).matches())
return entityPersistenceNamingStrategy.individualTimesSeriesMetaInformation(withoutEnding);
Expand All @@ -285,6 +285,15 @@ else if (getLoadProfileTimeSeriesPattern().matcher(withoutEnding).matches())
"Unknown format of '" + fileName + "'. Cannot extract meta information.");
}

public IndividualTimeSeriesMetaInformation individualTimeSeriesMetaInformation(String fileName) {
return entityPersistenceNamingStrategy.individualTimesSeriesMetaInformation(
removeFileNameEnding(fileName));
}

public static String removeFileNameEnding(String fileName) {
return fileName.replaceAll("(?:\\.[^.\\\\/\\s]{1,255}){1,2}$", "");
}

/**
* Get the entity name for coordinates
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,13 @@
*/
package edu.ie3.datamodel.io.naming;

import java.util.Objects;
import edu.ie3.datamodel.models.input.InputEntity;
import java.util.UUID;

/** Meta information, that describe a certain data source */
public abstract class TimeSeriesMetaInformation {
private final UUID uuid;
public abstract class TimeSeriesMetaInformation extends InputEntity {

protected TimeSeriesMetaInformation(UUID uuid) {
this.uuid = uuid;
}

public UUID getUuid() {
return uuid;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof TimeSeriesMetaInformation that)) return false;
return uuid.equals(that.uuid);
}

@Override
public int hashCode() {
return Objects.hash(uuid);
}

@Override
public String toString() {
return "TimeSeriesMetaInformation{" + "uuid=" + uuid + '}';
super(uuid);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ default Optional<UUID> getTimeSeriesUuid(UUID modelIdentifier) {
*
* @param timeSeriesUuid Unique identifier of the time series in question
* @return An Option onto the meta information
* @deprecated since 3.0. Use {@link TimeSeriesTypeSource#getTimeSeriesMetaInformation()} instead
* @deprecated since 3.0. Use {@link
* TimeSeriesMetaInformationSource#getTimeSeriesMetaInformation()} instead
*/
@Deprecated(since = "3.0", forRemoval = true)
Optional<edu.ie3.datamodel.io.csv.timeseries.IndividualTimeSeriesMetaInformation>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* © 2022. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/
package edu.ie3.datamodel.io.source;

import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme;
import edu.ie3.datamodel.io.naming.timeseries.IndividualTimeSeriesMetaInformation;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;

/** Source for all available time series with their {@link UUID} and {@link ColumnScheme} */
public interface TimeSeriesMetaInformationSource extends DataSource {

/**
* Get a mapping from time series {@link UUID} to its meta information {@link
* IndividualTimeSeriesMetaInformation}
*
* @return that mapping
*/
Map<UUID, IndividualTimeSeriesMetaInformation> getTimeSeriesMetaInformation();

/**
* Get an option on the given time series meta information
*
* @param timeSeriesUuid Unique identifier of the time series in question
* @return An Option on the meta information
*/
Optional<IndividualTimeSeriesMetaInformation> getTimeSeriesMetaInformation(UUID timeSeriesUuid);
}
Loading