Skip to content

Commit be219b6

Browse files
authored
Merge branch 'master' into 1930
2 parents cf9a2ae + 02c5307 commit be219b6

File tree

4 files changed

+151
-10
lines changed

4 files changed

+151
-10
lines changed

core/src/main/java/org/mobilitydata/gtfsvalidator/notice/PointNearOriginNotice.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,22 @@ public class PointNearOriginNotice extends ValidationNotice {
3535
private final String filename;
3636

3737
/** The row of the faulty row. */
38-
private final int csvRowNumber;
38+
@Nullable private final Integer csvRowNumber;
39+
40+
/** The index of the feature in the feature collection. */
41+
@Nullable private final Integer featureIndex;
3942

4043
/** The id of the faulty entity. */
4144
@Nullable private final String entityId;
4245

4346
/** The name of the field that uses latitude value. */
44-
private final String latFieldName;
47+
@Nullable private final String latFieldName;
4548

4649
/** The latitude of the faulty row. */
4750
private final double latFieldValue;
4851

4952
/** The name of the field that uses longitude value. */
50-
private final String lonFieldName;
53+
@Nullable private final String lonFieldName;
5154

5255
/** The longitude of the faulty row */
5356
private final double lonFieldValue;
@@ -67,6 +70,7 @@ public PointNearOriginNotice(
6770
this.latFieldValue = latFieldValue;
6871
this.lonFieldName = lonFieldName;
6972
this.lonFieldValue = lonFieldValue;
73+
this.featureIndex = null;
7074
}
7175

7276
public PointNearOriginNotice(
@@ -83,5 +87,22 @@ public PointNearOriginNotice(
8387
this.latFieldValue = latFieldValue;
8488
this.lonFieldName = lonFieldName;
8589
this.lonFieldValue = lonFieldValue;
90+
this.featureIndex = null;
91+
}
92+
93+
public PointNearOriginNotice(
94+
String filename,
95+
String entityId,
96+
double latFieldValue,
97+
double lonFieldValue,
98+
int featureIndex) {
99+
this.filename = filename;
100+
this.csvRowNumber = null;
101+
this.entityId = entityId;
102+
this.latFieldName = null;
103+
this.latFieldValue = latFieldValue;
104+
this.lonFieldName = null;
105+
this.lonFieldValue = lonFieldValue;
106+
this.featureIndex = featureIndex;
86107
}
87108
}

core/src/main/java/org/mobilitydata/gtfsvalidator/notice/PointNearPoleNotice.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,24 @@ public class PointNearPoleNotice extends ValidationNotice {
3535
private final String filename;
3636

3737
/** The row of the faulty row. */
38-
private final int csvRowNumber;
38+
@Nullable private final Integer csvRowNumber;
39+
40+
/** The index of the feature in the feature collection. */
41+
@Nullable private final Integer featureIndex;
3942

4043
/** The id of the faulty entity. */
4144
@Nullable private final String entityId;
4245

4346
/** The name of the field that uses latitude value. */
44-
private final String latFieldName;
47+
@Nullable private final String latFieldName;
4548

4649
/** The latitude of the faulty row. */
4750
private final double latFieldValue;
4851

4952
/** The name of the field that uses longitude value. */
50-
private final String lonFieldName;
53+
@Nullable private final String lonFieldName;
5154

52-
/** The longitude of the faulty row. */
55+
/** The longitude of the faulty row */
5356
private final double lonFieldValue;
5457

5558
public PointNearPoleNotice(
@@ -67,6 +70,7 @@ public PointNearPoleNotice(
6770
this.latFieldValue = latFieldValue;
6871
this.lonFieldName = lonFieldName;
6972
this.lonFieldValue = lonFieldValue;
73+
this.featureIndex = null;
7074
}
7175

7276
public PointNearPoleNotice(
@@ -83,5 +87,22 @@ public PointNearPoleNotice(
8387
this.latFieldValue = latFieldValue;
8488
this.lonFieldName = lonFieldName;
8589
this.lonFieldValue = lonFieldValue;
90+
this.featureIndex = null;
91+
}
92+
93+
public PointNearPoleNotice(
94+
String filename,
95+
String entityId,
96+
double latFieldValue,
97+
double lonFieldValue,
98+
int featureIndex) {
99+
this.filename = filename;
100+
this.csvRowNumber = null;
101+
this.entityId = entityId;
102+
this.latFieldName = null;
103+
this.latFieldValue = latFieldValue;
104+
this.lonFieldName = null;
105+
this.lonFieldValue = lonFieldValue;
106+
this.featureIndex = featureIndex;
86107
}
87108
}

main/src/main/java/org/mobilitydata/gtfsvalidator/table/GeoJsonFileLoader.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ public GtfsGeoJsonFeature extractFeature(
222222

223223
String type = geometry.get(GtfsGeoJsonFeature.GEOMETRY_TYPE_FIELD_NAME).getAsString();
224224

225+
validateCoordinates(noticeContainer, featureIndex, geometry, gtfsGeoJsonFeature);
226+
225227
if (type.equals(GeometryType.POLYGON.getType())) {
226228
gtfsGeoJsonFeature.setGeometryType(GeometryType.POLYGON);
227229
Polygon polygon =
@@ -270,6 +272,40 @@ public GtfsGeoJsonFeature extractFeature(
270272
return null;
271273
}
272274

275+
private static void validateCoordinates(
276+
NoticeContainer noticeContainer,
277+
int featureIndex,
278+
JsonObject geometry,
279+
GtfsGeoJsonFeature gtfsGeoJsonFeature) {
280+
// Validate that the coordinates are not near the origin or the poles
281+
JsonArray coordinates =
282+
geometry.getAsJsonArray(GtfsGeoJsonFeature.GEOMETRY_COORDINATES_FIELD_NAME);
283+
for (int i = 0; i < coordinates.size(); i++) {
284+
for (int j = 0; j < coordinates.get(i).getAsJsonArray().size(); j++) {
285+
JsonArray point = coordinates.get(i).getAsJsonArray().get(j).getAsJsonArray();
286+
double lon = point.get(0).getAsDouble();
287+
double lat = point.get(1).getAsDouble();
288+
if (Math.abs(lon) <= 1 && Math.abs(lat) <= 1) {
289+
noticeContainer.addValidationNotice(
290+
new PointNearOriginNotice(
291+
GtfsGeoJsonFeature.FILENAME,
292+
gtfsGeoJsonFeature.featureId(),
293+
lat,
294+
lon,
295+
featureIndex));
296+
} else if (Math.abs(lat) >= 89) {
297+
noticeContainer.addValidationNotice(
298+
new PointNearPoleNotice(
299+
GtfsGeoJsonFeature.FILENAME,
300+
gtfsGeoJsonFeature.featureId(),
301+
lat,
302+
lon,
303+
featureIndex));
304+
}
305+
}
306+
}
307+
}
308+
273309
private static void addMissingRequiredFieldsNotices(
274310
List<String> missingRequiredFields,
275311
NoticeContainer noticeContainer,

main/src/test/java/org/mobilitydata/gtfsvalidator/table/GeoJsonFileLoaderTest.java

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@
1212
import org.junit.Test;
1313
import org.junit.runner.RunWith;
1414
import org.junit.runners.JUnit4;
15-
import org.mobilitydata.gtfsvalidator.notice.DuplicateGeoJsonKeyNotice;
16-
import org.mobilitydata.gtfsvalidator.notice.InvalidGeometryNotice;
17-
import org.mobilitydata.gtfsvalidator.notice.NoticeContainer;
15+
import org.mobilitydata.gtfsvalidator.notice.*;
1816

1917
/** Runs GeoJsonFileLoader on test json data. */
2018
@RunWith(JUnit4.class)
@@ -23,6 +21,7 @@ public class GeoJsonFileLoaderTest {
2321
static String validGeoJsonData;
2422
static String invalidPolygonGeoJsonData;
2523
static String duplicateGeoJsonKeyData;
24+
static String invalidPointsGeoJsonData;
2625
NoticeContainer noticeContainer;
2726

2827
@BeforeClass
@@ -138,10 +137,54 @@ public static void setUpBeforeClass() {
138137
" ]",
139138
"}");
140139

140+
invalidPointsGeoJsonData =
141+
String.join(
142+
"\n",
143+
"{",
144+
" 'type': 'FeatureCollection',",
145+
" 'features': [",
146+
" {",
147+
" 'id': 'id1',",
148+
" 'type': 'Feature',",
149+
" 'geometry': {",
150+
" 'type': 'Polygon',",
151+
" 'coordinates': [",
152+
" [",
153+
" [0.0, 0.0],",
154+
" [101.0, 0.0],",
155+
" [101.0, 1.0],",
156+
" [100.0, 1.0],",
157+
" [100.0, 0.0]",
158+
" ]",
159+
" ]",
160+
" },",
161+
" 'properties': {}",
162+
" },",
163+
" {",
164+
" 'id': 'id2',",
165+
" 'type': 'Feature',",
166+
" 'geometry': {",
167+
" 'type': 'Polygon',",
168+
" 'coordinates': [",
169+
" [",
170+
" [200.0, 0.0],",
171+
" [201.0, 0.0],",
172+
" [201.0, 2.0],",
173+
" [200.0, -89.75],",
174+
" [200.0, 0.0]",
175+
" ]",
176+
" ]",
177+
" },",
178+
" 'properties': {}",
179+
" }",
180+
" ]",
181+
"}");
182+
141183
// Replace single quotes with double quotes for JSON compliance
142184
validGeoJsonData = validGeoJsonData.replace("'", "\"");
143185
invalidPolygonGeoJsonData = invalidPolygonGeoJsonData.replace("'", "\"");
144186
duplicateGeoJsonKeyData = duplicateGeoJsonKeyData.replace("'", "\"");
187+
invalidPointsGeoJsonData = invalidPointsGeoJsonData.replace("'", "\"");
145188
}
146189

147190
@Before
@@ -200,6 +243,26 @@ public void testDuplicateGeoJsonKeyNotice() {
200243
assertThat(notices.size()).isGreaterThan(0);
201244
}
202245

246+
@Test
247+
public void testPointNearOriginAndPole() {
248+
// Testing for invalid points near origin and pole
249+
createLoader(invalidPointsGeoJsonData);
250+
251+
// Check if the correct validation notice is generated for the invalid points
252+
List<PointNearOriginNotice> originNotices =
253+
noticeContainer.getValidationNotices().stream()
254+
.filter(PointNearOriginNotice.class::isInstance)
255+
.map(PointNearOriginNotice.class::cast)
256+
.collect(Collectors.toList());
257+
List<PointNearPoleNotice> poleNotices =
258+
noticeContainer.getValidationNotices().stream()
259+
.filter(PointNearPoleNotice.class::isInstance)
260+
.map(PointNearPoleNotice.class::cast)
261+
.collect(Collectors.toList());
262+
assertThat(originNotices.size()).isGreaterThan(0);
263+
assertThat(poleNotices.size()).isGreaterThan(0);
264+
}
265+
203266
private GtfsEntityContainer createLoader(String jsonData) {
204267
GeoJsonFileLoader loader = new GeoJsonFileLoader();
205268
var fileDescriptor = new GtfsGeoJsonFileDescriptor();

0 commit comments

Comments
 (0)