Add serviceCatalog rest services 71/39671/2
authorMatthieuGeerebaert <matthieu.geerebaert@orange.com>
Wed, 28 Mar 2018 11:36:26 +0000 (13:36 +0200)
committerMatthieuGeerebaert <matthieu.geerebaert@orange.com>
Tue, 3 Apr 2018 21:35:04 +0000 (23:35 +0200)
- Add get and find serviceSpecification operations
- Add API exceptions management
- Consumes SDC apis
- Add tests
- Fix pom.xml conflict

Change-Id: Id103d83dc8a981885100daabe868cdf18a922975
Issue-ID: EXTAPI-39
Signed-off-by: MatthieuGeerebaert <matthieu.geerebaert@orange.com>
28 files changed:
pom.xml
src/main/java/org/onap/nbi/OnapComponentsUrlPaths.java [new file with mode: 0644]
src/main/java/org/onap/nbi/apis/RestConfiguration.java [new file with mode: 0644]
src/main/java/org/onap/nbi/apis/servicecatalog/SdcClient.java [new file with mode: 0644]
src/main/java/org/onap/nbi/apis/servicecatalog/ServiceSpecificationResource.java [new file with mode: 0644]
src/main/java/org/onap/nbi/apis/servicecatalog/ServiceSpecificationService.java [new file with mode: 0644]
src/main/java/org/onap/nbi/apis/servicecatalog/ToscaInfosProcessor.java [new file with mode: 0644]
src/main/java/org/onap/nbi/apis/servicecatalog/jolt/FindServiceSpecJsonTransformer.java [new file with mode: 0644]
src/main/java/org/onap/nbi/apis/servicecatalog/jolt/GetServiceSpecJsonTransformer.java [new file with mode: 0644]
src/main/java/org/onap/nbi/exceptions/ApiError.java [new file with mode: 0644]
src/main/java/org/onap/nbi/exceptions/ApiException.java [new file with mode: 0644]
src/main/java/org/onap/nbi/exceptions/ApiExceptionHandler.java [new file with mode: 0644]
src/main/java/org/onap/nbi/exceptions/BackendErrorHandler.java [new file with mode: 0644]
src/main/java/org/onap/nbi/exceptions/BackendFunctionalException.java [new file with mode: 0644]
src/main/java/org/onap/nbi/exceptions/TechnicalException.java [new file with mode: 0644]
src/main/java/org/onap/nbi/exceptions/ValidationException.java [new file with mode: 0644]
src/main/resources/application-localhost.properties [new file with mode: 0644]
src/main/resources/application.properties
src/main/resources/jolt/findServiceCatalog.json [new file with mode: 0644]
src/main/resources/jolt/getServiceCatalog.json [new file with mode: 0644]
src/test/java/org/onap/nbi/apis/resources/ApiTest.java [new file with mode: 0644]
src/test/java/org/onap/nbi/apis/resources/ServiceCatalogAssertions.java [new file with mode: 0644]
src/test/java/org/onap/nbi/apis/resources/StatusResourceTest.java [moved from src/test/java/org/onap/nbi/apis/status/StatusTest.java with 91% similarity]
src/test/resources/application.properties [new file with mode: 0644]
src/test/resources/mappings/sdc_find.json [new file with mode: 0644]
src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439.json [new file with mode: 0644]
src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439_tosca.json [new file with mode: 0644]
src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439_withoutTosca.json [new file with mode: 0644]

diff --git a/pom.xml b/pom.xml
index b537ac2..2d04270 100644 (file)
--- a/pom.xml
+++ b/pom.xml
        <properties>
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
                <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-                <nexusproxy>https://nexus.onap.org</nexusproxy>
-                <snapshotNexusPath>/content/repositories/snapshots/</snapshotNexusPath>
-                <releaseNexusPath>/content/repositories/releases/</releaseNexusPath>
-                <stagingNexusPath>/content/repositories/staging/</stagingNexusPath>
+               <nexusproxy>https://nexus.onap.org</nexusproxy>
+               <snapshotNexusPath>/content/repositories/snapshots/</snapshotNexusPath>
+               <releaseNexusPath>/content/repositories/releases/</releaseNexusPath>
+               <stagingNexusPath>/content/repositories/staging/</stagingNexusPath>
                <java.version>1.8</java.version>
        </properties>
 
                        <url>http://download.java.net/maven/2/</url>
                        <layout>default</layout>
                </repository>
-                <repository>
-                        <id>ecomp-snapshots</id>
-                        <name>Snapshot Repository</name>
-                        <url>${nexusproxy}/${snapshotNexusPath}</url>
-                </repository>
-                <repository>
-                        <id>ecomp-staging</id>
-                        <name>Staging Repository</name>
-                        <url>${nexusproxy}/${stagingNexusPath}</url>
-                </repository>
+               <repository>
+                       <id>ecomp-snapshots</id>
+                       <name>Snapshot Repository</name>
+                       <url>${nexusproxy}/${snapshotNexusPath}</url>
+               </repository>
+               <repository>
+                       <id>ecomp-staging</id>
+                       <name>Staging Repository</name>
+                       <url>${nexusproxy}/${stagingNexusPath}</url>
+               </repository>
        </repositories>
 
-        <distributionManagement>
-                <repository>
-                        <id>ecomp-releases</id>
-                        <name>Release Repository</name>
-                        <url>${nexusproxy}/${releaseNexusPath}</url>
-                </repository>
-                <snapshotRepository>
-                        <id>ecomp-snapshots</id>
-                        <name>Snapshot Repository</name>
-                        <url>${nexusproxy}/${snapshotNexusPath}</url>
-                </snapshotRepository>
-        </distributionManagement>
-       
+       <distributionManagement>
+               <repository>
+                       <id>ecomp-releases</id>
+                       <name>Release Repository</name>
+                       <url>${nexusproxy}/${releaseNexusPath}</url>
+               </repository>
+               <snapshotRepository>
+                       <id>ecomp-snapshots</id>
+                       <name>Snapshot Repository</name>
+                       <url>${nexusproxy}/${snapshotNexusPath}</url>
+               </snapshotRepository>
+       </distributionManagement>
+
        <licenses>
                <license>
                        <name>Apache2</name>
                        <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
                </license>
-       </licenses>     
+       </licenses>
 
        <dependencies>
 
                        <artifactId>commons-lang3</artifactId>
                        <version>3.4</version>
                </dependency>
-               
-               <!-- test -->           
-               
+
+               <!-- jackson -->
+
+               <dependency>
+                       <groupId>com.fasterxml.jackson.dataformat</groupId>
+                       <artifactId>jackson-dataformat-yaml</artifactId>
+                       <version>2.8.0</version>
+               </dependency>
+
+               <!-- jolt -->
+
+               <dependency>
+                       <groupId>com.bazaarvoice.jolt</groupId>
+                       <artifactId>jolt-core</artifactId>
+                       <version>0.1.0</version>
+               </dependency>
+
+               <dependency>
+                       <groupId>com.bazaarvoice.jolt</groupId>
+                       <artifactId>json-utils</artifactId>
+                       <version>0.1.0</version>
+               </dependency>
+
+               <!-- test -->
+
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-test</artifactId>
                        <scope>test</scope>
                </dependency>
-               
+
+               <!-- wiremock -->
+
+               <dependency>
+                       <groupId>org.springframework.cloud</groupId>
+                       <artifactId>spring-cloud-contract-wiremock</artifactId>
+                       <version>1.0.0.RELEASE</version>
+                       <scope>test</scope>
+               </dependency>
+
+               <dependency>
+                       <groupId>org.eclipse.jetty</groupId>
+                       <artifactId>jetty-server</artifactId>
+                       <version>9.4.7.RC0</version>
+                       <scope>test</scope>
+               </dependency>
+
+               <dependency>
+                       <groupId>org.eclipse.jetty</groupId>
+                       <artifactId>jetty-servlet</artifactId>
+                       <scope>test</scope>
+               </dependency>
+
+               <dependency>
+                       <groupId>org.eclipse.jetty</groupId>
+                       <artifactId>jetty-servlets</artifactId>
+                       <scope>test</scope>
+               </dependency>
+
                <!-- runtime dev -->
-                               
+
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-devtools</artifactId>
                                <groupId>org.springframework.boot</groupId>
                                <artifactId>spring-boot-maven-plugin</artifactId>
                        </plugin>
-                        <plugin>
-                                <groupId>org.sonatype.plugins</groupId>
-                                <artifactId>nexus-staging-maven-plugin</artifactId>
-                                <version>1.6.7</version>
-                                <extensions>true</extensions>
-                                <configuration>
-                                        <nexusUrl>${nexusproxy}</nexusUrl>
-                                        <stagingProfileId>176c31dfe190a</stagingProfileId>
-                                        <serverId>ecomp-staging</serverId>
-                                </configuration>
-                        </plugin>
-                        <plugin>
-                                <groupId>org.apache.maven.plugins</groupId>
-                                <artifactId>maven-site-plugin</artifactId>
-                                <version>3.6</version>
-                                <dependencies>
-                                        <dependency>
-                                                <groupId>org.apache.maven.wagon</groupId>
-                                                <artifactId>wagon-webdav-jackrabbit</artifactId>
-                                                <version>2.10</version>
-                                        </dependency>
-                                </dependencies>
-                        </plugin>
+                       <plugin>
+                               <groupId>org.sonatype.plugins</groupId>
+                               <artifactId>nexus-staging-maven-plugin</artifactId>
+                               <version>1.6.7</version>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <nexusUrl>${nexusproxy}</nexusUrl>
+                                       <stagingProfileId>176c31dfe190a</stagingProfileId>
+                                       <serverId>ecomp-staging</serverId>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-site-plugin</artifactId>
+                               <version>3.6</version>
+                               <dependencies>
+                                       <dependency>
+                                               <groupId>org.apache.maven.wagon</groupId>
+                                               <artifactId>wagon-webdav-jackrabbit</artifactId>
+                                               <version>2.10</version>
+                                       </dependency>
+                               </dependencies>
+                       </plugin>
                </plugins>
        </build>
 </project>
diff --git a/src/main/java/org/onap/nbi/OnapComponentsUrlPaths.java b/src/main/java/org/onap/nbi/OnapComponentsUrlPaths.java
new file mode 100644 (file)
index 0000000..5ee6528
--- /dev/null
@@ -0,0 +1,29 @@
+package org.onap.nbi;
+
+/**
+ * Contains ONAP SDC and AAI urlPaths
+ *
+ */
+public final class OnapComponentsUrlPaths {
+
+    private OnapComponentsUrlPaths() {}
+
+    // SDC
+    public static final String SDC_ROOT_URL = "/sdc/v1/catalog/services/";
+    public static final String SDC_GET_PATH = "/metadata";
+    public static final String SDC_TOSCA_PATH = "/toscaModel";
+
+    // AAI
+    public static final String AAI_GET_TENANTS_PATH =
+            "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/$cloudOwner/$lcpCloudRegionId/tenants";
+    public static final String AAI_GET_CUSTOMER_PATH = "/aai/v11/business/customers/customer/";
+    public static final String AAI_GET_SERVICES_FOR_CUSTOMER_PATH =
+            "/aai/v11/business/customers/customer/$customerId/service-subscriptions";
+    public static final String AAI_PUT_SERVICE_FOR_CUSTOMER_PATH =
+            "/aai/v11/business/customers/customer/$customerId/service-subscriptions/service-subscription/";
+    public static final String AAI_GET_SERVICE_FOR_CUSTOMER_PATH =
+            "/aai/v11/business/customers/customer/$customerId/service-subscriptions/service-subscription/$serviceSpecName/service-instances/service-instance/$serviceId";
+    public static final String AAI_GET_SERVICE_INSTANCES_PATH =
+            "/aai/v11/business/customers/customer/$customerId/service-subscriptions/service-subscription/$serviceSpecName/service-instances/";
+
+}
diff --git a/src/main/java/org/onap/nbi/apis/RestConfiguration.java b/src/main/java/org/onap/nbi/apis/RestConfiguration.java
new file mode 100644 (file)
index 0000000..8152d6f
--- /dev/null
@@ -0,0 +1,18 @@
+package org.onap.nbi.apis;
+
+import org.onap.nbi.exceptions.BackendErrorHandler;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+@Configuration
+public class RestConfiguration {
+
+    @Bean
+    public RestTemplate restTemplate(RestTemplateBuilder builder) {
+        RestTemplate restTemplate = builder.build();
+        restTemplate.setErrorHandler(new BackendErrorHandler());
+        return restTemplate;
+    }
+}
diff --git a/src/main/java/org/onap/nbi/apis/servicecatalog/SdcClient.java b/src/main/java/org/onap/nbi/apis/servicecatalog/SdcClient.java
new file mode 100644 (file)
index 0000000..abc8bda
--- /dev/null
@@ -0,0 +1,145 @@
+package org.onap.nbi.apis.servicecatalog;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.io.IOUtils;
+import org.onap.nbi.OnapComponentsUrlPaths;
+import org.onap.nbi.exceptions.BackendFunctionalException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+
+/**
+ * @author user
+ *
+ */
+@Service
+public class SdcClient {
+
+    public static final String HTTP_CALL_SDC_ON = "HTTP call SDC on ";
+    @Autowired
+    private RestTemplate restTemplate;
+
+    @Value("${sdc.host}")
+    private String sdcHost;
+
+    @Value("${sdc.header.ecompInstanceId}")
+    private String ecompInstanceId;
+
+    @Value("${sdc.header.authorization}")
+    private String sdcHeaderAuthorization;
+
+    private static final String HEADER_ECOMP_INSTANCE_ID = "x-ecomp-instanceid";
+    private static final String HEADER_AUTHORIZATION = "Authorization";
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(SdcClient.class);
+
+
+    public LinkedHashMap callGet(String id) {
+        StringBuilder callURL = new StringBuilder().append(sdcHost).append(OnapComponentsUrlPaths.SDC_ROOT_URL).append(id)
+                .append(OnapComponentsUrlPaths.SDC_GET_PATH);
+
+        ResponseEntity<Object> response = callSdc(callURL.toString());
+        return (LinkedHashMap) response.getBody();
+
+    }
+
+    public List<LinkedHashMap> callFind(MultiValueMap<String, String> parametersMap) {
+
+        UriComponentsBuilder callURL = UriComponentsBuilder.fromHttpUrl(sdcHost + OnapComponentsUrlPaths.SDC_ROOT_URL);
+        if (parametersMap != null) {
+            Map<String, String> stringStringMap = parametersMap.toSingleValueMap();
+            for (String key : stringStringMap.keySet()) {
+                if (!key.equals("fields")) {
+                    callURL.queryParam(key, stringStringMap.get(key));
+                }
+            }
+        }
+
+        ResponseEntity<Object> response = callSdc(callURL.build().encode().toUri().toString());
+        return (List<LinkedHashMap>) response.getBody();
+
+    }
+
+
+    public File callGetWithAttachment(String toscaModelUrl) {
+        StringBuilder callURL = new StringBuilder().append(sdcHost).append(toscaModelUrl);
+
+        String fileName = System.currentTimeMillis() + "tosca.csar";
+        ResponseEntity<byte[]> response = callSdcWithAttachment(callURL.toString());
+        File toscaFile = new File(fileName);
+        try {
+            FileOutputStream toscaFileStream = new FileOutputStream(toscaFile);
+            if (response != null) {
+                IOUtils.write(response.getBody(), toscaFileStream);
+            }
+            toscaFileStream.close();
+        } catch (IOException e) {
+            LOGGER.error("cannot get TOSCA File for url " + toscaModelUrl);
+        }
+        return toscaFile;
+
+    }
+
+    private HttpEntity<String> buildRequestHeader() {
+        HttpHeaders httpHeaders = new HttpHeaders();
+        httpHeaders.add(HEADER_ECOMP_INSTANCE_ID, ecompInstanceId);
+        httpHeaders.add(HEADER_AUTHORIZATION, sdcHeaderAuthorization);
+        HttpEntity<String> entity = new HttpEntity<>("parameters", httpHeaders);
+
+        return entity;
+    }
+
+
+    private ResponseEntity<Object> callSdc(String callURL) {
+        ResponseEntity<Object> response =
+                restTemplate.exchange(callURL, HttpMethod.GET, buildRequestHeader(), Object.class);
+        LOGGER.debug("response body : " + response.getBody().toString());
+        LOGGER.info("response status : " + response.getStatusCodeValue());
+        loggDebugIfResponseKo(callURL, response);
+        return response;
+    }
+
+    private void loggDebugIfResponseKo(String callURL, ResponseEntity<Object> response) {
+        if (!response.getStatusCode().equals(HttpStatus.OK)) {
+            LOGGER.warn(HTTP_CALL_SDC_ON + callURL + " returns " + response.getStatusCodeValue() + ", "
+                    + response.getBody().toString());
+        }
+    }
+
+    private ResponseEntity<byte[]> callSdcWithAttachment(String callURL) {
+        try {
+            ResponseEntity<byte[]> response =
+                    restTemplate.exchange(callURL.toString(), HttpMethod.GET, buildRequestHeader(), byte[].class);
+            LOGGER.info("response status : " + response.getStatusCodeValue());
+            if (!response.getStatusCode().equals(HttpStatus.OK)) {
+                LOGGER.warn(HTTP_CALL_SDC_ON + callURL.toString() + " returns " + response.getStatusCodeValue() + ", "
+                        + response.getBody().toString());
+            }
+            return response;
+
+        } catch (BackendFunctionalException e) {
+            LOGGER.error(HTTP_CALL_SDC_ON + callURL.toString() + " error " + e);
+
+            return null;
+        }
+    }
+
+
+}
+
+
diff --git a/src/main/java/org/onap/nbi/apis/servicecatalog/ServiceSpecificationResource.java b/src/main/java/org/onap/nbi/apis/servicecatalog/ServiceSpecificationResource.java
new file mode 100644 (file)
index 0000000..512b088
--- /dev/null
@@ -0,0 +1,46 @@
+package org.onap.nbi.apis.servicecatalog;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import org.onap.nbi.commons.JsonRepresentation;
+import org.onap.nbi.commons.Resource;
+import org.onap.nbi.commons.ResourceManagement;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/serviceSpecification")
+public class ServiceSpecificationResource extends ResourceManagement<Resource> {
+
+
+    @Autowired
+    ServiceSpecificationService serviceSpecificationService;
+
+    @GetMapping(value = "/{serviceSpecId}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<Object> getServiceSpecification(@PathVariable String serviceSpecId,
+            @RequestParam MultiValueMap<String, String> params) {
+        LinkedHashMap response = serviceSpecificationService.get(serviceSpecId);
+        JsonRepresentation filter = new JsonRepresentation(params);
+        if (response.get("serviceSpecCharacteristic") != null) {
+            return this.getResponse(response, filter);
+        } else {
+            return this.getPartialResponse(response, filter);
+
+        }
+    }
+
+    @GetMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<Object> findServiceSpecification(@RequestParam MultiValueMap<String, String> params) {
+        List<LinkedHashMap> response = serviceSpecificationService.find(params);
+        JsonRepresentation filter = new JsonRepresentation(params);
+        return this.findResponse(response, filter, null);
+    }
+
+}
diff --git a/src/main/java/org/onap/nbi/apis/servicecatalog/ServiceSpecificationService.java b/src/main/java/org/onap/nbi/apis/servicecatalog/ServiceSpecificationService.java
new file mode 100644 (file)
index 0000000..3b56819
--- /dev/null
@@ -0,0 +1,51 @@
+package org.onap.nbi.apis.servicecatalog;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import org.onap.nbi.apis.servicecatalog.jolt.FindServiceSpecJsonTransformer;
+import org.onap.nbi.apis.servicecatalog.jolt.GetServiceSpecJsonTransformer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.MultiValueMap;
+
+@Service
+public class ServiceSpecificationService {
+
+    @Autowired
+    SdcClient sdcClient;
+
+    @Autowired
+    GetServiceSpecJsonTransformer getServiceSpecJsonTransformer;
+
+    @Autowired
+    FindServiceSpecJsonTransformer findServiceSpecJsonTransformer;
+
+    @Autowired
+    ToscaInfosProcessor toscaInfosProcessor;
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceSpecificationService.class);
+
+
+    public LinkedHashMap get(String serviceSpecId) {
+        LinkedHashMap sdcResponse = sdcClient.callGet(serviceSpecId);
+        LinkedHashMap serviceCatalogResponse = (LinkedHashMap) getServiceSpecJsonTransformer.transform(sdcResponse);
+        LinkedHashMap toscaInfosTopologyTemplate = toscaInfosProcessor.getToscaInfos(serviceCatalogResponse);
+        if (toscaInfosTopologyTemplate != null) {
+            LOGGER.debug("tosca file found, retrieving informations");
+            toscaInfosProcessor.buildResponseWithToscaInfos(toscaInfosTopologyTemplate, serviceCatalogResponse);
+        } else {
+            LOGGER.debug("no tosca file found, partial response");
+        }
+        return serviceCatalogResponse;
+    }
+
+
+    public List<LinkedHashMap> find(MultiValueMap<String, String> parametersMap) {
+        List<LinkedHashMap> sdcResponse = sdcClient.callFind(parametersMap);
+        List<LinkedHashMap> serviceCatalogResponse =
+                (List<LinkedHashMap>) findServiceSpecJsonTransformer.transform(sdcResponse);
+        return serviceCatalogResponse;
+    }
+}
diff --git a/src/main/java/org/onap/nbi/apis/servicecatalog/ToscaInfosProcessor.java b/src/main/java/org/onap/nbi/apis/servicecatalog/ToscaInfosProcessor.java
new file mode 100644 (file)
index 0000000..4bfbd7b
--- /dev/null
@@ -0,0 +1,249 @@
+package org.onap.nbi.apis.servicecatalog;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.io.FileUtils;
+import org.onap.nbi.exceptions.TechnicalException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+
+@Service
+public class ToscaInfosProcessor {
+
+    @Autowired
+    SdcClient sdcClient;
+
+    final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); // jackson databind
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ToscaInfosProcessor.class);
+
+    public void buildResponseWithToscaInfos(LinkedHashMap toscaInfosTopologyTemplate,
+            LinkedHashMap serviceCatalogResponse) {
+        if (toscaInfosTopologyTemplate.get("inputs") != null) {
+            ArrayList serviceSpecCharacteristic = new ArrayList();
+            LinkedHashMap toscaInfos = (LinkedHashMap) toscaInfosTopologyTemplate.get("inputs");
+            for (Object key : toscaInfos.keySet()) {
+                String keyString = (String) key;
+                LinkedHashMap inputParameter = (LinkedHashMap) toscaInfos.get(key);
+                LinkedHashMap mapParameter = new LinkedHashMap();
+                String parameterType = (String) inputParameter.get("type");
+                mapParameter.put("name", keyString);
+                mapParameter.put("description", inputParameter.get("description"));
+                mapParameter.put("valueType", parameterType);
+                mapParameter.put("@type", "ONAPserviceCharacteristic");
+                mapParameter.put("required", inputParameter.get("required"));
+                mapParameter.put("status", inputParameter.get("status"));
+                List<LinkedHashMap> serviceSpecCharacteristicValues =
+                        buildServiceSpecCharacteristicsValues(inputParameter, parameterType);
+                mapParameter.put("serviceSpecCharacteristicValue", serviceSpecCharacteristicValues);
+                serviceSpecCharacteristic.add(mapParameter);
+            }
+
+            serviceCatalogResponse.put("serviceSpecCharacteristic", serviceSpecCharacteristic);
+        }
+        LinkedHashMap node_templates = (LinkedHashMap) toscaInfosTopologyTemplate.get("node_templates");
+
+        List<LinkedHashMap> resourceSpecifications =
+                (List<LinkedHashMap>) serviceCatalogResponse.get("resourceSpecification");
+        for (LinkedHashMap resourceSpecification : resourceSpecifications) {
+            String id = (String) resourceSpecification.get("id");
+            LOGGER.debug("get tosca infos for service id: " + id);
+            LinkedHashMap toscaInfosFromResourceId = getToscaInfosFromResourceUUID(node_templates, id);
+            resourceSpecification.put("modelCustomizationId", toscaInfosFromResourceId.get("customizationUUID"));
+            resourceSpecification.put("modelCustomizationName", toscaInfosFromResourceId.get("name"));
+
+        }
+    }
+
+    private List<LinkedHashMap> buildServiceSpecCharacteristicsValues(LinkedHashMap parameter, String parameterType) {
+        List<LinkedHashMap> serviceSpecCharacteristicValues = new ArrayList<>();
+        if (!"map".equalsIgnoreCase(parameterType) && !"list".equalsIgnoreCase(parameterType)) {
+            LOGGER.debug("get tosca infos for serviceSpecCharacteristicValues of type map or string : " + parameter);
+            Object aDefault = parameter.get("default");
+            if (parameter.get("entry_schema") != null) {
+                ArrayList entry_schema = (ArrayList) parameter.get("entry_schema");
+                if (CollectionUtils.isNotEmpty(entry_schema)) {
+                    buildCharacteristicValuesFormShema(parameterType, serviceSpecCharacteristicValues, aDefault,
+                            entry_schema);
+                }
+            }
+        }
+        return serviceSpecCharacteristicValues;
+    }
+
+    private void buildCharacteristicValuesFormShema(String parameterType,
+            List<LinkedHashMap> serviceSpecCharacteristicValues, Object aDefault, ArrayList entry_schema) {
+        LinkedHashMap constraints = (LinkedHashMap) entry_schema.get(0);
+        if (constraints != null) {
+            ArrayList constraintsList = (ArrayList) constraints.get("constraints");
+            if (CollectionUtils.isNotEmpty(constraintsList)) {
+                LinkedHashMap valuesMap = (LinkedHashMap) constraintsList.get(0);
+                if (valuesMap != null) {
+                    List<Object> values = (List<Object>) valuesMap.get("valid_values");
+                    for (Object value : values) {
+                        String stringValue = value.toString();
+                        LinkedHashMap serviceSpecCharacteristicValue = new LinkedHashMap();
+                        serviceSpecCharacteristicValue.put("isDefault",
+                                aDefault != null && aDefault.toString().equals(stringValue));
+                        serviceSpecCharacteristicValue.put("value", stringValue);
+                        serviceSpecCharacteristicValue.put("valueType", parameterType);
+                        serviceSpecCharacteristicValues.add(serviceSpecCharacteristicValue);
+                    }
+                }
+            }
+        }
+    }
+
+
+    private LinkedHashMap getToscaInfosFromResourceUUID(LinkedHashMap node_templates, String name) {
+        for (Object nodeTemplateObject : node_templates.values()) {
+            LinkedHashMap nodeTemplate = (LinkedHashMap) nodeTemplateObject;
+            LinkedHashMap metadata = (LinkedHashMap) nodeTemplate.get("metadata");
+            String metadataUUID = (String) metadata.get("UUID");
+            String metadataType = (String) metadata.get("type");
+            if ("VF".equalsIgnoreCase(metadataType) && name.equalsIgnoreCase(metadataUUID)) {
+                return metadata;
+            }
+        }
+        return null;
+    }
+
+
+    public LinkedHashMap getToscaInfos(LinkedHashMap sdcResponse) {
+        String toscaModelUrl = (String) sdcResponse.get("toscaModelURL");
+        String serviceId = (String) sdcResponse.get("uuid");
+        File toscaFile = sdcClient.callGetWithAttachment(toscaModelUrl);
+        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
+        String tempFolderName = serviceId + timestamp;
+        File folderTemp = null;
+        LinkedHashMap topology_template = null;
+        try {
+            unZipArchive(toscaFile.getName(), tempFolderName);
+            folderTemp = new File(tempFolderName);
+            LOGGER.debug("temp folder for tosca files : " + folderTemp.getName());
+
+            LinkedHashMap toscaMetaFileHashMap = parseToscaFile(tempFolderName + "/TOSCA-Metadata/TOSCA.meta");
+            if (toscaMetaFileHashMap.get("Entry-Definitions") == null) {
+                throw new NullPointerException("no Entry-Definitions node in TOSCA.meta");
+            }
+            String toscaFilePath = (String) toscaMetaFileHashMap.get("Entry-Definitions");
+            LinkedHashMap toscaFileHashMap = parseToscaFile(tempFolderName + "/" + toscaFilePath);
+
+            if (toscaFileHashMap.get("topology_template") == null) {
+                throw new NullPointerException("no topology_template node in tosca file");
+            }
+            topology_template = (LinkedHashMap) toscaFileHashMap.get("topology_template");
+
+        } catch (NullPointerException e) {
+            LOGGER.error("unable to parse tosca file for id : " + serviceId + ", " + e.getMessage());
+            return null;
+        } finally {
+            try {
+                LOGGER.debug("deleting temp folder for tosca files : " + folderTemp.getName());
+                FileUtils.deleteDirectory(folderTemp);
+                LOGGER.debug("deleting tosca archive : " + toscaFile.getName());
+                FileUtils.forceDelete(toscaFile);
+                return topology_template;
+            } catch (IOException e) {
+                LOGGER.error("unable to delete temp directory tosca file for id : " + serviceId);
+                return null;
+
+            }
+        }
+    }
+
+
+    private LinkedHashMap parseToscaFile(String fileName) {
+
+        File toscaFile = new File(fileName);
+        if (toscaFile == null) {
+            throw new TechnicalException("unable to find  file : " + fileName);
+        }
+        try {
+            return (LinkedHashMap) mapper.readValue(toscaFile, Object.class);
+        } catch (IOException e) {
+            LOGGER.error("unable to parse tosca file : " + fileName);
+            LOGGER.error(e.getMessage());
+            throw new TechnicalException("Unable to parse tosca file : " + fileName);
+
+        } catch (NullPointerException e) {
+            LOGGER.error("unable to find tosca file : " + fileName);
+            LOGGER.error(e.getMessage());
+            throw new TechnicalException("unable to find tosca file : " + fileName);
+        }
+    }
+
+
+    /**
+     * Unzip it
+     *
+     * @param zipFile input zip file
+     * @param outputFolder zip file output folder
+     */
+    private void unZipArchive(String zipFile, String outputFolder) {
+
+        byte[] buffer = new byte[1024];
+
+        try {
+
+            // create output directory is not exists
+            File folder = new File(outputFolder);
+            if (!folder.exists()) {
+                folder.mkdir();
+            }
+
+            // get the zip file content
+            try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) {
+                // get the zipped file list entry
+                ZipEntry ze = zis.getNextEntry();
+
+                while (ze != null) {
+
+                    String fileName = ze.getName();
+                    File newFile = new File(outputFolder + File.separator + fileName);
+
+                    LOGGER.debug("File to unzip : " + newFile.getAbsoluteFile());
+
+                    // create all non exists folders
+                    // else you will hit FileNotFoundException for compressed folder
+                    new File(newFile.getParent()).mkdirs();
+
+                    try (FileOutputStream fos = new FileOutputStream(newFile)) {
+
+                        int len;
+                        while ((len = zis.read(buffer)) > 0) {
+                            fos.write(buffer, 0, len);
+                        }
+
+                        fos.close();
+                    }
+                    ze = zis.getNextEntry();
+                }
+
+                zis.closeEntry();
+                zis.close();
+            }
+
+            LOGGER.debug("Done");
+
+        } catch (IOException ex) {
+            LOGGER.error("Error while unzipping ToscaModel archive from ONAP : " + ex.getMessage());
+            throw new TechnicalException("Error while unzipping ToscaModel archive from ONAP");
+        }
+    }
+
+
+}
diff --git a/src/main/java/org/onap/nbi/apis/servicecatalog/jolt/FindServiceSpecJsonTransformer.java b/src/main/java/org/onap/nbi/apis/servicecatalog/jolt/FindServiceSpecJsonTransformer.java
new file mode 100644 (file)
index 0000000..b32f9fc
--- /dev/null
@@ -0,0 +1,36 @@
+package org.onap.nbi.apis.servicecatalog.jolt;
+
+import com.bazaarvoice.jolt.Chainr;
+import com.bazaarvoice.jolt.JsonUtils;
+import com.bazaarvoice.jolt.exception.JoltException;
+import org.onap.nbi.exceptions.TechnicalException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FindServiceSpecJsonTransformer {
+
+    private Chainr chainr;
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(FindServiceSpecJsonTransformer.class);
+
+    public FindServiceSpecJsonTransformer() {
+        List<Object> specs = JsonUtils.classpathToList("/jolt/findServiceCatalog.json");
+        this.chainr = Chainr.fromSpec(specs);
+    }
+
+    public Object transform(Object serviceSpec) {
+        Object output = null;
+        try {
+            output = chainr.transform(serviceSpec);
+        } catch (JoltException joE) {
+            LOGGER.error("Unable to transform SDC response with JOLT Transformer : " + joE.getMessage());
+            throw new TechnicalException("Error while parsing ONAP response");
+        }
+        return output;
+    }
+
+}
diff --git a/src/main/java/org/onap/nbi/apis/servicecatalog/jolt/GetServiceSpecJsonTransformer.java b/src/main/java/org/onap/nbi/apis/servicecatalog/jolt/GetServiceSpecJsonTransformer.java
new file mode 100644 (file)
index 0000000..784ed6f
--- /dev/null
@@ -0,0 +1,37 @@
+package org.onap.nbi.apis.servicecatalog.jolt;
+
+import com.bazaarvoice.jolt.Chainr;
+import com.bazaarvoice.jolt.JsonUtils;
+import com.bazaarvoice.jolt.exception.JoltException;
+import org.onap.nbi.exceptions.TechnicalException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class GetServiceSpecJsonTransformer {
+
+    private Chainr chainr;
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(GetServiceSpecJsonTransformer.class);
+
+
+    public GetServiceSpecJsonTransformer() {
+        List<Object> specs = JsonUtils.classpathToList("/jolt/getServiceCatalog.json");
+        this.chainr = Chainr.fromSpec(specs);
+    }
+
+    public Object transform(Object serviceSpec) {
+        Object output = null;
+        try {
+            output = chainr.transform(serviceSpec);
+        } catch (JoltException joE) {
+            LOGGER.error("Unable to transform SDC response with JOLT Transformer : " + joE.getMessage());
+            throw new TechnicalException("Error while parsing ONAP response");
+        }
+        return output;
+    }
+
+}
diff --git a/src/main/java/org/onap/nbi/exceptions/ApiError.java b/src/main/java/org/onap/nbi/exceptions/ApiError.java
new file mode 100644 (file)
index 0000000..5e030f8
--- /dev/null
@@ -0,0 +1,67 @@
+package org.onap.nbi.exceptions;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "Error", propOrder = {
+        "code",
+        "message",
+        "description",
+        "infoURL"
+})
+public class ApiError {
+    @XmlElement(required = true)
+    protected String code;
+    @XmlElement(required = true)
+    protected String message;
+    @XmlElement(required = true)
+    private String description;
+    @XmlElement(required = true)
+    protected String infoURL;
+
+    public ApiError() {
+    }
+
+    public ApiError(String code, String message, String description, String infoURL) {
+        this.code = code;
+        this.message = message;
+        this.description = description;
+        this.infoURL = infoURL;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getInfoURL() {
+        return infoURL;
+    }
+
+    public void setInfoURL(String infoURL) {
+        this.infoURL = infoURL;
+    }
+}
+
diff --git a/src/main/java/org/onap/nbi/exceptions/ApiException.java b/src/main/java/org/onap/nbi/exceptions/ApiException.java
new file mode 100644 (file)
index 0000000..d07d9db
--- /dev/null
@@ -0,0 +1,33 @@
+package org.onap.nbi.exceptions;
+
+import java.io.Serializable;
+
+public class ApiException extends RuntimeException implements Serializable {
+
+    protected final String localisationClass;
+    protected final String localisationMethod;
+
+    public ApiException() {
+        super();
+        localisationClass = "";
+        localisationMethod = "";
+    }
+
+    public ApiException(String message) {
+        super(message);
+        localisationClass = "";
+        localisationMethod = "";
+    }
+
+    public ApiException(String message, Throwable cause) {
+        super(message, cause);
+        localisationClass = "";
+        localisationMethod = "";
+    }
+
+    public ApiException(Throwable cause) {
+        super(cause);
+        localisationClass = "";
+        localisationMethod = "";
+    }
+}
diff --git a/src/main/java/org/onap/nbi/exceptions/ApiExceptionHandler.java b/src/main/java/org/onap/nbi/exceptions/ApiExceptionHandler.java
new file mode 100644 (file)
index 0000000..1f109cb
--- /dev/null
@@ -0,0 +1,46 @@
+package org.onap.nbi.exceptions;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.client.RestClientException;
+
+@ControllerAdvice
+public class ApiExceptionHandler {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ApiExceptionHandler.class);
+
+
+    @ExceptionHandler(BackendFunctionalException.class)
+    @ResponseBody
+    public ResponseEntity<ApiError> backendExceptionHandler(final BackendFunctionalException exception) {
+        ApiError apiError = new ApiError(String.valueOf(exception.getHttpStatus().value()), exception.getMessage(), "", "");
+        return new ResponseEntity<ApiError>(apiError, exception.getHttpStatus());
+    }
+
+    @ExceptionHandler(TechnicalException.class)
+    @ResponseBody
+    public ResponseEntity<ApiError> technicalExceptionHandler(final TechnicalException exception) {
+        ApiError apiError = new ApiError(String.valueOf(exception.getHttpStatus().value()), exception.getMessage(), "", "");
+        return new ResponseEntity<ApiError>(apiError, exception.getHttpStatus());
+    }
+
+    @ExceptionHandler(RestClientException.class)
+    @ResponseBody
+    public ResponseEntity<ApiError> RestClientExceptionHandler(final RestClientException exception) {
+        ApiError apiError = new ApiError("500", HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(), "Unable to " +
+                "reach ONAP services", "");
+        return new ResponseEntity<ApiError>(apiError, HttpStatus.INTERNAL_SERVER_ERROR);
+    }
+
+    @ExceptionHandler(ValidationException.class)
+    @ResponseBody
+    public ResponseEntity<ApiError> ValidationExceptionHandler(final ValidationException exception) {
+        ApiError apiError = new ApiError("400", HttpStatus.BAD_REQUEST.getReasonPhrase(), exception.getMessages(), "");
+        return new ResponseEntity<ApiError>(apiError, HttpStatus.INTERNAL_SERVER_ERROR);
+    }
+}
diff --git a/src/main/java/org/onap/nbi/exceptions/BackendErrorHandler.java b/src/main/java/org/onap/nbi/exceptions/BackendErrorHandler.java
new file mode 100644 (file)
index 0000000..34c4ac5
--- /dev/null
@@ -0,0 +1,24 @@
+package org.onap.nbi.exceptions;
+
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.web.client.DefaultResponseErrorHandler;
+import org.springframework.web.client.ResponseErrorHandler;
+
+import java.io.IOException;
+
+public class BackendErrorHandler implements ResponseErrorHandler {
+
+    private ResponseErrorHandler errorHandler = new DefaultResponseErrorHandler();
+
+    @Override
+    public boolean hasError(ClientHttpResponse response) throws IOException {
+        return errorHandler.hasError(response);
+    }
+
+    @Override
+    public void handleError(ClientHttpResponse response) throws IOException {
+        if (response.getStatusCode() != null) {
+            throw new BackendFunctionalException(response.getStatusCode(), response.getStatusText());
+        }
+    }
+}
diff --git a/src/main/java/org/onap/nbi/exceptions/BackendFunctionalException.java b/src/main/java/org/onap/nbi/exceptions/BackendFunctionalException.java
new file mode 100644 (file)
index 0000000..176186f
--- /dev/null
@@ -0,0 +1,22 @@
+package org.onap.nbi.exceptions;
+
+import org.springframework.http.HttpStatus;
+
+public class BackendFunctionalException extends ApiException {
+
+    private HttpStatus httpStatus;
+
+    public BackendFunctionalException(HttpStatus httpStatus, String message) {
+        super(message);
+        this.httpStatus = httpStatus;
+    }
+
+    public BackendFunctionalException() {
+        super();
+    }
+
+    public HttpStatus getHttpStatus() {
+        return httpStatus;
+    }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/onap/nbi/exceptions/TechnicalException.java b/src/main/java/org/onap/nbi/exceptions/TechnicalException.java
new file mode 100644 (file)
index 0000000..a2abe3e
--- /dev/null
@@ -0,0 +1,26 @@
+package org.onap.nbi.exceptions;
+
+import org.springframework.http.HttpStatus;
+
+public class TechnicalException extends ApiException {
+
+    private HttpStatus httpStatus;
+
+    public TechnicalException(String message) {
+        super(message);
+        this.httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
+    }
+
+    public TechnicalException() {
+        super();
+    }
+
+    public HttpStatus getHttpStatus() {
+        return httpStatus;
+    }
+
+    public void setHttpStatus(HttpStatus httpStatus) {
+        this.httpStatus = httpStatus;
+    }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/onap/nbi/exceptions/ValidationException.java b/src/main/java/org/onap/nbi/exceptions/ValidationException.java
new file mode 100644 (file)
index 0000000..316e8f2
--- /dev/null
@@ -0,0 +1,32 @@
+package org.onap.nbi.exceptions;
+
+import org.springframework.validation.FieldError;
+import org.springframework.validation.ObjectError;
+
+import java.util.List;
+
+public class ValidationException extends ApiException {
+
+    private String messages;
+
+    public ValidationException(List<ObjectError> listErrors) {
+        super();
+        StringBuilder sb = new StringBuilder();
+        for (ObjectError error : listErrors) {
+            if (error instanceof FieldError) {
+                sb.append(((FieldError) error).getField())
+                        .append(" ")
+                        .append(((FieldError) error).getDefaultMessage())
+                        .append(". ");
+            } else {
+                sb.append(" ").append(error.getDefaultMessage()).append(". ");
+            }
+        }
+        messages = sb.toString();
+
+    }
+
+    public String getMessages() {
+        return messages;
+    }
+}
diff --git a/src/main/resources/application-localhost.properties b/src/main/resources/application-localhost.properties
new file mode 100644 (file)
index 0000000..58b13f6
--- /dev/null
@@ -0,0 +1,7 @@
+# LOGGING
+logging.level.org.onap.nbi=DEBUG
+
+# SDC
+sdc.host=http://127.0.0.1:8090
+sdc.header.ecompInstanceId=Rene
+sdc.header.authorization=Basic YWFpOktwOGJKNFNYc3pNMFdYbGhhazNlSGxjc2UyZ0F3ODR2YW9HR21KdlV5MlU=
index 1d8ff27..10e0d7d 100644 (file)
@@ -3,4 +3,5 @@ server.contextPath=/nbi/api/v1
 server.port = 8080
 
 # LOGGING
-logging.level.org.onap.nbi=WARN
+logging.level.=WARN
+
diff --git a/src/main/resources/jolt/findServiceCatalog.json b/src/main/resources/jolt/findServiceCatalog.json
new file mode 100644 (file)
index 0000000..ffe5fe3
--- /dev/null
@@ -0,0 +1,28 @@
+[
+  {
+    "operation": "shift",
+    "spec": {
+      "*": {
+        "uuid": "[&1].id",
+        "description": "[&1].description",
+        "name": "[&1].name",
+        "invariantUUID": "[&1].invariantUUID",
+        "category": "[&1].category",
+        "distributionStatus": "[&1].distributionStatus",
+        "version": "[&1].version",
+        "lifecycleState": "[&1].lifecycleStatus",
+        "lastUpdaterUserId": "[&1].relatedParty.id"
+      }
+    }
+  },
+  {
+    "operation": "default",
+    "spec": {
+      "*": {
+        "relatedParty": {
+            "role": "lastUpdater"
+        }
+      }
+    }
+  }
+]
\ No newline at end of file
diff --git a/src/main/resources/jolt/getServiceCatalog.json b/src/main/resources/jolt/getServiceCatalog.json
new file mode 100644 (file)
index 0000000..cac223e
--- /dev/null
@@ -0,0 +1,77 @@
+[
+  {
+    "operation": "shift",
+     "spec": {
+      "uuid": "id",
+      "name": "name",
+      "description": "description",
+      "invariantUUID": "invariantUUID",
+      "toscaModelURL": "toscaModelURL",
+      "toscaResourceName": "toscaResourceName",
+      "category ": "category",
+      "subcategory": "subcategory",
+      "distributionStatus": "distributionStatus",
+      "version": "version",
+      "lifecycleState":"lifecycleStatus" ,
+      "artifacts" : {
+          "*": {
+            "artifactUUID": "attachment[&1].id",
+            "artifactName": "attachment[&1].name",
+            "artifactDescription": "attachment[&1].description",
+            "artifactLabel": "attachment[&1].artifactLabel",
+            "artifactGroupType": "attachment[&1].artifactGroupType",
+            "artifactTimeout": "attachment[&1].artifactTimeout",
+            "artifactChecksum": "attachment[&1].artifactChecksum",
+            "artifactVersion": "attachment[&1].artifactVersion",
+            "generatedFromUUID": "attachment[&1].generatedFromUUID",
+            "artifactURL": "attachment[&1].url",
+            "artifactType": "attachment[&1].mimeType"
+          }
+
+      },
+       "lastUpdaterUserId" : "relatedParty.id",
+       "lastUpdaterFullName" : "relatedParty.name",
+       "resources" : {
+         "*": {
+           "resourceUUID": "resourceSpecification[&1].id",
+           "resourceVersion": "resourceSpecification[&1].version",
+           "resourceName": "resourceSpecification[&1].name",
+           "resourceInstanceName": "resourceSpecification[&1].instanceName",
+           "resourceInvariantUUID": "resourceSpecification[&1].resourceInvariantUUID",
+           "resourceType": "resourceSpecification[&1].resourceType"
+         }
+
+       }
+
+
+
+     }
+  },
+  {
+    "operation": "modify-overwrite-beta",
+    "spec": {
+      "href": "=concat('serviceSpecification/',@(1,id))"
+    }
+  },
+    {
+    "operation": "default",
+    "spec": {
+      "@type": "ONAPservice",
+      "attachment[]" : {
+        "*": {
+          "@type": "ONAPartifact"
+        }
+
+      },
+      "relatedParty" : {
+          "role": "lastUpdater"
+      },
+      "resourceSpecification[]" : {
+        "*": {
+          "@type": "ONAPresource"
+        }
+
+      }
+    }
+  }
+]
\ No newline at end of file
diff --git a/src/test/java/org/onap/nbi/apis/resources/ApiTest.java b/src/test/java/org/onap/nbi/apis/resources/ApiTest.java
new file mode 100644 (file)
index 0000000..05d332c
--- /dev/null
@@ -0,0 +1,89 @@
+package org.onap.nbi.apis.resources;
+
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.nbi.apis.servicecatalog.ServiceSpecificationResource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.embedded.LocalServerPort;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import com.github.tomakehurst.wiremock.WireMockServer;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
+public class ApiTest {
+
+    @LocalServerPort
+    int randomServerPort;
+
+    String realServerPort;
+
+
+    static public WireMockServer wireMockServer = new WireMockServer(8091);
+
+    @Autowired
+    ServiceSpecificationResource serviceSpecificationResource;
+
+    @BeforeClass
+    public static void setUp() throws Exception {
+        wireMockServer.start();
+    }
+
+    @AfterClass
+    public static void tearsDown() throws Exception {
+        wireMockServer.stop();
+
+    }
+
+    @After
+    public void tearsDownUpPort() throws Exception {
+        wireMockServer.resetToDefaultMappings();
+    }
+
+    @Test
+    @Ignore
+    public void testServiceResourceGetCatalog() throws Exception {
+
+        ResponseEntity<Object> resource =
+                serviceSpecificationResource.getServiceSpecification("1e3feeb0-8e36-46c6-862c-236d9c626439", null);
+        ServiceCatalogAssertions.assertGetServiceCatalog(resource);
+
+    }
+
+    @Test
+    public void testServiceCatalogGetResourceWithoutTosca() throws Exception {
+
+        ResponseEntity<Object> resource = serviceSpecificationResource
+                .getServiceSpecification("1e3feeb0-8e36-46c6-862c-236d9c626439_withoutTosca", null);
+        ServiceCatalogAssertions.asserGetServiceCatalogWithoutTosca(resource);
+
+    }
+
+    @Test
+    public void testServiceCatalogFind() throws Exception {
+
+        ResponseEntity<Object> resource = serviceSpecificationResource.findServiceSpecification(null);
+        ServiceCatalogAssertions.assertFindServiceCatalog(resource);
+
+    }
+
+
+    @Test
+    public void testServiceCatalogFindWithFilter() throws Exception {
+
+        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
+        params.add("fields", "name");
+        ResponseEntity<Object> resource = serviceSpecificationResource.findServiceSpecification(params);
+        ServiceCatalogAssertions.assertFindServiceCatalogWIthFilter(resource);
+
+    }
+
+}
diff --git a/src/test/java/org/onap/nbi/apis/resources/ServiceCatalogAssertions.java b/src/test/java/org/onap/nbi/apis/resources/ServiceCatalogAssertions.java
new file mode 100644 (file)
index 0000000..19e2a2a
--- /dev/null
@@ -0,0 +1,135 @@
+package org.onap.nbi.apis.resources;
+
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+public class ServiceCatalogAssertions {
+
+
+    public static void assertGetServiceCatalog(ResponseEntity<Object> resource) {
+        assertThat(resource.getStatusCode()).isEqualTo(HttpStatus.OK);
+        LinkedHashMap service = (LinkedHashMap) resource.getBody();
+        assertThat(service.get("id")).isEqualTo("1e3feeb0-8e36-46c6-862c-236d9c626439");
+        assertThat(service.get("name")).isEqualTo("vFW");
+        assertThat(service.get("invariantUUID")).isEqualTo("b58a118e-eeb9-4f6e-bdca-e292f84d17df");
+        assertThat(service.get("toscaModelURL")).isEqualTo("/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/toscaModel");
+        assertThat(service.get("distributionStatus")).isEqualTo("DISTRIBUTED");
+        assertThat(service.get("version")).isEqualTo("2.0");
+        assertThat(service.get("lifecycleStatus")).isEqualTo("CERTIFIED");
+        assertThat(service.get("@type")).isEqualTo("ONAPservice");
+        assertThat(((ArrayList) service.get("attachment")).size()).isEqualTo(5);
+        LinkedHashMap relatedParty = (LinkedHashMap) service.get("relatedParty");
+        assertThat(relatedParty.get("name")).isEqualTo("Joni Mitchell");
+        assertThat(relatedParty.get("role")).isEqualTo("lastUpdater");
+
+
+        assertThat(((ArrayList) service.get("resourceSpecification")).size()).isEqualTo(2);
+        LinkedHashMap resource1 = (LinkedHashMap) ((ArrayList) service.get("resourceSpecification")).get(0);
+        assertThat(resource1.get("name")).isEqualTo("vFW-vSINK");
+        assertThat(resource1.get("instanceName")).isEqualTo("vFW-vSINK 0");
+        assertThat(resource1.get("resourceInvariantUUID")).isEqualTo("18b90934-aa82-456f-938e-e74a07a426f3");
+        assertThat(resource1.get("@type")).isEqualTo("ONAPresource");
+        assertThat(resource1.get("modelCustomizationId")).isEqualTo("f7ae574e-fd5f-41e7-9b21-75e001561c96");
+        assertThat(resource1.get("modelCustomizationName")).isEqualTo("vFW-vSINK");
+
+        assertThat(((ArrayList) service.get("serviceSpecCharacteristic")).size()).isEqualTo(4);
+        ArrayList serviceSPecCharacteristics = (ArrayList) service.get("serviceSpecCharacteristic");
+        for (Object serviceSPecCharacteristic : serviceSPecCharacteristics) {
+            LinkedHashMap serviceSPecCharacteristicMap = (LinkedHashMap) serviceSPecCharacteristic;
+            if (serviceSPecCharacteristicMap.get("name").toString().equals("cpus")) {
+                assertThat(serviceSPecCharacteristicMap.get("valueType")).isEqualTo("integer");
+                assertThat(serviceSPecCharacteristicMap.get("@type")).isEqualTo("ONAPserviceCharacteristic");
+                ArrayList serviceSpecCharacteristicValues = (ArrayList) serviceSPecCharacteristicMap.get("serviceSpecCharacteristicValue");
+                for (Object serviceSpecCharacteristicValue : serviceSpecCharacteristicValues) {
+                    LinkedHashMap serviceSpecCharacteristicValueMap = (LinkedHashMap) serviceSpecCharacteristicValue;
+                    if (serviceSpecCharacteristicValueMap.get("value").toString().equals("2")) {
+                        assertThat(serviceSpecCharacteristicValueMap.get("isDefault")).isEqualTo(true);
+                        assertThat(serviceSpecCharacteristicValueMap.get("valueType")).isEqualTo("integer");
+                    } else {
+                        assertThat(serviceSpecCharacteristicValueMap.get("isDefault")).isEqualTo(false);
+                        assertThat(serviceSpecCharacteristicValueMap.get("valueType")).isEqualTo("integer");
+                    }
+                }
+            }
+        }
+    }
+
+
+
+    public static void asserGetServiceCatalogWithoutTosca(ResponseEntity<Object> resource) {
+        assertThat(resource.getStatusCode()).isEqualTo(HttpStatus.PARTIAL_CONTENT);
+        LinkedHashMap service = (LinkedHashMap) resource.getBody();
+        assertThat(service.get("id")).isEqualTo("1e3feeb0-8e36-46c6-862c-236d9c626439");
+        assertThat(service.get("name")).isEqualTo("vFW");
+        assertThat(service.get("invariantUUID")).isEqualTo("b58a118e-eeb9-4f6e-bdca-e292f84d17df");
+        assertThat(service.get("toscaModelURL")).isEqualTo("/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439toto/toscaModel");
+        assertThat(service.get("distributionStatus")).isEqualTo("DISTRIBUTED");
+        assertThat(service.get("version")).isEqualTo("2.0");
+        assertThat(service.get("lifecycleStatus")).isEqualTo("CERTIFIED");
+        assertThat(service.get("@type")).isEqualTo("ONAPservice");
+        assertThat(((ArrayList) service.get("attachment")).size()).isEqualTo(5);
+        LinkedHashMap relatedParty = (LinkedHashMap) service.get("relatedParty");
+        assertThat(relatedParty.get("name")).isEqualTo("Joni Mitchell");
+        assertThat(relatedParty.get("role")).isEqualTo("lastUpdater");
+
+
+        assertThat(((ArrayList) service.get("resourceSpecification")).size()).isEqualTo(2);
+        LinkedHashMap resource1 = (LinkedHashMap) ((ArrayList) service.get("resourceSpecification")).get(0);
+        assertThat(resource1.get("name")).isEqualTo("vFW-vSINK");
+        assertThat(resource1.get("instanceName")).isEqualTo("vFW-vSINK 0");
+        assertThat(resource1.get("resourceInvariantUUID")).isEqualTo("18b90934-aa82-456f-938e-e74a07a426f3");
+        assertThat(resource1.get("@type")).isEqualTo("ONAPresource");
+        assertThat(resource1.get("modelCustomizationId")).isNull();
+        assertThat(resource1.get("modelCustomizationName")).isNull();
+
+        assertThat(service.get("serviceSpecCharacteristic")).isNull();
+    }
+
+
+
+
+    public static void assertFindServiceCatalog(ResponseEntity<Object> resource) {
+        assertThat(resource.getStatusCode()).isEqualTo(HttpStatus.OK);
+        ArrayList body = (ArrayList) resource.getBody();
+        assertThat(body.size()).isEqualTo(21);
+        LinkedHashMap service1 = (LinkedHashMap) body.get(0);
+        assertThat(service1.get("id")).isEqualTo("446afaf6-79b5-420e-aff8-7551b00bb510");
+        assertThat(service1.get("name")).isEqualTo("FreeRadius-service");
+        assertThat(service1.get("invariantUUID")).isEqualTo("7e4781e8-6c6e-41c5-b889-6a321d5f2490");
+        assertThat(service1.get("category")).isEqualTo("Network L4+");
+        assertThat(service1.get("distributionStatus")).isEqualTo("DISTRIBUTED");
+        assertThat(service1.get("version")).isEqualTo("1.0");
+        assertThat(service1.get("lifecycleStatus")).isEqualTo("CERTIFIED");
+        LinkedHashMap relatedParty = (LinkedHashMap) service1.get("relatedParty");
+        assertThat(relatedParty.get("role")).isEqualTo("lastUpdater");
+    }
+
+
+
+    public static void assertFindServiceCatalogWIthFilter(ResponseEntity<Object> resource) {
+        assertThat(resource.getStatusCode()).isEqualTo(HttpStatus.OK);
+        ArrayList body = (ArrayList) resource.getBody();
+        assertThat(body.size()).isEqualTo(21);
+
+
+        ObjectNode service1 = (ObjectNode) body.get(0);
+        assertThat(service1.get("id")).isNull();
+        assertThat(service1.get("name").asText()).isEqualTo("FreeRadius-service");
+        assertThat(service1.get("invariantUUID")).isNull();
+        assertThat(service1.get("category")).isNull();
+        assertThat(service1.get("distributionStatus")).isNull();
+        assertThat(service1.get("version")).isNull();
+        assertThat(service1.get("lifecycleStatus")).isNull();
+        assertThat(service1.get("relatedParty")).isNull();
+    }
+
+}
+
@@ -1,10 +1,11 @@
-package org.onap.nbi.apis.status;
+package org.onap.nbi.apis.resources;
 
 
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.onap.nbi.apis.status.StatusResource;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.http.HttpStatus;
@@ -16,7 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 @RunWith(SpringRunner.class)
 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
-public class StatusTest {
+public class StatusResourceTest {
 
     @Autowired
     StatusResource statusResource;
diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties
new file mode 100644 (file)
index 0000000..5d18ec8
--- /dev/null
@@ -0,0 +1,13 @@
+# SERVER
+server.contextPath=/nbi/api/v1
+server.port = 8080
+
+# LOGGING
+logging.level.org.onap.nbi=DEBUG
+logging.level.org.springframework.cloud.contract.wiremock=DEBUG
+
+# SDC
+sdc.host=http://127.0.0.1:8091
+sdc.header.ecompInstanceId=Rene
+sdc.header.authorization=Basic YWFpOktwOGJKNFNYc3pNMFdYbGhhazNlSGxjc2UyZ0F3ODR2YW9HR21KdlV5MlU=
+
diff --git a/src/test/resources/mappings/sdc_find.json b/src/test/resources/mappings/sdc_find.json
new file mode 100644 (file)
index 0000000..e992f2b
--- /dev/null
@@ -0,0 +1,244 @@
+{
+    "request": {
+        "method": "GET",
+        "urlPath": "/sdc/v1/catalog/services/"
+    },
+    "response": {
+        "status": 200,
+        "jsonBody": [{
+                "uuid": "446afaf6-79b5-420e-aff8-7551b00bb510",
+                "invariantUUID": "7e4781e8-6c6e-41c5-b889-6a321d5f2490",
+                "name": "FreeRadius-service",
+                "version": "1.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/446afaf6-79b5-420e-aff8-7551b00bb510/toscaModel",
+                "category": "Network L4+",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "35911438-4621-439b-a23d-3e07680c724b",
+                "invariantUUID": "ca2f0af5-95e4-4058-b037-5c0de0f80bfa",
+                "name": "vIMS",
+                "version": "1.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/35911438-4621-439b-a23d-3e07680c724b/toscaModel",
+                "category": "E2E Service",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "8cdc744a-9327-47cc-a9de-67d8d46b816f",
+                "invariantUUID": "d2b9c343-c41a-4f85-ae36-c53cd4b7abcc",
+                "name": "vIMSservice3",
+                "version": "1.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/8cdc744a-9327-47cc-a9de-67d8d46b816f/toscaModel",
+                "category": "VoIP Call Control",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "fcea1d5b-c8de-4355-8fda-64e0d84494e6",
+                "invariantUUID": "b58a118e-eeb9-4f6e-bdca-e292f84d17df",
+                "name": "vFW-service-2VF-based",
+                "version": "1.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/fcea1d5b-c8de-4355-8fda-64e0d84494e6/toscaModel",
+                "category": "Network Service",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "9d356a71-ac7a-40f0-b2b2-b302c8b4ef63",
+                "invariantUUID": "4526a034-e4fc-4ea3-87d0-8b8fca4a93b1",
+                "name": "serviceFRDBS",
+                "version": "1.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/9d356a71-ac7a-40f0-b2b2-b302c8b4ef63/toscaModel",
+                "category": "Network L4+",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "b821e80a-40a5-4fab-ac5d-3d49a54c4db3",
+                "invariantUUID": "9765d74e-c8f2-4982-bc90-548c854cbde6",
+                "name": "EricDebeau",
+                "version": "0.1",
+                "toscaModelURL": "/sdc/v1/catalog/services/b821e80a-40a5-4fab-ac5d-3d49a54c4db3/toscaModel",
+                "category": "Network L4+",
+                "lifecycleState": "NOT_CERTIFIED_CHECKIN",
+                "lastUpdaterUserId": "cs0008",
+                "distributionStatus": "DISTRIBUTION_NOT_APPROVED"
+            },
+            {
+                "uuid": "cc3ec088-227c-49e2-b4c3-237214b88c84",
+                "invariantUUID": "e1685613-136b-4990-a590-d0651a640a68",
+                "name": "vMRFaaS4",
+                "version": "1.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/cc3ec088-227c-49e2-b4c3-237214b88c84/toscaModel",
+                "category": "Network Service",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "10be4044-8217-4397-8b62-85c58688d4ba",
+                "invariantUUID": "a62a335f-a6e3-40dd-8b60-de8410301240",
+                "name": "OPL_FWtest1_service",
+                "version": "1.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/10be4044-8217-4397-8b62-85c58688d4ba/toscaModel",
+                "category": "Network L4+",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "3dd3923d-1681-4f5b-99bb-f695ab147004",
+                "invariantUUID": "026e8046-4d3a-41d9-b4c2-6793186fd83d",
+                "name": "vFW",
+                "version": "1.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/3dd3923d-1681-4f5b-99bb-f695ab147004/toscaModel",
+                "category": "Network Service",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "d15de0e3-d8fe-4cc3-a0b1-809ea95cbac8",
+                "invariantUUID": "6046d5f5-b39e-4306-a47e-0762c88d8b93",
+                "name": "1f298e99-082b-4a7f-a579",
+                "version": "1.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/d15de0e3-d8fe-4cc3-a0b1-809ea95cbac8/toscaModel",
+                "category": "Network L1-3",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "f5ab9333-692f-42bc-b5dc-3ed753aa0d14",
+                "invariantUUID": "83a9f465-24d2-4dd3-98b8-328481cf9340",
+                "name": "c55011b0-f26c-43dd-9a62",
+                "version": "1.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/f5ab9333-692f-42bc-b5dc-3ed753aa0d14/toscaModel",
+                "category": "Network L1-3",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "33826edf-fddd-4891-b726-8f16ea0e020c",
+                "invariantUUID": "0475334e-e141-42b3-b3ee-4df049c3cd53",
+                "name": "ccfc0cb4-bdff-4ae2-aa0e",
+                "version": "1.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/33826edf-fddd-4891-b726-8f16ea0e020c/toscaModel",
+                "category": "Network L1-3",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "340bf137-8c6c-4d5b-b185-19364dfc74ed",
+                "invariantUUID": "7e4781e8-6c6e-41c5-b889-6a321d5f2490",
+                "name": "FreeRadius-service",
+                "version": "2.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/340bf137-8c6c-4d5b-b185-19364dfc74ed/toscaModel",
+                "category": "Network L4+",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "d0cac11e-332f-47e8-86d8-cb0b82655bb9",
+                "invariantUUID": "ca2f0af5-95e4-4058-b037-5c0de0f80bfa",
+                "name": "vIMS",
+                "version": "2.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/d0cac11e-332f-47e8-86d8-cb0b82655bb9/toscaModel",
+                "category": "E2E Service",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "e245a0a2-34fc-46c7-912c-bd39305275c1",
+                "invariantUUID": "29db0b2c-a877-45e8-8175-4ac526d87eee",
+                "name": "vMRFaaS",
+                "version": "1.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/e245a0a2-34fc-46c7-912c-bd39305275c1/toscaModel",
+                "category": "Network L4+",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "b9e06990-99e2-480f-96ac-c6e50c83f2bb",
+                "invariantUUID": "008943ad-73be-4d57-9105-962c4cb16a71",
+                "name": "vMRFaas2",
+                "version": "1.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/b9e06990-99e2-480f-96ac-c6e50c83f2bb/toscaModel",
+                "category": "Network L4+",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "98d95267-5e0f-4531-abf8-f14b90031dc5",
+                "invariantUUID": "709d157b-52fb-4250-976e-7133dff5c347",
+                "name": "NewFreeRadius-service",
+                "version": "1.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/98d95267-5e0f-4531-abf8-f14b90031dc5/toscaModel",
+                "category": "Network L4+",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "d8d2429b-0863-462c-adc7-cd38d77331ed",
+                "invariantUUID": "e1685613-136b-4990-a590-d0651a640a68",
+                "name": "vMRFaaS4",
+                "version": "1.1",
+                "toscaModelURL": "/sdc/v1/catalog/services/d8d2429b-0863-462c-adc7-cd38d77331ed/toscaModel",
+                "category": "Network Service",
+                "lifecycleState": "NOT_CERTIFIED_CHECKOUT",
+                "lastUpdaterUserId": "cs0008",
+                "distributionStatus": "DISTRIBUTION_NOT_APPROVED"
+            },
+            {
+                "uuid": "9cfc73ad-795d-42ad-8a4f-54e6b3f33ef9",
+                "invariantUUID": "79f0574e-caf8-4bac-8189-909b2127e9e9",
+                "name": "vMRFaaS3",
+                "version": "1.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/9cfc73ad-795d-42ad-8a4f-54e6b3f33ef9/toscaModel",
+                "category": "Network Service",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "af1ac9db-9d8b-4ca0-964c-58755826b59a",
+                "invariantUUID": "d2b9c343-c41a-4f85-ae36-c53cd4b7abcc",
+                "name": "vIMSservice3",
+                "version": "2.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/af1ac9db-9d8b-4ca0-964c-58755826b59a/toscaModel",
+                "category": "VoIP Call Control",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            },
+            {
+                "uuid": "1e3feeb0-8e36-46c6-862c-236d9c626439",
+                "invariantUUID": "b58a118e-eeb9-4f6e-bdca-e292f84d17df",
+                "name": "vFW-service-2VF-based",
+                "version": "2.0",
+                "toscaModelURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/toscaModel",
+                "category": "Network Service",
+                "lifecycleState": "CERTIFIED",
+                "lastUpdaterUserId": "jm0007",
+                "distributionStatus": "DISTRIBUTED"
+            }
+        ],
+        "headers": {
+            "Content-Type": "application/json"
+        }
+    }
+}
diff --git a/src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439.json b/src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439.json
new file mode 100644 (file)
index 0000000..3aeff82
--- /dev/null
@@ -0,0 +1,213 @@
+{
+    "request": {
+        "method": "GET",
+        "urlPath": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/metadata"
+    },
+    "response": {
+        "status": 200,
+        "jsonBody": {
+            "uuid": "1e3feeb0-8e36-46c6-862c-236d9c626439",
+            "invariantUUID": "b58a118e-eeb9-4f6e-bdca-e292f84d17df",
+            "name": "vFW",
+            "version": "2.0",
+            "toscaModelURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/toscaModel",
+            "category": "Network Service",
+            "lifecycleState": "CERTIFIED",
+            "lastUpdaterUserId": "jm0007",
+            "distributionStatus": "DISTRIBUTED",
+            "lastUpdaterFullName": "Joni Mitchell",
+            "resources": [{
+                    "resourceInstanceName": "vFW-vSINK 0",
+                    "resourceName": "vFW-vSINK",
+                    "resourceInvariantUUID": "18b90934-aa82-456f-938e-e74a07a426f3",
+                    "resourceVersion": "2.0",
+                    "resoucreType": "VF",
+                    "resourceUUID": "89a6b4c5-3973-4c19-b651-fae3713ca8d5",
+                    "artifacts": [{
+                            "artifactName": "vf-license-model.xml",
+                            "artifactType": "VF_LICENSE",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/f6fa3f94-f5cd-4233-a7b2-b5e8dc2e1ec6",
+                            "artifactDescription": "VF license file",
+                            "artifactChecksum": "NDQ2NzIxNzgyMjZhNTc1NDNlMWU0ODI1ZmIyNjc3Zjg=",
+                            "artifactUUID": "f6fa3f94-f5cd-4233-a7b2-b5e8dc2e1ec6",
+                            "artifactVersion": "1",
+                            "artifactLabel": "vflicense",
+                            "artifactGroupType": "DEPLOYMENT"
+                        },
+                        {
+                            "artifactName": "vfwvsink0_modules.json",
+                            "artifactType": "VF_MODULES_METADATA",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/d0aaecf9-6ffb-4b4b-81fd-c59c1e8e6fb6",
+                            "artifactDescription": "Auto-generated VF Modules information artifact",
+                            "artifactChecksum": "ZGIyOWY3YzE0MTM2MjlhMjY1ZjkzNDg3YjE2ZmQxY2Y=",
+                            "artifactUUID": "d0aaecf9-6ffb-4b4b-81fd-c59c1e8e6fb6",
+                            "artifactVersion": "1",
+                            "artifactLabel": "vfModulesMetadata",
+                            "artifactGroupType": "DEPLOYMENT"
+                        },
+                        {
+                            "artifactName": "base_vfw.yaml",
+                            "artifactType": "HEAT",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/c94e8eec-b1a7-431c-ab6f-2fda5f0ee920",
+                            "artifactDescription": "created from csar",
+                            "artifactTimeout": 60,
+                            "artifactChecksum": "YTY0MDg5ODUwZDE4YzQyYWI0NjE5Y2NjYmM3ZDg5ZGE=",
+                            "artifactUUID": "c94e8eec-b1a7-431c-ab6f-2fda5f0ee920",
+                            "artifactVersion": "4",
+                            "artifactLabel": "heat1",
+                            "artifactGroupType": "DEPLOYMENT"
+                        },
+                        {
+                            "artifactName": "vendor-license-model.xml",
+                            "artifactType": "VENDOR_LICENSE",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/423d2c66-6c3a-4257-9342-7b57ebf9dd54",
+                            "artifactDescription": " Vendor license file",
+                            "artifactChecksum": "YTNhYTc3ZGE4ZWViMmYzOThkOGQ3ZTVjZGNmNmU0ZmQ=",
+                            "artifactUUID": "423d2c66-6c3a-4257-9342-7b57ebf9dd54",
+                            "artifactVersion": "1",
+                            "artifactLabel": "vendorlicense",
+                            "artifactGroupType": "DEPLOYMENT"
+                        },
+                        {
+                            "artifactName": "base_vfw.env",
+                            "artifactType": "HEAT_ENV",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/a1a58cc9-8225-4b6f-b81a-02fa3c7fb6ec",
+                            "artifactDescription": "Auto-generated HEAT Environment deployment artifact",
+                            "artifactChecksum": "ZmVkM2MwODhlZjcwNWY5MDk5ZGEyMjI5ZTAyYWRjNjY=",
+                            "artifactUUID": "a1a58cc9-8225-4b6f-b81a-02fa3c7fb6ec",
+                            "artifactVersion": "2",
+                            "generatedFromUUID": "32591489-33c9-4461-a47c-7c463250788d.heat1",
+                            "artifactLabel": "heat1env",
+                            "artifactGroupType": "DEPLOYMENT"
+                        }
+                    ]
+                },
+                {
+                    "resourceInstanceName": "vPkG 0",
+                    "resourceName": "vPkG",
+                    "resourceInvariantUUID": "8d8a20c0-746c-4d5e-a1a2-fa49fa5786ad",
+                    "resourceVersion": "2.0",
+                    "resoucreType": "VF",
+                    "resourceUUID": "31961e27-2a2c-4beb-87c9-bfe0067088f5",
+                    "artifacts": [{
+                            "artifactName": "vf-license-model.xml",
+                            "artifactType": "VF_LICENSE",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/7af6cc3b-2ba3-4164-9d7d-65b3b46a71f4",
+                            "artifactDescription": "VF license file",
+                            "artifactChecksum": "MWM5NDlmNjdhZTdmZTA5MzIzY2RhYjcxZmFkYzQyZDM=",
+                            "artifactUUID": "7af6cc3b-2ba3-4164-9d7d-65b3b46a71f4",
+                            "artifactVersion": "1",
+                            "artifactLabel": "vflicense",
+                            "artifactGroupType": "DEPLOYMENT"
+                        },
+                        {
+                            "artifactName": "vpkg0_modules.json",
+                            "artifactType": "VF_MODULES_METADATA",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/37b16173-bd54-447f-a5a2-1a5e24db8afb",
+                            "artifactDescription": "Auto-generated VF Modules information artifact",
+                            "artifactChecksum": "ZDA3MWQ3MTE3MTA1MzNkY2M1ODQ4YTUxN2YwMDk0MmM=",
+                            "artifactUUID": "37b16173-bd54-447f-a5a2-1a5e24db8afb",
+                            "artifactVersion": "1",
+                            "artifactLabel": "vfModulesMetadata",
+                            "artifactGroupType": "DEPLOYMENT"
+                        },
+                        {
+                            "artifactName": "base_vpkg.yaml",
+                            "artifactType": "HEAT",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/43184998-c107-40a7-92f6-00ba74de8539",
+                            "artifactDescription": "created from csar",
+                            "artifactTimeout": 60,
+                            "artifactChecksum": "NDZhY2U0YTExZjllNTFmZjc4ZTE4YzU2Zjk1ZDc2MWI=",
+                            "artifactUUID": "43184998-c107-40a7-92f6-00ba74de8539",
+                            "artifactVersion": "4",
+                            "artifactLabel": "heat1",
+                            "artifactGroupType": "DEPLOYMENT"
+                        },
+                        {
+                            "artifactName": "vendor-license-model.xml",
+                            "artifactType": "VENDOR_LICENSE",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/6cd5f968-20aa-4b86-9a50-97db5e4ca806",
+                            "artifactDescription": " Vendor license file",
+                            "artifactChecksum": "YTNhYTc3ZGE4ZWViMmYzOThkOGQ3ZTVjZGNmNmU0ZmQ=",
+                            "artifactUUID": "6cd5f968-20aa-4b86-9a50-97db5e4ca806",
+                            "artifactVersion": "1",
+                            "artifactLabel": "vendorlicense",
+                            "artifactGroupType": "DEPLOYMENT"
+                        },
+                        {
+                            "artifactName": "base_vpkg.env",
+                            "artifactType": "HEAT_ENV",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/60944038-d382-4aa6-b387-7b87c9c9df19",
+                            "artifactDescription": "Auto-generated HEAT Environment deployment artifact",
+                            "artifactChecksum": "OGU0OGFlZTFiZDdhYmQ0MmM0MjAyY2U5YjljYWViYTA=",
+                            "artifactUUID": "60944038-d382-4aa6-b387-7b87c9c9df19",
+                            "artifactVersion": "2",
+                            "generatedFromUUID": "0d3918df-ea14-4fc3-a5c9-34032eaae573.heat1",
+                            "artifactLabel": "heat1env",
+                            "artifactGroupType": "DEPLOYMENT"
+                        }
+                    ]
+                }
+            ],
+            "artifacts": [{
+                    "artifactName": "AAI-vFW-service-2VF-based-service-2.0.xml",
+                    "artifactType": "MODEL_INVENTORY_PROFILE",
+                    "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/2e6cd967-93c2-4f53-82bd-c56ab98e8df7",
+                    "artifactDescription": "AAI Service Model",
+                    "artifactChecksum": "ZTY5ZTJmYTY4YzE2NGUxMTQxNWNkN2QzMmI4MWIzNDU=",
+                    "artifactUUID": "2e6cd967-93c2-4f53-82bd-c56ab98e8df7",
+                    "artifactVersion": "1",
+                    "artifactLabel": "aaiservice1603481860",
+                    "artifactGroupType": "DEPLOYMENT"
+                },
+                {
+                    "artifactName": "AAI-Vpkg..base_vpkg..module-0-resource-2.xml",
+                    "artifactType": "MODEL_INVENTORY_PROFILE",
+                    "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/ad600a09-edde-4356-bb0a-9e638a671d06",
+                    "artifactDescription": "AAI Resource Model",
+                    "artifactChecksum": "MzQyMjczOGVmYzM1OWQ1NmFhZjBhOWUxM2JjMmYxZTQ=",
+                    "artifactUUID": "ad600a09-edde-4356-bb0a-9e638a671d06",
+                    "artifactVersion": "1",
+                    "artifactLabel": "aairesource529289386",
+                    "artifactGroupType": "DEPLOYMENT"
+                },
+                {
+                    "artifactName": "AAI-vFW-vSINK-resource-2.0.xml",
+                    "artifactType": "MODEL_INVENTORY_PROFILE",
+                    "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/413a631e-69c4-453b-ab68-fac09b390259",
+                    "artifactDescription": "AAI Resource Model",
+                    "artifactChecksum": "ZWRmMzQzYzc0MThlYjQ1YjY2ZTFkYzJmMjAyNzQ1YWU=",
+                    "artifactUUID": "413a631e-69c4-453b-ab68-fac09b390259",
+                    "artifactVersion": "1",
+                    "artifactLabel": "aairesource1461475898",
+                    "artifactGroupType": "DEPLOYMENT"
+                },
+                {
+                    "artifactName": "AAI-vPkG-resource-2.0.xml",
+                    "artifactType": "MODEL_INVENTORY_PROFILE",
+                    "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/aee30754-eec4-4820-ae3a-790b80b76e81",
+                    "artifactDescription": "AAI Resource Model",
+                    "artifactChecksum": "OGQ4ZTdhYjkyZDRkYmFiZTBhNWU4MDc4YTM2YjY1NmI=",
+                    "artifactUUID": "aee30754-eec4-4820-ae3a-790b80b76e81",
+                    "artifactVersion": "1",
+                    "artifactLabel": "aairesource936479495",
+                    "artifactGroupType": "DEPLOYMENT"
+                },
+                {
+                    "artifactName": "AAI-VfwVsink..base_vfw..module-0-resource-2.xml",
+                    "artifactType": "MODEL_INVENTORY_PROFILE",
+                    "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/ac9a3bbf-a052-4176-abff-fe2d2741194a",
+                    "artifactDescription": "AAI Resource Model",
+                    "artifactChecksum": "OWIzNjVhNmI2ZWYyZThlMjk1NjA2MDFhZTU3MGQ0ZDU=",
+                    "artifactUUID": "ac9a3bbf-a052-4176-abff-fe2d2741194a",
+                    "artifactVersion": "1",
+                    "artifactLabel": "aairesource1106409880",
+                    "artifactGroupType": "DEPLOYMENT"
+                }
+            ]
+        },
+        "headers": {
+            "Content-Type": "application/json"
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439_tosca.json b/src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439_tosca.json
new file mode 100644 (file)
index 0000000..2090397
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "request": {
+        "method": "GET",
+        "urlPath": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/toscaModel"
+    },
+    "response": {
+        "status": 200,
+        "bodyFileName": "response"
+    }
+}
\ No newline at end of file
diff --git a/src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439_withoutTosca.json b/src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439_withoutTosca.json
new file mode 100644 (file)
index 0000000..567503a
--- /dev/null
@@ -0,0 +1,213 @@
+{
+    "request": {
+        "method": "GET",
+        "urlPath": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439_withoutTosca/metadata"
+    },
+    "response": {
+        "status": 200,
+        "jsonBody": {
+            "uuid": "1e3feeb0-8e36-46c6-862c-236d9c626439",
+            "invariantUUID": "b58a118e-eeb9-4f6e-bdca-e292f84d17df",
+            "name": "vFW",
+            "version": "2.0",
+            "toscaModelURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439toto/toscaModel",
+            "category": "Network Service",
+            "lifecycleState": "CERTIFIED",
+            "lastUpdaterUserId": "jm0007",
+            "distributionStatus": "DISTRIBUTED",
+            "lastUpdaterFullName": "Joni Mitchell",
+            "resources": [{
+                    "resourceInstanceName": "vFW-vSINK 0",
+                    "resourceName": "vFW-vSINK",
+                    "resourceInvariantUUID": "18b90934-aa82-456f-938e-e74a07a426f3",
+                    "resourceVersion": "2.0",
+                    "resoucreType": "VF",
+                    "resourceUUID": "89a6b4c5-3973-4c19-b651-fae3713ca8d5",
+                    "artifacts": [{
+                            "artifactName": "vf-license-model.xml",
+                            "artifactType": "VF_LICENSE",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/f6fa3f94-f5cd-4233-a7b2-b5e8dc2e1ec6",
+                            "artifactDescription": "VF license file",
+                            "artifactChecksum": "NDQ2NzIxNzgyMjZhNTc1NDNlMWU0ODI1ZmIyNjc3Zjg=",
+                            "artifactUUID": "f6fa3f94-f5cd-4233-a7b2-b5e8dc2e1ec6",
+                            "artifactVersion": "1",
+                            "artifactLabel": "vflicense",
+                            "artifactGroupType": "DEPLOYMENT"
+                        },
+                        {
+                            "artifactName": "vfwvsink0_modules.json",
+                            "artifactType": "VF_MODULES_METADATA",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/d0aaecf9-6ffb-4b4b-81fd-c59c1e8e6fb6",
+                            "artifactDescription": "Auto-generated VF Modules information artifact",
+                            "artifactChecksum": "ZGIyOWY3YzE0MTM2MjlhMjY1ZjkzNDg3YjE2ZmQxY2Y=",
+                            "artifactUUID": "d0aaecf9-6ffb-4b4b-81fd-c59c1e8e6fb6",
+                            "artifactVersion": "1",
+                            "artifactLabel": "vfModulesMetadata",
+                            "artifactGroupType": "DEPLOYMENT"
+                        },
+                        {
+                            "artifactName": "base_vfw.yaml",
+                            "artifactType": "HEAT",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/c94e8eec-b1a7-431c-ab6f-2fda5f0ee920",
+                            "artifactDescription": "created from csar",
+                            "artifactTimeout": 60,
+                            "artifactChecksum": "YTY0MDg5ODUwZDE4YzQyYWI0NjE5Y2NjYmM3ZDg5ZGE=",
+                            "artifactUUID": "c94e8eec-b1a7-431c-ab6f-2fda5f0ee920",
+                            "artifactVersion": "4",
+                            "artifactLabel": "heat1",
+                            "artifactGroupType": "DEPLOYMENT"
+                        },
+                        {
+                            "artifactName": "vendor-license-model.xml",
+                            "artifactType": "VENDOR_LICENSE",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/423d2c66-6c3a-4257-9342-7b57ebf9dd54",
+                            "artifactDescription": " Vendor license file",
+                            "artifactChecksum": "YTNhYTc3ZGE4ZWViMmYzOThkOGQ3ZTVjZGNmNmU0ZmQ=",
+                            "artifactUUID": "423d2c66-6c3a-4257-9342-7b57ebf9dd54",
+                            "artifactVersion": "1",
+                            "artifactLabel": "vendorlicense",
+                            "artifactGroupType": "DEPLOYMENT"
+                        },
+                        {
+                            "artifactName": "base_vfw.env",
+                            "artifactType": "HEAT_ENV",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/a1a58cc9-8225-4b6f-b81a-02fa3c7fb6ec",
+                            "artifactDescription": "Auto-generated HEAT Environment deployment artifact",
+                            "artifactChecksum": "ZmVkM2MwODhlZjcwNWY5MDk5ZGEyMjI5ZTAyYWRjNjY=",
+                            "artifactUUID": "a1a58cc9-8225-4b6f-b81a-02fa3c7fb6ec",
+                            "artifactVersion": "2",
+                            "generatedFromUUID": "32591489-33c9-4461-a47c-7c463250788d.heat1",
+                            "artifactLabel": "heat1env",
+                            "artifactGroupType": "DEPLOYMENT"
+                        }
+                    ]
+                },
+                {
+                    "resourceInstanceName": "vPkG 0",
+                    "resourceName": "vPkG",
+                    "resourceInvariantUUID": "8d8a20c0-746c-4d5e-a1a2-fa49fa5786ad",
+                    "resourceVersion": "2.0",
+                    "resoucreType": "VF",
+                    "resourceUUID": "31961e27-2a2c-4beb-87c9-bfe0067088f5",
+                    "artifacts": [{
+                            "artifactName": "vf-license-model.xml",
+                            "artifactType": "VF_LICENSE",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/7af6cc3b-2ba3-4164-9d7d-65b3b46a71f4",
+                            "artifactDescription": "VF license file",
+                            "artifactChecksum": "MWM5NDlmNjdhZTdmZTA5MzIzY2RhYjcxZmFkYzQyZDM=",
+                            "artifactUUID": "7af6cc3b-2ba3-4164-9d7d-65b3b46a71f4",
+                            "artifactVersion": "1",
+                            "artifactLabel": "vflicense",
+                            "artifactGroupType": "DEPLOYMENT"
+                        },
+                        {
+                            "artifactName": "vpkg0_modules.json",
+                            "artifactType": "VF_MODULES_METADATA",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/37b16173-bd54-447f-a5a2-1a5e24db8afb",
+                            "artifactDescription": "Auto-generated VF Modules information artifact",
+                            "artifactChecksum": "ZDA3MWQ3MTE3MTA1MzNkY2M1ODQ4YTUxN2YwMDk0MmM=",
+                            "artifactUUID": "37b16173-bd54-447f-a5a2-1a5e24db8afb",
+                            "artifactVersion": "1",
+                            "artifactLabel": "vfModulesMetadata",
+                            "artifactGroupType": "DEPLOYMENT"
+                        },
+                        {
+                            "artifactName": "base_vpkg.yaml",
+                            "artifactType": "HEAT",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/43184998-c107-40a7-92f6-00ba74de8539",
+                            "artifactDescription": "created from csar",
+                            "artifactTimeout": 60,
+                            "artifactChecksum": "NDZhY2U0YTExZjllNTFmZjc4ZTE4YzU2Zjk1ZDc2MWI=",
+                            "artifactUUID": "43184998-c107-40a7-92f6-00ba74de8539",
+                            "artifactVersion": "4",
+                            "artifactLabel": "heat1",
+                            "artifactGroupType": "DEPLOYMENT"
+                        },
+                        {
+                            "artifactName": "vendor-license-model.xml",
+                            "artifactType": "VENDOR_LICENSE",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/6cd5f968-20aa-4b86-9a50-97db5e4ca806",
+                            "artifactDescription": " Vendor license file",
+                            "artifactChecksum": "YTNhYTc3ZGE4ZWViMmYzOThkOGQ3ZTVjZGNmNmU0ZmQ=",
+                            "artifactUUID": "6cd5f968-20aa-4b86-9a50-97db5e4ca806",
+                            "artifactVersion": "1",
+                            "artifactLabel": "vendorlicense",
+                            "artifactGroupType": "DEPLOYMENT"
+                        },
+                        {
+                            "artifactName": "base_vpkg.env",
+                            "artifactType": "HEAT_ENV",
+                            "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/60944038-d382-4aa6-b387-7b87c9c9df19",
+                            "artifactDescription": "Auto-generated HEAT Environment deployment artifact",
+                            "artifactChecksum": "OGU0OGFlZTFiZDdhYmQ0MmM0MjAyY2U5YjljYWViYTA=",
+                            "artifactUUID": "60944038-d382-4aa6-b387-7b87c9c9df19",
+                            "artifactVersion": "2",
+                            "generatedFromUUID": "0d3918df-ea14-4fc3-a5c9-34032eaae573.heat1",
+                            "artifactLabel": "heat1env",
+                            "artifactGroupType": "DEPLOYMENT"
+                        }
+                    ]
+                }
+            ],
+            "artifacts": [{
+                    "artifactName": "AAI-vFW-service-2VF-based-service-2.0.xml",
+                    "artifactType": "MODEL_INVENTORY_PROFILE",
+                    "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/2e6cd967-93c2-4f53-82bd-c56ab98e8df7",
+                    "artifactDescription": "AAI Service Model",
+                    "artifactChecksum": "ZTY5ZTJmYTY4YzE2NGUxMTQxNWNkN2QzMmI4MWIzNDU=",
+                    "artifactUUID": "2e6cd967-93c2-4f53-82bd-c56ab98e8df7",
+                    "artifactVersion": "1",
+                    "artifactLabel": "aaiservice1603481860",
+                    "artifactGroupType": "DEPLOYMENT"
+                },
+                {
+                    "artifactName": "AAI-Vpkg..base_vpkg..module-0-resource-2.xml",
+                    "artifactType": "MODEL_INVENTORY_PROFILE",
+                    "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/ad600a09-edde-4356-bb0a-9e638a671d06",
+                    "artifactDescription": "AAI Resource Model",
+                    "artifactChecksum": "MzQyMjczOGVmYzM1OWQ1NmFhZjBhOWUxM2JjMmYxZTQ=",
+                    "artifactUUID": "ad600a09-edde-4356-bb0a-9e638a671d06",
+                    "artifactVersion": "1",
+                    "artifactLabel": "aairesource529289386",
+                    "artifactGroupType": "DEPLOYMENT"
+                },
+                {
+                    "artifactName": "AAI-vFW-vSINK-resource-2.0.xml",
+                    "artifactType": "MODEL_INVENTORY_PROFILE",
+                    "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/413a631e-69c4-453b-ab68-fac09b390259",
+                    "artifactDescription": "AAI Resource Model",
+                    "artifactChecksum": "ZWRmMzQzYzc0MThlYjQ1YjY2ZTFkYzJmMjAyNzQ1YWU=",
+                    "artifactUUID": "413a631e-69c4-453b-ab68-fac09b390259",
+                    "artifactVersion": "1",
+                    "artifactLabel": "aairesource1461475898",
+                    "artifactGroupType": "DEPLOYMENT"
+                },
+                {
+                    "artifactName": "AAI-vPkG-resource-2.0.xml",
+                    "artifactType": "MODEL_INVENTORY_PROFILE",
+                    "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/aee30754-eec4-4820-ae3a-790b80b76e81",
+                    "artifactDescription": "AAI Resource Model",
+                    "artifactChecksum": "OGQ4ZTdhYjkyZDRkYmFiZTBhNWU4MDc4YTM2YjY1NmI=",
+                    "artifactUUID": "aee30754-eec4-4820-ae3a-790b80b76e81",
+                    "artifactVersion": "1",
+                    "artifactLabel": "aairesource936479495",
+                    "artifactGroupType": "DEPLOYMENT"
+                },
+                {
+                    "artifactName": "AAI-VfwVsink..base_vfw..module-0-resource-2.xml",
+                    "artifactType": "MODEL_INVENTORY_PROFILE",
+                    "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/ac9a3bbf-a052-4176-abff-fe2d2741194a",
+                    "artifactDescription": "AAI Resource Model",
+                    "artifactChecksum": "OWIzNjVhNmI2ZWYyZThlMjk1NjA2MDFhZTU3MGQ0ZDU=",
+                    "artifactUUID": "ac9a3bbf-a052-4176-abff-fe2d2741194a",
+                    "artifactVersion": "1",
+                    "artifactLabel": "aairesource1106409880",
+                    "artifactGroupType": "DEPLOYMENT"
+                }
+            ]
+        },
+        "headers": {
+            "Content-Type": "application/json"
+        }
+    }
+}
\ No newline at end of file