import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.databind.node.ArrayNode
import com.fasterxml.jackson.databind.node.NullNode
import com.fasterxml.jackson.databind.node.ObjectNode
import com.fasterxml.jackson.databind.node.TextNode
import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceAssignmentRuntimeService
import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants
-import org.onap.ccsdk.cds.controllerblueprints.core.*
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
+import org.onap.ccsdk.cds.controllerblueprints.core.checkFileExists
+import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty
+import org.onap.ccsdk.cds.controllerblueprints.core.common.ApplicationConstants.LOG_REDACTED
+import org.onap.ccsdk.cds.controllerblueprints.core.isComplexType
+import org.onap.ccsdk.cds.controllerblueprints.core.isNotEmpty
+import org.onap.ccsdk.cds.controllerblueprints.core.isNullOrMissing
+import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
+import org.onap.ccsdk.cds.controllerblueprints.core.nullToEmpty
+import org.onap.ccsdk.cds.controllerblueprints.core.rootFieldsToMap
import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
+import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintVelocityTemplateService
import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonReactorUtils
import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.PropertyDefinitionUtils.Companion.hasLogProtect
+import org.onap.ccsdk.cds.controllerblueprints.resource.dict.DictionaryMetadataEntry
+import org.onap.ccsdk.cds.controllerblueprints.resource.dict.KeyIdentifier
+import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResolutionSummary
import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition
import org.slf4j.LoggerFactory
-import java.util.*
+import java.util.Date
class ResourceAssignmentUtils {
companion object {
@Throws(BluePrintProcessorException::class)
fun setResourceDataValue(
resourceAssignment: ResourceAssignment,
- raRuntimeService: ResourceAssignmentRuntimeService, value: Any?
+ raRuntimeService: ResourceAssignmentRuntimeService,
+ value: Any?
) {
// TODO("See if Validation is needed in future with respect to conversion and Types")
return setResourceDataValue(resourceAssignment, raRuntimeService, value.asJsonType())
@Throws(BluePrintProcessorException::class)
fun setResourceDataValue(
resourceAssignment: ResourceAssignment,
- raRuntimeService: ResourceAssignmentRuntimeService, value: JsonNode
+ raRuntimeService: ResourceAssignmentRuntimeService,
+ value: JsonNode
) {
val resourceProp = checkNotNull(resourceAssignment.property) {
"Failed in setting resource value for resource mapping $resourceAssignment"
private fun setResourceValue(
resourceAssignment: ResourceAssignment,
- raRuntimeService: ResourceAssignmentRuntimeService, value: JsonNode
+ 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
+
+ val metadata = resourceAssignment.property?.metadata
+ metadata?.get(ResourceResolutionConstants.METADATA_TRANSFORM_TEMPLATE)
+ ?.let { if (it.contains("$")) it else null }
+ ?.let { template ->
+ val resolutionStore = raRuntimeService.getResolutionStore()
+ .mapValues { e -> e.value.asText() } as MutableMap<String, Any>
+ val newValue: JsonNode
+ try {
+ newValue = BluePrintVelocityTemplateService
+ .generateContent(template, null, true, resolutionStore)
+ .also { if (hasLogProtect(metadata))
+ logger.info("Transformed value: $resourceAssignment.name")
+ else
+ logger.info("Transformed value: $value -> $it") }
+ .let { v -> v.asJsonType() }
+ } catch (e: Exception) {
+ throw BluePrintProcessorException(
+ "transform-template failed: $template", e)
+ }
+ with(resourceAssignment) {
+ raRuntimeService.putResolutionStore(this.name, newValue)
+ raRuntimeService.putDictionaryStore(this.dictionaryName!!, newValue)
+ this.property!!.value = newValue
+ }
+ }
}
fun setFailedResourceDataValue(resourceAssignment: ResourceAssignment, message: String?) {
val resourceProp = checkNotNull(resourceAssignment.property) {
"Failed to populate mandatory resource resource mapping $resourceAssignment"
}
- if (resourceProp.required != null && resourceProp.required!!
- && (resourceProp.value == null || resourceProp.value!!.returnNullIfMissing() == null)
- ) {
+ if (resourceProp.required != null && resourceProp.required!! && resourceProp.value.isNullOrMissing()) {
logger.error("failed to populate mandatory resource mapping ($resourceAssignment)")
throw BluePrintProcessorException("failed to populate mandatory resource mapping ($resourceAssignment)")
}
val result: String
try {
val mapper = ObjectMapper()
+ mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true)
val root: ObjectNode = mapper.createObjectNode()
var containsLogProtected = false
val type = nullToEmpty(it.property?.type).toLowerCase()
val value = useDefaultValueIfNull(it, rName)
val valueToPrint = getValueToLog(metadata, value)
- if (checkIfLogIsProtected(metadata)) {
- containsLogProtected = true
- }
+ containsLogProtected = hasLogProtect(metadata)
logger.trace("Generating Resource name ($rName), type ($type), value ($valueToPrint)")
- root.set(rName, value)
+ root.set<JsonNode>(rName, value)
}
}
- result = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(root)
+ result = mapper.writerWithDefaultPrettyPrinter()
+ .writeValueAsString(mapper.treeToValue(root, Object::class.java))
if (!containsLogProtected) {
logger.info("Generated Resource Param Data ($result)")
return data
}
+ fun generateResolutionSummaryData(
+ resourceAssignments: List<ResourceAssignment>,
+ resourceDefinitions: Map<String, ResourceDefinition>
+ ): String {
+ val emptyTextNode = TextNode.valueOf("")
+ val resolutionSummaryList = resourceAssignments.map {
+ val definition = resourceDefinitions[it.name]
+ val description = definition?.property?.description ?: ""
+ val value = it.property?.value
+ ?.let { v -> if (v.isNullOrMissing()) emptyTextNode else v }
+ ?: emptyTextNode
+
+ var payload: JsonNode = definition?.sources?.get(it.dictionarySource)
+ ?.properties?.get("resolved-payload")
+ ?.let { p -> if (p.isNullOrMissing()) emptyTextNode else p }
+ ?: emptyTextNode
+
+ val metadata = definition?.property?.metadata
+ ?.map { e -> DictionaryMetadataEntry(e.key, e.value) }
+ ?.toMutableList() ?: mutableListOf()
+
+ val keyIdentifiers: MutableList<KeyIdentifier> = it.keyIdentifiers.map { k ->
+ if (k.value.isNullOrMissing()) KeyIdentifier(k.name, emptyTextNode) else k
+ }.toMutableList()
+
+ ResolutionSummary(
+ it.name,
+ value,
+ it.property?.required ?: false,
+ it.property?.type ?: "",
+ keyIdentifiers,
+ description,
+ metadata,
+ it.dictionaryName ?: "",
+ it.dictionarySource ?: "",
+ payload,
+ it.status ?: "",
+ it.message ?: ""
+ )
+ }
+ // Wrapper needed for integration with SDNC
+ val data = mapOf("resolution-summary" to resolutionSummaryList)
+ return JacksonUtils.getJson(data, includeNull = true)
+ }
+
private fun useDefaultValueIfNull(
resourceAssignment: ResourceAssignment,
resourceAssignmentName: String
@Throws(BluePrintProcessorException::class)
fun getPropertyType(
- raRuntimeService: ResourceAssignmentRuntimeService, dataTypeName: String,
+ raRuntimeService: ResourceAssignmentRuntimeService,
+ dataTypeName: String,
propertyName: String
): String {
lateinit var type: String
@Throws(BluePrintProcessorException::class)
fun parseResponseNode(
- responseNode: JsonNode, resourceAssignment: ResourceAssignment,
- raRuntimeService: ResourceAssignmentRuntimeService, outputKeyMapping: MutableMap<String, String>
+ responseNode: JsonNode,
+ resourceAssignment: ResourceAssignment,
+ raRuntimeService: ResourceAssignmentRuntimeService,
+ outputKeyMapping: MutableMap<String, String>
): JsonNode {
val metadata = resourceAssignment.property!!.metadata
try {
val type = resourceAssignment.property!!.type
val valueToPrint = getValueToLog(metadata, responseNode)
- logger.info("For template key (${resourceAssignment.name}) setting value as ($valueToPrint)")
+ logger.info("For template key (${resourceAssignment.name}) trying to get value from responseNode ($valueToPrint)")
return when (type) {
in BluePrintTypes.validPrimitiveTypes() -> {
- parseResponseNodeForPrimitiveTypes(responseNode, outputKeyMapping)
+ // Primitive Types
+ parseResponseNodeForPrimitiveTypes(responseNode, resourceAssignment, outputKeyMapping)
}
in BluePrintTypes.validCollectionTypes() -> {
// Array Types
private fun parseResponseNodeForPrimitiveTypes(
responseNode: JsonNode,
+ resourceAssignment: ResourceAssignment,
outputKeyMapping: MutableMap<String, String>
): JsonNode {
- if (responseNode.isComplexType()) {
- val outputKey = outputKeyMapping.keys.firstOrNull()
- var returnNode = if (responseNode is ArrayNode) {
- val arrayNode = responseNode.toList()
- if (outputKey.isNullOrEmpty()) {
- arrayNode.first()
- } else {
- arrayNode.firstOrNull { element ->
- element.isComplexType() && element.has(outputKeyMapping[outputKey])
- }
- }
- } else {
- responseNode
- }
+ // Return responseNode if is not a Complex Type
+ if (!responseNode.isComplexType()) {
+ return responseNode
+ }
- if (returnNode.isNull() || returnNode!!.isComplexType() && !returnNode.has(outputKeyMapping[outputKey])) {
- throw BluePrintProcessorException("Fail to find output key mapping ($outputKey) in the responseNode.")
- }
- return if (returnNode.isComplexType()) {
- returnNode[outputKeyMapping[outputKey]]
+ val outputKey = outputKeyMapping.keys.firstOrNull()
+ var returnNode = if (responseNode is ArrayNode) {
+ val arrayNode = responseNode.toList()
+ if (outputKey.isNullOrEmpty()) {
+ arrayNode.first()
} else {
- returnNode
+ arrayNode.firstOrNull { element ->
+ element.isComplexType() && element.has(outputKeyMapping[outputKey])
+ }
}
+ } else {
+ responseNode
}
- if (outputKeyMapping.isNotEmpty()) {
- throw BluePrintProcessorException("Fail to find key-value in response node to map output-key-mapping.")
+
+ if (returnNode.isNullOrMissing() || returnNode!!.isComplexType() && !returnNode.has(outputKeyMapping[outputKey])) {
+ throw BluePrintProcessorException("Fail to find output key mapping ($outputKey) in the responseNode.")
}
- return responseNode
+
+ val returnValue = if (returnNode.isComplexType()) {
+ returnNode[outputKeyMapping[outputKey]]
+ } else {
+ returnNode
+ }
+
+ outputKey?.let { KeyIdentifier(it, returnValue) }
+ ?.let { resourceAssignment.keyIdentifiers.add(it) }
+ return returnValue
}
private fun parseResponseNodeForCollection(
- responseNode: JsonNode, resourceAssignment: ResourceAssignment,
+ responseNode: JsonNode,
+ resourceAssignment: ResourceAssignment,
raRuntimeService: ResourceAssignmentRuntimeService,
outputKeyMapping: MutableMap<String, String>
): JsonNode {
val responseArrayNode = responseNode.toList()
for (responseSingleJsonNode in responseArrayNode) {
val arrayChildNode = parseSingleElementOfArrayResponseNode(
- entrySchemaType,
+ entrySchemaType, resourceAssignment,
outputKeyMapping, raRuntimeService, responseSingleJsonNode, metadata
)
arrayNode.add(arrayChildNode)
is ObjectNode -> {
val responseArrayNode = responseNode.rootFieldsToMap()
resultNode =
- parseObjectResponseNode(entrySchemaType, outputKeyMapping, responseArrayNode, metadata)
+ parseObjectResponseNode(
+ resourceAssignment, entrySchemaType, outputKeyMapping,
+ responseArrayNode, metadata
+ )
}
else -> {
throw BluePrintProcessorException("Key-value response expected to match the responseNode.")
}
private fun parseSingleElementOfArrayResponseNode(
- entrySchemaType: String, outputKeyMapping: MutableMap<String, String>,
+ entrySchemaType: String,
+ resourceAssignment: ResourceAssignment,
+ outputKeyMapping: MutableMap<String, String>,
raRuntimeService: ResourceAssignmentRuntimeService,
- responseNode: JsonNode, metadata: MutableMap<String, String>?
+ responseNode: JsonNode,
+ metadata: MutableMap<String, String>?
): ObjectNode {
val outputKeyMappingHasOnlyOneElement = checkIfOutputKeyMappingProvideOneElement(outputKeyMapping)
when (entrySchemaType) {
in BluePrintTypes.validPrimitiveTypes() -> {
if (outputKeyMappingHasOnlyOneElement) {
val outputKeyMap = outputKeyMapping.entries.first()
+ if (resourceAssignment.keyIdentifiers.none { it.name == outputKeyMap.key }) {
+ resourceAssignment.keyIdentifiers.add(
+ KeyIdentifier(outputKeyMap.key, JacksonUtils.objectMapper.createArrayNode())
+ )
+ }
return parseSingleElementNodeWithOneOutputKeyMapping(
+ resourceAssignment,
responseNode,
outputKeyMap.key,
outputKeyMap.value,
raRuntimeService
) -> {
parseSingleElementNodeWithAllOutputKeyMapping(
+ resourceAssignment,
responseNode,
outputKeyMapping,
entrySchemaType,
outputKeyMappingHasOnlyOneElement -> {
val outputKeyMap = outputKeyMapping.entries.first()
parseSingleElementNodeWithOneOutputKeyMapping(
+ resourceAssignment,
responseNode,
outputKeyMap.key,
outputKeyMap.value,
}
private fun parseObjectResponseNode(
- entrySchemaType: String, outputKeyMapping: MutableMap<String, String>,
- responseArrayNode: MutableMap<String, JsonNode>, metadata: MutableMap<String, String>?
+ resourceAssignment: ResourceAssignment,
+ 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(
+ val returnValue = parseObjectResponseNodeWithOneOutputKeyMapping(
responseArrayNode, outputKeyMap.key, outputKeyMap.value,
entrySchemaType, metadata
)
+ resourceAssignment.keyIdentifiers.add(KeyIdentifier(outputKeyMap.key, returnValue))
+ return returnValue
} 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>?
+ resourceAssignment: ResourceAssignment,
+ responseSingleJsonNode: JsonNode,
+ outputKeyMappingKey: String,
+ outputKeyMappingValue: String,
+ type: String,
+ metadata: MutableMap<String, String>?
): ObjectNode {
val arrayChildNode = JacksonUtils.objectMapper.createObjectNode()
logKeyValueResolvedResource(metadata, outputKeyMappingKey, responseKeyValue, type)
JacksonUtils.populateJsonNodeValues(outputKeyMappingKey, responseKeyValue, type, arrayChildNode)
-
+ resourceAssignment.keyIdentifiers.find { it.name == outputKeyMappingKey && it.value.isArray }
+ .let {
+ if (it != null)
+ (it.value as ArrayNode).add(responseKeyValue)
+ else
+ resourceAssignment.keyIdentifiers.add(
+ KeyIdentifier(outputKeyMappingKey, responseKeyValue))
+ }
return arrayChildNode
}
private fun parseSingleElementNodeWithAllOutputKeyMapping(
+ resourceAssignment: ResourceAssignment,
responseSingleJsonNode: JsonNode,
outputKeyMapping: MutableMap<String, String>,
- type: String, metadata: MutableMap<String, String>?
+ type: String,
+ metadata: MutableMap<String, String>?
): ObjectNode {
val arrayChildNode = JacksonUtils.objectMapper.createObjectNode()
outputKeyMapping.map {
logKeyValueResolvedResource(metadata, it.key, responseKeyValue, type)
JacksonUtils.populateJsonNodeValues(it.key, responseKeyValue, type, arrayChildNode)
+ resourceAssignment.keyIdentifiers.add(KeyIdentifier(it.key, responseKeyValue))
}
return arrayChildNode
}
private fun parseObjectResponseNodeWithOneOutputKeyMapping(
responseArrayNode: MutableMap<String, JsonNode>,
- outputKeyMappingKey: String, outputKeyMappingValue: String,
- type: String, metadata: MutableMap<String, String>?
+ outputKeyMappingKey: String,
+ outputKeyMappingValue: String,
+ type: String,
+ metadata: MutableMap<String, String>?
): ObjectNode {
val objectNode = JacksonUtils.objectMapper.createObjectNode()
val responseSingleJsonNode = responseArrayNode.filterKeys { key ->
}
private fun parseResponseNodeForComplexType(
- responseNode: JsonNode, resourceAssignment: ResourceAssignment,
+ responseNode: JsonNode,
+ resourceAssignment: ResourceAssignment,
raRuntimeService: ResourceAssignmentRuntimeService,
outputKeyMapping: MutableMap<String, String>
): JsonNode {
raRuntimeService
) -> {
parseSingleElementNodeWithAllOutputKeyMapping(
+ resourceAssignment,
responseNode,
outputKeyMapping,
entrySchemaType,
outputKeyMappingHasOnlyOneElement -> {
val outputKeyMap = outputKeyMapping.entries.first()
parseSingleElementNodeWithOneOutputKeyMapping(
- responseNode, outputKeyMap.key, outputKeyMap.value,
- entrySchemaType, metadata
+ resourceAssignment, responseNode, outputKeyMap.key,
+ outputKeyMap.value, entrySchemaType, metadata
)
}
else -> {
}
private fun checkOutputKeyMappingAllElementsInDataTypeProperties(
- dataTypeName: String, outputKeyMapping: MutableMap<String, String>,
+ dataTypeName: String,
+ outputKeyMapping: MutableMap<String, String>,
raRuntimeService: ResourceAssignmentRuntimeService
): Boolean {
val dataTypeProps = raRuntimeService.bluePrintContext().dataTypeByName(dataTypeName)?.properties
return (outputKeyMapping.size == 1)
}
- fun getValueToLog(metadata: MutableMap<String, String>?, value: Any): Any {
- return if (checkIfLogIsProtected(metadata)) {
- "*************"
- } else {
- value
- }
- }
-
- 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
- }
+ fun getValueToLog(metadata: MutableMap<String, String>?, value: Any): Any =
+ if (hasLogProtect(metadata)) LOG_REDACTED else value
}
-}
\ No newline at end of file
+}