Skip to content

Commit 5d1b7a2

Browse files
committed
Adding uniqueness check to CsvIdCoordinateSource and CsvWeatherSource.
1 parent 14dc0cc commit 5d1b7a2

File tree

12 files changed

+141
-57
lines changed

12 files changed

+141
-57
lines changed

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@
66
package edu.ie3.datamodel.io.factory.timeseries;
77

88
import edu.ie3.datamodel.io.factory.SimpleFactoryData;
9-
import edu.ie3.util.geo.GeoUtils;
9+
import edu.ie3.datamodel.models.input.IdCoordinatePair;
1010
import java.util.Collections;
1111
import java.util.List;
1212
import java.util.Set;
13-
import org.apache.commons.lang3.tuple.Pair;
14-
import org.locationtech.jts.geom.Point;
1513

1614
/**
1715
* Factory, that is able to build coordinate id to coordinate mapping from German Federal Weather
@@ -26,11 +24,11 @@ public class CosmoIdCoordinateFactory extends IdCoordinateFactory {
2624
private static final String LAT_ROT = "latRot";
2725

2826
@Override
29-
protected Pair<Integer, Point> buildModel(SimpleFactoryData data) {
27+
protected IdCoordinatePair buildModel(SimpleFactoryData data) {
3028
int coordinateId = data.getInt(COORDINATE_ID);
3129
double lat = data.getDouble(LAT_GEO);
3230
double lon = data.getDouble(LONG_GEO);
33-
return Pair.of(coordinateId, GeoUtils.buildPoint(lat, lon));
31+
return IdCoordinatePair.of(coordinateId, lat, lon);
3432
}
3533

3634
@Override

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@
66
package edu.ie3.datamodel.io.factory.timeseries;
77

88
import edu.ie3.datamodel.io.factory.SimpleFactoryData;
9-
import edu.ie3.util.geo.GeoUtils;
9+
import edu.ie3.datamodel.models.input.IdCoordinatePair;
1010
import java.util.Collections;
1111
import java.util.List;
1212
import java.util.Set;
13-
import org.apache.commons.lang3.tuple.Pair;
14-
import org.locationtech.jts.geom.Point;
1513

1614
/**
1715
* Factory, that is able to build coordinate id to coordinate mapping from German Federal Weather
@@ -24,11 +22,11 @@ public class IconIdCoordinateFactory extends IdCoordinateFactory {
2422
private static final String TYPE = "coordinateType";
2523

2624
@Override
27-
protected Pair<Integer, Point> buildModel(SimpleFactoryData data) {
25+
protected IdCoordinatePair buildModel(SimpleFactoryData data) {
2826
int coordinateId = data.getInt(COORDINATE_ID);
2927
double lat = data.getDouble(LAT);
3028
double lon = data.getDouble(LONG);
31-
return Pair.of(coordinateId, GeoUtils.buildPoint(lat, lon));
29+
return IdCoordinatePair.of(coordinateId, lat, lon);
3230
}
3331

3432
@Override

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,16 @@
77

88
import edu.ie3.datamodel.io.factory.Factory;
99
import edu.ie3.datamodel.io.factory.SimpleFactoryData;
10-
import org.apache.commons.lang3.tuple.Pair;
11-
import org.locationtech.jts.geom.Point;
10+
import edu.ie3.datamodel.models.input.IdCoordinatePair;
1211

1312
/**
1413
* Abstract class definition for a factory, that is able to build single mapping entries from
1514
* coordinate identifier to actual coordinate
1615
*/
1716
public abstract class IdCoordinateFactory
18-
extends Factory<Pair, SimpleFactoryData, Pair<Integer, Point>> {
17+
extends Factory<IdCoordinatePair, SimpleFactoryData, IdCoordinatePair> {
1918
protected IdCoordinateFactory() {
20-
super(Pair.class);
19+
super(IdCoordinatePair.class);
2120
}
2221

2322
/** @return the field id for the coordinate id */

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77

88
import edu.ie3.datamodel.exceptions.FactoryException;
99
import edu.ie3.datamodel.io.factory.SimpleFactoryData;
10+
import edu.ie3.datamodel.models.input.IdCoordinatePair;
1011
import edu.ie3.util.geo.GeoUtils;
1112
import java.util.Collections;
1213
import java.util.List;
1314
import java.util.Set;
14-
import org.apache.commons.lang3.tuple.Pair;
1515
import org.locationtech.jts.geom.Coordinate;
1616
import org.locationtech.jts.geom.Point;
1717
import org.locationtech.jts.io.ParseException;
@@ -23,15 +23,15 @@ public class SqlIdCoordinateFactory extends IdCoordinateFactory {
2323
private final WKBReader reader = new WKBReader();
2424

2525
@Override
26-
protected Pair<Integer, Point> buildModel(SimpleFactoryData data) {
26+
protected IdCoordinatePair buildModel(SimpleFactoryData data) {
2727
try {
2828
int coordinateId = data.getInt(COORDINATE_ID);
2929
byte[] byteArr = WKBReader.hexToBytes(data.getField(COORDINATE));
3030

3131
Coordinate coordinate = reader.read(byteArr).getCoordinate();
3232

3333
Point point = GeoUtils.buildPoint(coordinate);
34-
return Pair.of(coordinateId, point);
34+
return IdCoordinatePair.of(coordinateId, point);
3535

3636
} catch (ParseException e) {
3737
throw new FactoryException(e);

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@ public interface IdCoordinateSource {
2727
*/
2828
Optional<Set<String>> getSourceFields() throws SourceException;
2929

30-
/** Returns a set of fields that needs to be unique for the source. */
31-
default Set<String> getUniqueFields() {
32-
return Set.of("");
33-
}
34-
3530
/**
3631
* Get the matching coordinate for the given ID
3732
*

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

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55
*/
66
package edu.ie3.datamodel.io.source.csv;
77

8+
import edu.ie3.datamodel.exceptions.DuplicateEntitiesException;
89
import edu.ie3.datamodel.exceptions.SourceException;
910
import edu.ie3.datamodel.exceptions.ValidationException;
1011
import edu.ie3.datamodel.io.factory.SimpleFactoryData;
1112
import edu.ie3.datamodel.io.factory.timeseries.IdCoordinateFactory;
1213
import edu.ie3.datamodel.io.source.IdCoordinateSource;
14+
import edu.ie3.datamodel.models.input.IdCoordinatePair;
1315
import edu.ie3.datamodel.utils.Try;
1416
import edu.ie3.datamodel.utils.Try.*;
17+
import edu.ie3.datamodel.utils.validation.UniquenessValidationUtils;
1518
import edu.ie3.util.geo.CoordinateDistance;
1619
import edu.ie3.util.geo.GeoUtils;
1720
import java.io.BufferedReader;
@@ -62,14 +65,27 @@ public CsvIdCoordinateSource(IdCoordinateFactory factory, CsvDataSource dataSour
6265
* @return Mapping from coordinate id to coordinate
6366
*/
6467
private Map<Integer, Point> setupIdToCoordinateMap() throws SourceException {
65-
return buildStreamWithFieldsToAttributesMap()
66-
.map(
67-
data ->
68-
data.map(fieldToValues -> new SimpleFactoryData(fieldToValues, Pair.class))
69-
.map(factory::get))
70-
.flatMap(s -> Try.scanStream(s, "Pair<Integer, Point>").transformF(SourceException::new))
71-
.map(s -> s.collect(Collectors.toMap(Pair::getKey, Pair::getValue)))
72-
.getOrThrow();
68+
List<IdCoordinatePair> pairs =
69+
buildStreamWithFieldsToAttributesMap()
70+
.map(
71+
data ->
72+
data.map(
73+
fieldToValues ->
74+
new SimpleFactoryData(fieldToValues, IdCoordinatePair.class))
75+
.map(factory::get))
76+
.flatMap(
77+
s -> Try.scanStream(s, "Pair<Integer, Point>").transformF(SourceException::new))
78+
.getOrThrow()
79+
.toList();
80+
81+
try {
82+
// check the uniqueness of the source
83+
UniquenessValidationUtils.checkIdCoordinateUniqueness(pairs);
84+
} catch (DuplicateEntitiesException de) {
85+
throw new SourceException("Due to: ", de);
86+
}
87+
88+
return pairs.stream().collect(Collectors.toMap(Pair::getKey, Pair::getValue));
7389
}
7490

7591
/**
@@ -171,7 +187,7 @@ public int getCoordinateCount() {
171187
final String[] headline = dataSource.parseCsvRow(reader.readLine(), dataSource.csvSep);
172188

173189
// validating read file
174-
factory.validate(Set.of(headline), Pair.class).getOrThrow();
190+
factory.validate(Set.of(headline), IdCoordinatePair.class).getOrThrow();
175191

176192
// by default try-with-resources closes the reader directly when we leave this method (which
177193
// is wanted to avoid a lock on the file), but this causes a closing of the stream as well.

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

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
*/
66
package edu.ie3.datamodel.io.source.csv;
77

8+
import static edu.ie3.datamodel.utils.validation.UniquenessValidationUtils.checkWeatherUniqueness;
9+
10+
import edu.ie3.datamodel.exceptions.DuplicateEntitiesException;
811
import edu.ie3.datamodel.exceptions.SourceException;
912
import edu.ie3.datamodel.exceptions.ValidationException;
1013
import edu.ie3.datamodel.io.connectors.CsvFileConnector;
@@ -20,6 +23,7 @@
2023
import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue;
2124
import edu.ie3.datamodel.models.value.Value;
2225
import edu.ie3.datamodel.models.value.WeatherValue;
26+
import edu.ie3.datamodel.utils.ExceptionUtils;
2327
import edu.ie3.datamodel.utils.TimeSeriesUtils;
2428
import edu.ie3.datamodel.utils.Try;
2529
import edu.ie3.datamodel.utils.Try.*;
@@ -188,7 +192,22 @@ private Map<Point, IndividualTimeSeries<WeatherValue>> readWeatherTimeSeries(
188192
throw new SourceException("Validation failed for file " + data.getFullFilePath() + ".", e);
189193
}
190194
}
191-
return weatherTimeSeries;
195+
196+
// checking the uniqueness before returning the time series
197+
List<DuplicateEntitiesException> exceptions =
198+
Try.getExceptions(
199+
weatherTimeSeries.values().stream()
200+
.map(
201+
ts ->
202+
Try.ofVoid(
203+
() -> checkWeatherUniqueness(ts.getEntries()),
204+
DuplicateEntitiesException.class)));
205+
206+
if (exceptions.isEmpty()) {
207+
return weatherTimeSeries;
208+
} else {
209+
throw new SourceException("Due to: " + ExceptionUtils.getMessages(exceptions));
210+
}
192211
}
193212

194213
private Try<Stream<Map<String, String>>, SourceException> buildStreamWithFieldsToAttributesMap(

src/main/java/edu/ie3/datamodel/io/source/sql/SqlIdCoordinateSource.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import edu.ie3.datamodel.io.factory.timeseries.SqlIdCoordinateFactory;
1414
import edu.ie3.datamodel.io.naming.DatabaseNamingStrategy;
1515
import edu.ie3.datamodel.io.source.IdCoordinateSource;
16+
import edu.ie3.datamodel.models.input.IdCoordinatePair;
1617
import edu.ie3.datamodel.models.value.CoordinateValue;
1718
import edu.ie3.datamodel.utils.Try;
1819
import edu.ie3.util.geo.CoordinateDistance;
@@ -21,7 +22,6 @@
2122
import java.sql.PreparedStatement;
2223
import java.util.*;
2324
import javax.measure.quantity.Length;
24-
import org.apache.commons.lang3.tuple.Pair;
2525
import org.locationtech.jts.geom.Envelope;
2626
import org.locationtech.jts.geom.Point;
2727
import tech.units.indriya.ComparableQuantity;
@@ -65,7 +65,9 @@ public SqlIdCoordinateSource(
6565
fieldsOpt
6666
.map(
6767
fields ->
68-
factory.validate(fields, Pair.class).transformF(SourceException::new))
68+
factory
69+
.validate(fields, IdCoordinatePair.class)
70+
.transformF(SourceException::new))
6971
.orElse(Try.Success.empty()))
7072
.getOrThrow();
7173

@@ -198,9 +200,10 @@ public List<CoordinateDistance> getClosestCoordinates(
198200
private CoordinateValue createCoordinateValue(Map<String, String> fieldToValues) {
199201
fieldToValues.remove("distance");
200202

201-
SimpleFactoryData simpleFactoryData = new SimpleFactoryData(fieldToValues, Pair.class);
203+
SimpleFactoryData simpleFactoryData =
204+
new SimpleFactoryData(fieldToValues, IdCoordinatePair.class);
202205

203-
Pair<Integer, Point> pair = factory.get(simpleFactoryData).getOrThrow();
206+
IdCoordinatePair pair = factory.get(simpleFactoryData).getOrThrow();
204207
return new CoordinateValue(pair.getKey(), pair.getValue());
205208
}
206209

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* © 2024. 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.models.input;
7+
8+
import edu.ie3.util.geo.GeoUtils;
9+
import org.apache.commons.lang3.tuple.ImmutablePair;
10+
import org.locationtech.jts.geom.Point;
11+
12+
public class IdCoordinatePair extends ImmutablePair<Integer, Point> implements InputEntity {
13+
/**
14+
* Create a new pair instance.
15+
*
16+
* @param left the left value, may be null
17+
* @param right the right value, may be null
18+
*/
19+
private IdCoordinatePair(Integer left, Point right) {
20+
super(left, right);
21+
}
22+
23+
/**
24+
* Creates an {@link IdCoordinatePair}.
25+
*
26+
* @param id of the pair
27+
* @param lat of the pair
28+
* @param lon of the pair
29+
* @return a new {@link IdCoordinatePair}
30+
*/
31+
public static IdCoordinatePair of(Integer id, double lat, double lon) {
32+
return new IdCoordinatePair(id, GeoUtils.buildPoint(lat, lon));
33+
}
34+
35+
/**
36+
* Creates an {@link IdCoordinatePair}.
37+
*
38+
* @param id of the pair
39+
* @param point of the pair
40+
* @return a new {@link IdCoordinatePair}
41+
*/
42+
public static IdCoordinatePair of(Integer id, Point point) {
43+
return new IdCoordinatePair(id, point);
44+
}
45+
}

src/main/java/edu/ie3/datamodel/utils/validation/UniquenessValidationUtils.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
import edu.ie3.datamodel.models.Entity;
1111
import edu.ie3.datamodel.models.UniqueEntity;
1212
import edu.ie3.datamodel.models.input.AssetInput;
13+
import edu.ie3.datamodel.models.input.IdCoordinatePair;
1314
import edu.ie3.datamodel.models.result.ResultEntity;
1415
import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue;
1516
import edu.ie3.datamodel.models.value.WeatherValue;
1617
import edu.ie3.datamodel.utils.Try;
17-
import edu.ie3.datamodel.utils.Try.*;
18+
import edu.ie3.datamodel.utils.Try.Success;
1819
import java.util.*;
1920
import java.util.function.Function;
2021
import java.util.stream.Collectors;
@@ -30,9 +31,10 @@ public class UniquenessValidationUtils extends ValidationUtils {
3031
entity -> Set.of(entity.getTime(), entity.getInputModel());
3132
protected static final FieldSetSupplier<MappingEntry> mappingFieldSupplier =
3233
entity -> Set.of(entity.participant());
33-
protected static final FieldSetSupplier<TimeBasedValue<WeatherValue>>
34-
timeBasedValueFieldSupplier =
35-
entity -> Set.of(entity.getTime(), entity.getValue().getCoordinate());
34+
protected static final FieldSetSupplier<IdCoordinatePair> idCoordinateSupplier =
35+
pair -> Set.of(pair.getKey(), pair.getValue());
36+
protected static final FieldSetSupplier<TimeBasedValue<WeatherValue>> weatherValueFieldSupplier =
37+
entity -> Set.of(entity.getTime(), entity.getValue().getCoordinate());
3638

3739
/**
3840
* Checks the uniqueness of a collection of {@link UniqueEntity}.
@@ -88,6 +90,17 @@ public static void checkMappingEntryUniqueness(Collection<MappingEntry> entities
8890
checkUniqueness(entities, mappingFieldSupplier).getOrThrow();
8991
}
9092

93+
/**
94+
* Checks the uniqueness of a collection of
95+
*
96+
* @param entities to be checked
97+
* @throws DuplicateEntitiesException if uniqueness is violated
98+
*/
99+
public static void checkIdCoordinateUniqueness(Collection<IdCoordinatePair> entities)
100+
throws DuplicateEntitiesException {
101+
checkUniqueness(entities, idCoordinateSupplier).getOrThrow();
102+
}
103+
91104
/**
92105
* Checks the uniqueness of TimeBasedWeatherValues.
93106
*
@@ -96,7 +109,7 @@ public static void checkMappingEntryUniqueness(Collection<MappingEntry> entities
96109
*/
97110
public static void checkWeatherUniqueness(Collection<TimeBasedValue<WeatherValue>> entities)
98111
throws DuplicateEntitiesException {
99-
checkUniqueness(entities, timeBasedValueFieldSupplier).getOrThrow();
112+
checkUniqueness(entities, weatherValueFieldSupplier).getOrThrow();
100113
}
101114

102115
/**

0 commit comments

Comments
 (0)