Skip to content

Commit 51c8603

Browse files
authored
Fix NPE when a line references an unknown substation (#48)
1 parent e42c3b1 commit 51c8603

File tree

2 files changed

+82
-3
lines changed

2 files changed

+82
-3
lines changed

geo-data-server/src/main/java/org/gridsuite/geodata/server/GeoDataService.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,13 +240,32 @@ boolean emptyOrEquals(String emptyable, String s) {
240240
return emptyable.isEmpty() || s.equals(emptyable);
241241
}
242242

243+
/**
244+
* returns the line gps coordinates in the network order with the substations
245+
* coordinates added at each extremity.
246+
*
247+
* returns null when the substations at the end of the line are missing.
248+
*/
243249
private LineGeoData getLineGeoDataWithEndSubstations(Map<String, LineGeoData> linesGeoDataDb, Map<String, SubstationGeoData> substationGeoDataDb, Line line) {
244250
LineGeoData geoData = linesGeoDataDb.get(line.getId());
245251
Substation sub1 = line.getTerminal1().getVoltageLevel().getSubstation();
246252
Substation sub2 = line.getTerminal2().getVoltageLevel().getSubstation();
247-
Coordinate substation1Coordinate = substationGeoDataDb.get(sub1.getId()).getCoordinate();
248-
Coordinate substation2Coordinate = substationGeoDataDb.get(sub2.getId()).getCoordinate();
253+
SubstationGeoData substation1GeoData = substationGeoDataDb.get(sub1.getId());
254+
SubstationGeoData substation2GeoData = substationGeoDataDb.get(sub2.getId());
255+
256+
// TODO: we return null here even if we have line data
257+
// because the method is called "withEndSubstations"...
258+
// We could refactor this in separate methods if we ever have a
259+
// need to return the line in the network order without the substations
260+
if (substation1GeoData == null || substation2GeoData == null) {
261+
LOGGER.error("line {} has substations with unknown gps positions({}={}, {}={})", line.getId(),
262+
sub1.getId(), substation1GeoData,
263+
sub2.getId(), substation2GeoData);
264+
return null;
265+
}
249266

267+
Coordinate substation1Coordinate = substation1GeoData.getCoordinate();
268+
Coordinate substation2Coordinate = substation2GeoData.getCoordinate();
250269
if (geoData == null || geoData.getCoordinates().isEmpty() || (geoData.getSubstationStart().isEmpty() && geoData.getSubstationEnd().isEmpty())) {
251270
return new LineGeoData(line.getId(), sub1.getNullableCountry(), sub2.getNullableCountry(), sub1.getId(), sub2.getId(),
252271
List.of(substation1Coordinate, substation2Coordinate));
@@ -303,7 +322,8 @@ List<LineGeoData> getLines(Network network, Set<Country> countries) {
303322
lines.stream().flatMap(line -> line.getTerminals().stream().map(term -> term.getVoltageLevel().getSubstation().getNullableCountry()).filter(Objects::nonNull))
304323
.collect(Collectors.toSet());
305324
Map<String, SubstationGeoData> substationGeoDataDb = getSubstationMap(network, countryAndNextTo);
306-
List<LineGeoData> lineGeoData = lines.stream().map(line -> getLineGeoDataWithEndSubstations(linesGeoDataDb, substationGeoDataDb, line)).collect(Collectors.toList());
325+
List<LineGeoData> lineGeoData = lines.stream().map(line -> getLineGeoDataWithEndSubstations(linesGeoDataDb, substationGeoDataDb, line))
326+
.filter(Objects::nonNull).collect(Collectors.toList());
307327
LOGGER.info("{} lines read from DB in {} ms", linesGeoDataDb.size(), stopWatch.getTime(TimeUnit.MILLISECONDS));
308328

309329
return lineGeoData;

geo-data-server/src/test/java/org/gridsuite/geodata/server/GeoDataServiceTest.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,65 @@ public void test() {
150150
assertEquals(1, substationsGeoData2.stream().filter(s -> s.getId().equals("P5")).collect(Collectors.toList()).get(0).getCoordinate().getLon(), 0);
151151
}
152152

153+
@Test
154+
public void testNonExisting() {
155+
Network network = EurostagTutorialExample1Factory.create();
156+
Substation notexistsub1 = network.newSubstation()
157+
.setId("NOTEXISTSUB1")
158+
.setCountry(Country.FR)
159+
.setTso("RTE")
160+
.add();
161+
VoltageLevel notexistvl1 = notexistsub1.newVoltageLevel()
162+
.setId("NOTEXISTVL1")
163+
.setNominalV(380)
164+
.setTopologyKind(TopologyKind.BUS_BREAKER)
165+
.add();
166+
Bus notexistbus1 = notexistvl1.getBusBreakerView().newBus()
167+
.setId("NOTEXISTBUS1")
168+
.add();
169+
170+
Substation notexistsub2 = network.newSubstation()
171+
.setId("NOTEXISTSUB2")
172+
.setCountry(Country.FR)
173+
.setTso("RTE")
174+
.add();
175+
VoltageLevel notexistvl2 = notexistsub2.newVoltageLevel()
176+
.setId("NOTEXISTVL2")
177+
.setNominalV(380)
178+
.setTopologyKind(TopologyKind.BUS_BREAKER)
179+
.add();
180+
Bus notexistbus2 = notexistvl2.getBusBreakerView().newBus()
181+
.setId("NOTEXISTBUS2")
182+
.add();
183+
184+
Line notexistline = network.newLine()
185+
.setId("NOTEXISTLINE1")
186+
.setVoltageLevel1(notexistvl1.getId())
187+
.setBus1(notexistbus1.getId())
188+
.setConnectableBus1(notexistbus1.getId())
189+
.setVoltageLevel2(notexistvl2.getId())
190+
.setBus2(notexistbus2.getId())
191+
.setConnectableBus2(notexistbus2.getId())
192+
.setR(3.0)
193+
.setX(33.0)
194+
.setG1(0.0)
195+
.setB1(386E-6 / 2)
196+
.setG2(0.0)
197+
.setB2(386E-6 / 2)
198+
.add();
199+
List<SubstationGeoData> substationsGeoData = geoDataService.getSubstations(network, new HashSet<>(Collections.singletonList(Country.FR)));
200+
assertFalse("Must not contain nulls", substationsGeoData.stream().anyMatch(Objects::isNull));
201+
assertFalse("Must not contain unknown substation " + notexistsub1.getId(),
202+
substationsGeoData.stream().anyMatch(s -> notexistsub1.getId().equals(s.getId())));
203+
assertFalse("Must not contain unknown substation " + notexistsub2.getId(),
204+
substationsGeoData.stream().anyMatch(s -> notexistsub2.getId().equals(s.getId())));
205+
206+
List<LineGeoData> linesGeoData = geoDataService.getLines(network, new HashSet<>(Collections.singletonList(Country.FR)));
207+
assertFalse("Must not contain nulls", linesGeoData.stream().anyMatch(Objects::isNull));
208+
assertFalse("Must not contain unknown lines " + notexistline.getId(),
209+
linesGeoData.stream().anyMatch(s -> notexistline.getId().equals(s.getId())));
210+
}
211+
153212
private Network createGeoDataNetwork() {
154213
Network network = EurostagTutorialExample1Factory.create();
155214

0 commit comments

Comments
 (0)