From 4393d54cb1f76beef314dd6810f00624d87b0db6 Mon Sep 17 00:00:00 2001 From: emartin Date: Fri, 5 Apr 2019 09:51:13 +0000 Subject: Fix required config validation *Nested objects and list validation Change-Id: Icf615a610dd6e669d66ae07adc1316ca167a671b Issue-ID: DCAEGEN2-1327 Signed-off-by: emartin --- .../services/pmmapper/model/MeasFilterConfig.java | 1 + .../pmmapper/utils/RequiredFieldDeserializer.java | 42 ++++++++++++++++------ .../pmmapper/config/ConfigHandlerTests.java | 30 ++++++++++++++-- src/test/resources/incomplete_mapper_config.json | 24 ------------- 4 files changed, 60 insertions(+), 37 deletions(-) delete mode 100644 src/test/resources/incomplete_mapper_config.json (limited to 'src') diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/model/MeasFilterConfig.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/model/MeasFilterConfig.java index 0f1aaa9..a7d211f 100644 --- a/src/main/java/org/onap/dcaegen2/services/pmmapper/model/MeasFilterConfig.java +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/model/MeasFilterConfig.java @@ -33,6 +33,7 @@ import org.onap.dcaegen2.services.pmmapper.utils.GSONRequired; @NoArgsConstructor public class MeasFilterConfig { + @GSONRequired @SerializedName("filters") public List filters; diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/utils/RequiredFieldDeserializer.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/utils/RequiredFieldDeserializer.java index e956398..258b831 100644 --- a/src/main/java/org/onap/dcaegen2/services/pmmapper/utils/RequiredFieldDeserializer.java +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/utils/RequiredFieldDeserializer.java @@ -25,8 +25,13 @@ import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; +import lombok.NonNull; + import java.lang.reflect.Field; import java.lang.reflect.Type; +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; /** @@ -38,20 +43,35 @@ public class RequiredFieldDeserializer implements JsonDeserializer { @Override public T deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { T obj = new Gson().fromJson(jsonElement, type); - for (Field field : obj.getClass().getDeclaredFields()) { - if (field.getAnnotation(GSONRequired.class) != null) { - field.setAccessible(true); - try { - if (field.get(obj) == null) { - throw new JsonParseException(String.format("Field: '%s', is required but not found.", field.getName())); - } - } catch (Exception exception) { - throw new JsonParseException("Failed to check fields.", exception); - } + validateRequiredFields(obj.getClass().getDeclaredFields(), obj); + return obj; + } + + private void validateRequiredFields(@NonNull Field[] fields, @NonNull Object pojo) { + if (pojo instanceof List) { + final List pojoList = (List) pojo; + for (final Object pojoListPojo : pojoList) { + validateRequiredFields(pojoListPojo.getClass().getDeclaredFields(), pojoListPojo); } } - return obj; + Stream.of(fields) + .filter(field -> field.getAnnotation(GSONRequired.class) != null) + .forEach(field -> { + try { + field.setAccessible(true); + Object fieldObj = Optional.ofNullable(field.get(pojo)) + .orElseThrow(()-> new JsonParseException( + String.format("Field '%s' in class '%s' is required but not found.", + field.getName(), pojo.getClass().getSimpleName()))); + + Field[] declaredFields = fieldObj.getClass().getDeclaredFields(); + validateRequiredFields(declaredFields, fieldObj); + } + catch (Exception exception) { + throw new JsonParseException("Failed to check fields.", exception); + } + }); } } diff --git a/src/test/java/org/onap/dcaegen2/pmmapper/config/ConfigHandlerTests.java b/src/test/java/org/onap/dcaegen2/pmmapper/config/ConfigHandlerTests.java index f6aa2a8..e2bb4f5 100644 --- a/src/test/java/org/onap/dcaegen2/pmmapper/config/ConfigHandlerTests.java +++ b/src/test/java/org/onap/dcaegen2/pmmapper/config/ConfigHandlerTests.java @@ -25,6 +25,8 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.Map; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -48,6 +50,8 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.read.ListAppender; @@ -114,8 +118,24 @@ public class ConfigHandlerTests { @Test public void mapper_parse_valid_json_missing_attributes() throws Exception { - when(sender.send(anyString())).thenReturn(getFileContents("incomplete_mapper_config.json")); - assertThrows(MapperConfigException.class, this::getMapperConfig); + Map invalidConfigs = new HashMap<>(); + invalidConfigs.put("streams_subscribes", "{}"); + invalidConfigs.put("streams_publishes", "{}"); + invalidConfigs.put("streams_publishes", null); + invalidConfigs.remove("streams_publishes"); + invalidConfigs.put("pm-mapper-filter", null); + invalidConfigs.put("pm-mapper-filter", "{}"); + invalidConfigs.put("pm-mapper-filter", "{ \"filters\": null},"); + invalidConfigs.put("pm-mapper-filter", "{ \"filters\": [{\"pmDefVsn\": \"V9\"}] },"); + + invalidConfigs.forEach( (k,v) -> { + try { + when(sender.send(anyString())).thenReturn( getInvalidConfig(k,v)); + assertThrows(MapperConfigException.class, this::getMapperConfig); + } catch (Exception e) { + e.printStackTrace(); + } + }); } private MapperConfig getMapperConfig() @@ -136,4 +156,10 @@ public class ConfigHandlerTests { return fileAsString; } + private String getInvalidConfig(String validKey, String invalidValue) { + JsonObject invalidConfigJson = new JsonParser().parse(validMapperConfig).getAsJsonObject(); + invalidConfigJson.addProperty(validKey, invalidValue); + return invalidConfigJson.toString(); + } + } diff --git a/src/test/resources/incomplete_mapper_config.json b/src/test/resources/incomplete_mapper_config.json deleted file mode 100644 index ed4ebd7..0000000 --- a/src/test/resources/incomplete_mapper_config.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "_comment": "This mapper config is missing streams_subscribes", - "pm-mapper-filter": { - "filters": "{[]}" - }, - "3GPP.schema.file": "{\"3GPP_Schema\":\"./etc/3GPP_relaxed_schema.xsd\"}", - "streams_subscribes": null, - "streams_publishes": { - "pm_mapper_handle_out": { - "type": "message_router", - "aaf_password": null, - "dmaap_info": { - "topic_url": "https://we-are-message-router.us:3905/events/some-topic", - "client_role": null, - "location": null, - "client_id": null - }, - "aaf_username": null - } - }, - "some parameter": "unauthenticated.PM_VES_OUTPUT", - "some field": "1", - "services_calls": {} -} \ No newline at end of file -- cgit 1.2.3-korg