Refactor the ValidationService
[aai/aai-common.git] / aai-core / src / main / java / org / onap / aai / prevalidation / ValidationService.java
index 70e16e2..939c838 100644 (file)
@@ -29,6 +29,7 @@ import java.net.ConnectException;
 import java.net.SocketTimeoutException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -46,7 +47,6 @@ import org.onap.aai.rest.ueb.NotificationEvent;
 import org.onap.aai.restclient.RestClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Profile;
@@ -63,55 +63,33 @@ import org.springframework.stereotype.Service;
 @Profile("pre-validation")
 public class ValidationService {
 
-    /**
-     * Error indicating that the service trying to connect is down
-     */
     static final String CONNECTION_REFUSED_STRING =
             "Connection refused to the validation microservice due to service unreachable";
-
-    /**
-     * Error indicating that the server is unable to reach the port
-     * Could be server related connectivity issue
-     */
     static final String CONNECTION_TIMEOUT_STRING = "Connection timeout to the validation microservice as this could "
             + "indicate the server is unable to reach port, "
             + "please check on server by running: nc -w10 -z -v ${VALIDATION_HOST} ${VALIDATION_PORT}";
-
-    /**
-     * Error indicating that the request exceeded the allowed time
-     *
-     * Note: This means that the service could be active its
-     * just taking some time to process our request
-     */
     static final String REQUEST_TIMEOUT_STRING =
             "Request to validation service took longer than the currently set timeout";
-
     static final String VALIDATION_ENDPOINT = "/v1/validate";
     static final String VALIDATION_HEALTH_ENDPOINT = "/v1/info";
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(ValidationService.class);
     private static final String ENTITY_TYPE = "entity-type";
     private static final String ACTION = "action";
     private static final String SOURCE_NAME = "source-name";
-
     private static final String DELETE = "DELETE";
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(ValidationService.class);
-
     private final RestClient validationRestClient;
-
     private final String appName;
-
     private final Set<String> validationNodeTypes;
+    private final Gson gson;
 
     private List<Pattern> exclusionList;
 
-    private final Gson gson;
-
-    @Autowired
     public ValidationService(@Qualifier("validationRestClient") RestClient validationRestClient,
             @Value("${spring.application.name}") String appName,
             @Value("${validation.service.node-types}") String validationNodes,
-            @Value("${validation.service.exclusion-regexes}") String exclusionRegexes) {
+            @Value("${validation.service.exclusion-regexes:#{null}}") String exclusionRegexes) {
         this.validationRestClient = validationRestClient;
         this.appName = appName;
 
@@ -129,20 +107,19 @@ public class ValidationService {
 
     @PostConstruct
     public void initialize() throws AAIException {
+        doHealthCheckRequest();
+    }
 
+    private void doHealthCheckRequest() throws AAIException {
         Map<String, String> httpHeaders = new HashMap<>();
-
         httpHeaders.put("X-FromAppId", appName);
         httpHeaders.put("X-TransactionID", UUID.randomUUID().toString());
         httpHeaders.put("Content-Type", "application/json");
 
         ResponseEntity<String> healthCheckResponse = null;
-
         try {
-
             healthCheckResponse =
                     validationRestClient.execute(VALIDATION_HEALTH_ENDPOINT, HttpMethod.GET, httpHeaders, null);
-
         } catch (Exception ex) {
             AAIException validationException = new AAIException("AAI_4021", ex);
             throw validationException;
@@ -160,50 +137,29 @@ public class ValidationService {
     }
 
     public void validate(List<NotificationEvent> notificationEvents) throws AAIException {
-
-        if (notificationEvents == null || notificationEvents.isEmpty()) {
+        if (notificationEvents == null || notificationEvents.isEmpty() || isSourceExcluded(notificationEvents)) {
             return;
         }
 
-        {
-            // Get the first notification and if the source of that notification
-            // is in one of the regexes then we skip sending it to validation
-            NotificationEvent notification = notificationEvents.get(0);
-            Introspector eventHeader = notification.getEventHeader();
-            if (eventHeader != null) {
-                String source = eventHeader.getValue(SOURCE_NAME);
-                for (Pattern pattern : exclusionList) {
-                    if (pattern.matcher(source).matches()) {
-                        return;
-                    }
-                }
-            }
-
-        }
-
         for (NotificationEvent event : notificationEvents) {
-
             Introspector eventHeader = event.getEventHeader();
-
             if (eventHeader == null) {
                 // Should I skip processing the request and let it continue
                 // or fail the request and cause client impact
                 continue;
             }
 
-            String entityType = eventHeader.getValue(ENTITY_TYPE);
-            String action = eventHeader.getValue(ACTION);
-
-            /**
+            /*
              * Skipping the delete events for now
              * Note: Might revisit this later when validation supports DELETE events
              */
-            if (DELETE.equalsIgnoreCase(action)) {
+            if (isDelete(eventHeader)) {
                 continue;
             }
+            String entityType = eventHeader.getValue(ENTITY_TYPE);
 
             if (this.shouldValidate(entityType)) {
-                List<String> violations = this.preValidate(event.getNotificationEvent());
+                List<String> violations = preValidate(event.getNotificationEvent());
                 if (!violations.isEmpty()) {
                     AAIException aaiException = new AAIException("AAI_4019");
                     aaiException.getTemplateVars().addAll(violations);
@@ -213,10 +169,33 @@ public class ValidationService {
         }
     }
 
-    List<String> preValidate(String body) throws AAIException {
+    /**
+     * Determine if event is of type delete
+     */
+    private boolean isDelete(Introspector eventHeader) {
+        String action = eventHeader.getValue(ACTION);
+        return DELETE.equalsIgnoreCase(action);
+    }
+
+    /**
+     * Checks the `source` attribute of the first event to determine if validation should be skipped
+     * @param notificationEvents
+     * @return
+     */
+    private boolean isSourceExcluded(List<NotificationEvent> notificationEvents) {
+        // Get the first notification and if the source of that notification
+        // is in one of the regexes then we skip sending it to validation
+        NotificationEvent notification = notificationEvents.get(0);
+        Introspector eventHeader = notification.getEventHeader();
+        if (eventHeader != null) {
+            String source = eventHeader.getValue(SOURCE_NAME);
+            return exclusionList.stream().anyMatch(pattern -> pattern.matcher(source).matches());
+        }
+        return false;
+    }
 
+    public List<String> preValidate(String body) throws AAIException {
         Map<String, String> httpHeaders = new HashMap<>();
-
         httpHeaders.put("X-FromAppId", appName);
         httpHeaders.put("X-TransactionID", UUID.randomUUID().toString());
         httpHeaders.put("Content-Type", "application/json");
@@ -224,26 +203,19 @@ public class ValidationService {
         List<String> violations = new ArrayList<>();
         ResponseEntity<String> responseEntity;
         try {
-
             responseEntity = validationRestClient.execute(VALIDATION_ENDPOINT, HttpMethod.POST, httpHeaders, body);
-
             Object responseBody = responseEntity.getBody();
             if (isSuccess(responseEntity)) {
                 LOGGER.debug("Validation Service returned following response status code {} and body {}",
                         responseEntity.getStatusCodeValue(), responseEntity.getBody());
             } else if (responseBody != null) {
-                Validation validation = null;
-                try {
-                    validation = gson.fromJson(responseBody.toString(), Validation.class);
-                } catch (JsonSyntaxException jsonException) {
-                    LOGGER.warn("Unable to convert the response body {}", jsonException.getMessage());
-                }
+                Validation validation = getValidation(responseBody);
 
                 if (validation == null) {
                     LOGGER.debug("Validation Service following status code {} with body {}",
                             responseEntity.getStatusCodeValue(), responseEntity.getBody());
                 } else {
-                    violations.addAll(extractViolations(validation));
+                    violations = extractViolations(validation);
                 }
             } else {
                 LOGGER.warn("Unable to convert the response body null");
@@ -267,27 +239,27 @@ public class ValidationService {
         return violations;
     }
 
+    private Validation getValidation(Object responseBody) {
+        Validation validation = null;
+        try {
+            validation = gson.fromJson(responseBody.toString(), Validation.class);
+        } catch (JsonSyntaxException jsonException) {
+            LOGGER.warn("Unable to convert the response body {}", jsonException.getMessage());
+        }
+        return validation;
+    }
+
     boolean isSuccess(ResponseEntity<String> responseEntity) {
         return responseEntity != null && responseEntity.getStatusCode().is2xxSuccessful();
     }
 
-    List<String> extractViolations(Validation validation) {
-
-        List<String> errorMessages = new ArrayList<>();
-
-        if (validation == null) {
-            return errorMessages;
+    public List<String> extractViolations(Validation validation) {
+        if (validation == null || validation.getViolations() == null) {
+            return Collections.emptyList();
         }
-
-        List<Violation> violations = validation.getViolations();
-
-        if (violations != null && !violations.isEmpty()) {
-            for (Violation violation : validation.getViolations()) {
-                LOGGER.info(violation.getErrorMessage());
-                errorMessages.add(violation.getErrorMessage());
-            }
-        }
-
-        return errorMessages;
+        return validation.getViolations().stream()
+            .map(Violation::getErrorMessage)
+            .peek(LOGGER::info)
+            .collect(Collectors.toList());
     }
 }