hub resource format date 68/76268/3
authorromaingimbert <romain.gimbert@orange.com>
Thu, 24 Jan 2019 10:01:03 +0000 (11:01 +0100)
committerromaingimbert <romain.gimbert@orange.com>
Thu, 24 Jan 2019 11:28:42 +0000 (12:28 +0100)
-fix code
-add listener for testing
-add karate test

Change-Id: Ife2d7812c77316b75c55e86056f59d838e117069
Issue-ID: EXTAPI-180
Signed-off-by: romaingimbert <romain.gimbert@orange.com>
src/main/java/org/onap/nbi/apis/hub/HubResource.java
src/main/java/org/onap/nbi/apis/hub/model/Event.java
src/main/java/org/onap/nbi/apis/hub/service/EventFactory.java
src/main/java/org/onap/nbi/apis/hub/service/NotifierService.java
src/main/java/org/onap/nbi/apis/serviceorder/SoClient.java
src/test/java/org/onap/nbi/api/listener/ListenerResource.java [new file with mode: 0644]
src/test/java/org/onap/nbi/apis/servicecatalog/ToscaInfosProcessorTest.java [new file with mode: 0644]
src/test/resources/karatetest/data/serviceOrder.json
src/test/resources/karatetest/features/03--Subscriber.feature

index 9ef5235..cccd0a8 100755 (executable)
@@ -1,15 +1,14 @@
 /**
  * Copyright (c) 2018 Orange
  *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
  *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
  */
 package org.onap.nbi.apis.hub;
 
@@ -44,10 +43,6 @@ import org.springframework.web.bind.annotation.ResponseStatus;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
 
-import java.net.URI;
-import java.util.List;
-import java.util.stream.Collectors;
-
 @RestController
 @RequestMapping("/hub")
 @EnableScheduling
@@ -71,10 +66,10 @@ public class HubResource extends ResourceManagement {
         Subscriber subscriber = subscriptionService.createSubscription(subscription);
 
         URI location = ServletUriComponentsBuilder
-                .fromCurrentRequest()
-                .path("/{id}")
-                .buildAndExpand(subscriber.getId())
-                .toUri();
+            .fromCurrentRequest()
+            .path("/{id}")
+            .buildAndExpand(subscriber.getId())
+            .toUri();
 
         return ResponseEntity.created(location).build();
     }
@@ -82,7 +77,7 @@ public class HubResource extends ResourceManagement {
     @GetMapping(value = "/{subscriptionId}", produces = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<Subscription> getSubscription(@PathVariable String subscriptionId) {
 
-        Subscriber subscriber  = subscriptionService.findSubscriptionById(subscriptionId);
+        Subscriber subscriber = subscriptionService.findSubscriptionById(subscriptionId);
         if (subscriber == null) {
             return ResponseEntity.notFound().build();
         }
@@ -100,8 +95,8 @@ public class HubResource extends ResourceManagement {
         headers.add("X-Total-Count", String.valueOf(totalCount));
         headers.add("X-Result-Count", String.valueOf(subscribers.size()));
         List<Subscription> subscriptions = subscribers.stream()
-                .map(Subscription::createFromSubscriber)
-                .collect(Collectors.toList());
+            .map(Subscription::createFromSubscriber)
+            .collect(Collectors.toList());
 
         return this.findResponse(subscriptions, filter, headers);
 
index cf6c790..8540167 100755 (executable)
@@ -1,24 +1,21 @@
 /**
- *     Copyright (c) 2018 Orange
+ * Copyright (c) 2018 Orange
  *
- *     Licensed under the Apache License, Version 2.0 (the "License");
- *     you may not use this file except in compliance with the License.
- *     You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
  *
- *         http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- *     Unless required by applicable law or agreed to in writing, software
- *     distributed under the License is distributed on an "AS IS" BASIS,
- *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *     See the License for the specific language governing permissions and
- *     limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
  */
 package org.onap.nbi.apis.hub.model;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.databind.JsonNode;
-
-import javax.validation.constraints.NotNull;
 import java.util.Date;
+import javax.validation.constraints.NotNull;
 
 
 public class Event {
@@ -40,6 +37,7 @@ public class Event {
         this.eventId = eventId;
     }
 
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
     public Date getEventDate() {
         return eventDate;
     }
index 3e04b84..e935a1c 100644 (file)
@@ -1,17 +1,14 @@
 /**
- *     Copyright (c) 2018 Orange
+ * Copyright (c) 2018 Orange
  *
- *     Licensed under the Apache License, Version 2.0 (the "License");
- *     you may not use this file except in compliance with the License.
- *     You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
  *
- *         http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- *     Unless required by applicable law or agreed to in writing, software
- *     distributed under the License is distributed on an "AS IS" BASIS,
- *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *     See the License for the specific language governing permissions and
- *     limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
  */
 package org.onap.nbi.apis.hub.service;
 
@@ -19,6 +16,10 @@ import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.MappingJsonFactory;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.UUID;
 import org.onap.nbi.apis.hub.model.Event;
 import org.onap.nbi.apis.hub.model.EventType;
 import org.onap.nbi.apis.serviceorder.model.ServiceOrder;
@@ -26,9 +27,6 @@ import org.onap.nbi.apis.serviceorder.model.ServiceOrderItem;
 import org.onap.nbi.commons.JacksonFilter;
 import org.onap.nbi.commons.JsonRepresentation;
 
-import java.util.Date;
-import java.util.UUID;
-
 public class EventFactory {
 
     private static final ObjectMapper mapper = new ObjectMapper(new MappingJsonFactory());
@@ -39,11 +37,14 @@ public class EventFactory {
         event.setEventDate(new Date());
         event.setEventType(eventType.value());
 
+        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+        mapper.setDateFormat(df);
+
         JsonNode serviceOrderJson = mapper.valueToTree(filterServiceOrder(serviceOrder));
 
         if (EventType.SERVICE_ORDER_ITEM_STATE_CHANGE.equals(eventType)) {
             JsonNode serviceOrderItemJson = mapper.valueToTree(serviceOrderItem);
-            ((ObjectNode)serviceOrderJson).putArray("orderItem").add(serviceOrderItemJson);
+            ((ObjectNode) serviceOrderJson).putArray("orderItem").add(serviceOrderItemJson);
         }
 
         event.setEvent(serviceOrderJson);
index 4f7a549..90cc7a4 100755 (executable)
@@ -1,35 +1,31 @@
 /**
- *     Copyright (c) 2018 Orange
+ * Copyright (c) 2018 Orange
  *
- *     Licensed under the Apache License, Version 2.0 (the "License");
- *     you may not use this file except in compliance with the License.
- *     You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
  *
- *         http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- *     Unless required by applicable law or agreed to in writing, software
- *     distributed under the License is distributed on an "AS IS" BASIS,
- *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *     See the License for the specific language governing permissions and
- *     limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
  */
 package org.onap.nbi.apis.hub.service;
 
+import javax.validation.Valid;
 import org.onap.nbi.apis.hub.model.Event;
 import org.onap.nbi.apis.hub.model.Subscriber;
+import org.onap.nbi.exceptions.BackendFunctionalException;
 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.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.web.client.RestTemplate;
 
-import javax.validation.Valid;
-
 @Service
 public class NotifierService {
+
     private final Logger logger = LoggerFactory.getLogger(NotifierService.class);
 
     @Autowired
@@ -37,7 +33,12 @@ public class NotifierService {
 
     @Async
     public void run(Subscriber subscriber, @Valid Event event) {
-        ResponseEntity<String> re = restTemplate.postForEntity(subscriber.getCallback(), event, String.class);
-        if (re.getStatusCode() == HttpStatus.OK) logger.debug("FAILED");
+        try {
+            restTemplate.postForEntity(subscriber.getCallback(), event, Object.class);
+        } catch (BackendFunctionalException e) {
+            logger.error(" unable to post event to {} , receive {}, {}", subscriber.getCallback(), e.getHttpStatus(),
+                e.getBodyResponse());
+        }
+
     }
 }
index 21bfbcd..0d863d1 100644 (file)
@@ -70,19 +70,25 @@ public class SoClient {
 
     @PostConstruct
     private void setUpAndLogSOUrl() {
-        createSoUrl = new StringBuilder().append(soHostname).append(OnapComponentsUrlPaths.MSO_CREATE_SERVICE_INSTANCE_PATH).toString();
-        createE2ESoUrl = new StringBuilder().append(soHostname).append(OnapComponentsUrlPaths.MSO_CREATE_E2ESERVICE_INSTANCE_PATH).toString();
-        deleteSoUrl= new StringBuilder().append(soHostname).append(OnapComponentsUrlPaths.MSO_DELETE_REQUEST_STATUS_PATH).toString();
-        deleteE2ESoUrl= new StringBuilder().append(soHostname).append(OnapComponentsUrlPaths.MSO_DELETE_E2ESERVICE_INSTANCE_PATH).toString();
-        getSoStatus= new StringBuilder().append(soHostname).append(OnapComponentsUrlPaths.MSO_GET_REQUEST_STATUS_PATH).toString();
-        getE2ESoStatus= new StringBuilder().append(soHostname).append(OnapComponentsUrlPaths.MSO_GET_E2EREQUEST_STATUS_PATH).toString();
-
-        LOGGER.info("SO create service url :  "+ createSoUrl);
-        LOGGER.info("SO create e2e service url :  "+ createE2ESoUrl);
-        LOGGER.info("SO delete service url :  "+deleteSoUrl);
-        LOGGER.info("SO delete e2e service url :  "+deleteE2ESoUrl);
-        LOGGER.info("SO get so status url :  "+getSoStatus);
-        LOGGER.info("SO get e2e so status url :  "+getE2ESoStatus);
+        createSoUrl = new StringBuilder().append(soHostname)
+            .append(OnapComponentsUrlPaths.MSO_CREATE_SERVICE_INSTANCE_PATH).toString();
+        createE2ESoUrl = new StringBuilder().append(soHostname)
+            .append(OnapComponentsUrlPaths.MSO_CREATE_E2ESERVICE_INSTANCE_PATH).toString();
+        deleteSoUrl = new StringBuilder().append(soHostname)
+            .append(OnapComponentsUrlPaths.MSO_DELETE_REQUEST_STATUS_PATH).toString();
+        deleteE2ESoUrl = new StringBuilder().append(soHostname)
+            .append(OnapComponentsUrlPaths.MSO_DELETE_E2ESERVICE_INSTANCE_PATH).toString();
+        getSoStatus = new StringBuilder().append(soHostname).append(OnapComponentsUrlPaths.MSO_GET_REQUEST_STATUS_PATH)
+            .toString();
+        getE2ESoStatus = new StringBuilder().append(soHostname)
+            .append(OnapComponentsUrlPaths.MSO_GET_E2EREQUEST_STATUS_PATH).toString();
+
+        LOGGER.info("SO create service url :  " + createSoUrl);
+        LOGGER.info("SO create e2e service url :  " + createE2ESoUrl);
+        LOGGER.info("SO delete service url :  " + deleteSoUrl);
+        LOGGER.info("SO delete e2e service url :  " + deleteE2ESoUrl);
+        LOGGER.info("SO get so status url :  " + getSoStatus);
+        LOGGER.info("SO get e2e so status url :  " + getE2ESoStatus);
 
     }
 
@@ -101,14 +107,14 @@ public class SoClient {
             return response;
 
         } catch (BackendFunctionalException e) {
-            LOGGER.error(ERROR_ON_CALLING + createSoUrl + " ," + e);
-            return new ResponseEntity(e.getBodyResponse(),e.getHttpStatus());
+            LOGGER.error(ERROR_ON_CALLING + createSoUrl + " ," + e.getHttpStatus() + " , " + e.getBodyResponse());
+            return new ResponseEntity(e.getBodyResponse(), e.getHttpStatus());
         } catch (ResourceAccessException e) {
-            LOGGER.error(ERROR_ON_CALLING + createSoUrl + " ," + e);
+            LOGGER.error(ERROR_ON_CALLING + createSoUrl + " ," + e.getMessage());
             return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
         }
     }
-    
+
     public ResponseEntity<CreateE2EServiceInstanceResponse> callE2ECreateServiceInstance(MSOE2EPayload msoPayloadE2E) {
 
         if (LOGGER.isDebugEnabled()) {
@@ -116,22 +122,24 @@ public class SoClient {
         }
 
         try {
-            ResponseEntity<CreateE2EServiceInstanceResponse> response = restTemplate.exchange(createE2ESoUrl, HttpMethod.POST,
+            ResponseEntity<CreateE2EServiceInstanceResponse> response = restTemplate
+                .exchange(createE2ESoUrl, HttpMethod.POST,
                     new HttpEntity<>(msoPayloadE2E, buildRequestHeader()), CreateE2EServiceInstanceResponse.class);
 
             logE2EResponsePost(createE2ESoUrl, response);
             return response;
 
         } catch (BackendFunctionalException e) {
-            LOGGER.error(ERROR_ON_CALLING + createE2ESoUrl + " ," + e);
-            return new ResponseEntity(e.getBodyResponse(),e.getHttpStatus());
+            LOGGER.error(ERROR_ON_CALLING + createSoUrl + " ," + e.getHttpStatus() + " , " + e.getBodyResponse());
+            return new ResponseEntity(e.getBodyResponse(), e.getHttpStatus());
         } catch (ResourceAccessException e) {
-            LOGGER.error(ERROR_ON_CALLING + createE2ESoUrl + " ," + e);
+            LOGGER.error(ERROR_ON_CALLING + createE2ESoUrl + " ," + e.getMessage());
             return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
         }
     }
 
-    public ResponseEntity<CreateServiceInstanceResponse> callDeleteServiceInstance(MSOPayload msoPayload, String serviceId) {
+    public ResponseEntity<CreateServiceInstanceResponse> callDeleteServiceInstance(MSOPayload msoPayload,
+        String serviceId) {
 
         if (LOGGER.isDebugEnabled()) {
             LOGGER.debug("Calling SO DeleteServiceInstance with msoPayload : " + msoPayload.toString());
@@ -156,42 +164,47 @@ public class SoClient {
 
     }
 
-    public ResponseEntity<CreateE2EServiceInstanceResponse> callE2EDeleteServiceInstance(String globalSubscriberId, String serviceType,
-            String serviceInstanceId) {
+    public ResponseEntity<CreateE2EServiceInstanceResponse> callE2EDeleteServiceInstance(String globalSubscriberId,
+        String serviceType,
+        String serviceInstanceId) {
 
-            String url = deleteE2ESoUrl + serviceInstanceId;
-            MSODeleteE2EPayload msoDeleteE2EPayload = new MSODeleteE2EPayload();
-            msoDeleteE2EPayload.setGlobalSubscriberId(globalSubscriberId);
-            msoDeleteE2EPayload.setServiceType(serviceType);
-            
-            if (LOGGER.isDebugEnabled()) {
-                LOGGER.debug("Calling SO DeleteE2EServiceInstance with url : " + url + " MSODeleteE2EPayload : " + msoDeleteE2EPayload.toString() );
-            }
-            
-            try {
-                ResponseEntity<DeleteE2EServiceInstanceResponse> deleteresponse = restTemplate.exchange(url, HttpMethod.DELETE,
-                        new HttpEntity<>(msoDeleteE2EPayload, buildRequestHeader()), DeleteE2EServiceInstanceResponse.class);
-
-                // For E2E Services , Create and Delete Service responses are different, to maintain consistentcy with ServiceInstances
-                // Copy contents of DeleteE2EServiceInstanceResponse to CreateE2EServiceInstanceResponse
-                CreateE2EServiceInstanceResponse dummyresponse = new CreateE2EServiceInstanceResponse();
-                ServiceResponse serviceResponse = new ServiceResponse();
-                dummyresponse.setService(serviceResponse);
-                dummyresponse.getService().setOperationId(deleteresponse.getBody().getOperationId());
-                dummyresponse.getService().setServiceId(serviceInstanceId);
-                
-                ResponseEntity<CreateE2EServiceInstanceResponse> response = new ResponseEntity(dummyresponse, deleteresponse.getStatusCode());  
-                logE2EResponsePost(url, response);
-                return response;
-
-            } catch (BackendFunctionalException e) {
-                LOGGER.error(ERROR_ON_CALLING + url + " ," + e);
-                return new ResponseEntity<>(e.getHttpStatus());
-            } catch (ResourceAccessException e) {
-                LOGGER.error(ERROR_ON_CALLING + url + " ," + e);
-                return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
-            }
-       }
+        String url = deleteE2ESoUrl + serviceInstanceId;
+        MSODeleteE2EPayload msoDeleteE2EPayload = new MSODeleteE2EPayload();
+        msoDeleteE2EPayload.setGlobalSubscriberId(globalSubscriberId);
+        msoDeleteE2EPayload.setServiceType(serviceType);
+
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("Calling SO DeleteE2EServiceInstance with url : " + url + " MSODeleteE2EPayload : "
+                + msoDeleteE2EPayload.toString());
+        }
+
+        try {
+            ResponseEntity<DeleteE2EServiceInstanceResponse> deleteresponse = restTemplate
+                .exchange(url, HttpMethod.DELETE,
+                    new HttpEntity<>(msoDeleteE2EPayload, buildRequestHeader()),
+                    DeleteE2EServiceInstanceResponse.class);
+
+            // For E2E Services , Create and Delete Service responses are different, to maintain consistentcy with ServiceInstances
+            // Copy contents of DeleteE2EServiceInstanceResponse to CreateE2EServiceInstanceResponse
+            CreateE2EServiceInstanceResponse dummyresponse = new CreateE2EServiceInstanceResponse();
+            ServiceResponse serviceResponse = new ServiceResponse();
+            dummyresponse.setService(serviceResponse);
+            dummyresponse.getService().setOperationId(deleteresponse.getBody().getOperationId());
+            dummyresponse.getService().setServiceId(serviceInstanceId);
+
+            ResponseEntity<CreateE2EServiceInstanceResponse> response = new ResponseEntity(dummyresponse,
+                deleteresponse.getStatusCode());
+            logE2EResponsePost(url, response);
+            return response;
+
+        } catch (BackendFunctionalException e) {
+            LOGGER.error(ERROR_ON_CALLING + url + " ," + e);
+            return new ResponseEntity<>(e.getHttpStatus());
+        } catch (ResourceAccessException e) {
+            LOGGER.error(ERROR_ON_CALLING + url + " ," + e);
+            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
 
     private void logResponsePost(String url, ResponseEntity<CreateServiceInstanceResponse> response) {
         LOGGER.info(RESPONSE_STATUS + response.getStatusCodeValue());
@@ -225,10 +238,11 @@ public class SoClient {
             ResponseEntity<GetRequestStatusResponse> response = restTemplate.exchange(url, HttpMethod.GET,
                 new HttpEntity<>(buildRequestHeader()), GetRequestStatusResponse.class);
             logResponseGet(url, response);
-            if (null == response)
+            if (null == response) {
                 return null;
-            else
+            } else {
                 return response.getBody();
+            }
 
         } catch (BackendFunctionalException | ResourceAccessException e) {
             LOGGER.error(ERROR_ON_CALLING + url + " ," + e);
@@ -236,26 +250,28 @@ public class SoClient {
         }
     }
 
-public GetE2ERequestStatusResponse callE2EGetRequestStatus(String operationId, String serviceId) {
-       
+    public GetE2ERequestStatusResponse callE2EGetRequestStatus(String operationId, String serviceId) {
+
         String callUrlFormated = getE2ESoStatus.replace("$serviceId", serviceId);
         callUrlFormated = callUrlFormated.replace("$operationId", operationId);
 
         if (LOGGER.isDebugEnabled()) {
-            LOGGER.debug("Calling SO callE2EGetRequestStatus with url : " + callUrlFormated );
+            LOGGER.debug("Calling SO callE2EGetRequestStatus with url : " + callUrlFormated);
         }
-        
+
         try {
 
-            ResponseEntity<GetE2ERequestStatusResponse> response = restTemplate.exchange(callUrlFormated, HttpMethod.GET,
-                new HttpEntity<>(buildRequestHeader()), GetE2ERequestStatusResponse.class);
+            ResponseEntity<GetE2ERequestStatusResponse> response = restTemplate
+                .exchange(callUrlFormated, HttpMethod.GET,
+                    new HttpEntity<>(buildRequestHeader()), GetE2ERequestStatusResponse.class);
             logE2EResponseGet(callUrlFormated, response);
-            if (null == response)
+            if (null == response) {
                 return null;
-            else
+            } else {
                 return response.getBody();
+            }
 
-        } catch (BackendFunctionalException|ResourceAccessException e) {
+        } catch (BackendFunctionalException | ResourceAccessException e) {
             LOGGER.error(ERROR_ON_CALLING + callUrlFormated + " ," + e);
             return null;
         }
@@ -275,19 +291,19 @@ public GetE2ERequestStatusResponse callE2EGetRequestStatus(String operationId, S
             LOGGER.info("no response calling url {}", url);
         }
     }
-    
+
     private void logE2EResponseGet(String url, ResponseEntity<GetE2ERequestStatusResponse> response) {
-        if(response!=null){
-               if (LOGGER.isDebugEnabled()) {
+        if (response != null) {
+            if (LOGGER.isDebugEnabled()) {
                 LOGGER.debug("response body : {}", response.getBody().toString());
             }
-               LOGGER.info("response status : {}", response.getStatusCodeValue());
+            LOGGER.info("response status : {}", response.getStatusCodeValue());
             if (LOGGER.isWarnEnabled() && !response.getStatusCode().equals(HttpStatus.OK)) {
                 LOGGER.warn("HTTP call SO on {} returns {} , {}", url, response.getStatusCodeValue(),
                     response.getBody().toString());
             }
         } else {
-            LOGGER.info("no response calling url {}",url);
+            LOGGER.info("no response calling url {}", url);
         }
     }
 
diff --git a/src/test/java/org/onap/nbi/api/listener/ListenerResource.java b/src/test/java/org/onap/nbi/api/listener/ListenerResource.java
new file mode 100644 (file)
index 0000000..aa9efac
--- /dev/null
@@ -0,0 +1,112 @@
+/**
+ * Copyright (c) 2019 Orange
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.onap.nbi.api.listener;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.nbi.commons.ResourceManagement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+
+@RestController
+@RequestMapping("/test/listener")
+public class ListenerResource extends ResourceManagement {
+
+    Logger logger = LoggerFactory.getLogger(ListenerResource.class);
+
+    Map<String, JsonNode> events = new HashMap<>();
+
+    /*
+        listener resource test for hub resource
+     */
+    @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<JsonNode> postListener(@RequestBody JsonNode event) {
+        if (logger.isDebugEnabled()) {
+            logger.debug("POST event from nbi : {}", event.toString());
+        }
+        String eventId = event.get("eventId").asText();
+        events.put(eventId, event);
+
+        URI location = ServletUriComponentsBuilder
+            .fromCurrentRequest()
+            .path("/{id}")
+            .buildAndExpand(eventId)
+            .toUri();
+
+        return ResponseEntity.created(location).body(event);
+    }
+
+
+    @GetMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<Collection<JsonNode>> findEvents(@RequestParam MultiValueMap<String, String> params) {
+        Collection<JsonNode> values = new ArrayList<>();
+        String serviceOrderId = params.getFirst("serviceOrderId");
+        if(StringUtils.isNotEmpty(serviceOrderId)) {
+            for (JsonNode jsonNode : events.values()) {
+                String id = jsonNode.get("event").get("id").asText();
+                if(id.equals(serviceOrderId)) {
+                    values.add(jsonNode);
+                }
+            }
+            if(!values.isEmpty()) {
+                return ResponseEntity.ok(values);
+            } else {
+                return ResponseEntity.notFound().build();
+            }
+        } else {
+            values=events.values();
+        }
+        return ResponseEntity.ok(values);
+    }
+
+    @GetMapping(value = "/{eventId}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<Object> getEvent(@PathVariable String eventId) {
+
+        return ResponseEntity.ok(events.get(eventId));
+
+    }
+
+    @DeleteMapping(value = "/{eventId}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<Object> deleteEvent(@PathVariable String eventId) {
+
+        events.remove(eventId);
+        return ResponseEntity.noContent().build();
+
+    }
+
+    @DeleteMapping(produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<Object> deleteEvents() {
+
+        events.clear();
+        return ResponseEntity.noContent().build();
+
+    }
+
+}
diff --git a/src/test/java/org/onap/nbi/apis/servicecatalog/ToscaInfosProcessorTest.java b/src/test/java/org/onap/nbi/apis/servicecatalog/ToscaInfosProcessorTest.java
new file mode 100644 (file)
index 0000000..3a770ae
--- /dev/null
@@ -0,0 +1,273 @@
+/**
+ * Copyright (c) 2018 Orange
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.onap.nbi.apis.servicecatalog;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertNull;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+import org.assertj.core.api.AbstractBooleanAssert;
+import org.junit.Test;
+import org.onap.nbi.exceptions.TechnicalException;
+import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException;
+
+
+public class ToscaInfosProcessorTest {
+
+    final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); // jackson databind
+
+    ToscaInfosProcessor toscaInfosProcessor = new ToscaInfosProcessor();
+
+
+    private LinkedHashMap parseToscaFile(String fileName) {
+
+        File toscaFile = new File(fileName);
+        if (!toscaFile.exists()) {
+            throw new TechnicalException("unable to find  file : " + fileName);
+        }
+        try {
+            return (LinkedHashMap) mapper.readValue(toscaFile, Object.class);
+        } catch (IOException e) {
+            throw new TechnicalException("Unable to parse tosca file : " + fileName);
+
+        } catch (NullPointerException e) {
+            throw new TechnicalException("unable to find tosca file : " + fileName);
+        }
+    }
+
+
+    @Test
+    public void buildResponseWithToscaInfos() {
+
+        ClassLoader classLoader = getClass().getClassLoader();
+        File file = new File(classLoader.getResource("toscafile/service-TestNetwork-template.yml").getFile());
+        List<LinkedHashMap> resources = new ArrayList<>();
+        LinkedHashMap resource1 = new LinkedHashMap();
+        resource1.put("id", "e2b12ac6-cbb6-4517-9c58-b846d1f68caf");
+        resources.add(resource1);
+        LinkedHashMap toscaFile = parseToscaFile(file.getPath());
+        LinkedHashMap response = new LinkedHashMap();
+        response.put("resourceSpecification", resources);
+        toscaInfosProcessor.buildResponseWithToscaInfos((LinkedHashMap) toscaFile.get("topology_template"), response);
+
+        resources = (List<LinkedHashMap>) response.get("resourceSpecification");
+        assertNull(resources.get(0).get("modelCustomizationId"));
+        assertNull(resources.get(0).get("modelCustomizationName"));
+
+    }
+
+    @Test
+    public void buildResponseWithSdcToscaParser() {
+
+        ClassLoader classLoader = getClass().getClassLoader();
+        Path path = new File(classLoader.getResource("toscafile/service-Sdwanvpninfraservice-csar.csar").getFile()).toPath().toAbsolutePath();
+        List<LinkedHashMap> resources = new ArrayList<>();
+        LinkedHashMap resource1 = new LinkedHashMap();
+        resource1.put("id", "7baa7742-3a13-4288-8330-868015adc340");
+        resources.add(resource1);
+        LinkedHashMap resource2 = new LinkedHashMap();
+        resource2.put("id", "81b9430b-8abe-45d6-8bf9-f41a8f5c735f");
+        resources.add(resource2);
+        LinkedHashMap response = new LinkedHashMap();
+        response.put("resourceSpecification", resources);
+
+        try {
+            toscaInfosProcessor.buildResponseWithSdcToscaParser(path, response);
+        }
+        catch(SdcToscaParserException e) {
+            throw new TechnicalException("unable to build response from tosca csar using sdc-parser : " + path.toString()+" "+e.getMessage());
+        }
+        resources = (List<LinkedHashMap>) response.get("resourceSpecification");
+        List<LinkedHashMap> serviceSpecCharacteristic = new ArrayList<>();
+        serviceSpecCharacteristic = (List<LinkedHashMap>) response.get("serviceSpecCharacteristic");
+        assertThat(serviceSpecCharacteristic.get(0).get("name")).isEqualTo("sdwanconnectivity0_topology");
+        assertThat(serviceSpecCharacteristic.get(1).get("valueType")).isEqualTo("string");
+        assertThat(serviceSpecCharacteristic.get(0).get("required")).isEqualTo(true);
+        assertThat(serviceSpecCharacteristic.get(1).get("name")).isEqualTo("sdwanconnectivity0_name");
+        assertThat(serviceSpecCharacteristic.get(1).get("valueType")).isEqualTo("string");
+        assertThat(serviceSpecCharacteristic.get(1).get("required")).isEqualTo(true);
+        assertThat(resources.get(0).get("modelCustomizationId")).isEqualTo("94ec574b-2306-4cbd-8214-09662b040f73");
+        assertThat(resources.get(1).get("modelCustomizationId")).isEqualTo("a7baba5d-6ac3-42b5-b47d-070841303ab1");
+
+    }
+
+    @Test
+    public void buildResponseWithSdcToscaParserWithDefaultInputs() {
+
+        ClassLoader classLoader = getClass().getClassLoader();
+        Path path = new File(classLoader.getResource("toscafile/service-Sotnvpninfraservice-csar.csar").getFile()).toPath().toAbsolutePath();
+        List<LinkedHashMap> resources = new ArrayList<>();
+        LinkedHashMap resource1 = new LinkedHashMap();
+        resource1.put("id", "218df3c3-50dd-4c26-9e36-4771387bb771");
+        resources.add(resource1);
+        LinkedHashMap resource2 = new LinkedHashMap();
+        resource2.put("id", "81b9430b-8abe-45d6-8bf9-f41a8f5c735f");
+        resources.add(resource2);
+        LinkedHashMap response = new LinkedHashMap();
+        response.put("resourceSpecification", resources);
+
+        try {
+            toscaInfosProcessor.buildResponseWithSdcToscaParser(path, response);
+        }
+        catch(SdcToscaParserException e) {
+            throw new TechnicalException("unable to build response from tosca csar using sdc-parser : " + path.toString()+" "+e.getMessage());
+        }
+        resources = (List<LinkedHashMap>) response.get("resourceSpecification");
+        List<LinkedHashMap> serviceSpecCharacteristic = new ArrayList<>();
+        serviceSpecCharacteristic = (List<LinkedHashMap>) response.get("serviceSpecCharacteristic");
+        assertThat(resources.get(0).get("modelCustomizationId")).isEqualTo("b44071c8-04fd-4d6b-b6af-772cbfaa1129");
+        assertThat(resources.get(1).get("modelCustomizationId")).isEqualTo("c3612284-6c67-4d8c-8b41-b699cc90e76d");
+        assertThat(serviceSpecCharacteristic.get(12).get("serviceSpecCharacteristicValue")).isNull();
+        assertThat(serviceSpecCharacteristic.get(13).get("serviceSpecCharacteristicValue")).isNotNull();
+    }
+
+    @Test
+    public void buildResponseWithSdcToscaParserwithMetaDataMisMatch() {
+
+        ClassLoader classLoader = getClass().getClassLoader();
+        Path path = new File(classLoader.getResource("toscafile/service-Sdwanvpninfraservice-csar.csar").getFile()).toPath().toAbsolutePath();
+        List<LinkedHashMap> resources = new ArrayList<>();
+        LinkedHashMap resource1 = new LinkedHashMap();
+        resource1.put("id", "some bad resource id no in TOSCA CSAR");
+        resources.add(resource1);
+        LinkedHashMap resource2 = new LinkedHashMap();
+        resource2.put("id", "some bad resource id no in TOSCA CSAR");
+        resources.add(resource2);
+        LinkedHashMap response = new LinkedHashMap();
+        response.put("resourceSpecification", resources);
+
+        try {
+            toscaInfosProcessor.buildResponseWithSdcToscaParser(path, response);
+        }
+        catch(SdcToscaParserException e) {
+            throw new TechnicalException("unable to build response from tosca csar using sdc-parser : " + path.toString()+" "+e.getMessage());
+        }
+        resources = (List<LinkedHashMap>) response.get("resourceSpecification");
+        List<LinkedHashMap> serviceSpecCharacteristic = new ArrayList<>();
+        serviceSpecCharacteristic = (List<LinkedHashMap>) response.get("serviceSpecCharacteristic");
+        assertThat(serviceSpecCharacteristic.get(0).get("name")).isEqualTo("sdwanconnectivity0_topology");
+        assertThat(serviceSpecCharacteristic.get(1).get("valueType")).isEqualTo("string");
+        assertThat(serviceSpecCharacteristic.get(0).get("required")).isEqualTo(true);
+        assertThat(serviceSpecCharacteristic.get(1).get("name")).isEqualTo("sdwanconnectivity0_name");
+        assertThat(serviceSpecCharacteristic.get(1).get("valueType")).isEqualTo("string");
+        assertThat(serviceSpecCharacteristic.get(1).get("required")).isEqualTo(true);
+        // Check that resources cannot be found in the TOSCA template
+        assertThat(resources.get(0).get("modelCustomizationId")).isNull();
+        assertThat(resources.get(1).get("modelCustomizationId")).isNull();
+
+    }
+    @Test
+    public void buildResponseWithToscaInfosOk() {
+
+        ClassLoader classLoader = getClass().getClassLoader();
+        File file = new File(classLoader.getResource("toscafile/service-VfwService2vfBased-template.yml").getFile());
+        List<LinkedHashMap> resources = new ArrayList<>();
+        LinkedHashMap resource1 = new LinkedHashMap();
+        resource1.put("id", "e2b12ac6-cbb6-4517-9c58-b846d1f68caf");
+        resources.add(resource1);
+        LinkedHashMap toscaFile = parseToscaFile(file.getPath());
+        LinkedHashMap response = new LinkedHashMap();
+        response.put("resourceSpecification", resources);
+        toscaInfosProcessor.buildResponseWithToscaInfos((LinkedHashMap) toscaFile.get("topology_template"), response);
+
+        ArrayList toscaInfos = (ArrayList) response.get("serviceSpecCharacteristic");
+        assertThat(toscaInfos.size()).isEqualTo(4);
+
+        for (Object toscaInfo : toscaInfos) {
+            LinkedHashMap info = (LinkedHashMap) toscaInfo;
+            if (((String) info.get("name")).equalsIgnoreCase("fortigate_image_url")) {
+                assertThat(info.get("name")).isEqualTo("fortigate_image_url");
+                assertThat(info.get("description")).isNull();
+                assertThat(info.get("valueType")).isEqualTo("string");
+                assertThat(info.get("@type")).isEqualTo("ONAPserviceCharacteristic");
+                assertThat(info.get("required")).isEqualTo(false);
+                assertThat(info.get("status")).isNull();
+                assertThat(((ArrayList) info.get("serviceSpecCharacteristicValue")).size()).isEqualTo(0);
+
+            }
+
+            if (((String) info.get("name")).equalsIgnoreCase("flavor")) {
+                assertThat(info.get("name")).isEqualTo("flavor");
+                assertThat(info.get("description")).isNull();
+                assertThat(info.get("valueType")).isEqualTo("string");
+                assertThat(info.get("@type")).isEqualTo("ONAPserviceCharacteristic");
+                assertThat(info.get("required")).isNull();
+                assertThat(info.get("status")).isNull();
+                assertThat(((ArrayList) info.get("serviceSpecCharacteristicValue")).size()).isEqualTo(0);
+
+            }
+
+            if (((String) info.get("name")).equalsIgnoreCase("external_network_name")) {
+                assertThat(info.get("name")).isEqualTo("external_network_name");
+                assertThat(info.get("description")).isNull();
+                assertThat(info.get("valueType")).isEqualTo("string");
+                assertThat(info.get("@type")).isEqualTo("ONAPserviceCharacteristic");
+                assertThat(info.get("required")).isNull();
+                assertThat(info.get("status")).isEqualTo("inactive");
+                ;
+                assertThat(((ArrayList) info.get("serviceSpecCharacteristicValue")).size()).isEqualTo(0);
+
+            }
+
+            if (((String) info.get("name")).equalsIgnoreCase("cpus")) {
+                assertThat(info.get("name")).isEqualTo("cpus");
+                assertThat(info.get("description")).isEqualTo("Number of CPUs for the server.");
+                assertThat(info.get("valueType")).isEqualTo("integer");
+                assertThat(info.get("@type")).isEqualTo("ONAPserviceCharacteristic");
+                assertThat(info.get("required")).isNull();
+                assertThat(info.get("status")).isNull();
+                ;
+                assertThat(((ArrayList) info.get("serviceSpecCharacteristicValue")).size()).isEqualTo(4);
+                ArrayList serviceSpecCharacteristicValues = (ArrayList) info.get("serviceSpecCharacteristicValue");
+
+                for (Object serviceSpecCharacteristicValue : serviceSpecCharacteristicValues) {
+                    LinkedHashMap serviceSpecValue = (LinkedHashMap) serviceSpecCharacteristicValue;
+                    if (((String) serviceSpecValue.get("value")).equalsIgnoreCase("1")) {
+                        assertThat(serviceSpecValue.get("isDefault")).isEqualTo(false);
+                        assertThat(serviceSpecValue.get("value")).isEqualTo("1");
+                        assertThat(serviceSpecValue.get("valueType")).isEqualTo("integer");
+                    }
+                    if (((String) serviceSpecValue.get("value")).equalsIgnoreCase("2")) {
+                        assertThat(serviceSpecValue.get("isDefault")).isEqualTo(true);
+                        assertThat(serviceSpecValue.get("value")).isEqualTo("2");
+                        assertThat(serviceSpecValue.get("valueType")).isEqualTo("integer");
+                    }
+                    if (((String) serviceSpecValue.get("value")).equalsIgnoreCase("3")) {
+                        assertThat(serviceSpecValue.get("isDefault")).isEqualTo(false);
+                        assertThat(serviceSpecValue.get("value")).isEqualTo("3");
+                        assertThat(serviceSpecValue.get("valueType")).isEqualTo("integer");
+                    }
+                    if (((String) serviceSpecValue.get("value")).equalsIgnoreCase("4")) {
+                        assertThat(serviceSpecValue.get("isDefault")).isEqualTo(false);
+                        assertThat(serviceSpecValue.get("value")).isEqualTo("4");
+                        assertThat(serviceSpecValue.get("valueType")).isEqualTo("integer");
+                    }
+
+                }
+
+
+            }
+
+        }
+
+
+    }
+}
\ No newline at end of file
index 89cc6e8..7ec577e 100644 (file)
         ]
       }
     ]
+  },
+  {
+    "state": "acknowledged",
+    "externalId": "extid2",
+    "priority": "1",
+    "description": "toto",
+    "category": "Consumer",
+    "requestedStartDate": "2019-01-23T12:34:56.123456789Z",
+    "requestedCompletionDate": "2019-01-23T12:34:56.123456789Z",
+    "@baseType": "toto",
+    "completionDateTime": "2019-01-23T12:34:56.123456789Z",
+    "expectedCompletionDate": "2019-01-23T12:34:56.123456789Z",
+    "@schemaLocation": "/tutu",
+    "orderRelationship": [
+      {
+        "id": "test",
+        "href": "test",
+        "referredType": "test",
+        "type": "test"
+      }
+    ],
+    "relatedParty": [
+      {
+        "id": "6490",
+        "role": "ONAPcustomer",
+        "referredType": "individual",
+        "name": "Jean Pontus"
+      }
+    ],
+    "orderItem": [
+      {
+        "id": "A",
+        "action": "add",
+        "state": "active",
+        "service": {
+          "state": "active",
+          "serviceSpecification": {
+            "id": "1e3feeb0-8e36-46c6-862c-236d9c626439"
+          }
+        }
+      },
+      {
+        "id": "B",
+        "action": "add",
+        "state": "active",
+        "service": {
+          "state": "active",
+          "serviceSpecification": {
+            "id": "1e3feeb0-8e36-46c6-862c-236d9c626439"
+          }
+        },
+        "orderItemRelationship": [
+          {
+            "id": "A",
+            "type": "reliesOn"
+          }
+        ]
+      }
+    ]
   }
 ]
index 851ac73..3a41c34 100644 (file)
@@ -8,7 +8,16 @@ Background:
 * def Context = Java.type('org.onap.nbi.test.Context');
 * call Context.startServers();
 * def data = read('../data/subscriber.json')
-    
+* def serviceOrderData = read('../data/serviceOrder.json')
+* def checkDateFormat =
+"""
+function(s) {
+  var SimpleDateFormat = Java.type("java.text.SimpleDateFormat");
+  var sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+  return sdf.parse(s);
+}
+"""
+
 Scenario: testFindWhenNoSubscriber
 Given path 'hub'
 When method get
@@ -64,3 +73,39 @@ And def Id = $[0].id
 Given path 'hub',Id
 When method delete
 Then status 204
+
+Scenario: testSubscriberWithTestListener
+* def listenerUrl = nbiBaseUrl + "/test/listener"
+Given path 'test/listener'
+When method delete
+Then status 204
+Given path 'hub'
+And request { id : 'id', callback : '#(listenerUrl)' , query : 'eventType = ServiceOrderCreationNotification' }
+When method post
+Then status 201
+Given path 'hub'
+When method get
+And def hubId = $[0].id
+Given path 'serviceOrder'
+And request serviceOrderData[17]
+When method post
+Then status 201
+And def serviceOrderId = $.id
+Given path 'test/listener'
+And params {serviceOrderId : '#(serviceOrderId)'}
+When method get
+Then status 200
+And assert response.length == 1
+And match $[0] contains { eventId : '#notnull' , eventType : 'ServiceOrderCreationNotification' , eventDate : '#notnull' , event :'#notnull'}
+And def eventId = $[0].eventId
+And def eventDate = $[0].eventDate
+And call checkDateFormat(eventDate)
+Given path 'hub',hubId
+When method delete
+Then status 204
+Given path 'test/listener',eventId
+When method delete
+Then status 204
+Given path 'serviceOrder',serviceOrderId
+When method delete
+Then status 204
\ No newline at end of file