Merge "Handle non transient policy deletion"
diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java
index 53cf62a..630be49 100644
--- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java
+++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java
@@ -126,7 +126,6 @@
         return Mono.just(new ResponseEntity<>(toPolicyTypeIdsJson(types), HttpStatus.OK));
     }
 
-
     @Override
     public Mono<ResponseEntity<PolicyInfo>> getPolicy(String policyId, final ServerWebExchange exchange)
             throws EntityNotFoundException {
@@ -142,6 +141,7 @@
         Policy policy = policies.getPolicy(policyId);
         keepServiceAlive(policy.getOwnerServiceId());
 
+        logger.trace("Policy to be deleted: {}", policy.getId());
         return authorization.doAccessControl(exchange.getRequest().getHeaders().toSingleValueMap(), policy, AccessType.WRITE)
                 .flatMap(x -> policy.getRic().getLock().lock(Lock.LockType.SHARED, "deletePolicy"))
                 .flatMap(grant -> deletePolicy(grant, policy))
@@ -162,13 +162,11 @@
     public Mono<ResponseEntity<Object>> putPolicy(final Mono<PolicyInfo> policyInfo, final ServerWebExchange exchange) {
 
         return policyInfo.flatMap(policyInfoValue -> {
-                String jsonString  = gson.toJson(policyInfoValue.getPolicyData());
-            return Mono.zip(
-                            Mono.justOrEmpty(rics.get(policyInfoValue.getRicId()))
+            String jsonString = gson.toJson(policyInfoValue.getPolicyData());
+            return Mono.zip(Mono.justOrEmpty(rics.get(policyInfoValue.getRicId()))
                                     .switchIfEmpty(Mono.error(new EntityNotFoundException("Near-RT RIC not found"))),
                             Mono.justOrEmpty(policyTypes.get(policyInfoValue.getPolicytypeId()))
-                                    .switchIfEmpty(Mono.error(new EntityNotFoundException("policy type not found")))
-                    )
+                                    .switchIfEmpty(Mono.error(new EntityNotFoundException("policy type not found"))))
                     .flatMap(tuple -> {
                         Ric ric = tuple.getT1();
                         PolicyType type = tuple.getT2();
@@ -187,13 +185,10 @@
                         return authorization.doAccessControl(exchange.getRequest().getHeaders().toSingleValueMap(), policy, AccessType.WRITE)
                                 .flatMap(x -> ric.getLock().lock(Lock.LockType.SHARED, "putPolicy"))
                                 .flatMap(grant -> putPolicy(grant, policy));
-                    })
-                    .onErrorResume(this::handleException);
+                    }).onErrorResume(this::handleException);
         });
     }
 
-
-
     private Mono<ResponseEntity<Object>> putPolicy(Lock.Grant grant, Policy policy) {
         final boolean isCreate = this.policies.get(policy.getId()) == null;
         final Ric ric = policy.getRic();
@@ -328,32 +323,31 @@
     }
 
     private PolicyInfo toPolicyInfo(Policy policy) {
-       try {
-           PolicyInfo policyInfo = new PolicyInfo()
-                   .policyId(policy.getId())
-                   .policyData(objectMapper.readTree(policy.getJson()))
-                   .ricId(policy.getRic().id())
-                   .policytypeId(policy.getType().getId())
-                   .serviceId(policy.getOwnerServiceId())
-                   ._transient(policy.isTransient());
-           if (!policy.getStatusNotificationUri().isEmpty()) {
-               policyInfo.setStatusNotificationUri(policy.getStatusNotificationUri());
-           }
-           return policyInfo;
-       } catch (JsonProcessingException ex) {
-           throw new RuntimeException(ex);
-       }
+        try {
+            PolicyInfo policyInfo = new PolicyInfo()
+                    .policyId(policy.getId())
+                    .policyData(objectMapper.readTree(policy.getJson()))
+                    .ricId(policy.getRic().id())
+                    .policytypeId(policy.getType().getId())
+                    .serviceId(policy.getOwnerServiceId())
+                    ._transient(policy.isTransient());
+            if (!policy.getStatusNotificationUri().isEmpty()) {
+                policyInfo.setStatusNotificationUri(policy.getStatusNotificationUri());
+            }
+            return policyInfo;
+        } catch (JsonProcessingException ex) {
+            throw new RuntimeException(ex);
+        }
     }
 
     private PolicyInfoList policiesToJson(Collection<Policy> policies) {
-
-                List<PolicyInfo> policiesList = new ArrayList<>(policies.size());
-                PolicyInfoList policyInfoList = new PolicyInfoList();
-                for (Policy policy : policies) {
-                    policiesList.add(toPolicyInfo(policy));
-                }
-                policyInfoList.setPolicies(policiesList);
-                return policyInfoList;
+        List<PolicyInfo> policiesList = new ArrayList<>(policies.size());
+        PolicyInfoList policyInfoList = new PolicyInfoList();
+        for (Policy policy : policies) {
+            policiesList.add(toPolicyInfo(policy));
+        }
+        policyInfoList.setPolicies(policiesList);
+        return policyInfoList;
     }
 
     private Object fromJson(String jsonStr) {
@@ -373,12 +367,12 @@
 
     private PolicyIdList toPolicyIdsJson(Collection<Policy> policies) {
 
-            List<String> policyIds = new ArrayList<>(policies.size());
-            PolicyIdList idList = new PolicyIdList();
-            for (Policy policy : policies) {
-                policyIds.add(policy.getId());
-            }
-            idList.setPolicyIds(policyIds);
-            return idList;
+        List<String> policyIds = new ArrayList<>(policies.size());
+        PolicyIdList idList = new PolicyIdList();
+        for (Policy policy : policies) {
+            policyIds.add(policy.getId());
+        }
+        idList.setPolicyIds(policyIds);
+        return idList;
     }
 }
diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceController.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceController.java
index 5c92b54..09dfe44 100644
--- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceController.java
+++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceController.java
@@ -20,9 +20,6 @@
 
 package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import org.onap.ccsdk.oran.a1policymanagementservice.controllers.api.v2.ServiceRegistryAndSupervisionApi;
 import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException;
@@ -33,13 +30,17 @@
 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policy;
 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Service;
 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Services;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.server.ServerWebExchange;
+
 import reactor.core.publisher.Mono;
 
+import java.lang.invoke.MethodHandles;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.time.Duration;
@@ -61,10 +62,10 @@
     private final Services services;
     private final Policies policies;
 
-    @Autowired
-    private ObjectMapper objectMapper;
+    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-    private static Gson gson = new GsonBuilder().create();
+    @Autowired
+    private PolicyController policyController;
 
     ServiceController(Services services, Policies policies) {
         this.services = services;
@@ -118,50 +119,66 @@
             + "Policies can be created even if the service is not registerred. This is a feature which it is optional to use.";
 
     @Override
-    public Mono<ResponseEntity<Object>> putService(
-            final Mono<ServiceRegistrationInfo> registrationInfo, final ServerWebExchange exchange) {
-            return registrationInfo.flatMap(info -> {
-                try {
-                    validateRegistrationInfo(info);
-                } catch(Exception e) {
-                    return ErrorResponse.createMono(e, HttpStatus.BAD_REQUEST);
-                }
-                final boolean isCreate = this.services.get(info.getServiceId()) == null;
-                this.services.put(toService(info));
-                return Mono.just(new ResponseEntity<>(isCreate ? HttpStatus.CREATED : HttpStatus.OK));
-            }).onErrorResume(Exception.class, e -> ErrorResponse.createMono(e, HttpStatus.BAD_REQUEST));
+    public Mono<ResponseEntity<Object>> putService(final Mono<ServiceRegistrationInfo> registrationInfo, final ServerWebExchange exchange) {
+        return registrationInfo.flatMap(info -> {
+            try {
+                validateRegistrationInfo(info);
+            } catch (Exception e) {
+                return ErrorResponse.createMono(e, HttpStatus.BAD_REQUEST);
+            }
+            final boolean isCreate = this.services.get(info.getServiceId()) == null;
+            this.services.put(toService(info));
+            return Mono.just(new ResponseEntity<>(isCreate ? HttpStatus.CREATED : HttpStatus.OK));
+        }).onErrorResume(Exception.class, e -> ErrorResponse.createMono(e, HttpStatus.BAD_REQUEST));
     }
 
     @Override
     public Mono<ResponseEntity<Object>> deleteService(final String serviceId, final ServerWebExchange exchange) {
         try {
             Service service = removeService(serviceId);
-            // Remove the policies from the repo and let the consistency monitoring
-            // do the rest.
-            removePolicies(service);
+            removePolicies(service, exchange);
             return Mono.just(new ResponseEntity<>(HttpStatus.NO_CONTENT));
-        } catch (ServiceException e) {
+        } catch (ServiceException | NullPointerException e) {
+            logger.warn("Exception caught during service deletion while deleting service {}: {}", serviceId,
+                    e.getMessage());
             return ErrorResponse.createMono(e, HttpStatus.NOT_FOUND);
         }
     }
 
     @Override
     public Mono<ResponseEntity<Object>> keepAliveService(final String serviceId, final ServerWebExchange exchange) throws ServiceException {
-
-            services.getService(serviceId).keepAlive();
-            return Mono.just(new ResponseEntity<>(HttpStatus.OK));
+        services.getService(serviceId).keepAlive();
+        return Mono.just(new ResponseEntity<>(HttpStatus.OK));
     }
 
     private Service removeService(String name) throws ServiceException {
         Service service = this.services.getService(name); // Just to verify that it exists
+        logger.trace("Service name to be deleted: {}", service.getName());
         this.services.remove(service.getName());
         return service;
     }
 
-    private void removePolicies(Service service) {
+    private void removePolicies(Service service, ServerWebExchange exchange) {
         Collection<Policy> policyList = this.policies.getForService(service.getName());
+        logger.trace("Policies to be deleted: {}", policyList);
         for (Policy policy : policyList) {
-            this.policies.remove(policy);
+            try {
+                policyController.deletePolicy(policy.getId(), exchange).doOnNext(resp -> {
+                    if (resp.getStatusCode().is2xxSuccessful()) {
+                        logger.trace("Deleting Policy '{}' when deleting Service '{}'", policy.getId(),
+                                service.getName());
+                    } else {
+                        logger.warn("Possible problem deleting Policy '{}' when deleting Service '{}'. Continuing, "
+                                + "but might trigger a re-sync with affected ric '{}'. Repsonse: \"{}\"",
+                                policy.getId(), service.getName(), policy.getRic().getConfig().getRicId(),
+                                resp.toString());
+                    }
+                }).subscribe();
+            } catch (Exception e) {
+                logger.warn("Problem deleting Policy '{}' when deleting Service '{}'."
+                        + " Continuing, but might trigger a re-sync with affected ric '{}'. Problem: \"{}\"",
+                        policy.getId(), service.getName(), policy.getRic().getConfig().getRicId(), e.getMessage());
+            }
         }
     }
 
diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RicSupervision.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RicSupervision.java
index f11e30f..ed6139e 100644
--- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RicSupervision.java
+++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RicSupervision.java
@@ -166,6 +166,7 @@
     }
 
     private Mono<RicData> validateInstances(Collection<String> ricPolicies, RicData ric) {
+        logger.trace("Policies to be validated: {} , against: {} , in ric: {}", ricPolicies, ric.ric.getManagedElementIds(), ric.ric.id());
         synchronized (this.policies) {
             if (ricPolicies.size() != policies.getForRic(ric.ric.id()).size()) {
                 logger.debug("RicSupervision, starting ric: {} synchronization (noOfPolicices == {}, expected == {})",