diff options
Diffstat (limited to 'ms/blueprintsprocessor/functions/resource-resolution/src')
6 files changed, 354 insertions, 273 deletions
diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt index 2a9218df3..537074383 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt @@ -29,5 +29,5 @@ object ResourceResolutionConstants { const val RESOURCE_RESOLUTION_INPUT_OCCURRENCE = "occurrence" const val RESOURCE_RESOLUTION_INPUT_RESOURCE_ID = "resource-id" const val RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE = "resource-type" - val DATA_DICTIONARY_SECRET_SOURCE_TYPES = arrayOf("vault-data") //Add more secret data dictionary source type here + const val RESOURCE_RESOLUTION_LOG_PROTECTED_METADATA = "log-protect" }
\ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt index 6645a631a..5043c9a78 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt @@ -57,9 +57,8 @@ open class DatabaseResourceAssignmentProcessor(private val bluePrintDBLibPropert // Check if It has Input try { val value = raRuntimeService.getInputValue(resourceAssignment.name) - if (value.returnNullIfMissing() != null) { - logger.info("processor-db source template key (${resourceAssignment.name}) found from input and value is ($value)") - ResourceAssignmentUtils.setResourceDataValue(resourceAssignment, raRuntimeService, value) + if (ResourceAssignmentUtils.checkIfInputWasProvided(resourceAssignment, value)) { + ResourceAssignmentUtils.setInputValueIfProvided(resourceAssignment, raRuntimeService, value) } else { setValueFromDB(resourceAssignment) } diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/InputResourceResolutionProcessor.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/InputResourceResolutionProcessor.kt index db51453b4..f26da141b 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/InputResourceResolutionProcessor.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/InputResourceResolutionProcessor.kt @@ -38,8 +38,6 @@ import org.springframework.stereotype.Service @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) open class InputResourceResolutionProcessor : ResourceAssignmentProcessor() { - private val logger = LoggerFactory.getLogger(InputResourceResolutionProcessor::class.java) - override fun getName(): String { return "${PREFIX_RESOURCE_RESOLUTION_PROCESSOR}source-input" } @@ -49,9 +47,8 @@ open class InputResourceResolutionProcessor : ResourceAssignmentProcessor() { if (isNotEmpty(resourceAssignment.name)) { val value = raRuntimeService.getInputValue(resourceAssignment.name) // if value is null don't call setResourceDataValue to populate the value - if (value !is MissingNode && value !is NullNode) { - logger.info("input source template key (${resourceAssignment.name}) found from input and value is ($value)") - ResourceAssignmentUtils.setResourceDataValue(resourceAssignment, raRuntimeService, value) + if (ResourceAssignmentUtils.checkIfInputWasProvided(resourceAssignment, value)) { + ResourceAssignmentUtils.setInputValueIfProvided(resourceAssignment, raRuntimeService, value) } } // Check the value has populated for mandatory case diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt index 6515b11cd..ecc2c2be1 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt @@ -17,9 +17,6 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor -import com.fasterxml.jackson.databind.node.MissingNode -import com.fasterxml.jackson.databind.node.NullNode -import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants.DATA_DICTIONARY_SECRET_SOURCE_TYPES import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.RestResourceSource import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils @@ -54,8 +51,11 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS validate(resourceAssignment) // Check if It has Input - val value = getFromInput(resourceAssignment) - if (value == null || value is MissingNode || value is NullNode) { + val value = raRuntimeService.getInputValue(resourceAssignment.name) + if (ResourceAssignmentUtils.checkIfInputWasProvided(resourceAssignment, value)) { + ResourceAssignmentUtils.setInputValueIfProvided(resourceAssignment, raRuntimeService, value) + } + else { val dName = resourceAssignment.dictionaryName!! val dSource = resourceAssignment.dictionarySource!! val resourceDefinition = resourceDefinition(dName) @@ -126,7 +126,7 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS val dName = resourceAssignment.dictionaryName val dSource = resourceAssignment.dictionarySource val type = nullToEmpty(resourceAssignment.property?.type) - lateinit var entrySchemaType: String + val metadata = resourceAssignment.property!!.metadata val outputKeyMapping = checkNotNull(sourceProperties.outputKeyMapping) { "failed to get output-key-mappings for $dName under $dSource properties" @@ -136,12 +136,10 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS val responseNode = checkNotNull(JacksonUtils.jsonNode(restResponse).at(path)) { "Failed to find path ($path) in response ($restResponse)" } - if (resourceAssignment.dictionarySource in DATA_DICTIONARY_SECRET_SOURCE_TYPES) { - logger.info("populating value for output mapping ($outputKeyMapping), from json (*************)") - } - else { - logger.info("populating value for output mapping ($outputKeyMapping), from json ($responseNode)") - } + + val valueToPrint = ResourceAssignmentUtils.getValueToLog(metadata, responseNode) + logger.info("populating value for output mapping ($outputKeyMapping), from json ($valueToPrint)") + val parsedResponseNode = ResourceAssignmentUtils.parseResponseNode(responseNode, resourceAssignment, raRuntimeService, outputKeyMapping) diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt index 819246b99..7854aa49a 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt @@ -71,15 +71,11 @@ class ResourceAssignmentUtils { try { if (resourceProp.type.isNotEmpty()) { - if (resourceAssignment.dictionarySource in ResourceResolutionConstants.DATA_DICTIONARY_SECRET_SOURCE_TYPES) { - logger.info("Setting Resource Value (*********) for Resource Name " + - "(${resourceAssignment.name}) of type (${resourceProp.type})") - } - else { - logger.info("Setting Resource Value ($value) for Resource Name " + - "(${resourceAssignment.name}), definition(${resourceAssignment.dictionaryName}) " + - "of type (${resourceProp.type})") - } + val metadata = resourceAssignment.property!!.metadata + val valueToPrint = getValueToLog(metadata, value) + logger.info("Setting Resource Value ($valueToPrint) for Resource Name " + + "(${resourceAssignment.name}), definition(${resourceAssignment.dictionaryName}) " + + "of type (${resourceProp.type})") setResourceValue(resourceAssignment, raRuntimeService, value) resourceAssignment.updatedDate = Date() resourceAssignment.updatedBy = BluePrintConstants.USER_SYSTEM @@ -110,6 +106,22 @@ class ResourceAssignmentUtils { } @Throws(BluePrintProcessorException::class) + fun setInputValueIfProvided(resourceAssignment: ResourceAssignment, + raRuntimeService: ResourceAssignmentRuntimeService, value: JsonNode) { + logger.info("${resourceAssignment.dictionarySource} source template key (${resourceAssignment.name}) " + + "found from input and value is ($value)") + try { + ResourceAssignmentUtils.setResourceDataValue(resourceAssignment, raRuntimeService, value) + } + catch (e: Exception) { + throw BluePrintProcessorException("Failed to set input value in resource name " + + "(${resourceAssignment.name}) and dictionary key (${resourceAssignment.dictionaryName}) of " + + "type (${resourceAssignment.property!!.type}) with error message (${e.message})", e) + } + + } + + @Throws(BluePrintProcessorException::class) fun assertTemplateKeyValueNotNull(resourceAssignment: ResourceAssignment) { val resourceProp = checkNotNull(resourceAssignment.property) { "Failed to populate mandatory resource resource mapping $resourceAssignment" @@ -128,27 +140,24 @@ class ResourceAssignmentUtils { val mapper = ObjectMapper() val root: ObjectNode = mapper.createObjectNode() - var containsSecret = false + var containsLogProtected = false assignments.forEach { if (isNotEmpty(it.name) && it.property != null) { val rName = it.name + val metadata = it.property!!.metadata val type = nullToEmpty(it.property?.type).toLowerCase() val value = useDefaultValueIfNull(it, rName) - if (it.dictionarySource in ResourceResolutionConstants.DATA_DICTIONARY_SECRET_SOURCE_TYPES) { - logger.info("Generating Resource name ($rName), type ($type), value (************)") - containsSecret = true - } - else { - logger.info("Generating Resource name ($rName), type ($type), value ($value)") + val valueToPrint = getValueToLog(metadata, value) + if (checkIfLogIsProtected(metadata)) { + containsLogProtected = true } + logger.trace("Generating Resource name ($rName), type ($type), value ($valueToPrint)") root.set(rName, value) } } result = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(root) - if (containsSecret) { - logger.info("Generated Resource Param Data (***********)") - } - else{ + + if (!containsLogProtected) { logger.info("Generated Resource Param Data ($result)") } } catch (e: Exception) { @@ -164,14 +173,12 @@ class ResourceAssignmentUtils { assignments.forEach { if (isNotEmpty(it.name) && it.property != null) { val rName = it.name + val metadata = it.property!!.metadata val type = nullToEmpty(it.property?.type).toLowerCase() val value = useDefaultValueIfNull(it, rName) - if (it.dictionarySource in ResourceResolutionConstants.DATA_DICTIONARY_SECRET_SOURCE_TYPES) { - logger.trace("Generating Resource name ($rName), type ($type), value (************)") - } - else { - logger.trace("Generating Resource name ($rName), type ($type), value ($value)") - } + val valueToPrint = getValueToLog(metadata, value) + + logger.trace("Generating Resource name ($rName), type ($type), value ($valueToPrint)") data[rName] = value } } @@ -218,19 +225,17 @@ class ResourceAssignmentUtils { @Throws(BluePrintProcessorException::class) fun parseResponseNode(responseNode: JsonNode, resourceAssignment: ResourceAssignment, raRuntimeService: ResourceAssignmentRuntimeService, outputKeyMapping: MutableMap<String, String>): JsonNode { + val metadata = resourceAssignment.property!!.metadata try { if ((resourceAssignment.property?.type).isNullOrEmpty()) { throw BluePrintProcessorException("Couldn't get data dictionary type for dictionary name (${resourceAssignment.name})") } val type = resourceAssignment.property!!.type - if (resourceAssignment.dictionarySource in ResourceResolutionConstants.DATA_DICTIONARY_SECRET_SOURCE_TYPES) { - logger.info("For template key (${resourceAssignment.name}) setting value as (***************)") - } - else { - logger.info("For template key (${resourceAssignment.name}) setting value as ($responseNode)") - } - + val valueToPrint = getValueToLog(metadata, responseNode) + + logger.info("For template key (${resourceAssignment.name}) setting value as ($valueToPrint)") + return when (type) { in BluePrintTypes.validPrimitiveTypes() -> { parseResponseNodeForPrimitiveTypes(responseNode, outputKeyMapping) @@ -255,7 +260,7 @@ class ResourceAssignmentUtils { var result: JsonNode? = responseNode if (responseNode.isComplexType()) { val key = outputKeyMapping.keys.firstOrNull() - var returnNode: JsonNode? = responseNode + var returnNode: JsonNode? if (responseNode is ArrayNode) { val arrayNode = responseNode.toList() val firstElement = if (key.isNullOrEmpty()) { @@ -267,22 +272,30 @@ class ResourceAssignmentUtils { } } - if (firstElement.isNull() || (firstElement!!.isComplexType() && !firstElement!!.has(outputKeyMapping[key])) - || (!result!!.isComplexType() && result is NullNode)) { - if (key.isNullOrEmpty()) { - throw BluePrintProcessorException("Fail to find mapping in the responseNode.") - } - else { - throw BluePrintProcessorException("Fail to find response with output key mapping ($key) in result.") - } - } returnNode = firstElement } - result = if (returnNode!!.isComplexType()) { + else{ + returnNode = responseNode + } + + if (returnNode.isNull() || (returnNode!!.isComplexType() && !returnNode.has(outputKeyMapping[key]))) { + if (key.isNullOrEmpty()) { + throw BluePrintProcessorException("Fail to find mapping in the responseNode.") + } + else { + throw BluePrintProcessorException("Fail to find response with output key mapping ($key) in result.") + } + } + result = if (returnNode.isComplexType()) { returnNode[outputKeyMapping[key]] } else { - returnNode + responseNode + } + } + else { + if (outputKeyMapping.isNotEmpty()) { + throw BluePrintProcessorException("Fail to find key-value in response node to map output-key-mapping.") } } return result!! @@ -292,7 +305,8 @@ class ResourceAssignmentUtils { raRuntimeService: ResourceAssignmentRuntimeService, outputKeyMapping: MutableMap<String, String>): JsonNode { val dName = resourceAssignment.dictionaryName - val dSource = resourceAssignment.dictionarySource + val metadata = resourceAssignment.property!!.metadata + var resultNode: JsonNode if ((resourceAssignment.property?.entrySchema?.type).isNullOrEmpty()) { throw BluePrintProcessorException("Couldn't get data type for dictionary type " + "(${resourceAssignment.property!!.type}) and dictionary name ($dName)") @@ -300,22 +314,20 @@ class ResourceAssignmentUtils { val entrySchemaType = resourceAssignment.property!!.entrySchema!!.type var arrayNode = JacksonUtils.objectMapper.createArrayNode() - if (outputKeyMapping.isNotEmpty()) { when (responseNode) { is ArrayNode -> { val responseArrayNode = responseNode.toList() for (responseSingleJsonNode in responseArrayNode) { - val arrayChildNode = parseArrayNodeElementWithOutputKeyMapping(raRuntimeService, responseSingleJsonNode, - outputKeyMapping, entrySchemaType, dSource!!) + val arrayChildNode = parseSingleElementOfArrayResponseNode(entrySchemaType, + outputKeyMapping, raRuntimeService, responseSingleJsonNode, metadata) arrayNode.add(arrayChildNode) } + resultNode = arrayNode } is ObjectNode -> { val responseArrayNode = responseNode.rootFieldsToMap() - val arrayNodeResult = parseObjectNodeWithOutputKeyMapping(responseArrayNode, - outputKeyMapping, entrySchemaType, dSource!!) - arrayNode.addAll(arrayNodeResult) + resultNode = parseObjectResponseNode(entrySchemaType, outputKeyMapping, responseArrayNode, metadata) } else -> { throw BluePrintProcessorException("Key-value response expected to match the responseNode.") @@ -328,121 +340,196 @@ class ResourceAssignmentUtils { responseNode.forEach { elementNode -> arrayNode.add(elementNode) } + resultNode = arrayNode } is ObjectNode -> { val responseArrayNode = responseNode.rootFieldsToMap() for ((key, responseSingleJsonNode) in responseArrayNode) { val arrayChildNode = JacksonUtils.objectMapper.createObjectNode() + logKeyValueResolvedResource(metadata, key, responseSingleJsonNode, entrySchemaType) JacksonUtils.populateJsonNodeValues(key, responseSingleJsonNode, entrySchemaType, arrayChildNode) arrayNode.add(arrayChildNode) } + resultNode = arrayNode } else -> { - arrayNode.add(responseNode) + resultNode = responseNode } } } - return arrayNode - } - private fun parseResponseNodeForComplexType(responseNode: JsonNode, resourceAssignment: ResourceAssignment, - raRuntimeService: ResourceAssignmentRuntimeService, - outputKeyMapping: MutableMap<String, String>): JsonNode { - val entrySchemaType = resourceAssignment.property!!.type - val dictionarySource = resourceAssignment.dictionarySource!! - val dictionaryName = resourceAssignment.dictionaryName!! + return resultNode + } - var result: ObjectNode - if (checkOutputKeyMappingInDataTypeProperties(entrySchemaType, outputKeyMapping, raRuntimeService)) - { - result = parseArrayNodeElementWithOutputKeyMapping(raRuntimeService, responseNode, outputKeyMapping, entrySchemaType, dictionarySource!!) - } - else { - val childNode = JacksonUtils.objectMapper.createObjectNode() - if (outputKeyMapping.isNotEmpty()) { - outputKeyMapping.map { - val responseKeyValue = if (responseNode.has(it.key)) { - responseNode.get(it.key) + private fun parseSingleElementOfArrayResponseNode(entrySchemaType: String, outputKeyMapping: MutableMap<String, String>, + raRuntimeService: ResourceAssignmentRuntimeService, + responseNode: JsonNode, metadata: MutableMap<String, String>?): ObjectNode { + val outputKeyMappingHasOnlyOneElement = checkIfOutputKeyMappingProvideOneElement(outputKeyMapping) + when (entrySchemaType) { + in BluePrintTypes.validPrimitiveTypes() -> { + if (outputKeyMappingHasOnlyOneElement) { + val outputKeyMap = outputKeyMapping.entries.first() + return parseSingleElementNodeWithOneOutputKeyMapping(responseNode, outputKeyMap.key, outputKeyMap.value, entrySchemaType, metadata) + } + else { + throw BluePrintProcessorException("Expect one entry in output-key-mapping") + } + } + else -> { + return when { + checkOutputKeyMappingAllElementsInDataTypeProperties(entrySchemaType, outputKeyMapping, raRuntimeService) -> { + parseSingleElementNodeWithAllOutputKeyMapping(responseNode, outputKeyMapping, entrySchemaType, metadata) } - else { - NullNode.getInstance() + outputKeyMappingHasOnlyOneElement -> { + val outputKeyMap = outputKeyMapping.entries.first() + parseSingleElementNodeWithOneOutputKeyMapping(responseNode, outputKeyMap.key, outputKeyMap.value, entrySchemaType, metadata) + } + else -> { + throw BluePrintProcessorException("Output-key-mapping do not map the Data Type $entrySchemaType") } - - logKeyValueResolvedResource(it.key, responseKeyValue, entrySchemaType, dictionarySource) - - JacksonUtils.populateJsonNodeValues(it.value, - responseKeyValue, entrySchemaType, childNode) } } - else { - JacksonUtils.populateJsonNodeValues(dictionaryName, responseNode, entrySchemaType, childNode) - } - result = childNode } - return result } - private fun parseArrayNodeElementWithOutputKeyMapping(raRuntimeService: ResourceAssignmentRuntimeService, - responseSingleJsonNode: JsonNode, outputKeyMapping: - MutableMap<String, String>, entrySchemaType: String, - dictionarySource: String): ObjectNode { + private fun parseObjectResponseNode(entrySchemaType: String, outputKeyMapping: MutableMap<String, String>, + responseArrayNode: MutableMap<String, JsonNode>, metadata: MutableMap<String, String>?): ObjectNode { + val outputKeyMappingHasOnlyOneElement = checkIfOutputKeyMappingProvideOneElement(outputKeyMapping) + if (outputKeyMappingHasOnlyOneElement) { + val outputKeyMap = outputKeyMapping.entries.first() + return parseObjectResponseNodeWithOneOutputKeyMapping(responseArrayNode, outputKeyMap.key, outputKeyMap.value, + entrySchemaType, metadata) + } + else { + throw BluePrintProcessorException("Output-key-mapping do not map the Data Type $entrySchemaType") + } + } + + private fun parseSingleElementNodeWithOneOutputKeyMapping(responseSingleJsonNode: JsonNode, outputKeyMappingKey: + String, outputKeyMappingValue: String, type: String, metadata: MutableMap<String, String>?): ObjectNode { val arrayChildNode = JacksonUtils.objectMapper.createObjectNode() + val responseKeyValue = if (responseSingleJsonNode.has(outputKeyMappingValue)) { + responseSingleJsonNode.get(outputKeyMappingValue) + } + else { + NullNode.getInstance() + } + + logKeyValueResolvedResource(metadata, outputKeyMappingKey, responseKeyValue, type) + JacksonUtils.populateJsonNodeValues(outputKeyMappingKey, responseKeyValue, type, arrayChildNode) + + return arrayChildNode + } + + private fun parseSingleElementNodeWithAllOutputKeyMapping(responseSingleJsonNode: JsonNode, + outputKeyMapping: MutableMap<String, String>, + type: String, metadata: MutableMap<String, String>?): ObjectNode { + val arrayChildNode = JacksonUtils.objectMapper.createObjectNode() outputKeyMapping.map { - val responseKeyValue = if (responseSingleJsonNode.has(it.key)) { - responseSingleJsonNode.get(it.key) - } - else { + val responseKeyValue = if (responseSingleJsonNode.has(it.value)) { + responseSingleJsonNode.get(it.value) + } else { NullNode.getInstance() } - val propertyTypeForDataType = ResourceAssignmentUtils - .getPropertyType(raRuntimeService, entrySchemaType, it.key) - - logKeyValueResolvedResource(it.key, responseKeyValue, propertyTypeForDataType, dictionarySource) - JacksonUtils.populateJsonNodeValues(it.value, - responseKeyValue, propertyTypeForDataType, arrayChildNode) + logKeyValueResolvedResource(metadata, it.key, responseKeyValue, type) + JacksonUtils.populateJsonNodeValues(it.key, responseKeyValue, type, arrayChildNode) } return arrayChildNode } - private fun parseObjectNodeWithOutputKeyMapping(responseArrayNode: MutableMap<String, JsonNode>, - outputKeyMapping: MutableMap<String, String>, - entrySchemaType: String, - dictionarySource: String): ArrayNode { - val arrayNode = JacksonUtils.objectMapper.createArrayNode() - outputKeyMapping.map { - val objectNode = JacksonUtils.objectMapper.createObjectNode() - val responseSingleJsonNode = responseArrayNode.filterKeys { key -> key == it.key }.entries.firstOrNull() - - val responseNode = responseSingleJsonNode?.value ?: NullNode.getInstance() + private fun parseObjectResponseNodeWithOneOutputKeyMapping(responseArrayNode: MutableMap<String, JsonNode>, + outputKeyMappingKey: String, outputKeyMappingValue: String, + type: String, metadata: MutableMap<String, String>?): ObjectNode { + val objectNode = JacksonUtils.objectMapper.createObjectNode() + val responseSingleJsonNode = responseArrayNode.filterKeys { key -> + key == outputKeyMappingValue }.entries.firstOrNull() - logKeyValueResolvedResource(it.key, responseNode, entrySchemaType, dictionarySource) + if (responseSingleJsonNode == null) { + logKeyValueResolvedResource(metadata, outputKeyMappingKey, NullNode.getInstance(), type) + JacksonUtils.populateJsonNodeValues(outputKeyMappingKey, NullNode.getInstance(), type, objectNode) + } + else + { + logKeyValueResolvedResource(metadata, outputKeyMappingKey, responseSingleJsonNode.value, type) + JacksonUtils.populateJsonNodeValues(outputKeyMappingKey, responseSingleJsonNode.value, type, objectNode) + } + return objectNode + } - JacksonUtils.populateJsonNodeValues(it.value, responseNode, entrySchemaType, objectNode) + private fun parseResponseNodeForComplexType(responseNode: JsonNode, resourceAssignment: ResourceAssignment, + raRuntimeService: ResourceAssignmentRuntimeService, + outputKeyMapping: MutableMap<String, String>): JsonNode { + val entrySchemaType = resourceAssignment.property!!.type + val dictionaryName = resourceAssignment.dictionaryName!! + val metadata = resourceAssignment.property!!.metadata + val outputKeyMappingHasOnlyOneElement = checkIfOutputKeyMappingProvideOneElement(outputKeyMapping) - arrayNode.add(objectNode) + if (outputKeyMapping.isNotEmpty()) { + return when { + checkOutputKeyMappingAllElementsInDataTypeProperties(entrySchemaType, outputKeyMapping, raRuntimeService) -> { + parseSingleElementNodeWithAllOutputKeyMapping(responseNode, outputKeyMapping, entrySchemaType, metadata) + } + outputKeyMappingHasOnlyOneElement -> { + val outputKeyMap = outputKeyMapping.entries.first() + parseSingleElementNodeWithOneOutputKeyMapping(responseNode, outputKeyMap.key, outputKeyMap.value, + entrySchemaType, metadata) + } + else -> { + throw BluePrintProcessorException("Output-key-mapping do not map the Data Type $entrySchemaType") + } + } + } + else { + val childNode = JacksonUtils.objectMapper.createObjectNode() + JacksonUtils.populateJsonNodeValues(dictionaryName, responseNode, entrySchemaType, childNode) + return childNode } - - return arrayNode } - private fun checkOutputKeyMappingInDataTypeProperties(dataTypeName: String, outputKeyMapping: MutableMap<String, String>, - raRuntimeService: ResourceAssignmentRuntimeService): Boolean { + private fun checkOutputKeyMappingAllElementsInDataTypeProperties(dataTypeName: String, outputKeyMapping: MutableMap<String, String>, + raRuntimeService: ResourceAssignmentRuntimeService): Boolean { val dataTypeProps = raRuntimeService.bluePrintContext().dataTypeByName(dataTypeName)?.properties val result = outputKeyMapping.filterKeys { !dataTypeProps!!.containsKey(it) }.keys.firstOrNull() return result == null } - private fun logKeyValueResolvedResource(key: String, value: JsonNode, type: String, dictionarySource: String) { - if (dictionarySource in ResourceResolutionConstants.DATA_DICTIONARY_SECRET_SOURCE_TYPES) { - logger.info("For List Type Resource: key ($key), value (****************), " + - "type ({$type})") + private fun logKeyValueResolvedResource(metadata: MutableMap<String, String>?, key: String, value: JsonNode, type: String) { + val valueToPrint = getValueToLog(metadata, value) + + logger.info("For List Type Resource: key ($key), value ($valueToPrint), " + + "type ({$type})") + } + + private fun checkIfOutputKeyMappingProvideOneElement(outputKeyMapping: MutableMap<String, String>): Boolean { + return (outputKeyMapping.size == 1) + } + + fun getValueToLog(metadata: MutableMap<String, String>?, value: Any): Any { + return if (checkIfLogIsProtected(metadata)) { + "*************" } - else { - logger.info("For List Type Resource: key ($key), value ($value), " + - "type ({$type})") + else{ + value + } + } + + fun checkIfInputWasProvided(resourceAssignment: ResourceAssignment, value: JsonNode) : Boolean{ + val defaultValueNode = resourceAssignment.property!!.defaultValue.asJsonType() + return (value.returnNullIfMissing() != null && value != defaultValueNode) + } + + private fun checkIfLogIsProtected(metadata: MutableMap<String, String>?) : Boolean { + var checkProtected = false + if (metadata != null && + metadata.containsKey(ResourceResolutionConstants.RESOURCE_RESOLUTION_LOG_PROTECTED_METADATA)) { + val protectedMetadata = metadata[ResourceResolutionConstants.RESOURCE_RESOLUTION_LOG_PROTECTED_METADATA] + if (protectedMetadata == "yes" || protectedMetadata == "y") { + checkProtected = true + } } + return checkProtected } } }
\ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt index 9365c3e34..728e1165a 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt @@ -22,7 +22,6 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils import com.fasterxml.jackson.databind.JsonNode -import com.fasterxml.jackson.databind.node.NullNode import com.fasterxml.jackson.databind.node.TextNode import io.mockk.every import io.mockk.spyk @@ -42,11 +41,25 @@ import kotlin.test.assertEquals data class IpAddress(val port: String, val ip: String) data class Host(val name: String, val ipAddress: IpAddress) data class ExpectedResponseIp(val ip: String) -data class ExpectedResponsePort(val port: String) +data class ExpectedResponseIpAddress(val ipAddress: IpAddress) class ResourceAssignmentUtilsTest { private lateinit var resourceAssignmentRuntimeService: ResourceAssignmentRuntimeService + private lateinit var inputMapToTestPrimitiveTypeWithValue: JsonNode + private lateinit var inputMapToTestPrimitiveTypeWithKeyValue: JsonNode + private lateinit var inputMapToTestCollectionOfPrimitiveType: JsonNode + private lateinit var inputMapToTestCollectionOfComplexTypeWithOneOutputKeyMapping: JsonNode + private lateinit var inputMapToTestCollectionOfComplexTypeWithAllOutputKeyMapping: JsonNode + private lateinit var inputMapToTestComplexTypeWithOneOutputKeyMapping: JsonNode + private lateinit var inputMapToTestComplexTypeWithAllOutputKeyMapping: JsonNode + private lateinit var expectedValueToTestPrimitiveType: JsonNode + private lateinit var expectedValueToTesCollectionOfPrimitiveType: JsonNode + private lateinit var expectedValueToTestCollectionOfComplexTypeWithOneOutputKeyMapping: JsonNode + private lateinit var expectedValueToTestComplexTypeWithOneOutputKeyMapping: JsonNode + private lateinit var expectedValueToTestComplexTypeWithAllOutputKeyMapping: JsonNode + private lateinit var expectedValueToTestCollectionOfComplexTypeWithAllOutputKeyMapping: JsonNode + @Before fun setup() { @@ -55,6 +68,11 @@ class ResourceAssignmentUtilsTest { resourceAssignmentRuntimeService = spyk(ResourceAssignmentRuntimeService("1234", bluePrintContext)) + //Init input map and expected values for tests + initInputMapAndExpectedValuesForPrimitiveType() + initInputMapAndExpectedValuesForCollection() + initInputMapAndExpectedValuesForComplexType() + val propertiesDefinition1 = PropertyDefinition().apply { type = "string" id = "port" @@ -149,146 +167,127 @@ class ResourceAssignmentUtilsTest { @Test fun parseResponseNodeTestForPrimitivesTypes(){ - // Input values for primitive type - val keyValue = mutableMapOf<String, String>() - keyValue["value"]= "1.2.3.1" - val expectedPrimitiveType = TextNode("1.2.3.1") + var outcome = prepareResponseNodeForTest("sample-value", "string", "", + inputMapToTestPrimitiveTypeWithValue) + assertEquals(expectedValueToTestPrimitiveType, outcome, "Unexpected outcome returned for primitive type of simple String") - var outcome = prepareResponseNodeForTest("sample-value", "string", - "", "1.2.3.1".asJsonPrimitive()) - assertEquals(expectedPrimitiveType, outcome, "Unexpected outcome returned for primitive type of simple String") - outcome = prepareResponseNodeForTest("sample-key-value", "string", "", keyValue) - assertEquals(expectedPrimitiveType, outcome, "Unexpected outcome returned for primitive type of key-value String") + outcome = prepareResponseNodeForTest("sample-key-value", "string", "", + inputMapToTestPrimitiveTypeWithKeyValue) + assertEquals(expectedValueToTestPrimitiveType, outcome, "Unexpected outcome returned for primitive type of key-value String") } @Test fun parseResponseNodeTestForCollectionsOfString(){ - // Input values for collection type - val mapOfString = mutableMapOf<String, String>() - mapOfString["value1"] = "1.2.3.1" - mapOfString["port"] = "8888" - mapOfString["value2"] = "1.2.3.2" - val arrayOfKeyValue = arrayListOf(ExpectedResponseIp("1.2.3.1"), - ExpectedResponsePort( "8888"), ExpectedResponseIp("1.2.3.2")) - - val mutableMapKeyValue = mutableMapOf<String, String>() - mutableMapKeyValue["value1"] = "1.2.3.1" - mutableMapKeyValue["port"] = "8888" - - //List - val expectedListOfString = arrayOfKeyValue.asJsonType() var outcome = prepareResponseNodeForTest("listOfString", "list", - "string", mapOfString.asJsonType()) - assertEquals(expectedListOfString, outcome, "unexpected outcome returned for list of String") + "string", inputMapToTestCollectionOfPrimitiveType) + assertEquals(expectedValueToTesCollectionOfPrimitiveType, outcome, "unexpected outcome returned for list of String") - //Map - val expectedMapOfString = mutableMapOf<String, JsonNode>() - expectedMapOfString["ip"] = "1.2.3.1".asJsonPrimitive() - expectedMapOfString["port"] = "8888".asJsonPrimitive() - - val arrayNode = JacksonUtils.objectMapper.createArrayNode() - expectedMapOfString.map { - val arrayChildNode = JacksonUtils.objectMapper.createObjectNode() - arrayChildNode.set(it.key, it.value) - arrayNode.add(arrayChildNode) - } - val arrayChildNode1 = JacksonUtils.objectMapper.createObjectNode() - arrayChildNode1.set("ip", NullNode.getInstance()) - arrayNode.add(arrayChildNode1) outcome = prepareResponseNodeForTest("mapOfString", "map", "string", - mutableMapKeyValue.asJsonType()) - assertEquals(arrayNode, outcome, "unexpected outcome returned for map of String") - } - - @Test - fun parseResponseNodeTestForCollectionsOfJsonNode(){ - // Input values for collection type - val mapOfString = mutableMapOf<String, JsonNode>() - mapOfString["value1"] = "1.2.3.1".asJsonPrimitive() - mapOfString["port"] = "8888".asJsonPrimitive() - mapOfString["value2"] = "1.2.3.2".asJsonPrimitive() - val arrayOfKeyValue = arrayListOf(ExpectedResponseIp("1.2.3.1"), - ExpectedResponsePort( "8888"), ExpectedResponseIp("1.2.3.2")) - - val mutableMapKeyValue = mutableMapOf<String, JsonNode>() - mutableMapKeyValue["value1"] = "1.2.3.1".asJsonPrimitive() - mutableMapKeyValue["port"] = "8888".asJsonPrimitive() - - //List - val expectedListOfString = arrayOfKeyValue.asJsonType() - var outcome = prepareResponseNodeForTest("listOfString", "list", - "string", mapOfString.asJsonType()) - assertEquals(expectedListOfString, outcome, "unexpected outcome returned for list of String") - - //Map - val expectedMapOfString = mutableMapOf<String, JsonNode>() - expectedMapOfString["ip"] = "1.2.3.1".asJsonPrimitive() - expectedMapOfString["port"] = "8888".asJsonPrimitive() - val arrayNode = JacksonUtils.objectMapper.createArrayNode() - expectedMapOfString.map { - val arrayChildNode = JacksonUtils.objectMapper.createObjectNode() - arrayChildNode.set(it.key, it.value) - arrayNode.add(arrayChildNode) - } - val arrayChildNode1 = JacksonUtils.objectMapper.createObjectNode() - arrayChildNode1.set("ip", NullNode.getInstance()) - arrayNode.add(arrayChildNode1) - outcome = prepareResponseNodeForTest("mapOfString", "map", - "string", mutableMapKeyValue.asJsonType()) - assertEquals(arrayNode, outcome, "unexpected outcome returned for map of String") + inputMapToTestCollectionOfPrimitiveType) + assertEquals(expectedValueToTesCollectionOfPrimitiveType, outcome, "unexpected outcome returned for map of String") } @Test fun parseResponseNodeTestForCollectionsOfComplexType(){ - // Input values for collection type - val mapOfComplexType = mutableMapOf<String, JsonNode>() - mapOfComplexType["value1"] = IpAddress("1111", "1.2.3.1").asJsonType() - mapOfComplexType["value2"] = IpAddress("2222", "1.2.3.2").asJsonType() - mapOfComplexType["value3"] = IpAddress("3333", "1.2.3.3").asJsonType() + var outcome = prepareResponseNodeForTest("listOfMyDataTypeWithOneOutputKeyMapping", "list", + "ip-address", inputMapToTestCollectionOfComplexTypeWithOneOutputKeyMapping) + assertEquals(expectedValueToTestCollectionOfComplexTypeWithOneOutputKeyMapping, outcome, "unexpected outcome returned for list of String") - //List - val arrayNode = JacksonUtils.objectMapper.createArrayNode() - mapOfComplexType.map { - val arrayChildNode = JacksonUtils.objectMapper.createObjectNode() - arrayChildNode.set("ipAddress", it.value) - arrayNode.add(arrayChildNode) - } - var outcome = prepareResponseNodeForTest("listOfMyDataType", "list", - "ip-address", mapOfComplexType.asJsonType()) - assertEquals(arrayNode, outcome, "unexpected outcome returned for list of String") + outcome = prepareResponseNodeForTest("listOfMyDataTypeWithAllOutputKeyMapping", "list", + "ip-address", inputMapToTestCollectionOfComplexTypeWithAllOutputKeyMapping) + assertEquals(expectedValueToTestCollectionOfComplexTypeWithAllOutputKeyMapping, outcome, "unexpected outcome returned for list of String") } @Test fun `parseResponseNodeTestForComplexType find one output key mapping`(){ - // Input values for complex type - val objectNode = JacksonUtils.objectMapper.createObjectNode() - - // Input values for collection type - val mapOfComplexType = mutableMapOf<String, JsonNode>() - mapOfComplexType["value"] = Host("my-ipAddress", IpAddress("1111", "1.2.3.1")).asJsonType() - mapOfComplexType["port"] = "8888".asJsonType() - mapOfComplexType["something"] = "1.2.3.2".asJsonType() - - val expectedComplexType = objectNode.set("ipAddress", Host("my-ipAddress", IpAddress("1111", "1.2.3.1")).asJsonType()) val outcome = prepareResponseNodeForTest("complexTypeOneKeys", "host", - "", mapOfComplexType.asJsonType()) - assertEquals(expectedComplexType, outcome, "Unexpected outcome returned for complex type") + "", inputMapToTestComplexTypeWithOneOutputKeyMapping) + assertEquals(expectedValueToTestComplexTypeWithOneOutputKeyMapping, outcome, "Unexpected outcome returned for complex type") } @Test fun `parseResponseNodeTestForComplexType find all output key mapping`(){ - // Input values for complex type - val objectNode = JacksonUtils.objectMapper.createObjectNode() + val outcome = prepareResponseNodeForTest("complexTypeAllKeys", "host", + "", inputMapToTestComplexTypeWithAllOutputKeyMapping) + assertEquals(expectedValueToTestComplexTypeWithAllOutputKeyMapping, outcome, "Unexpected outcome returned for complex type") + } + + private fun initInputMapAndExpectedValuesForPrimitiveType() { + inputMapToTestPrimitiveTypeWithValue = "1.2.3.1".asJsonType() + val keyValue = mutableMapOf<String, String>() + keyValue["value"]= "1.2.3.1" + inputMapToTestPrimitiveTypeWithKeyValue = keyValue.asJsonType() + expectedValueToTestPrimitiveType = TextNode("1.2.3.1") + } + + private fun initInputMapAndExpectedValuesForCollection(){ + val listOfIps = arrayListOf("1.2.3.1", "1.2.3.2", "1.2.3.3") + val arrayNodeForList1 = JacksonUtils.objectMapper.createArrayNode() + listOfIps.forEach { + val arrayChildNode = JacksonUtils.objectMapper.createObjectNode() + arrayChildNode.set("value", it.asJsonPrimitive()) + arrayNodeForList1.add(arrayChildNode) + } + inputMapToTestCollectionOfPrimitiveType = arrayNodeForList1 + + expectedValueToTesCollectionOfPrimitiveType = arrayListOf(ExpectedResponseIp("1.2.3.1"), + ExpectedResponseIp( "1.2.3.2"), ExpectedResponseIp("1.2.3.3")).asJsonType() + - // Input values for collection type + val listOfIpAddresses = arrayListOf(IpAddress("1111", "1.2.3.1").asJsonType(), + IpAddress("2222", "1.2.3.2").asJsonType(), IpAddress("3333", "1.2.3.3").asJsonType()) + val arrayNodeForList2 = JacksonUtils.objectMapper.createArrayNode() + listOfIpAddresses.forEach { + val arrayChildNode = JacksonUtils.objectMapper.createObjectNode() + arrayChildNode.set("value", it.asJsonType()) + arrayNodeForList2.add(arrayChildNode) + } + inputMapToTestCollectionOfComplexTypeWithOneOutputKeyMapping = arrayNodeForList2 + + val arrayNodeForList3 = JacksonUtils.objectMapper.createArrayNode() + var childNode = JacksonUtils.objectMapper.createObjectNode() + childNode.set("port", "1111".asJsonPrimitive()) + childNode.set("ip", "1.2.3.1".asJsonPrimitive()) + arrayNodeForList3.add(childNode) + childNode = JacksonUtils.objectMapper.createObjectNode() + childNode.set("port", "2222".asJsonPrimitive()) + childNode.set("ip", "1.2.3.2".asJsonPrimitive()) + arrayNodeForList3.add(childNode) + childNode = JacksonUtils.objectMapper.createObjectNode() + childNode.set("port", "3333".asJsonPrimitive()) + childNode.set("ip", "1.2.3.3".asJsonPrimitive()) + arrayNodeForList3.add(childNode) + inputMapToTestCollectionOfComplexTypeWithAllOutputKeyMapping = arrayNodeForList3 + + expectedValueToTestCollectionOfComplexTypeWithOneOutputKeyMapping = arrayListOf(ExpectedResponseIpAddress(IpAddress("1111", "1.2.3.1")), + ExpectedResponseIpAddress(IpAddress("2222", "1.2.3.2")), ExpectedResponseIpAddress( + IpAddress("3333", "1.2.3.3"))).asJsonType() + expectedValueToTestCollectionOfComplexTypeWithAllOutputKeyMapping = arrayListOf(IpAddress("1111", "1.2.3.1"), + IpAddress("2222", "1.2.3.2"), + IpAddress("3333", "1.2.3.3")).asJsonType() + } + + private fun initInputMapAndExpectedValuesForComplexType(){ val mapOfComplexType = mutableMapOf<String, JsonNode>() - mapOfComplexType["name"] = "my-ipAddress".asJsonType() - mapOfComplexType["ipAddress"] = IpAddress("1111", "1.2.3.1").asJsonType() + mapOfComplexType["value"] = Host("my-ipAddress", IpAddress("1111", "1.2.3.1")).asJsonType() + mapOfComplexType["port"] = "8888".asJsonType() + mapOfComplexType["something"] = "1.2.3.2".asJsonType() + inputMapToTestComplexTypeWithOneOutputKeyMapping = mapOfComplexType.asJsonType() - val expectedComplexType = Host("my-ipAddress", IpAddress("1111", "1.2.3.1")).asJsonType() - val outcome = prepareResponseNodeForTest("complexTypeAllKeys", "host", - "", mapOfComplexType.asJsonType()) - assertEquals(expectedComplexType, outcome, "Unexpected outcome returned for complex type") + val objectNode = JacksonUtils.objectMapper.createObjectNode() + expectedValueToTestComplexTypeWithOneOutputKeyMapping = objectNode.set("host", Host("my-ipAddress", IpAddress("1111", "1.2.3.1")).asJsonType()) + + val childNode1 = JacksonUtils.objectMapper.createObjectNode() + childNode1.set("name", "my-ipAddress".asJsonPrimitive()) + childNode1.set("ipAddress", IpAddress("1111", "1.2.3.1").asJsonType()) + childNode1.set("port", "8888".asJsonType()) + childNode1.set("something", IpAddress("2222", "1.2.3.1").asJsonType()) + inputMapToTestComplexTypeWithAllOutputKeyMapping = childNode1 + + val childNode2 = JacksonUtils.objectMapper.createObjectNode() + childNode2.set("name", "my-ipAddress".asJsonPrimitive()) + childNode2.set("ipAddress", IpAddress("1111", "1.2.3.1").asJsonType()) + expectedValueToTestComplexTypeWithAllOutputKeyMapping = childNode2 } private fun prepareResponseNodeForTest(dictionary_source: String, sourceType: String, entrySchema: String, @@ -355,27 +354,28 @@ class ResourceAssignmentUtilsTest { val outputMapping = mutableMapOf<String, String>() when (dictionary_source) { - "listOfString", "mapOfString" -> { - //List of string - outputMapping["value1"] = "ip" - outputMapping["port"] = "port" - outputMapping["value2"] = "ip" - } - "listOfMyDataType", "mapOfMyDataType" -> { - //List or map of complex Type - outputMapping["value1"] = "ipAddress" - outputMapping["value2"] = "ipAddress" - outputMapping["value3"] = "ipAddress" - } "sample-key-value", "sample-value" -> { //Primary Type if (dictionary_source=="sample-key-value") outputMapping["sample-ip"] = "value" } + "listOfString", "mapOfString" -> { + //List of string + outputMapping["ip"] = "value" + } + "listOfMyDataTypeWithOneOutputKeyMapping", "listOfMyDataTypeWithAllOutputKeyMapping" -> { + //List or map of complex Type + if (dictionary_source == "listOfMyDataTypeWithOneOutputKeyMapping") + outputMapping["ipAddress"] = "value" + else { + outputMapping["port"] = "port" + outputMapping["ip"] = "ip" + } + } else -> { //Complex Type if (dictionary_source == "complexTypeOneKeys") - outputMapping["value"] = "ipAddress" + outputMapping["host"] = "value" else { outputMapping["name"] = "name" outputMapping["ipAddress"] = "ipAddress" |