Merge "Renamed things to fit with namechange of RicSynchronizationTask"
[nonrtric.git] / policy-agent / src / main / java / org / oransc / policyagent / controllers / PolicyController.java
index 987cd97..0f3b391 100644 (file)
@@ -32,6 +32,8 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
+import lombok.Getter;
+
 import org.oransc.policyagent.clients.A1ClientFactory;
 import org.oransc.policyagent.exceptions.ServiceException;
 import org.oransc.policyagent.repository.ImmutablePolicy;
@@ -53,12 +55,24 @@ import org.springframework.web.bind.annotation.PutMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.reactive.function.client.WebClientResponseException;
 import reactor.core.publisher.Mono;
 
 @RestController
 @Api(tags = "A1 Policy Management")
 public class PolicyController {
 
+    public static class RejectionException extends Exception {
+        private static final long serialVersionUID = 1L;
+        @Getter
+        private final HttpStatus status;
+
+        public RejectionException(String message, HttpStatus status) {
+            super(message);
+            this.status = status;
+        }
+    }
+
     @Autowired
     private Rics rics;
     @Autowired
@@ -168,7 +182,7 @@ public class PolicyController {
             policy = policies.getPolicy(id);
             keepServiceAlive(policy.ownerServiceName());
             if (policy.ric().getState() != Ric.RicState.IDLE) {
-                return Mono.just(new ResponseEntity<>("Busy, recovering", HttpStatus.LOCKED));
+                return Mono.just(new ResponseEntity<>("Busy, synchronizing", HttpStatus.LOCKED));
             }
             Ric ric = policy.ric();
             return ric.getLock().lock(LockType.SHARED) // //
@@ -177,7 +191,8 @@ public class PolicyController {
                 .flatMap(client -> client.deletePolicy(policy)) //
                 .doOnNext(notUsed -> ric.getLock().unlockBlocking()) //
                 .doOnError(notUsed -> ric.getLock().unlockBlocking()) //
-                .flatMap(notUsed -> Mono.just(new ResponseEntity<>(HttpStatus.NO_CONTENT)));
+                .flatMap(notUsed -> Mono.just(new ResponseEntity<>(HttpStatus.NO_CONTENT)))
+                .onErrorResume(this::handleException);
         } catch (ServiceException e) {
             return Mono.just(new ResponseEntity<>(HttpStatus.NOT_FOUND));
         }
@@ -190,10 +205,10 @@ public class PolicyController {
             @ApiResponse(code = 201, message = "Policy created", response = Object.class), //
             @ApiResponse(code = 200, message = "Policy updated", response = Object.class), //
             @ApiResponse(code = 423, message = "RIC is locked", response = String.class), //
-            @ApiResponse(code = 404, message = "RIC or policy type is not found", response = String.class), //
-            @ApiResponse(code = 405, message = "Change is not allowed", response = String.class)})
+            @ApiResponse(code = 404, message = "RIC or policy type is not found", response = String.class) //
+        })
     public Mono<ResponseEntity<Object>> putPolicy( //
-        @RequestParam(name = "type", required = true) String typeName, //
+        @RequestParam(name = "type", required = false, defaultValue = "") String typeName, //
         @RequestParam(name = "instance", required = true) String instanceId, //
         @RequestParam(name = "ric", required = true) String ricName, //
         @RequestParam(name = "service", required = true) String service, //
@@ -223,20 +238,39 @@ public class PolicyController {
                 .doOnNext(notUsed -> ric.getLock().unlockBlocking()) //
                 .doOnError(t -> ric.getLock().unlockBlocking()) //
                 .flatMap(notUsed -> Mono.just(new ResponseEntity<>(isCreate ? HttpStatus.CREATED : HttpStatus.OK))) //
-                .onErrorResume(t -> Mono.just(new ResponseEntity<>(t.getMessage(), HttpStatus.METHOD_NOT_ALLOWED)));
+                .onErrorResume(this::handleException);
         }
 
         return ric == null || type == null ? Mono.just(new ResponseEntity<>(HttpStatus.NOT_FOUND))
-            : Mono.just(new ResponseEntity<>(HttpStatus.LOCKED)); // Recovering
+            : Mono.just(new ResponseEntity<>(HttpStatus.LOCKED)); // Synchronizing
+    }
+
+    @SuppressWarnings({"unchecked"})
+    private <T> Mono<ResponseEntity<T>> createResponseEntity(String message, HttpStatus status) {
+        ResponseEntity<T> re = new ResponseEntity<>((T) message, status);
+        return Mono.just(re);
+    }
+
+    private <T> Mono<ResponseEntity<T>> handleException(Throwable throwable) {
+        if (throwable instanceof WebClientResponseException) {
+            WebClientResponseException e = (WebClientResponseException) throwable;
+            return createResponseEntity(e.getResponseBodyAsString(), e.getStatusCode());
+        } else if (throwable instanceof RejectionException) {
+            RejectionException e = (RejectionException) throwable;
+            return createResponseEntity(e.getMessage(), e.getStatus());
+        } else {
+            return createResponseEntity(throwable.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
+        }
     }
 
     private Mono<Object> validateModifiedPolicy(Policy policy) {
         // Check that ric is not updated
         Policy current = this.policies.get(policy.id());
         if (current != null && !current.ric().name().equals(policy.ric().name())) {
-            return Mono.error(new Exception("Policy cannot change RIC, policyId: " + current.id() + //
+            RejectionException e = new RejectionException("Policy cannot change RIC, policyId: " + current.id() + //
                 ", RIC name: " + current.ric().name() + //
-                ", new name: " + policy.ric().name()));
+                ", new name: " + policy.ric().name(), HttpStatus.CONFLICT);
+            return Mono.error(e);
         }
         return Mono.just("OK");
     }
@@ -259,27 +293,30 @@ public class PolicyController {
             return new ResponseEntity<>("RIC not found", HttpStatus.NOT_FOUND);
         }
         synchronized (policies) {
-            Collection<Policy> result = null;
-
-            if (type != null) {
-                result = policies.getForType(type);
-                result = filter(result, null, ric, service);
-            } else if (service != null) {
-                result = policies.getForService(service);
-                result = filter(result, type, ric, null);
-            } else if (ric != null) {
-                result = filter(policies.getForRic(ric), type, null, service);
-            } else {
-                result = policies.getAll();
-            }
+            String filteredPolicies = policiesToJson(filter(type, ric, service));
+            return new ResponseEntity<>(filteredPolicies, HttpStatus.OK);
+        }
+    }
 
-            String policiesJson;
-            try {
-                policiesJson = policiesToJson(result);
-            } catch (ServiceException e) {
-                return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
-            }
-            return new ResponseEntity<>(policiesJson, HttpStatus.OK);
+    @GetMapping("/policy_ids")
+    @ApiOperation(value = "Query policies, only IDs returned")
+    @ApiResponses(
+        value = {@ApiResponse(code = 200, message = "Policy ids", response = String.class, responseContainer = "List"),
+            @ApiResponse(code = 404, message = "RIC or type not found", response = String.class)})
+    public ResponseEntity<String> getPolicyIds( //
+        @RequestParam(name = "type", required = false) String type, //
+        @RequestParam(name = "ric", required = false) String ric, //
+        @RequestParam(name = "service", required = false) String service) //
+    {
+        if ((type != null && this.policyTypes.get(type) == null)) {
+            return new ResponseEntity<>("Policy type not found", HttpStatus.NOT_FOUND);
+        }
+        if ((ric != null && this.rics.get(ric) == null)) {
+            return new ResponseEntity<>("RIC not found", HttpStatus.NOT_FOUND);
+        }
+        synchronized (policies) {
+            String policyIdsJson = toPolicyIdsJson(filter(type, ric, service));
+            return new ResponseEntity<>(policyIdsJson, HttpStatus.OK);
         }
     }
 
@@ -297,7 +334,8 @@ public class PolicyController {
 
             return a1ClientFactory.createA1Client(policy.ric()) //
                 .flatMap(client -> client.getPolicyStatus(policy)) //
-                .flatMap(status -> Mono.just(new ResponseEntity<>(status, HttpStatus.OK)));
+                .flatMap(status -> Mono.just(new ResponseEntity<>(status, HttpStatus.OK)))
+                .onErrorResume(this::handleException);
         } catch (ServiceException e) {
             return Mono.just(new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND));
         }
@@ -328,7 +366,21 @@ public class PolicyController {
         return filtered;
     }
 
-    private String policiesToJson(Collection<Policy> policies) throws ServiceException {
+    private Collection<Policy> filter(String type, String ric, String service) {
+        synchronized (policies) {
+            if (type != null) {
+                return filter(policies.getForType(type), null, ric, service);
+            } else if (service != null) {
+                return filter(policies.getForService(service), type, ric, null);
+            } else if (ric != null) {
+                return filter(policies.getForRic(ric), type, null, service);
+            } else {
+                return policies.getAll();
+            }
+        }
+    }
+
+    private String policiesToJson(Collection<Policy> policies) {
         List<PolicyInfo> v = new ArrayList<>(policies.size());
         for (Policy p : policies) {
             PolicyInfo policyInfo = new PolicyInfo();
@@ -339,7 +391,7 @@ public class PolicyController {
             policyInfo.service = p.ownerServiceName();
             policyInfo.lastModified = p.lastModified();
             if (!policyInfo.validate()) {
-                throw new ServiceException("BUG, all fields must be set");
+                throw new NullPointerException("BUG, all fields must be set");
             }
             v.add(policyInfo);
         }
@@ -373,6 +425,14 @@ public class PolicyController {
         return gson.toJson(v);
     }
 
+    private String toPolicyIdsJson(Collection<Policy> policies) {
+        List<String> v = new ArrayList<>(policies.size());
+        for (Policy p : policies) {
+            v.add(p.id());
+        }
+        return gson.toJson(v);
+    }
+
     private String getTimeStampUtc() {
         return java.time.Instant.now().toString();
     }