Improve data type handling 76/84276/1
authorMuthuramalingam, Brinda Santh <brindasanth@in.ibm.com>
Thu, 4 Apr 2019 21:11:01 +0000 (17:11 -0400)
committerMuthuramalingam, Brinda Santh <brindasanth@in.ibm.com>
Thu, 4 Apr 2019 21:11:01 +0000 (17:11 -0400)
Change-Id: I5ebcfcecdf1781e30be1ca929b4bf9e1526691a3
Issue-ID: CCSDK-1127
Signed-off-by: Muthuramalingam, Brinda Santh <brindasanth@in.ibm.com>
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/CustomFunctions.kt

index f17257c..e8b61a8 100644 (file)
@@ -43,7 +43,8 @@ import java.util.*
  */
 @Service("${PREFIX_RESOURCE_RESOLUTION_PROCESSOR}source-processor-db")
 @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
-open class DatabaseResourceAssignmentProcessor(private val bluePrintDBLibPropertySevice: BluePrintDBLibPropertySevice, private val primaryDBLibGenericService: PrimaryDBLibGenericService)
+open class DatabaseResourceAssignmentProcessor(private val bluePrintDBLibPropertySevice: BluePrintDBLibPropertySevice,
+                                               private val primaryDBLibGenericService: PrimaryDBLibGenericService)
     : ResourceAssignmentProcessor() {
 
     private val logger = LoggerFactory.getLogger(DatabaseResourceAssignmentProcessor::class.java)
@@ -84,11 +85,17 @@ open class DatabaseResourceAssignmentProcessor(private val bluePrintDBLibPropert
                 ?: throw BluePrintProcessorException("couldn't get resource dictionary definition for $dName")
         val resourceSource = resourceDefinition.sources[dSource]
                 ?: throw BluePrintProcessorException("couldn't get resource definition $dName source($dSource)")
-        val resourceSourceProperties = checkNotNull(resourceSource.properties) { "failed to get source properties for $dName " }
+        val resourceSourceProperties = checkNotNull(resourceSource.properties) {
+            "failed to get source properties for $dName "
+        }
         val sourceProperties = JacksonUtils.getInstanceFromMap(resourceSourceProperties, DatabaseResourceSource::class.java)
 
-        val sql = checkNotNull(sourceProperties.query) { "failed to get request query for $dName under $dSource properties" }
-        val inputKeyMapping = checkNotNull(sourceProperties.inputKeyMapping) { "failed to get input-key-mappings for $dName under $dSource properties" }
+        val sql = checkNotNull(sourceProperties.query) {
+            "failed to get request query for $dName under $dSource properties"
+        }
+        val inputKeyMapping = checkNotNull(sourceProperties.inputKeyMapping) {
+            "failed to get input-key-mappings for $dName under $dSource properties"
+        }
 
         logger.info("$dSource dictionary information : ($sql), ($inputKeyMapping), (${sourceProperties.outputKeyMapping})")
         val jdbcTemplate = blueprintDBLibService(sourceProperties)
@@ -129,7 +136,7 @@ open class DatabaseResourceAssignmentProcessor(private val bluePrintDBLibPropert
             logger.trace("Reference dictionary key (${it.key}) resulted in value ($expressionValue)")
             namedParameters[it.key] = expressionValue
         }
-        logger.info("Parameter information : ({})", namedParameters)
+        logger.info("Parameter information : ($namedParameters)")
         return namedParameters
     }
 
@@ -139,7 +146,9 @@ open class DatabaseResourceAssignmentProcessor(private val bluePrintDBLibPropert
         val dSource = resourceAssignment.dictionarySource
         val type = nullToEmpty(resourceAssignment.property?.type)
 
-        val outputKeyMapping = checkNotNull(sourceProperties.outputKeyMapping) { "failed to get output-key-mappings for $dName under $dSource properties" }
+        val outputKeyMapping = checkNotNull(sourceProperties.outputKeyMapping) {
+            "failed to get output-key-mappings for $dName under $dSource properties"
+        }
         logger.info("Response processing type($type)")
 
         // Primitive Types
@@ -150,8 +159,10 @@ open class DatabaseResourceAssignmentProcessor(private val bluePrintDBLibPropert
                 ResourceAssignmentUtils.setResourceDataValue(resourceAssignment, raRuntimeService, dbColumnValue)
             }
             in BluePrintTypes.validCollectionTypes() -> {
-                val entrySchemaType = checkNotEmpty(resourceAssignment.property?.entrySchema?.type) { "Entry schema is not defined for dictionary ($dName) info" }
-                val arrayNode = JsonNodeFactory.instance.arrayNode()
+                val entrySchemaType = checkNotEmpty(resourceAssignment.property?.entrySchema?.type) {
+                    "Entry schema is not defined for dictionary ($dName) info"
+                }
+                val arrayNode = JacksonUtils.objectMapper.createArrayNode()
                 rows.forEach {
                     if (entrySchemaType in BluePrintTypes.validPrimitiveTypes()) {
                         val dbColumnValue = it[outputKeyMapping[dName]]
@@ -172,9 +183,9 @@ open class DatabaseResourceAssignmentProcessor(private val bluePrintDBLibPropert
                 ResourceAssignmentUtils.setResourceDataValue(resourceAssignment, raRuntimeService, arrayNode)
             }
             else -> {
-                // Complex Types
+                // Custom Simple Complex Types
                 val row = rows[0]
-                val objectNode = JsonNodeFactory.instance.objectNode()
+                val objectNode = JacksonUtils.objectMapper.createObjectNode()
                 for (mapping in outputKeyMapping.entries) {
                     val dbColumnValue = checkNotNull(row[mapping.key])
                     val propertyTypeForDataType = ResourceAssignmentUtils.getPropertyType(raRuntimeService, type, mapping.key)
index d95d6b6..cd93852 100644 (file)
@@ -18,7 +18,6 @@
 package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor
 
 import com.fasterxml.jackson.databind.node.ArrayNode
-import com.fasterxml.jackson.databind.node.JsonNodeFactory
 import com.fasterxml.jackson.databind.node.MissingNode
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.RestResourceSource
@@ -61,15 +60,20 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS
                 val dSource = resourceAssignment.dictionarySource
                 val resourceDefinition = resourceDictionaries[dName]
                         ?: throw BluePrintProcessorException("couldn't get resource dictionary definition for $dName")
+
                 val resourceSource = resourceDefinition.sources[dSource]
                         ?: throw BluePrintProcessorException("couldn't get resource definition $dName source($dSource)")
+
                 val resourceSourceProperties =
                         checkNotNull(resourceSource.properties) { "failed to get source properties for $dName " }
+
                 val sourceProperties =
                         JacksonUtils.getInstanceFromMap(resourceSourceProperties, RestResourceSource::class.java)
+
                 val path = nullToEmpty(sourceProperties.path)
-                val inputKeyMapping =
-                        checkNotNull(sourceProperties.inputKeyMapping) { "failed to get input-key-mappings for $dName under $dSource properties" }
+                val inputKeyMapping = checkNotNull(sourceProperties.inputKeyMapping) {
+                    "failed to get input-key-mappings for $dName under $dSource properties"
+                }
                 val resolvedInputKeyMapping = resolveInputKeyMappingVariables(inputKeyMapping)
 
                 // Resolving content Variables
@@ -116,12 +120,14 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS
         val type = nullToEmpty(resourceAssignment.property?.type)
         lateinit var entrySchemaType: String
 
-        val outputKeyMapping =
-                checkNotNull(sourceProperties.outputKeyMapping) { "failed to get output-key-mappings for $dName under $dSource properties" }
+        val outputKeyMapping = checkNotNull(sourceProperties.outputKeyMapping) {
+            "failed to get output-key-mappings for $dName under $dSource properties"
+        }
         logger.info("Response processing type($type)")
 
-        val responseNode =
-                checkNotNull(JacksonUtils.jsonNode(restResponse).at(path)) { "Failed to find path ($path) in response ($restResponse)" }
+        val responseNode = checkNotNull(JacksonUtils.jsonNode(restResponse).at(path)) {
+            "Failed to find path ($path) in response ($restResponse)"
+        }
         logger.info("populating value for output mapping ($outputKeyMapping), from json ($responseNode)")
 
 
@@ -132,23 +138,28 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS
             }
             in BluePrintTypes.validCollectionTypes() -> {
                 // Array Types
-                entrySchemaType =
-                        checkNotEmpty(resourceAssignment.property?.entrySchema?.type) { "Entry schema is not defined for dictionary ($dName) info" }
+                entrySchemaType = checkNotEmpty(resourceAssignment.property?.entrySchema?.type) {
+                    "Entry schema is not defined for dictionary ($dName) info"
+                }
                 val arrayNode = responseNode as ArrayNode
 
                 if (entrySchemaType !in BluePrintTypes.validPrimitiveTypes()) {
+
                     val responseArrayNode = responseNode.toList()
                     for (responseSingleJsonNode in responseArrayNode) {
-                        val arrayChildNode = JsonNodeFactory.instance.objectNode()
+
+                        val arrayChildNode = JacksonUtils.objectMapper.createObjectNode()
+
                         outputKeyMapping.map {
                             val responseKeyValue = responseSingleJsonNode.get(it.key)
-                            val propertyTypeForDataType =
-                                    ResourceAssignmentUtils.getPropertyType(raRuntimeService, entrySchemaType, it.key)
-                            logger.info("For List Type Resource: key (${it.key}), value ($responseKeyValue), type  ({$propertyTypeForDataType})")
+                            val propertyTypeForDataType = ResourceAssignmentUtils
+                                    .getPropertyType(raRuntimeService, entrySchemaType, it.key)
+
+                            logger.info("For List Type Resource: key (${it.key}), value ($responseKeyValue), " +
+                                    "type  ({$propertyTypeForDataType})")
+
                             JacksonUtils.populateJsonNodeValues(it.value,
-                                    responseKeyValue,
-                                    propertyTypeForDataType,
-                                    arrayChildNode)
+                                    responseKeyValue, propertyTypeForDataType, arrayChildNode)
                         }
                         arrayNode.add(arrayChildNode)
                     }
@@ -159,13 +170,15 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS
             }
             else -> {
                 // Complex Types
-                entrySchemaType =
-                        checkNotEmpty(resourceAssignment.property?.type) { "Entry schema is not defined for dictionary ($dName) info" }
-                val objectNode = JsonNodeFactory.instance.objectNode()
+                entrySchemaType = checkNotEmpty(resourceAssignment.property?.type) {
+                    "Entry schema is not defined for dictionary ($dName) info"
+                }
+                val objectNode = JacksonUtils.objectMapper.createObjectNode()
                 outputKeyMapping.map {
                     val responseKeyValue = responseNode.get(it.key)
-                    val propertyTypeForDataType =
-                            ResourceAssignmentUtils.getPropertyType(raRuntimeService, entrySchemaType, it.key)
+                    val propertyTypeForDataType = ResourceAssignmentUtils
+                            .getPropertyType(raRuntimeService, entrySchemaType, it.key)
+
                     logger.info("For List Type Resource: key (${it.key}), value ($responseKeyValue), type  ({$propertyTypeForDataType})")
                     JacksonUtils.populateJsonNodeValues(it.value, responseKeyValue, propertyTypeForDataType, objectNode)
                 }
index 86440e6..656e861 100644 (file)
@@ -26,7 +26,6 @@ import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.Reso
 import org.onap.ccsdk.cds.controllerblueprints.core.*
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonReactorUtils
-import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition
 import org.slf4j.LoggerFactory
@@ -44,57 +43,53 @@ class ResourceAssignmentUtils {
             return JacksonReactorUtils.getMapFromFile(dictionaryFile, ResourceDefinition::class.java)
         }
 
-        // TODO("Modify Value type from Any to JsonNode")
         @Throws(BluePrintProcessorException::class)
         fun setResourceDataValue(resourceAssignment: ResourceAssignment,
                                  raRuntimeService: ResourceAssignmentRuntimeService, value: Any?) {
+            // TODO("See if Validation is needed in future with respect to conversion and Types")
+            return setResourceDataValue(resourceAssignment, raRuntimeService, value.asJsonType())
+        }
 
-            val resourceProp = checkNotNull(resourceAssignment.property) { "Failed in setting resource value for resource mapping $resourceAssignment" }
+        @Throws(BluePrintProcessorException::class)
+        fun setResourceDataValue(resourceAssignment: ResourceAssignment,
+                                 raRuntimeService: ResourceAssignmentRuntimeService, value: JsonNode) {
+            val resourceProp = checkNotNull(resourceAssignment.property) {
+                "Failed in setting resource value for resource mapping $resourceAssignment"
+            }
             checkNotEmpty(resourceAssignment.name) {
                 "Failed in setting resource value for resource mapping $resourceAssignment"
             }
 
             if (resourceAssignment.dictionaryName.isNullOrEmpty()) {
                 resourceAssignment.dictionaryName = resourceAssignment.name
-                logger.warn("Missing dictionary key, setting with template key (${resourceAssignment.name}) as dictionary key (${resourceAssignment.dictionaryName})")
+                logger.warn("Missing dictionary key, setting with template key (${resourceAssignment.name}) " +
+                        "as dictionary key (${resourceAssignment.dictionaryName})")
             }
 
             try {
                 if (resourceProp.type.isNotEmpty()) {
-                    val convertedValue = convertResourceValue(resourceProp.type, value)
-                    logger.info("Setting Resource Value ($convertedValue) for Resource Name (${resourceAssignment.dictionaryName}) of type (${resourceProp.type})")
-                    setResourceValue(resourceAssignment, raRuntimeService, convertedValue)
+                    logger.info("Setting Resource Value ($value) for Resource Name " +
+                            "(${resourceAssignment.dictionaryName}) of type (${resourceProp.type})")
+                    setResourceValue(resourceAssignment, raRuntimeService, value)
                     resourceAssignment.updatedDate = Date()
                     resourceAssignment.updatedBy = BluePrintConstants.USER_SYSTEM
                     resourceAssignment.status = BluePrintConstants.STATUS_SUCCESS
                 }
             } catch (e: Exception) {
-                throw BluePrintProcessorException("Failed in setting value for template key (${resourceAssignment.name}) and " +
-                        "dictionary key (${resourceAssignment.dictionaryName}) of type (${resourceProp.type}) with error message (${e.message})", e)
+                throw BluePrintProcessorException("Failed in setting value for template key " +
+                        "(${resourceAssignment.name}) and dictionary key (${resourceAssignment.dictionaryName}) of " +
+                        "type (${resourceProp.type}) with error message (${e.message})", e)
             }
         }
 
-        private fun setResourceValue(resourceAssignment: ResourceAssignment, raRuntimeService: ResourceAssignmentRuntimeService, value: JsonNode) {
+        private fun setResourceValue(resourceAssignment: ResourceAssignment,
+                                     raRuntimeService: ResourceAssignmentRuntimeService, value: JsonNode) {
+            // TODO("See if Validation is needed wrt to type before storing")
             raRuntimeService.putResolutionStore(resourceAssignment.name, value)
             raRuntimeService.putDictionaryStore(resourceAssignment.dictionaryName!!, value)
             resourceAssignment.property!!.value = value
         }
 
-        private fun convertResourceValue(type: String, value: Any?): JsonNode {
-
-            return if (value == null || value is NullNode) {
-                logger.info("Returning {} value from convertResourceValue", value)
-                NullNode.instance
-            } else if (BluePrintTypes.validPrimitiveTypes().contains(type) && value is String) {
-                JacksonUtils.convertPrimitiveResourceValue(type, value)
-            } else if (value is String) {
-                JacksonUtils.jsonNode(value)
-            } else {
-                JacksonUtils.getJsonNode(value)
-            }
-
-        }
-
         fun setFailedResourceDataValue(resourceAssignment: ResourceAssignment, message: String?) {
             if (isNotEmpty(resourceAssignment.name)) {
                 resourceAssignment.updatedDate = Date()
@@ -106,8 +101,11 @@ class ResourceAssignmentUtils {
 
         @Throws(BluePrintProcessorException::class)
         fun assertTemplateKeyValueNotNull(resourceAssignment: ResourceAssignment) {
-            val resourceProp = checkNotNull(resourceAssignment.property) { "Failed to populate mandatory resource resource mapping $resourceAssignment" }
-            if (resourceProp.required != null && resourceProp.required!! && (resourceProp.value == null || resourceProp.value !is NullNode)) {
+            val resourceProp = checkNotNull(resourceAssignment.property) {
+                "Failed to populate mandatory resource resource mapping $resourceAssignment"
+            }
+            if (resourceProp.required != null && resourceProp.required!!
+                    && (resourceProp.value == null || resourceProp.value !is NullNode)) {
                 logger.error("failed to populate mandatory resource mapping ($resourceAssignment)")
                 throw BluePrintProcessorException("failed to populate mandatory resource mapping ($resourceAssignment)")
             }
@@ -138,8 +136,11 @@ class ResourceAssignmentUtils {
             return result
         }
 
-        fun transformToRARuntimeService(blueprintRuntimeService: BluePrintRuntimeService<*>, templateArtifactName: String): ResourceAssignmentRuntimeService {
-            val resourceAssignmentRuntimeService = ResourceAssignmentRuntimeService(blueprintRuntimeService.id(), blueprintRuntimeService.bluePrintContext())
+        fun transformToRARuntimeService(blueprintRuntimeService: BluePrintRuntimeService<*>,
+                                        templateArtifactName: String): ResourceAssignmentRuntimeService {
+
+            val resourceAssignmentRuntimeService = ResourceAssignmentRuntimeService(blueprintRuntimeService.id(),
+                    blueprintRuntimeService.bluePrintContext())
             resourceAssignmentRuntimeService.createUniqueId(templateArtifactName)
             resourceAssignmentRuntimeService.setExecutionContext(blueprintRuntimeService.getExecutionContext() as MutableMap<String, JsonNode>)
 
@@ -147,10 +148,12 @@ class ResourceAssignmentUtils {
         }
 
         @Throws(BluePrintProcessorException::class)
-        fun getPropertyType(raRuntimeService: ResourceAssignmentRuntimeService, dataTypeName: String, propertyName: String): String {
+        fun getPropertyType(raRuntimeService: ResourceAssignmentRuntimeService, dataTypeName: String,
+                            propertyName: String): String {
             lateinit var type: String
             try {
                 val dataTypeProps = checkNotNull(raRuntimeService.bluePrintContext().dataTypeByName(dataTypeName)?.properties)
+
                 val propertyDefinition = checkNotNull(dataTypeProps[propertyName])
                 type = checkNotEmpty(propertyDefinition.type) { "Couldn't get data type ($dataTypeName)" }
                 logger.trace("Data type({})'s property ({}) is ({})", dataTypeName, propertyName, type)
index 0493deb..d45571c 100644 (file)
@@ -45,11 +45,32 @@ fun Double.asJsonPrimitive(): DoubleNode {
     return DoubleNode.valueOf(this)
 }
 
-fun MutableMap<String, *>.asJsonNode(): JsonNode {
+fun <T : Any?> T.asJsonType(): JsonNode {
+    return if (this == null) {
+        NullNode.instance
+    } else {
+        when (this) {
+            is JsonNode ->
+                this
+            is String ->
+                TextNode(this)
+            is Boolean ->
+                BooleanNode.valueOf(this)
+            is Int ->
+                IntNode.valueOf(this.toInt())
+            is Double ->
+                DoubleNode.valueOf(this.toDouble())
+            else ->
+                JacksonUtils.jsonNodeFromObject(this)
+        }
+    }
+}
+
+fun Map<String, *>.asJsonNode(): JsonNode {
     return JacksonUtils.jsonNodeFromObject(this)
 }
 
-fun MutableMap<String, *>.asObjectNode(): ObjectNode {
+fun Map<String, *>.asObjectNode(): ObjectNode {
     return JacksonUtils.objectNodeFromObject(this)
 }
 
@@ -60,7 +81,7 @@ fun format(message: String, vararg args: Any?): String {
     return message
 }
 
-fun <T : Any> MutableMap<String, *>.castOptionalValue(key: String, valueType: KClass<T>): T? {
+fun <T : Any> Map<String, *>.castOptionalValue(key: String, valueType: KClass<T>): T? {
     if (containsKey(key)) {
         return get(key) as? T
     } else {
@@ -68,7 +89,7 @@ fun <T : Any> MutableMap<String, *>.castOptionalValue(key: String, valueType: KC
     }
 }
 
-fun <T : Any> MutableMap<String, *>.castValue(key: String, valueType: KClass<T>): T {
+fun <T : Any> Map<String, *>.castValue(key: String, valueType: KClass<T>): T {
     if (containsKey(key)) {
         return get(key) as T
     } else {
@@ -93,35 +114,23 @@ fun JsonNode.rootFieldsToMap(): MutableMap<String, JsonNode> {
 
 
 fun MutableMap<String, JsonNode>.putJsonElement(key: String, value: Any) {
-    when (value) {
-        is JsonNode ->
-            this[key] = value
-        is String ->
-            this[key] = TextNode(value)
-        is Boolean ->
-            this[key] = BooleanNode.valueOf(value)
-        is Int ->
-            this[key] = IntNode.valueOf(value.toInt())
-        is Double ->
-            this[key] = DoubleNode.valueOf(value.toDouble())
-        else ->
-            this[key] = JacksonUtils.jsonNodeFromObject(value)
-    }
+    val convertedValue = value.asJsonType()
+    this[key] = convertedValue
 }
 
-fun MutableMap<String, JsonNode>.getAsString(key: String): String {
+fun Map<String, JsonNode>.getAsString(key: String): String {
     return this[key]?.asText() ?: throw BluePrintException("couldn't find value for key($key)")
 }
 
-fun MutableMap<String, JsonNode>.getAsBoolean(key: String): Boolean {
+fun Map<String, JsonNode>.getAsBoolean(key: String): Boolean {
     return this[key]?.asBoolean() ?: throw BluePrintException("couldn't find value for key($key)")
 }
 
-fun MutableMap<String, JsonNode>.getAsInt(key: String): Int {
+fun Map<String, JsonNode>.getAsInt(key: String): Int {
     return this[key]?.asInt() ?: throw BluePrintException("couldn't find value for key($key)")
 }
 
-fun MutableMap<String, JsonNode>.getAsDouble(key: String): Double {
+fun Map<String, JsonNode>.getAsDouble(key: String): Double {
     return this[key]?.asDouble() ?: throw BluePrintException("couldn't find value for key($key)")
 }