From 6966a9e1867defefd244dc67b040d058de9a4dcb Mon Sep 17 00:00:00 2001 From: Arsen Grigoryan <Grigoryan> Date: Sat, 25 Jun 2022 01:24:41 +0400 Subject: [PATCH] BUG 7154 [osdu][search][indexer] Indexer skipped the entire record with malformed SpatialLocation --- .../FeatureCollectionDeserializer.java | 4 +- .../indexer/util/parser/GeoShapeParser.java | 3 + .../FeatureCollectionDeserializerTest.java | 202 ------------------ .../util/parser/GeoShapeParserTest.java | 11 + .../input/invalid_feature_collection.json | 15 ++ 5 files changed, 31 insertions(+), 204 deletions(-) delete mode 100644 indexer-core/src/test/java/org/opengroup/osdu/indexer/model/geojson/jackson/FeatureCollectionDeserializerTest.java create mode 100644 indexer-core/src/test/resources/geojson/parsing/input/invalid_feature_collection.json diff --git a/indexer-core/src/main/java/org/opengroup/osdu/indexer/model/geojson/jackson/FeatureCollectionDeserializer.java b/indexer-core/src/main/java/org/opengroup/osdu/indexer/model/geojson/jackson/FeatureCollectionDeserializer.java index e1b45fc89..390229859 100644 --- a/indexer-core/src/main/java/org/opengroup/osdu/indexer/model/geojson/jackson/FeatureCollectionDeserializer.java +++ b/indexer-core/src/main/java/org/opengroup/osdu/indexer/model/geojson/jackson/FeatureCollectionDeserializer.java @@ -14,12 +14,12 @@ package org.opengroup.osdu.indexer.model.geojson.jackson; +import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.ObjectCodec; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; -import com.google.gson.JsonSyntaxException; import org.opengroup.osdu.indexer.model.geojson.Feature; import org.opengroup.osdu.indexer.model.geojson.FeatureCollection; @@ -42,7 +42,7 @@ public class FeatureCollectionDeserializer extends JsonDeserializer<FeatureColle JsonNode features = featureCollection.get("features"); if(features == null){ - throw new JsonSyntaxException("Missing feature field in the "); + throw new JsonParseException(jsonParser, "Missing feature field in the "); } final List<Feature> result = new ArrayList<>(); diff --git a/indexer-core/src/main/java/org/opengroup/osdu/indexer/util/parser/GeoShapeParser.java b/indexer-core/src/main/java/org/opengroup/osdu/indexer/util/parser/GeoShapeParser.java index 8bd6ec834..3674ca795 100644 --- a/indexer-core/src/main/java/org/opengroup/osdu/indexer/util/parser/GeoShapeParser.java +++ b/indexer-core/src/main/java/org/opengroup/osdu/indexer/util/parser/GeoShapeParser.java @@ -14,6 +14,7 @@ package org.opengroup.osdu.indexer.util.parser; +import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; @@ -42,6 +43,8 @@ public class GeoShapeParser { }); } catch (InvalidTypeIdException e) { throw new IllegalArgumentException("must be a valid FeatureCollection"); + } catch (JsonParseException e){ + throw new IllegalArgumentException(e.getMessage()); } catch (JsonProcessingException e) { throw new IllegalArgumentException("unable to parse FeatureCollection"); } diff --git a/indexer-core/src/test/java/org/opengroup/osdu/indexer/model/geojson/jackson/FeatureCollectionDeserializerTest.java b/indexer-core/src/test/java/org/opengroup/osdu/indexer/model/geojson/jackson/FeatureCollectionDeserializerTest.java deleted file mode 100644 index fa61f1447..000000000 --- a/indexer-core/src/test/java/org/opengroup/osdu/indexer/model/geojson/jackson/FeatureCollectionDeserializerTest.java +++ /dev/null @@ -1,202 +0,0 @@ -package org.opengroup.osdu.indexer.model.geojson.jackson; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import joptsimple.internal.Strings; -import lombok.SneakyThrows; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.opengroup.osdu.indexer.model.geojson.Feature; -import org.opengroup.osdu.indexer.model.geojson.FeatureCollection; -import org.springframework.test.context.junit4.SpringRunner; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.util.List; -import java.util.Map; - -import static org.hamcrest.CoreMatchers.containsString; -import static org.junit.Assert.*; - -@RunWith(SpringRunner.class) -public class FeatureCollectionDeserializerTest { - - @InjectMocks - private FeatureCollectionDeserializer featureCollectionDeserializer; - - private final ObjectMapper mapper = new ObjectMapper(); - private final JsonFactory factory = mapper.getFactory(); - - @Test - public void should_throwException_provided_emptyFeatureJson() { - String shapeJson = "{}"; - - this.validateInput(shapeJson, Strings.EMPTY, "feature not included"); - } - - @Test - public void should_throwException_parseInvalidPoint() { - String shapeJson = getFeatureFromFile("input/invalid_point.json"); - this.validateInput(shapeJson, Strings.EMPTY, "unable to parse FeatureCollection"); - } - - @Test - public void should_throwException_parseInvalidPoint_NaN() { - String shapeJson = getFeatureFromFile("input/invalid_point_nan.json"); - this.validateInput(shapeJson, Strings.EMPTY, "unable to parse FeatureCollection"); - } - - @Test - public void should_throwException_parseInvalidPoint_missingLatitude() { - String shapeJson = getFeatureFromFile("input/invalid_point_missing_latitude.json"); - this.validateInput(shapeJson, Strings.EMPTY, "unable to parse FeatureCollection"); - } - - @Test - public void should_throwException_missingMandatoryAttribute() { - String shapeJson = getFeatureFromFile("input/missing_mandatory_attribute.json"); - this.validateInput(shapeJson, Strings.EMPTY, "must be a valid FeatureCollection"); - } - - @Test - public void should_throwException_parseInvalidShape() { - String shapeJson = getFeatureFromFile("input/invalid_shape.json"); - this.validateInput(shapeJson, Strings.EMPTY, "must be a valid FeatureCollection"); - } - - @Test - public void should_parseValidPoint() { - String shapeJson = getFeatureFromFile("input/valid_point.json"); - this.validateInput(shapeJson, shapeJson, Strings.EMPTY); - } - - @Test - public void should_parseValidMultiPoint() { - String shapeJson = getFeatureFromFile("input/valid_multi_point.json"); - this.validateInput(shapeJson, shapeJson, Strings.EMPTY); - } - - @Test - public void should_parseValidLineString() { - String shapeJson = getFeatureFromFile("input/valid_line_string.json"); - this.validateInput(shapeJson, shapeJson, Strings.EMPTY); - } - - @Test - public void should_parseValidMultiLineString() { - String shapeJson = getFeatureFromFile("input/valid_multi_line_string.json"); - this.validateInput(shapeJson, shapeJson, Strings.EMPTY); - } - - @Test - public void should_parseValidPolygon() { - String shapeJson = getFeatureFromFile("input/valid_polygon.json"); - this.validateInput(shapeJson, shapeJson, Strings.EMPTY); - } - - @Test - public void should_throwException_parseInvalidPolygon_malformedLatitude() { - String shapeJson = getFeatureFromFile("input/invalid_polygon_malformed_latitude.json"); - this.validateInput(shapeJson, Strings.EMPTY, "unable to parse FeatureCollection"); - } - - @Test - public void should_parseValidMultiPolygon() { - String shapeJson = getFeatureFromFile("input/valid_multi_polygon.json"); - this.validateInput(shapeJson, shapeJson, Strings.EMPTY); - } - - @Test - public void should_parseValidGeometryCollection() { - String shapeJson = getFeatureFromFile("input/valid_geometry_collection.json"); - this.validateInput(shapeJson, shapeJson, Strings.EMPTY); - } - - @Test - public void should_parseValidFeatureCollection() { - String shapeJson = getFeatureFromFile("input/valid_feature_collection.json"); - this.validateInput(shapeJson, shapeJson, Strings.EMPTY); - } - - @Test - public void should_parseValidFeatureCollection_withZCoordinate() { - String shapeJson = getFeatureFromFile("input/valid_feature_collection_with_z_coordinate.json"); - this.validateInput(shapeJson, shapeJson, Strings.EMPTY); - } - - @Test - public void should_throwException_parseUnsupportedType_feature() { - String shapeJson = getFeatureFromFile("input/valid_feature_collection_with_z_coordinate.json"); - this.validateInput(shapeJson, shapeJson, Strings.EMPTY); - } - - @Test - public void shouldParseValidMultiPolygonWithZCoordinates() { - String shapeJson = getFeatureFromFile("input/multi_polygon_with_z_coordinates.json"); - this.validateInput(shapeJson, shapeJson, Strings.EMPTY); - } - - @Test - public void shouldParseValidLineStringWithZCoordinates() { - String shapeJson = getFeatureFromFile("input/line_string_with_z_coordinate.json"); - this.validateInput(shapeJson, shapeJson, Strings.EMPTY); - } - - @Test - public void shouldParseValidMultiLineStringWithZCoordinates() { - String shapeJson = getFeatureFromFile("input/valid_milti_line_string_with_z_coordinate.json"); - this.validateInput(shapeJson, shapeJson, Strings.EMPTY); - } - - - private void validateInput(String shapeJson, String expectedParsedShape, String errorMessage) { - try { - Type type = new TypeToken<Map<String, Object>>() {}.getType(); - Map<String, Object> expectedShape = new Gson().fromJson(expectedParsedShape, type); - FeatureCollection featureCollection = mapper.convertValue(expectedShape, FeatureCollection.class); - - JsonParser parser = factory.createParser(shapeJson); - List<Feature> result = (List<Feature>) callPrivateMethod_ExtractFeature(parser); - - assertNotNull(result); - assertTrue(Strings.isNullOrEmpty(errorMessage)); - assertEquals(featureCollection.getFeatures(), result); - } catch (IllegalArgumentException e) { - if (Strings.isNullOrEmpty(errorMessage)) { - fail(String.format("error parsing valid feature-json %s", shapeJson)); - } else { - assertThat(String.format("Incorrect error message for feature-json parsing [ %s ]", shapeJson), e.getMessage(), containsString(errorMessage)); - } - } catch (IOException | InvocationTargetException | NoSuchMethodException | IllegalAccessException e) { - e.printStackTrace(); - } - } - - @SneakyThrows - private String getFeatureFromFile(String file) { - InputStream inStream = this.getClass().getResourceAsStream("/geojson/parsing/" + file); - assert inStream != null; - BufferedReader br = new BufferedReader(new InputStreamReader(inStream)); - StringBuilder stringBuilder = new StringBuilder(); - String sCurrentLine; - while ((sCurrentLine = br.readLine()) != null) { - stringBuilder.append(sCurrentLine).append("\n"); - } - return stringBuilder.toString(); - } - - public Object callPrivateMethod_ExtractFeature(JsonParser parser) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException { - Method method = featureCollectionDeserializer.getClass().getDeclaredMethod("extractFeature", JsonParser.class); - method.setAccessible(true); - return method.invoke(featureCollectionDeserializer, parser); - } -} diff --git a/indexer-core/src/test/java/org/opengroup/osdu/indexer/util/parser/GeoShapeParserTest.java b/indexer-core/src/test/java/org/opengroup/osdu/indexer/util/parser/GeoShapeParserTest.java index 2b47f5ab3..fdec74784 100644 --- a/indexer-core/src/test/java/org/opengroup/osdu/indexer/util/parser/GeoShapeParserTest.java +++ b/indexer-core/src/test/java/org/opengroup/osdu/indexer/util/parser/GeoShapeParserTest.java @@ -34,6 +34,7 @@ import java.util.function.Function; import static org.hamcrest.CoreMatchers.containsString; import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.assertThrows; @RunWith(SpringRunner.class) public class GeoShapeParserTest { @@ -178,6 +179,16 @@ public class GeoShapeParserTest { this.validateInput(this.sut::parseGeoJson, shapeJson, expectedParsedShape, Strings.EMPTY); } + @Test + public void should_throwException_parseInvalidFeatureCollection() { + String shapeJson = getGeoShapeFromFile("input/invalid_feature_collection.json"); + + Type type = new TypeToken<Map<String, Object>>() {}.getType(); + Map<String, Object> shapeObj = new Gson().fromJson(shapeJson, type); + + assertThrows(IllegalArgumentException.class, () -> this.sut.parseGeoJson(shapeObj)); + } + private void validateInput(Function<Map<String, Object>, Map<String, Object>> parser, String shapeJson, String expectedParsedShape, String errorMessage) { try { Type type = new TypeToken<Map<String, Object>>() {}.getType(); diff --git a/indexer-core/src/test/resources/geojson/parsing/input/invalid_feature_collection.json b/indexer-core/src/test/resources/geojson/parsing/input/invalid_feature_collection.json new file mode 100644 index 000000000..5a91d57a7 --- /dev/null +++ b/indexer-core/src/test/resources/geojson/parsing/input/invalid_feature_collection.json @@ -0,0 +1,15 @@ +{ + "type": "FeatureCollection", + "featur3es": [ + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -105.01621, + 39.57422 + ] + } + } + ] +} \ No newline at end of file -- GitLab