Skip to content

Commit 736c1ac

Browse files
Merge branch 'dev' into df/#1131-psdm-update-for-tap-water-demand
2 parents 5b12f0a + a1a5270 commit 736c1ac

31 files changed

+567
-65
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
## [Unreleased/Snapshot]
88

99
### Added
10+
- Enhance `TimeSeriesSource` with method to retrieve all time keys after a given key [#543](https://github.com/ie3-institute/PowerSystemDataModel/issues/543)
11+
- Enhance `WeatherSource` with method to retrieve all time keys after a given key [#572](https://github.com/ie3-institute/PowerSystemDataModel/issues/572)
1012

1113
### Fixed
1214

build.gradle

+3-3
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ dependencies {
7373
testImplementation 'org.junit.jupiter:junit-jupiter:5.11.0'
7474
testImplementation "org.spockframework:spock-core:2.3-groovy-$groovyVersion"
7575
testImplementation 'org.objenesis:objenesis:3.4' // Mock creation with constructor parameters
76-
testImplementation 'net.bytebuddy:byte-buddy:1.14.18' // Mocks of classes
76+
testImplementation 'net.bytebuddy:byte-buddy:1.15.0' // Mocks of classes
7777

7878
// testcontainers (docker framework for testing)
7979
testImplementation "org.testcontainers:testcontainers:$testcontainersVersion"
@@ -91,11 +91,11 @@ dependencies {
9191
// Databases
9292
implementation 'org.influxdb:influxdb-java:2.24'
9393
implementation 'com.couchbase.client:java-client:3.7.2'
94-
runtimeOnly 'org.postgresql:postgresql:42.7.3' // postgresql jdbc driver required during runtime
94+
runtimeOnly 'org.postgresql:postgresql:42.7.4' // postgresql jdbc driver required during runtime
9595

9696
implementation 'commons-io:commons-io:2.16.1' // I/O functionalities
9797
implementation 'commons-codec:commons-codec:1.17.1' // needed by commons-compress
98-
implementation 'org.apache.commons:commons-compress:1.27.0' // I/O functionalities
98+
implementation 'org.apache.commons:commons-compress:1.27.1' // I/O functionalities
9999
}
100100

101101
tasks.withType(JavaCompile) {

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

-5
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,6 @@ public CosmoTimeBasedWeatherValueFactory() {
4545
super();
4646
}
4747

48-
@Override
49-
public String getTimeFieldString() {
50-
return TIME;
51-
}
52-
5348
@Override
5449
protected List<Set<String>> getFields(Class<?> entityClass) {
5550
Set<String> minConstructorParams =

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

-5
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,6 @@ public IconTimeBasedWeatherValueFactory(DateTimeFormatter dateTimeFormatter) {
4242
super(dateTimeFormatter);
4343
}
4444

45-
@Override
46-
public String getTimeFieldString() {
47-
return TIME;
48-
}
49-
5045
@Override
5146
protected List<Set<String>> getFields(Class<?> entityClass) {
5247
Set<String> minParameters =

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

+1-15
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import edu.ie3.datamodel.models.StandardUnits;
1212
import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue;
1313
import edu.ie3.datamodel.models.value.*;
14-
import edu.ie3.util.TimeUtil;
1514
import java.time.ZonedDateTime;
1615
import java.time.format.DateTimeFormatter;
1716
import java.util.*;
@@ -26,26 +25,13 @@ public class TimeBasedSimpleValueFactory<V extends Value>
2625
private static final String REACTIVE_POWER = "q";
2726
private static final String HEAT_DEMAND = "heatDemand";
2827

29-
private final TimeUtil timeUtil;
30-
3128
public TimeBasedSimpleValueFactory(Class<? extends V> valueClasses) {
3229
super(valueClasses);
33-
this.timeUtil = TimeUtil.withDefaults;
3430
}
3531

3632
public TimeBasedSimpleValueFactory(
3733
Class<? extends V> valueClasses, DateTimeFormatter dateTimeFormatter) {
38-
super(valueClasses);
39-
this.timeUtil = new TimeUtil(dateTimeFormatter);
40-
}
41-
42-
/**
43-
* Return the field name for the date time
44-
*
45-
* @return the field name for the date time
46-
*/
47-
public String getTimeFieldString() {
48-
return TIME;
34+
super(valueClasses, dateTimeFormatter);
4935
}
5036

5137
@Override

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

+49
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
import edu.ie3.datamodel.io.factory.Factory;
99
import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue;
1010
import edu.ie3.datamodel.models.value.Value;
11+
import edu.ie3.util.TimeUtil;
12+
import java.time.ZonedDateTime;
13+
import java.time.format.DateTimeFormatter;
14+
import java.util.Map;
1115

1216
/**
1317
* Abstract class that is able to build {@link TimeBasedValue}s from "flat" information
@@ -18,7 +22,52 @@
1822
public abstract class TimeBasedValueFactory<D extends TimeBasedValueData<V>, V extends Value>
1923
extends Factory<V, D, TimeBasedValue<V>> {
2024

25+
protected static final String TIME = "time";
26+
27+
protected final TimeUtil timeUtil;
28+
2129
protected TimeBasedValueFactory(Class<? extends V>... valueClasses) {
2230
super(valueClasses);
31+
this.timeUtil = TimeUtil.withDefaults;
32+
}
33+
34+
protected TimeBasedValueFactory(
35+
Class<? extends V> valueClasses, DateTimeFormatter dateTimeFormatter) {
36+
super(valueClasses);
37+
this.timeUtil = new TimeUtil(dateTimeFormatter);
38+
}
39+
40+
protected TimeBasedValueFactory(Class<? extends V> valueClasses, TimeUtil timeUtil) {
41+
super(valueClasses);
42+
this.timeUtil = timeUtil;
43+
}
44+
45+
/**
46+
* Return the field name for the date time
47+
*
48+
* @return the field name for the date time
49+
*/
50+
public String getTimeFieldString() {
51+
return TIME;
52+
}
53+
54+
/**
55+
* Method to extract a time string from a given map and convert into a {@link ZonedDateTime}.
56+
*
57+
* @param fieldsToAttributes map with time field
58+
* @return a {@link ZonedDateTime}
59+
*/
60+
public ZonedDateTime extractTime(Map<String, String> fieldsToAttributes) {
61+
return toZonedDateTime(fieldsToAttributes.get(getTimeFieldString()));
62+
}
63+
64+
/**
65+
* Method to convert a given string into a {@link ZonedDateTime}.
66+
*
67+
* @param time string to convert
68+
* @return a {@link ZonedDateTime}
69+
*/
70+
public ZonedDateTime toZonedDateTime(String time) {
71+
return timeUtil.toZonedDateTime(time);
2372
}
2473
}

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

+2-15
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,18 @@
1515
*/
1616
public abstract class TimeBasedWeatherValueFactory
1717
extends TimeBasedValueFactory<TimeBasedWeatherValueData, WeatherValue> {
18-
protected static final String TIME = "time";
1918
protected static final String COORDINATE_ID = "coordinateId";
2019

21-
protected final TimeUtil timeUtil;
22-
2320
protected TimeBasedWeatherValueFactory() {
2421
super(WeatherValue.class);
25-
this.timeUtil = TimeUtil.withDefaults;
2622
}
2723

2824
protected TimeBasedWeatherValueFactory(DateTimeFormatter dateTimeFormatter) {
29-
super(WeatherValue.class);
30-
this.timeUtil = new TimeUtil(dateTimeFormatter);
25+
super(WeatherValue.class, dateTimeFormatter);
3126
}
3227

3328
protected TimeBasedWeatherValueFactory(TimeUtil timeUtil) {
34-
super(WeatherValue.class);
35-
this.timeUtil = timeUtil;
29+
super(WeatherValue.class, timeUtil);
3630
}
3731

3832
/**
@@ -43,11 +37,4 @@ protected TimeBasedWeatherValueFactory(TimeUtil timeUtil) {
4337
public String getCoordinateIdFieldString() {
4438
return COORDINATE_ID;
4539
}
46-
47-
/**
48-
* Return the field name for the date time
49-
*
50-
* @return the field name for the date time
51-
*/
52-
public abstract String getTimeFieldString();
5340
}

src/main/java/edu/ie3/datamodel/io/source/TimeSeriesSource.java

+8
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,12 @@ public abstract IndividualTimeSeries<V> getTimeSeries(ClosedInterval<ZonedDateTi
5151
throws SourceException;
5252

5353
public abstract Optional<V> getValue(ZonedDateTime time) throws SourceException;
54+
55+
/**
56+
* Method to return all time keys after a given timestamp.
57+
*
58+
* @param time given time
59+
* @return a list of time keys
60+
*/
61+
public abstract List<ZonedDateTime> getTimeKeysAfter(ZonedDateTime time);
5462
}

src/main/java/edu/ie3/datamodel/io/source/WeatherSource.java

+40-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.util.*;
1919
import java.util.stream.Collectors;
2020
import java.util.stream.Stream;
21+
import org.apache.commons.lang3.tuple.Pair;
2122
import org.locationtech.jts.geom.Point;
2223
import org.slf4j.Logger;
2324
import org.slf4j.LoggerFactory;
@@ -29,8 +30,6 @@ public abstract class WeatherSource extends EntitySource {
2930

3031
protected TimeBasedWeatherValueFactory weatherFactory;
3132

32-
protected Map<Point, IndividualTimeSeries<WeatherValue>> coordinateToTimeSeries;
33-
3433
protected IdCoordinateSource idCoordinateSource;
3534

3635
protected static final String COORDINATE_ID = "coordinateid";
@@ -65,6 +64,14 @@ public abstract Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
6564
public abstract Optional<TimeBasedValue<WeatherValue>> getWeather(
6665
ZonedDateTime date, Point coordinate) throws SourceException;
6766

67+
public abstract Map<Point, List<ZonedDateTime>> getTimeKeysAfter(ZonedDateTime time)
68+
throws SourceException;
69+
70+
public List<ZonedDateTime> getTimeKeysAfter(ZonedDateTime time, Point coordinate)
71+
throws SourceException {
72+
return getTimeKeysAfter(time).getOrDefault(coordinate, Collections.emptyList());
73+
}
74+
6875
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
6976

7077
/**
@@ -111,6 +118,37 @@ protected Map<Point, IndividualTimeSeries<WeatherValue>> mapWeatherValuesToPoint
111118
return coordinateToTimeSeriesMap;
112119
}
113120

121+
protected Map<Point, List<ZonedDateTime>> toTimeKeys(
122+
Stream<Map<String, String>> fieldMaps, TimeBasedWeatherValueFactory factory) {
123+
return groupTime(
124+
fieldMaps.map(
125+
fieldMap -> {
126+
String coordinateValue = fieldMap.get(COORDINATE_ID);
127+
int coordinateId = Integer.parseInt(coordinateValue);
128+
Optional<Point> coordinate = idCoordinateSource.getCoordinate(coordinateId);
129+
ZonedDateTime time = factory.extractTime(fieldMap);
130+
131+
if (coordinate.isEmpty()) {
132+
log.warn("Unable to match coordinate ID {} to a point", coordinateId);
133+
}
134+
return Pair.of(coordinate, time);
135+
}));
136+
}
137+
138+
protected Map<Point, List<ZonedDateTime>> groupTime(
139+
Stream<Pair<Optional<Point>, ZonedDateTime>> values) {
140+
return values
141+
.filter(pair -> pair.getKey().isPresent())
142+
.map(pair -> Pair.of(pair.getKey().get(), pair.getValue()))
143+
.collect(Collectors.groupingBy(Pair::getKey, Collectors.toSet()))
144+
.entrySet()
145+
.stream()
146+
.collect(
147+
Collectors.toMap(
148+
Map.Entry::getKey,
149+
e -> e.getValue().stream().map(Pair::getValue).sorted().toList()));
150+
}
151+
114152
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
115153

116154
/**

src/main/java/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSource.java

+44
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.concurrent.CompletableFuture;
2626
import java.util.concurrent.CompletionException;
2727
import java.util.stream.Collectors;
28+
import org.apache.commons.lang3.tuple.Pair;
2829
import org.locationtech.jts.geom.Point;
2930
import org.slf4j.Logger;
3031
import org.slf4j.LoggerFactory;
@@ -165,6 +166,37 @@ public Optional<TimeBasedValue<WeatherValue>> getWeather(ZonedDateTime date, Poi
165166
}
166167
}
167168

169+
@Override
170+
public Map<Point, List<ZonedDateTime>> getTimeKeysAfter(ZonedDateTime time) {
171+
String query = createQueryStringForFollowingTimeKeys(time);
172+
CompletableFuture<QueryResult> futureResult = connector.query(query);
173+
QueryResult queryResult = futureResult.join();
174+
List<JsonObject> jsonWeatherInputs = Collections.emptyList();
175+
try {
176+
jsonWeatherInputs = queryResult.rowsAsObject();
177+
} catch (DecodingFailureException ex) {
178+
logger.error("Querying weather inputs failed!", ex);
179+
}
180+
if (jsonWeatherInputs != null && !jsonWeatherInputs.isEmpty()) {
181+
return groupTime(
182+
jsonWeatherInputs.stream()
183+
.map(
184+
json -> {
185+
int coordinateId = json.getInt(COORDINATE_ID);
186+
Optional<Point> coordinate = idCoordinateSource.getCoordinate(coordinateId);
187+
ZonedDateTime timestamp =
188+
weatherFactory.toZonedDateTime(
189+
json.getString(weatherFactory.getTimeFieldString()));
190+
if (coordinate.isEmpty()) {
191+
log.warn("Unable to match coordinate ID {} to a point", coordinateId);
192+
}
193+
return Pair.of(coordinate, timestamp);
194+
})
195+
.filter(value -> value.getValue().isAfter(time)));
196+
}
197+
return Collections.emptyMap();
198+
}
199+
168200
/**
169201
* Generates a key for weather documents with the pattern: {@code
170202
* weather::<coordinate_id>::<time>}
@@ -199,6 +231,18 @@ private String createQueryStringForIntervalAndCoordinate(
199231
return basicQuery + whereClause;
200232
}
201233

234+
/**
235+
* Create a query string to search for all time keys that comes after the given time.
236+
*
237+
* @param time given timestamp
238+
* @return the query string
239+
*/
240+
public String createQueryStringForFollowingTimeKeys(ZonedDateTime time) {
241+
String basicQuery = "SELECT a.coordinateid, a.time FROM " + connector.getBucketName() + " AS a";
242+
String whereClause = " WHERE META().id > '" + generateWeatherKey(time, 0) + "'";
243+
return basicQuery + whereClause;
244+
}
245+
202246
/**
203247
* Converts a JsonObject into TimeBasedWeatherValueData by extracting all fields into a field to
204248
* value map and then removing the coordinate from it to supply as a parameter

src/main/java/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesSource.java

+5
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ public Optional<V> getValue(ZonedDateTime time) {
128128
return timeSeries.getValue(time);
129129
}
130130

131+
@Override
132+
public List<ZonedDateTime> getTimeKeysAfter(ZonedDateTime time) {
133+
return timeSeries.getTimeKeysAfter(time);
134+
}
135+
131136
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
132137

133138
/**

src/main/java/edu/ie3/datamodel/io/source/csv/CsvWeatherSource.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
/** Implements a WeatherSource for CSV files by using the CsvTimeSeriesSource as a base */
4343
public class CsvWeatherSource extends WeatherSource {
44+
private final Map<Point, IndividualTimeSeries<WeatherValue>> coordinateToTimeSeries;
4445

4546
private final CsvDataSource dataSource;
4647

@@ -64,8 +65,7 @@ public CsvWeatherSource(
6465
throws SourceException {
6566
super(idCoordinateSource, weatherFactory);
6667
this.dataSource = new CsvDataSource(csvSep, folderPath, fileNamingStrategy);
67-
68-
coordinateToTimeSeries = getWeatherTimeSeries();
68+
this.coordinateToTimeSeries = getWeatherTimeSeries();
6969
}
7070

7171
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
@@ -111,6 +111,12 @@ public Optional<TimeBasedValue<WeatherValue>> getWeather(ZonedDateTime date, Poi
111111
return timeSeries.getTimeBasedValue(date);
112112
}
113113

114+
@Override
115+
public Map<Point, List<ZonedDateTime>> getTimeKeysAfter(ZonedDateTime time) {
116+
return coordinateToTimeSeries.entrySet().stream()
117+
.collect(Collectors.toMap(Map.Entry::getKey, t -> t.getValue().getTimeKeysAfter(time)));
118+
}
119+
114120
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
115121

116122
/**

0 commit comments

Comments
 (0)