diff --git a/pom.xml b/pom.xml
index 767b7f99185d4b62de61f066bef57daab515fa63..e7b37d77751b66fb5c74a79f7727119a0eec82be 100644
--- a/pom.xml
+++ b/pom.xml
@@ -303,6 +303,11 @@
2.0.1
test
+
+ org.json
+ json
+ 20210307
+
@@ -444,6 +449,31 @@
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.2.5
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.12
+
+
+
+ prepare-agent
+
+
+
+ report
+ prepare-package
+
+ report
+
+
+
+
diff --git a/src/main/java/org/etsi/osl/tmf/scm633/reposervices/ServiceSpecificationRepoService.java b/src/main/java/org/etsi/osl/tmf/scm633/reposervices/ServiceSpecificationRepoService.java
index c0d6f7b35fa6274ffddfcc443b4faf4a3e052a2a..9fd5474732f67d7b8ff4724701b111ff376a59bb 100644
--- a/src/main/java/org/etsi/osl/tmf/scm633/reposervices/ServiceSpecificationRepoService.java
+++ b/src/main/java/org/etsi/osl/tmf/scm633/reposervices/ServiceSpecificationRepoService.java
@@ -75,11 +75,13 @@ import org.etsi.osl.tmf.stm653.model.ServiceTestSpecificationUpdate;
import org.etsi.osl.tmf.stm653.reposervices.ServiceTestSpecificationRepoService;
import org.etsi.osl.tmf.util.AttachmentUtil;
import org.etsi.osl.tmf.util.KrokiClient;
+import org.etsi.osl.tmf.util.PrimitivesParser;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.transform.ResultTransformer;
+import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
@@ -1209,6 +1211,14 @@ public class ServiceSpecificationRepoService {
logger.error("nsdid getConstituentVxF null returned: " + nsd.toString() );
}
+
+ /******************** Begin Primitives Handling ********************/
+
+ JSONObject allPrimitives = PrimitivesParser.extractPrimitives(nsd);
+
+ addServiceSpecCharacteristic(serviceSpec, "PrimitivesList", "NSPrimitives", new Any(allPrimitives.toString(), ""), EValueType.TEXT);
+
+ /********************* End Primitives Handling *********************/
ResourceSpecificationRef resourceSpecificationItemRef = new ResourceSpecificationRef();
diff --git a/src/main/java/org/etsi/osl/tmf/util/PrimitivesParser.java b/src/main/java/org/etsi/osl/tmf/util/PrimitivesParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..64557ad5e9fdda97daa56ba449b5232ee0e21740
--- /dev/null
+++ b/src/main/java/org/etsi/osl/tmf/util/PrimitivesParser.java
@@ -0,0 +1,540 @@
+/**
+ * @Author: Eduardo Santos
+ * @Date: 2024-05-30 12:49:06
+ * @Last Modified by: Eduardo Santos
+ * @Last Modified time: 2024-05-31 13:27:02
+ */
+
+ /*-
+ * ========================LICENSE_START=================================
+ * org.etsi.osl.tmf.api
+ * %%
+ * Copyright (C) 2019 openslice.io
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =========================LICENSE_END==================================
+ */
+
+package org.etsi.osl.tmf.util;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.yaml.snakeyaml.Yaml;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.etsi.osl.model.nfv.NetworkServiceDescriptor;
+import org.etsi.osl.model.nfv.ConstituentVxF;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * This class is responsible for parsing available primitives from a Network Service
+* from its Network Service Descriptor (NSD) and Virtual Network Function Descriptor (VNFD).
+*/
+public class PrimitivesParser {
+
+ private static final transient Log logger = LogFactory.getLog(PrimitivesParser.class.getName());
+
+ public static Map cpdToVduMap = new HashMap();
+
+
+ /**
+ * Extracts all available primitives from a given Network Service Descriptor (NSD).
+ * This method processes the NSD to retrieve and map its constituent VNF descriptors (VNFDs) and Virtual Deployment Units (VDUs),
+ * then extracts the configuration primitives associated with each VDU and VNF, returning a consolidated JSON object with all primitives.
+ *
+ * @param nsd The NetworkServiceDescriptor object containing the network service data.
+ * @return A JSONObject containing all the extracted primitives from the NSD.
+ */
+ public static JSONObject extractPrimitives(NetworkServiceDescriptor nsd) {
+ JSONObject allPrimitives = new JSONObject();
+
+ try {
+ // Access the first element only, to handle the case where there are duplicate descriptor fields
+ ConstituentVxF vxf = nsd.getConstituentVxF().get(0);
+
+ if (vxf.getVxfref() == null) {
+ throw new NullPointerException("vxf.getVxfref() is null");
+ }
+
+ JSONObject nsdJson = PrimitivesParser.processNSD(nsd);
+ JSONObject vnfdJson = PrimitivesParser.processVxF(vxf);
+
+ JSONObject vnfs = PrimitivesParser.extractVNFIds(nsdJson);
+
+ vnfs = PrimitivesParser.mapVDUsToVNFs(vnfdJson, vnfs);
+
+ JSONObject vduPrimitives = PrimitivesParser.extractVDUPrimitives(vnfdJson, vnfs);
+
+ allPrimitives = PrimitivesParser.extractVNFPrimitives(vnfdJson, vduPrimitives);
+ } catch (NullPointerException e) {
+ logger.error("Error extracting primitives: " + e.getMessage());
+ e.printStackTrace();
+ // allPrimitives is already initialized to an empty JSONObject
+ } catch (Exception e) {
+ logger.error("Error extracting primitives.");
+ e.printStackTrace();
+ }
+
+ return allPrimitives;
+
+ }
+
+
+ /**
+ * Converts a NetworkServiceDescriptor's descriptor from YAML string to a JSONObject.
+ * This method utilizes the YAML library to parse the descriptor of the NetworkServiceDescriptor,
+ * converting it into a Map and then into a JSONObject for easier manipulation in Java.
+ *
+ * @param nsd The NetworkServiceDescriptor object containing the YAML string in its descriptor.
+ * @return A JSONObject representing the parsed YAML descriptor.
+ */
+ public static JSONObject processNSD(NetworkServiceDescriptor nsd) {
+ // Parse the NSD descriptor from string to YAML
+ Yaml yaml = new Yaml();
+ Map yamlMap = yaml.load(nsd.getDescriptor());
+
+ // Parse the NSD descriptor from YAML to JSONObject
+ JSONObject nsdJson = new JSONObject(yamlMap);
+
+ return nsdJson;
+ }
+
+
+ /**
+ * Converts a VNF descriptor from JSON string to JSONObject.
+ * This method takes the JSON descriptor from a ConstituentVxF object, manipulates the string to ensure proper JSON format,
+ * and converts it into a JSONObject.
+ *
+ * @param vxf The ConstituentVxF object containing the JSON string of the VNF descriptor.
+ * @return A JSONObject representing the VNF descriptor.
+ */
+ public static JSONObject processVxF(ConstituentVxF vxf) {
+ // Parse the VNF descriptor from JSON string to JSONObject
+ //JSONObject vnfdJson = new JSONObject(vxf.getVxfref().getDescriptor().substring(1, vxf.getVxfref().getDescriptor().length() - 1));
+
+ String descriptor = vxf.getVxfref().getDescriptor();
+ JSONObject vnfdJson;
+
+ // Check if the descriptor starts with a JSON array or object syntax
+ if (descriptor.trim().startsWith("[")) {
+ // It's JSON
+ vnfdJson = new JSONObject(descriptor.substring(1, descriptor.length() - 1));
+ } else {
+ // It's YAML
+ Yaml yaml = new Yaml();
+ Map yamlMap = yaml.load(descriptor);
+
+ // Convert the Map to a JSONObject
+ vnfdJson = new JSONObject(yamlMap).getJSONObject("vnfd");
+ }
+
+ return vnfdJson;
+ }
+
+
+ /**
+ * Extracts VNF identifiers and their constituent CPD IDs from a NSD.
+ * This method serves as the orchestrator that calls other methods to handle specific parts of the JSON structure.
+ *
+ * @param nsdJson The JSONObject containing the NSD data.
+ * @return JSONObject containing an array of VNFs with their IDs and associated constituent CPD IDs.
+ */
+ public static JSONObject extractVNFIds(JSONObject nsdJson) {
+ // JSONObject to hold the VNFs and their details
+ JSONObject vnfs = new JSONObject();
+
+ //JSONArray to store each VNF
+ JSONArray vnfsArray = new JSONArray();
+
+ // Attach the empty array to the JSONObject under the key "vnfs"
+ vnfs.put("vnfs", vnfsArray);
+
+ JSONArray nsdArray = nsdJson.getJSONObject("nsd").getJSONArray("nsd");
+
+ // Assuming that there might be multiple 'nsd' entries, iterate over them
+ processNSDEntries(nsdArray, vnfsArray);
+
+ return vnfs;
+ }
+
+
+ /**
+ * Processes each NSD entry.
+ *
+ * @param nsdArray The array of NSD entries.
+ * @param vnfsArray The array to store processed VNF data.
+ */
+ private static void processNSDEntries(JSONArray nsdArray, JSONArray vnfsArray) {
+ for (int nsdIndex = 0; nsdIndex < nsdArray.length(); nsdIndex++) {
+ JSONArray nsdDf = nsdArray.getJSONObject(nsdIndex).getJSONArray("df");
+
+ processDeploymentFlavors(nsdDf, vnfsArray);
+ }
+ }
+
+
+ /**
+ * Processes each deployment flavor within an NSD.
+ *
+ * @param nsdDf The array of deployment flavors.
+ * @param vnfsArray The array to store processed VNF data.
+ */
+ private static void processDeploymentFlavors(JSONArray nsdDf, JSONArray vnfsArray) {
+ for (int dfIndex = 0; dfIndex < nsdDf.length(); dfIndex++) {
+ JSONArray vnfProfilesArray = nsdDf.getJSONObject(dfIndex).getJSONArray("vnf-profile");
+
+ processVNFProfiles(vnfProfilesArray, vnfsArray);
+ }
+ }
+
+
+ /**
+ * Processes each VNF profile to extract the VNF details.
+ *
+ * @param vnfProfilesArray The array of VNF profiles.
+ * @param vnfsArray The array to store VNF data.
+ */
+ private static void processVNFProfiles(JSONArray vnfProfilesArray, JSONArray vnfsArray) {
+ for (int vnfIndex = 0; vnfIndex < vnfProfilesArray.length(); vnfIndex++) {
+ // For each VNF, extract its id
+ JSONObject vnfProfile = vnfProfilesArray.getJSONObject(vnfIndex);
+
+ extractVNFDetails(vnfProfile, vnfsArray);
+ }
+ }
+
+
+ /**
+ * Extracts details from each VNF profile and adds them to the VNFS array.
+ *
+ * @param vnfProfile The VNF profile JSONObject.
+ * @param vnfsArray The array to store VNF data.
+ */
+ private static void extractVNFDetails(JSONObject vnfProfile, JSONArray vnfsArray) {
+ String vnfId = vnfProfile.getString("id");
+
+ // Create a new JSONObject for this VNF, storing its ID
+ JSONObject vnfObj = new JSONObject();
+
+ vnfObj.put("id", vnfId);
+
+ // Extract virtual link connectivity information for each VNF
+ JSONArray virtualLinkConnectivityArray = vnfProfile.getJSONArray("virtual-link-connectivity");
+ JSONArray constituentCpdIdArray = new JSONArray();
+
+ for (int vlcIndex = 0; vlcIndex < virtualLinkConnectivityArray.length(); vlcIndex++) {
+ // Extract and iterate over the constituent cpd ids for each virtual link connectivity
+ JSONArray constituentCpdIds = virtualLinkConnectivityArray.getJSONObject(vlcIndex).getJSONArray("constituent-cpd-id");
+
+ for (int cpdIndex = 0; cpdIndex < constituentCpdIds.length(); cpdIndex++) {
+ String constituentCpdId = constituentCpdIds.getJSONObject(cpdIndex).getString("constituent-cpd-id");
+
+ constituentCpdIdArray.put(constituentCpdId);
+ }
+
+ // Associate the array of constituent cpd ids with the corresponding VNF
+ vnfObj.put("constituent-cpd-ids", constituentCpdIdArray);
+ }
+ vnfsArray.put(vnfObj);
+ }
+
+
+ /**
+ * Maps VDUs to VNFs based on the provided JSON representations
+ *
+ * @param vnfdJson JSON object representing the Virtual Network Function Descriptor (VNFD).
+ * @param vnfs JSON object representing the Virtual Network Functions (VNFs).
+ * @return JSON object with VNFs updated with VDU IDs.
+ */
+ public static JSONObject mapVDUsToVNFs(JSONObject vnfdJson, JSONObject vnfs) {
+ buildCpdToVduMap(vnfdJson);
+
+ return updateVNFsWithVDUIds(vnfs);
+ }
+
+
+ /**
+ * Builds a mapping of CPDs to VDU IDs based on the VNFD JSON.
+ *
+ * @param vnfdJson JSON object representing the VNFD.
+ */
+ private static void buildCpdToVduMap(JSONObject vnfdJson) {
+ // Retrieve the array of external connection point descriptors from the VNFD
+ JSONArray extCpdArray = vnfdJson.optJSONArray("ext-cpd");
+
+ if (extCpdArray == null) return; // Early return if the array doesn't exist
+
+ // Iterate through each connection point descriptor to map them to VDU ids
+ for (int i = 0; i < extCpdArray.length(); i++) {
+ JSONObject cpdEntry = extCpdArray.getJSONObject(i);
+ String id = cpdEntry.optString("id", null); // cpd id
+ JSONObject intCpd = cpdEntry.optJSONObject("int-cpd"); // VDU id linked to this cpd
+
+ if (id != null && intCpd != null) {
+ String vduId = intCpd.optString("vdu-id", "Unknown");
+
+ // Map each CPD id to its corresponding VDU id
+ cpdToVduMap.put(id, vduId);
+ }
+ }
+ }
+
+
+ /**
+ * Updates VNF JSON objects with VDU IDs based on the mapping created by {@link #buildCpdToVduMap(JSONObject)}.
+ *
+ * @param vnfs JSON object representing the Virtual Network Functions (VNFs).
+ * @return JSON object with VNFs updated with VDU IDs.
+ */
+ private static JSONObject updateVNFsWithVDUIds(JSONObject vnfs) {
+ // Modify vnfs JSON using the map
+ JSONArray vnfsArray = vnfs.optJSONArray("vnfs");
+
+ if (vnfsArray == null) return vnfs; // Early return if no VNFs found
+
+ // Iterate through each VNF to replace "constituent-cpd-ids" with "vdu-ids"
+ for (int i = 0; i < vnfsArray.length(); i++) {
+ JSONObject vnf = vnfsArray.getJSONObject(i);
+
+ updateVNFWithVDUIds(vnf);
+ }
+ return vnfs;
+ }
+
+
+ /**
+ * Updates a single VNF JSON object with VDU IDs by replacing "constituent-cpd-ids" with "vdu-ids".
+ *
+ * @param vnf JSON object representing a single VNF.
+ */
+ private static void updateVNFWithVDUIds(JSONObject vnf) {
+ JSONArray cpdIds = vnf.optJSONArray("constituent-cpd-ids");
+ if (cpdIds == null) return; // Early return if no cpd ids
+
+ JSONArray vduIds = new JSONArray();
+
+ // Replace each cpd id with the corresponding VDU id
+ for (int j = 0; j < cpdIds.length(); j++) {
+ String cpdId = cpdIds.optString(j, null);
+
+ if (cpdId != null) {
+ // Get the VDU ID associated with the CPD ID, or mark as "Unknown" if no mapping exists
+ String vduId = cpdToVduMap.getOrDefault(cpdId, "Unknown");
+
+ vduIds.put(vduId);
+ }
+ }
+
+ // Update the VNF JSON object: replace "constituent-cpd-ids" with "vdu-ids"
+ vnf.put("vdu-ids", vduIds);
+ vnf.remove("constituent-cpd-ids");
+ }
+
+
+ /**
+ * Extracts VNF primitives based on management connection points and updates the VNFs with the corresponding VDU configurations.
+ *
+ * @param vnfdJson The JSON object containing the VNFD data.
+ * @param vnfs The JSON object containing VNF configurations.
+ * @return JSONObject Updated JSON object with VNFs containing corresponding VDU configurations.
+ */
+ public static JSONObject extractVNFPrimitives(JSONObject vnfdJson, JSONObject vnfs) {
+ // Extract the array of VNF configurations from the provided JSON object
+ JSONArray vnfsArray = vnfs.getJSONArray("vnfs");
+
+ // Retrieve the management connection point from the VNFD JSON
+ String vnfMgmtCp = vnfdJson.getString("mgmt-cp");
+
+ // Iterate through each VNF in the array
+ processVNFs(vnfsArray, vnfMgmtCp);
+
+ return vnfs;
+ }
+
+
+ /**
+ * Process each VNF to check and update its configuration based on VDU management connection points.
+ *
+ * @param vnfsArray JSONArray of VNFs.
+ * @param vnfMgmtCp The management connection point identifier from VNFD.
+ */
+ private static void processVNFs(JSONArray vnfsArray, String vnfMgmtCp) {
+ for (int i = 0; i < vnfsArray.length(); i++) {
+ // Get the VDU configurations for the current VNF
+ JSONArray vduConfigs = vnfsArray.getJSONObject(i).getJSONArray("vdu-configs");
+
+ // Iterate through each VDU configuration
+ processVDUConfigurations(vduConfigs, vnfsArray.getJSONObject(i), vnfMgmtCp);
+ }
+ }
+
+
+ /**
+ * Iterates through VDU configurations and checks for matches with the VNF's management connection point to update configuration primitives.
+ *
+ * @param vduConfigs JSONArray of VDU configurations for a VNF.
+ * @param vnf JSONObject of the current VNF.
+ * @param vnfMgmtCp The management connection point identifier.
+ */
+ private static void processVDUConfigurations(JSONArray vduConfigs, JSONObject vnf, String vnfMgmtCp) {
+ for (int j = 0; j < vduConfigs.length(); j++) {
+ checkAndUpdateVNFConfiguration(vduConfigs.getJSONObject(j), vnf, vnfMgmtCp);
+ }
+ }
+
+
+ /**
+ * Checks if the VDU configuration matches the management connection point and updates the VNF configuration if it does.
+ *
+ * @param vduConfig JSONObject of the current VDU configuration.
+ * @param vnf JSONObject of the current VNF.
+ * @param vnfMgmtCp The management connection point identifier.
+ */
+ private static void checkAndUpdateVNFConfiguration(JSONObject vduConfig, JSONObject vnf, String vnfMgmtCp) {
+ String vduConfigId = vduConfig.getString("id");
+
+ // Check each entry in the map for a matching management connection point
+ for (String key : cpdToVduMap.keySet()) {
+
+ // If the VDU's external connection point equal the VNF's management connection point
+ // this means that the VDU is the VNF's management VDU, i.e., when invoking the
+ // VNF-level primitives, the invoked primitives will be the magagement VDU ones
+ if (key.equals(vnfMgmtCp) && cpdToVduMap.get(key).equals(vduConfigId)) {
+ // Update the VNF object with the configuration primitives from the correspondent management VDU
+ vnf.put("config-primitive", vduConfig.getJSONArray("config-primitive"));
+ }
+ }
+ }
+
+
+ /**
+ * Processes VNFD JSON to extract and map VDU primitives based on configurations, then updates VNFs JSON structure accordingly.
+ *
+ * @param vnfdJson The VNFD JSON object containing deployment flavors and operational configurations.
+ * @param vnfs The JSON object containing VNFs that will be updated with VDU configurations.
+ * @return JSONObject Updated VNFs JSON object with VDU configurations.
+ */
+ public static JSONObject extractVDUPrimitives(JSONObject vnfdJson, JSONObject vnfs) {
+ JSONArray vnfsArray = vnfs.getJSONArray("vnfs");
+ JSONArray dfs = vnfdJson.getJSONArray("df");
+
+ for (int i = 0; i < dfs.length(); i++) {
+ JSONObject vduToConfig = mapVDUConfigs(dfs.getJSONObject(i));
+ updateVNFsWithVDUConfigs(vnfsArray, vduToConfig);
+ }
+
+ return vnfs;
+ }
+
+
+ /**
+ * Maps each VDU ID to its config-primitives, excluding the 'execution-environment-ref' from the primitives.
+ *
+ * @param df The deployment flavor JSON object.
+ * @return JSONObject Mapping of VDU IDs to their config primitives.
+ */
+ private static JSONObject mapVDUConfigs(JSONObject df) {
+ // Mapping from VDU id to config-primitives
+ JSONArray day1_2 = df.getJSONObject("lcm-operations-configuration")
+ .getJSONObject("operate-vnf-op-config")
+ .getJSONArray("day1-2");
+
+ if (day1_2 == null || day1_2.length() == 0) {
+ logger.error("Error: Day 1-2 configuration array is missing or empty.");
+
+ // Return an empty JSONObject if no data is present
+ return new JSONObject();
+ }
+
+ JSONObject vduToConfig = new JSONObject();
+
+ for (int i = 0; i < day1_2.length(); i++) {
+ JSONObject vduConfig = day1_2.getJSONObject(i);
+
+ vduToConfig.put(vduConfig.getString("id"), filterConfigPrimitives(vduConfig.getJSONArray("config-primitive")));
+ }
+
+ return vduToConfig;
+ }
+
+
+ /**
+ * Removes 'execution-environment-ref' from each config primitive and returns a filtered array of config primitives.
+ *
+ * @param configPrimitives The JSON array of config primitives.
+ * @return JSONArray The filtered array of config primitives.
+ */
+ private static JSONArray filterConfigPrimitives(JSONArray configPrimitives) {
+ JSONArray filteredConfigPrimitives = new JSONArray();
+
+ // Remove execution-environment-ref from each config-primitive
+ for (int j = 0; j < configPrimitives.length(); j++) {
+ JSONObject primitive = configPrimitives.getJSONObject(j);
+
+ primitive.remove("execution-environment-ref");
+ filteredConfigPrimitives.put(primitive);
+ }
+
+ return filteredConfigPrimitives;
+ }
+
+
+ /**
+ * Updates each VNF in the vnfsArray with the mapped VDU configurations.
+ *
+ * @param vnfsArray The JSON array of VNFs to update.
+ * @param vduToConfig The mapping of VDU IDs to their filtered config primitives.
+ */
+ private static void updateVNFsWithVDUConfigs(JSONArray vnfsArray, JSONObject vduToConfig) {
+ // Append the filtered config-primitive to each VDU in the VNFs JSON and remove vdu-ids
+ JSONObject vnf;
+ for (int i = 0; i < vnfsArray.length(); i++) {
+ vnf = vnfsArray.getJSONObject(i);
+
+ updateVNFWithVDUConfig(vnf, vduToConfig);
+ }
+ }
+
+
+ /**
+ * Updates a single VNF with VDU configurations using provided mappings.
+ *
+ * @param vnf The JSON object of the VNF to update.
+ * @param vduToConfig The mapping of VDU IDs to their filtered config primitives.
+ */
+ private static void updateVNFWithVDUConfig(JSONObject vnf, JSONObject vduToConfig) {
+ JSONArray vduIds = vnf.getJSONArray("vdu-ids");
+ JSONArray vduConfigs = new JSONArray();
+
+ JSONObject vduConfig;
+ for (int j = 0; j < vduIds.length(); j++) {
+ String vduId = vduIds.getString(j);
+ vduConfig = new JSONObject();
+
+ vduConfig.put("id", vduId);
+ vduConfig.put("config-primitive", vduToConfig.getJSONArray(vduId));
+ vduConfigs.put(vduConfig);
+ }
+
+ vnf.put("vdu-configs", vduConfigs);
+ // Removing the 'vdu-ids' key after updating
+ vnf.remove("vdu-ids");
+ }
+}
+
diff --git a/src/test/java/org/etsi/osl/services/reposervices/scm633/ServiceSpecificationRepoServiceTest.java b/src/test/java/org/etsi/osl/services/reposervices/scm633/ServiceSpecificationRepoServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a3ea0b35041c947db4a420d0460150cbeadca245
--- /dev/null
+++ b/src/test/java/org/etsi/osl/services/reposervices/scm633/ServiceSpecificationRepoServiceTest.java
@@ -0,0 +1,527 @@
+/**
+ * @Author: Eduardo Santos
+ * @Date: 2024-05-30 12:52:02
+ * @Last Modified by: Eduardo Santos
+ * @Last Modified time: 2024-05-31 13:30:14
+ */
+
+package org.etsi.osl.services.reposervices.scm633;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+
+import org.etsi.osl.model.nfv.NetworkServiceDescriptor;
+import org.etsi.osl.tmf.OpenAPISpringBoot;
+import org.etsi.osl.tmf.common.model.Any;
+import org.etsi.osl.tmf.rcm634.model.ResourceSpecification;
+import org.etsi.osl.tmf.rcm634.reposervices.ResourceSpecificationRepoService;
+import org.etsi.osl.tmf.scm633.api.ServiceSpecificationApiRouteBuilderNSD;
+import org.etsi.osl.tmf.scm633.model.ServiceSpecCharacteristic;
+import org.etsi.osl.tmf.scm633.model.ServiceSpecCharacteristicValue;
+import org.etsi.osl.tmf.scm633.model.ServiceSpecification;
+import org.etsi.osl.tmf.scm633.reposervices.ServiceSpecificationRepoService;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import org.junit.runner.RunWith;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import org.mockito.Mock;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import jakarta.validation.Valid;
+
+@RunWith(SpringRunner.class)
+@ActiveProfiles("testing")
+@SpringBootTest(classes = OpenAPISpringBoot.class)
+public class ServiceSpecificationRepoServiceTest {
+
+ @Autowired
+ private ServiceSpecificationRepoService serviceSpecificationRepoService;
+
+ @MockBean
+ private ServiceSpecificationApiRouteBuilderNSD serviceSpecificationApiRouteBuilderNSD;
+
+ @Mock
+ private static ResourceSpecificationRepoService resourceSpecRepoService;
+
+ private static NetworkServiceDescriptor nsd;
+
+ private static ResourceSpecification resourceNSD;
+
+ @BeforeClass
+ public static void setupBeforeClass() {
+ // Load NSD from JSON file to NetworkServiceDescriptor.class
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+
+ nsd = mapper.readValue(
+ new File(
+ "src/test/resources/reposervices/scm633/nsd.json"),
+ NetworkServiceDescriptor.class);
+
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ // Assert that the NSD was properly loaded
+ assertNotNull(nsd);
+
+ // Mock resourceNSD
+ resourceNSD = mock(ResourceSpecification.class);
+ resourceNSD.setName(nsd.getName());
+ resourceNSD.setVersion(nsd.getVersion());
+ resourceNSD.setDescription(nsd.getShortDescription());
+ }
+
+ @Before
+ public void setupBefore() {
+ when(serviceSpecificationApiRouteBuilderNSD.retrieveNSD(anyString())).thenReturn(nsd);
+ when(resourceSpecRepoService.addResourceSpec(any())).thenReturn(resourceNSD);
+ }
+
+
+ /**
+ * Tests that specFromNSDID returns a non-null result when retrieveNSD returns a non-null NetworkServiceDescriptor.
+ *
+ * This test verifies that the method retrieveNSD correctly returns a non-null NetworkServiceDescriptor
+ * and that the specFromNSDID method does not return null in such a case.
+ */
+ @Test
+ public void testSpecFromNSDIDReturnsNonNullWhenRetrieveNSDReturnsNonNull() {
+ // Setup
+ String id = "testId";
+
+ NetworkServiceDescriptor mockNsd = mock(NetworkServiceDescriptor.class);
+ when(serviceSpecificationApiRouteBuilderNSD.retrieveNSD(id)).thenReturn(mockNsd);
+
+ NetworkServiceDescriptor result = serviceSpecificationApiRouteBuilderNSD.retrieveNSD(id);
+
+ // Assertion
+ assertNotNull("The result should not be null when NSD is not null", result);
+ }
+
+
+ /**
+ * Tests that retrieveNSD returns null when the method is mocked to return null.
+ *
+ * This test verifies that the method retrieveNSD correctly returns null when it is expected to.
+ */
+ @Test
+ public void testRetrieveNSDReturnsNull() {
+ // When retrieveNSD return null
+ String id = "SomeId";
+ when(serviceSpecificationApiRouteBuilderNSD.retrieveNSD(id)).thenReturn(null);
+
+ // Act
+ NetworkServiceDescriptor result = serviceSpecificationApiRouteBuilderNSD.retrieveNSD(id);
+
+ // Assert
+ assertNull(result);
+ }
+
+
+ /**
+ * Tests the basic properties of the ServiceSpecification.
+ *
+ * This test verifies that the ServiceSpecification object created from the NSD ID
+ * has the correct name, version, and description. It also checks that the correct number
+ * of ServiceSpecification objects are created.
+ */
+ @Test
+ public void testServiceSpecificationBaseProperties() {
+ String testId = "validId";
+
+ // Invoke the SUT
+ List result = serviceSpecificationRepoService.specFromNSDID(testId);
+
+ // Evaluate the obtained results
+ // Assert that two service specifications are created
+ assertEquals(1, result.size());
+
+ ServiceSpecification serviceSpec = result.get(0);
+
+ // Assert that the name, version, and description are the correct ones
+ assertEquals("tutorial_ns@osm14", serviceSpec.getName());
+ assertEquals("1.0", serviceSpec.getVersion());
+ assertEquals("tutorial_ns", serviceSpec.getDescription());
+ }
+
+
+ /**
+ * Tests the characteristics of the ServiceSpecification objects.
+ *
+ * This test verifies that the method specFromNSDID correctly creates a list of
+ * ServiceSpecification objects from a given NSD ID and that these objects have the expected
+ * characteristics. It checks that the list contains exactly one ServiceSpecification object and
+ * that this object has the expected characteristics, including the correct name, value, and alias
+ * for each characteristic.
+ */
+ @Test
+ public void testServiceSpecificationCharacteristics() {
+ String testId = "validId";
+
+ // Invoke the SUT
+ List result = serviceSpecificationRepoService.specFromNSDID(testId);
+
+ // Evaluate the obtained results
+ // Assert that two service specifications are created
+ assertEquals(1, result.size());
+
+ ServiceSpecification serviceSpec = result.get(0);
+
+ // Evaluate each Service Specification Characteristic
+ // Get all Service Specification Characteristics
+ Set serviceSpecCharacteristics = serviceSpec.getServiceSpecCharacteristic();
+
+ // Cast Service Specification Characteristics Set to ArrayList
+ List serviceSpecCharacteristicsList = new ArrayList<>(serviceSpecCharacteristics);
+
+ // Order Service Specification Characteristics list by characterists' name
+ Collections.sort(serviceSpecCharacteristicsList, Comparator.comparing(ServiceSpecCharacteristic::getName));
+
+ // Assert that the Service Specification Characterists are the ones desired
+ assertEquals(27, serviceSpec.getServiceSpecCharacteristic().size());
+
+ /********************* Assert Service Specification Characteristic APPLY_CONFIG *********************/
+
+ ServiceSpecCharacteristic serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(0);
+ @Valid Set serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ Any v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ String value = v.getValue();
+ String alias = v.getAlias();
+
+ assertEquals("APPLY_CONFIG", serviceSpecCharacteristic.getName());
+ assertEquals("", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic ConfigStatus *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(1);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("ConfigStatus", serviceSpecCharacteristic.getName());
+ assertEquals("", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic ConstituentVnfrIps *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(2);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("ConstituentVnfrIps", serviceSpecCharacteristic.getName());
+ assertEquals("", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic DeploymentRequestID *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(3);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("DeploymentRequestID", serviceSpecCharacteristic.getName());
+ assertEquals("", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic InstanceId *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(4);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("InstanceId", serviceSpecCharacteristic.getName());
+ assertEquals("", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic MANOproviderID *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(5);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("MANOproviderID", serviceSpecCharacteristic.getName());
+ assertEquals("1", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic MANOproviderName *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(6);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("MANOproviderName", serviceSpecCharacteristic.getName());
+ assertEquals("osm14", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic MemberVNFIndex_vnf1 *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(7);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("MemberVNFIndex_vnf1", serviceSpecCharacteristic.getName());
+ assertEquals("vnf1", value);
+ assertEquals("tutorial_vnf", alias);
+
+ /********************* Assert Service Specification Characteristic MemberVNFIndex_vnf2 *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(8);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("MemberVNFIndex_vnf2", serviceSpecCharacteristic.getName());
+ assertEquals("vnf2", value);
+ assertEquals("tutorial_vnf", alias);
+
+ /********************* Assert Service Specification Characteristic NSDID *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(9);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("NSDID", serviceSpecCharacteristic.getName());
+ assertEquals("4", value);
+ assertEquals("id", alias);
+
+ /********************* Assert Service Specification Characteristic NSLCM *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(10);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("NSLCM", serviceSpecCharacteristic.getName());
+ assertEquals("", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic NSR *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(11);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("NSR", serviceSpecCharacteristic.getName());
+ assertEquals("", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic OSM_CONFIG *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(12);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("OSM_CONFIG", serviceSpecCharacteristic.getName());
+ assertEquals("{\"nsdId\":\"9dc24900-e63e-4c0e-b686-ee2ef124c5c2\", \"vimAccountId\":\"479356bf-72ff-4dfd-8483-5c23f48dd0bc\"}", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic OSM_NSDCATALOGID *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(13);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("OSM_NSDCATALOGID", serviceSpecCharacteristic.getName());
+ assertEquals("9dc24900-e63e-4c0e-b686-ee2ef124c5c2", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic OnBoardDescriptorID *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(14);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("OnBoardDescriptorID", serviceSpecCharacteristic.getName());
+ assertEquals("4", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic OnBoardDescriptorUUID *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(15);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("OnBoardDescriptorUUID", serviceSpecCharacteristic.getName());
+ assertEquals("c271dcf1-d823-4458-99dc-7fd80ba93a06", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic OnBoardingStatus *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(16);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("OnBoardingStatus", serviceSpecCharacteristic.getName());
+ assertEquals("ONBOARDED", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic OperationalStatus *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(17);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("OperationalStatus", serviceSpecCharacteristic.getName());
+ assertEquals("", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic PackageLocation *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(18);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("PackageLocation", serviceSpecCharacteristic.getName());
+ assertEquals("http://10.255.28.246/osapi/packages/da63085b-12f9-48a7-b4bb-e7039b128bc3/tutorial_ns.tar.gz", value);
+ assertEquals("PackageLocation", alias);
+
+ /********************* Assert Service Specification Characteristic PackagingFormat *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(19);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("PackagingFormat", serviceSpecCharacteristic.getName());
+ assertEquals("OSMvTHIRTEEN", value);
+ assertEquals("PackagingFormat", alias);
+
+ /********************* Assert Service Specification Characteristic Primitives *********************/
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(20);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("PrimitivesList", serviceSpecCharacteristic.getName());
+ assertEquals("{\"vnfs\":[{\"config-primitive\":[{\"parameter\":[{\"name\":\"filename\",\"data-type\":\"STRING\"}],\"name\":\"run-touch-command\"}],\"id\":\"vnf1\",\"vdu-configs\":[{\"config-primitive\":[{\"parameter\":[{\"name\":\"filename\",\"data-type\":\"STRING\"}],\"name\":\"run-touch-command\"}],\"id\":\"vdu1\"},{\"config-primitive\":[{\"parameter\":[{\"name\":\"filename\",\"data-type\":\"STRING\"}],\"name\":\"run-touch-command\"}],\"id\":\"vdu2\"}]},{\"config-primitive\":[{\"parameter\":[{\"name\":\"filename\",\"data-type\":\"STRING\"}],\"name\":\"run-touch-command\"}],\"id\":\"vnf2\",\"vdu-configs\":[{\"config-primitive\":[{\"parameter\":[{\"name\":\"filename\",\"data-type\":\"STRING\"}],\"name\":\"run-touch-command\"}],\"id\":\"vdu1\"},{\"config-primitive\":[{\"parameter\":[{\"name\":\"filename\",\"data-type\":\"STRING\"}],\"name\":\"run-touch-command\"}],\"id\":\"vdu2\"}]}]}", value);
+ assertEquals("", alias);
+
+
+ /********************* Assert Service Specification Characteristic SSHKEY *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(21);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("SSHKEY", serviceSpecCharacteristic.getName());
+ assertEquals("", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic SSPEC_GRAPH_NOTATION *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(22);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("SSPEC_GRAPH_NOTATION", serviceSpecCharacteristic.getName());
+ //assertEquals("blockdiag {default_textcolor = white;\r\ndefault_fontsize = 12;\r\n\r\n\"null\" -> \"7690ef08-e94f-4c9f-923d-e8a3ad125908\";\r\n\"7690ef08-e94f-4c9f-923d-e8a3ad125908\" [ label = \"tutorial_ns\", shape = roundedbox, color = \"#e28743\"]; \"null\" [ label = \"tutorial_ns@osm14\", color = \"#2596be\"]; }", value);
+ assertEquals("SSPEC_GRAPH_NOTATION", alias);
+
+ /********************* Assert Service Specification Characteristic Status *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(23);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("Status", serviceSpecCharacteristic.getName());
+ assertEquals("", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic VNFINDEXREF_INFO_vnf1 *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(24);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("VNFINDEXREF_INFO_vnf1", serviceSpecCharacteristic.getName());
+ assertEquals("", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic VNFINDEXREF_INFO_vnf2 *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(25);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("VNFINDEXREF_INFO_vnf2", serviceSpecCharacteristic.getName());
+ assertEquals("", value);
+ assertEquals("", alias);
+
+ /********************* Assert Service Specification Characteristic Vendor *********************/
+
+ serviceSpecCharacteristic = serviceSpecCharacteristicsList.get(26);
+ serviceSpecCharacteristicValues = serviceSpecCharacteristic.getServiceSpecCharacteristicValue();
+ v = serviceSpecCharacteristicValues.iterator().next().getValue();
+ value = v.getValue();
+ alias = v.getAlias();
+
+ assertEquals("Vendor", serviceSpecCharacteristic.getName());
+ assertEquals(null, value);
+ assertEquals("Vendor", alias);
+
+ }
+
+}
diff --git a/src/test/resources/reposervices/scm633/nsd.json b/src/test/resources/reposervices/scm633/nsd.json
new file mode 100644
index 0000000000000000000000000000000000000000..bf9085b36957fee8120e8d0c56c316ebe136269d
--- /dev/null
+++ b/src/test/resources/reposervices/scm633/nsd.json
@@ -0,0 +1 @@
+{"id":4,"owner":{"id":2,"organization":null,"firstname":null,"lastname":null,"email":null,"username":"admin","createdAt":null},"uuid":"da63085b-12f9-48a7-b4bb-e7039b128bc3","name":"tutorial_ns","iconsrc":null,"shortDescription":"tutorial_ns","longDescription":"tutorial_ns","version":"1.0","packageLocation":"http://10.255.28.246/osapi/packages/da63085b-12f9-48a7-b4bb-e7039b128bc3/tutorial_ns.tar.gz","dateCreated":1717002820596,"dateUpdated":1717002820596,"categories":null,"extensions":null,"validationJobs":null,"screenshots":null,"vendor":null,"published":false,"termsOfUse":null,"descriptor":"nsd:\n nsd:\n - description: Simple NS with one VNF and a single Virtual Link\n df:\n - id: default-df\n vnf-profile:\n - id: \"vnf1\"\n virtual-link-connectivity:\n - constituent-cpd-id:\n - constituent-base-element-id: \"1\"\n constituent-cpd-id: vnf-vdu1-ext # this must be equal to the vdu's ext-cpd's id \n virtual-link-profile-id: mgmtnet_2\n - constituent-cpd-id:\n - constituent-base-element-id: \"1\"\n constituent-cpd-id: vnf-vdu2-ext # this must be equal to the vdu's ext-cpd's id \n virtual-link-profile-id: mgmtnet_2\n vnfd-id: tutorial_vnf\n - id: \"vnf2\"\n virtual-link-connectivity:\n - constituent-cpd-id:\n - constituent-base-element-id: \"1\"\n constituent-cpd-id: vnf-vdu1-ext # this must be equal to the vdu's ext-cpd's id \n virtual-link-profile-id: mgmtnet_2\n - constituent-cpd-id:\n - constituent-base-element-id: \"1\"\n constituent-cpd-id: vnf-vdu2-ext # this must be equal to the vdu's ext-cpd's id \n virtual-link-profile-id: mgmtnet_2\n vnfd-id: tutorial_vnf\n id: tutorial_ns\n name: tutorial_ns\n version: \"1.0\"\n virtual-link-desc:\n - id: mgmtnet_2\n mgmt-network: true\n vim-network-name: new_5gasp\n vnfd-id:\n - tutorial_vnf","descriptorHTML":"tutorial_ns
Vendor: null
Version: 1.0
Description: tutorial_ns
VNF Count: 1
VM Count: 0
vCPU Count: 0
Memory: 0 MB
Storage: 0 GB
ConstituentVnfds
VnfdId: default-df
","valid":false,"validationStatus":"NOT_STARTED","packagingFormat":"OSMvTHIRTEEN","experimentOnBoardDescriptors":[{"id":4,"obMANOprovider":{"id":1,"name":"osm14","description":null,"vims":[{"id":1,"organization":null,"name":"Jarvis","email":null,"infrastructureStatus":"UNKNOWN","dateCreated":null,"datacentername":"osm14","vimid":"479356bf-72ff-4dfd-8483-5c23f48dd0bc","mp":null,"refSupportedImages":[]}],"supportedMANOplatform":{"id":1,"name":"OSMFOURTEEN","version":"OSMvTHIRTEEN","description":null},"apiEndpoint":"https://10.255.28.219:9999","authorizationBasicHeader":null,"username":"admin","password":"admin","project":"admin","enabledForONBOARDING":true,"enabledForSYNC":true},"onBoardingStatus":"ONBOARDED","lastOnboarding":1717002821939,"deployId":"9dc24900-e63e-4c0e-b686-ee2ef124c5c2","feedbackMessage":"NSD Onboarded Successfully","uuid":"c271dcf1-d823-4458-99dc-7fd80ba93a06","experimentMANOProviderID":"tutorial_ns","experimentid":4}],"constituentVxF":[{"membervnfIndex":"vnf2","vnfdidRef":"tutorial_vnf","vxfref":{"id":3,"owner":{"id":2,"organization":null,"firstname":null,"lastname":null,"email":null,"username":"admin","createdAt":null},"uuid":"0c3bb7df-5063-4844-818f-3a6b6507718e","name":"tutorial_vnf","iconsrc":null,"shortDescription":"tutorial_vnf","longDescription":null,"version":"1.0","packageLocation":"http://10.255.28.246/osapi/packages/0c3bb7df-5063-4844-818f-3a6b6507718e/tutorial_vnf.tar.gz","dateCreated":1717002803785,"dateUpdated":1717002803785,"categories":null,"extensions":null,"validationJobs":null,"screenshots":null,"vendor":null,"published":false,"termsOfUse":null,"descriptor":"vnfd:\n description: A basic VNF descriptor with two VDUs\n mgmt-cp: vnf-vdu1-ext\n int-virtual-link-desc:\n - id: internal-vl\n flavour:\n - id: internal-vl-flavor\n product-name: tutorial_vnf\n id: tutorial_vnf\n df:\n - id: default-df\n instantiation-level:\n - id: default-instantiation-level\n vdu-level:\n - number-of-instances: \"1\"\n vdu-id: vdu1\n - number-of-instances: \"1\"\n vdu-id: vdu2\n vdu-profile:\n - id: vdu1\n min-number-of-instances: \"1\"\n - id: vdu2\n min-number-of-instances: \"1\"\n # Juju/LCM Actions\n lcm-operations-configuration:\n operate-vnf-op-config:\n day1-2:\n - execution-environment-list:\n - id: configure-vnf\n external-connection-point-ref: vnf-vdu1-ext\n juju:\n charm: simple-touch\n proxy: true\n id: tutorial_vnf\n config-access:\n ssh-access:\n default-user: ubuntu\n required: true\n initial-config-primitive:\n - execution-environment-ref: configure-vnf\n name: config\n parameter:\n - name: ssh-hostname\n value: \n - name: ssh-username\n value: ubuntu\n - name: ssh-password\n value: tutorial\n seq: 1\n config-primitive:\n - name: run-touch-command\n execution-environment-ref: configure-vnf\n parameter:\n - name: filename\n data-type: STRING\n #####################################\n - execution-environment-list:\n - id: vdu1-ee\n external-connection-point-ref: vnf-vdu1-ext\n juju:\n charm: simple-touch\n proxy: true\n id: vdu1 # this must be equal to the vdu's id\n config-access:\n ssh-access:\n default-user: ubuntu\n required: true\n initial-config-primitive:\n - execution-environment-ref: vdu1-ee\n name: config\n parameter:\n - name: ssh-hostname\n value: \n - name: ssh-username\n value: ubuntu\n - name: ssh-password\n value: tutorial\n seq: 1\n config-primitive:\n - name: run-touch-command\n execution-environment-ref: vdu1-ee\n parameter:\n - name: filename\n data-type: STRING\n - execution-environment-list:\n - id: vdu2-ee\n #external-connection-point-ref: vnf-cp2-ext\n juju:\n charm: simple-touch\n proxy: true\n id: vdu2 # this must be equal to the vdu's id\n config-access:\n ssh-access:\n default-user: ubuntu\n required: true\n initial-config-primitive:\n - execution-environment-ref: vdu2-ee\n name: config\n parameter:\n - name: ssh-hostname\n value: \n - name: ssh-username\n value: ubuntu\n - name: ssh-password\n value: tutorial\n seq: 1\n config-primitive:\n - name: run-touch-command\n execution-environment-ref: vdu2-ee\n parameter:\n - name: filename\n data-type: STRING\n ext-cpd:\n - id: vnf-vdu1-ext\n int-cpd:\n cpd: vdu1-int-out\n vdu-id: vdu1\n - id: vnf-vdu2-ext\n int-cpd:\n cpd: vdu2-int-out\n vdu-id: vdu2\n sw-image-desc:\n - id: \"ubuntu-20.04-server-cloudimg-amd64\"\n image: \"ubuntu-20.04-server-cloudimg-amd64\"\n name: \"ubuntu-20.04-server-cloudimg-amd64\"\n vdu:\n - cloud-init-file: cloud-config.txt\n id: vdu1\n int-cpd:\n - id: vdu1-int-out\n virtual-network-interface-requirement:\n - name: vdu1-out\n virtual-interface:\n type: PARAVIRT\n - id: vdu1-int-in\n int-virtual-link-desc: internal-vl\n virtual-network-interface-requirement:\n - name: vdu1-in\n virtual-interface:\n type: PARAVIRT\n name: vdu1\n sw-image-desc: \"ubuntu-20.04-server-cloudimg-amd64\"\n virtual-compute-desc: vdu1-compute\n virtual-storage-desc:\n - vdu1-storage\n - cloud-init-file: cloud-config.txt\n id: vdu2\n int-cpd:\n - id: vdu2-int-out\n virtual-network-interface-requirement:\n - name: vdu2-out\n virtual-interface:\n type: PARAVIRT\n - id: vdu2-int-in\n int-virtual-link-desc: internal-vl\n virtual-network-interface-requirement:\n - name: vdu2-in\n virtual-interface:\n type: PARAVIRT\n name: vdu2\n sw-image-desc: \"ubuntu-20.04-server-cloudimg-amd64\"\n virtual-compute-desc: vdu2-compute\n virtual-storage-desc:\n - vdu2-storage\n version: \"1.0\"\n virtual-compute-desc:\n - id: vdu1-compute\n virtual-cpu:\n num-virtual-cpu: \"1\"\n virtual-memory:\n size: \"1.0\"\n - id: vdu2-compute\n virtual-cpu:\n num-virtual-cpu: \"1\"\n virtual-memory:\n size: \"1.0\"\n virtual-storage-desc:\n - id: vdu1-storage\n size-of-storage: \"10\"\n - id: vdu2-storage\n size-of-storage: \"10\"","descriptorHTML":"tutorial_vnf
Vendor: null
Version: 1.0
Description: null
VM Count: 2
vCPU Count: 1
Memory: 1 MB
Storage: 10 GB
","certified":false,"certifiedBy":null,"validationStatus":"UNDER_REVIEW","packagingFormat":"OSMvTHIRTEEN","supportedMANOPlatforms":null,"vxfOnBoardedDescriptors":null,"vfimagesVDU":null}},{"membervnfIndex":"vnf1","vnfdidRef":"tutorial_vnf","vxfref":{"id":3,"owner":{"id":2,"organization":null,"firstname":null,"lastname":null,"email":null,"username":"admin","createdAt":null},"uuid":"0c3bb7df-5063-4844-818f-3a6b6507718e","name":"tutorial_vnf","iconsrc":null,"shortDescription":"tutorial_vnf","longDescription":null,"version":"1.0","packageLocation":"http://10.255.28.246/osapi/packages/0c3bb7df-5063-4844-818f-3a6b6507718e/tutorial_vnf.tar.gz","dateCreated":1717002803785,"dateUpdated":1717002803785,"categories":null,"extensions":null,"validationJobs":null,"screenshots":null,"vendor":null,"published":false,"termsOfUse":null,"descriptor":"vnfd:\n description: A basic VNF descriptor with two VDUs\n mgmt-cp: vnf-vdu1-ext\n int-virtual-link-desc:\n - id: internal-vl\n flavour:\n - id: internal-vl-flavor\n product-name: tutorial_vnf\n id: tutorial_vnf\n df:\n - id: default-df\n instantiation-level:\n - id: default-instantiation-level\n vdu-level:\n - number-of-instances: \"1\"\n vdu-id: vdu1\n - number-of-instances: \"1\"\n vdu-id: vdu2\n vdu-profile:\n - id: vdu1\n min-number-of-instances: \"1\"\n - id: vdu2\n min-number-of-instances: \"1\"\n # Juju/LCM Actions\n lcm-operations-configuration:\n operate-vnf-op-config:\n day1-2:\n - execution-environment-list:\n - id: configure-vnf\n external-connection-point-ref: vnf-vdu1-ext\n juju:\n charm: simple-touch\n proxy: true\n id: tutorial_vnf\n config-access:\n ssh-access:\n default-user: ubuntu\n required: true\n initial-config-primitive:\n - execution-environment-ref: configure-vnf\n name: config\n parameter:\n - name: ssh-hostname\n value: \n - name: ssh-username\n value: ubuntu\n - name: ssh-password\n value: tutorial\n seq: 1\n config-primitive:\n - name: run-touch-command\n execution-environment-ref: configure-vnf\n parameter:\n - name: filename\n data-type: STRING\n #####################################\n - execution-environment-list:\n - id: vdu1-ee\n external-connection-point-ref: vnf-vdu1-ext\n juju:\n charm: simple-touch\n proxy: true\n id: vdu1 # this must be equal to the vdu's id\n config-access:\n ssh-access:\n default-user: ubuntu\n required: true\n initial-config-primitive:\n - execution-environment-ref: vdu1-ee\n name: config\n parameter:\n - name: ssh-hostname\n value: \n - name: ssh-username\n value: ubuntu\n - name: ssh-password\n value: tutorial\n seq: 1\n config-primitive:\n - name: run-touch-command\n execution-environment-ref: vdu1-ee\n parameter:\n - name: filename\n data-type: STRING\n - execution-environment-list:\n - id: vdu2-ee\n #external-connection-point-ref: vnf-cp2-ext\n juju:\n charm: simple-touch\n proxy: true\n id: vdu2 # this must be equal to the vdu's id\n config-access:\n ssh-access:\n default-user: ubuntu\n required: true\n initial-config-primitive:\n - execution-environment-ref: vdu2-ee\n name: config\n parameter:\n - name: ssh-hostname\n value: \n - name: ssh-username\n value: ubuntu\n - name: ssh-password\n value: tutorial\n seq: 1\n config-primitive:\n - name: run-touch-command\n execution-environment-ref: vdu2-ee\n parameter:\n - name: filename\n data-type: STRING\n ext-cpd:\n - id: vnf-vdu1-ext\n int-cpd:\n cpd: vdu1-int-out\n vdu-id: vdu1\n - id: vnf-vdu2-ext\n int-cpd:\n cpd: vdu2-int-out\n vdu-id: vdu2\n sw-image-desc:\n - id: \"ubuntu-20.04-server-cloudimg-amd64\"\n image: \"ubuntu-20.04-server-cloudimg-amd64\"\n name: \"ubuntu-20.04-server-cloudimg-amd64\"\n vdu:\n - cloud-init-file: cloud-config.txt\n id: vdu1\n int-cpd:\n - id: vdu1-int-out\n virtual-network-interface-requirement:\n - name: vdu1-out\n virtual-interface:\n type: PARAVIRT\n - id: vdu1-int-in\n int-virtual-link-desc: internal-vl\n virtual-network-interface-requirement:\n - name: vdu1-in\n virtual-interface:\n type: PARAVIRT\n name: vdu1\n sw-image-desc: \"ubuntu-20.04-server-cloudimg-amd64\"\n virtual-compute-desc: vdu1-compute\n virtual-storage-desc:\n - vdu1-storage\n - cloud-init-file: cloud-config.txt\n id: vdu2\n int-cpd:\n - id: vdu2-int-out\n virtual-network-interface-requirement:\n - name: vdu2-out\n virtual-interface:\n type: PARAVIRT\n - id: vdu2-int-in\n int-virtual-link-desc: internal-vl\n virtual-network-interface-requirement:\n - name: vdu2-in\n virtual-interface:\n type: PARAVIRT\n name: vdu2\n sw-image-desc: \"ubuntu-20.04-server-cloudimg-amd64\"\n virtual-compute-desc: vdu2-compute\n virtual-storage-desc:\n - vdu2-storage\n version: \"1.0\"\n virtual-compute-desc:\n - id: vdu1-compute\n virtual-cpu:\n num-virtual-cpu: \"1\"\n virtual-memory:\n size: \"1.0\"\n - id: vdu2-compute\n virtual-cpu:\n num-virtual-cpu: \"1\"\n virtual-memory:\n size: \"1.0\"\n virtual-storage-desc:\n - id: vdu1-storage\n size-of-storage: \"10\"\n - id: vdu2-storage\n size-of-storage: \"10\"","descriptorHTML":"tutorial_vnf
Vendor: null
Version: 1.0
Description: null
VM Count: 2
vCPU Count: 1
Memory: 1 MB
Storage: 10 GB
","certified":false,"certifiedBy":null,"validationStatus":"UNDER_REVIEW","packagingFormat":"OSMvTHIRTEEN","supportedMANOPlatforms":null,"vxfOnBoardedDescriptors":null,"vfimagesVDU":null}}]}
\ No newline at end of file