Revert "Renaming Files having BluePrint to have Blueprint"
[ccsdk/cds.git] / ms / blueprintsprocessor / modules / blueprints / blueprint-core / src / main / kotlin / org / onap / ccsdk / cds / controllerblueprints / core / utils / JacksonUtils.kt
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  * Modifications Copyright © 2018-2019 IBM.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 package org.onap.ccsdk.cds.controllerblueprints.core.utils
18
19 import com.fasterxml.jackson.annotation.JsonInclude
20 import com.fasterxml.jackson.databind.JsonNode
21 import com.fasterxml.jackson.databind.SerializationFeature
22 import com.fasterxml.jackson.databind.node.ArrayNode
23 import com.fasterxml.jackson.databind.node.BooleanNode
24 import com.fasterxml.jackson.databind.node.DoubleNode
25 import com.fasterxml.jackson.databind.node.FloatNode
26 import com.fasterxml.jackson.databind.node.IntNode
27 import com.fasterxml.jackson.databind.node.MissingNode
28 import com.fasterxml.jackson.databind.node.NullNode
29 import com.fasterxml.jackson.databind.node.ObjectNode
30 import com.fasterxml.jackson.databind.node.TextNode
31 import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
32 import kotlinx.coroutines.Dispatchers
33 import kotlinx.coroutines.runBlocking
34 import kotlinx.coroutines.withContext
35 import org.apache.commons.io.IOUtils
36 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
37 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
38 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
39 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
40 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
41 import org.onap.ccsdk.cds.controllerblueprints.core.readNBText
42 import java.io.File
43 import java.io.InputStream
44 import java.nio.charset.Charset
45
46 /**
47  *
48  *
49  * @author Brinda Santh
50  */
51 class JacksonUtils {
52
53     companion object {
54
55         val objectMapper = jacksonObjectMapper()
56
57         inline fun <reified T : Any> readValue(content: String): T =
58             objectMapper.readValue(content, T::class.java)
59
60         inline fun <reified T : Any> readValue(stream: InputStream): T =
61             objectMapper.readValue(stream, T::class.java)
62
63         fun <T> readValue(content: String, valueType: Class<T>): T? {
64             return objectMapper.readValue(content, valueType)
65         }
66
67         fun <T> readValue(stream: InputStream, valueType: Class<T>): T? {
68             return objectMapper.readValue(stream, valueType)
69         }
70
71         fun <T> readValue(node: JsonNode, valueType: Class<T>): T? {
72             return objectMapper.treeToValue(node, valueType)
73         }
74
75         fun getContent(fileName: String): String = runBlocking {
76             try {
77                 normalizedFile(fileName).readNBText()
78             } catch (e: Exception) {
79                 throw BluePrintException("couldn't get file ($fileName) content : ${e.message}")
80             }
81         }
82
83         fun getClassPathFileContent(fileName: String): String {
84             return runBlocking {
85                 withContext(Dispatchers.Default) {
86                     IOUtils.toString(
87                         JacksonUtils::class.java.classLoader
88                             .getResourceAsStream(fileName),
89                         Charset.defaultCharset()
90                     )
91                 }
92             }
93         }
94
95         fun <T> readValueFromFile(fileName: String, valueType: Class<T>): T? {
96             val content: String = getContent(fileName)
97             return readValue(content, valueType)
98         }
99
100         fun <T> readValueFromClassPathFile(fileName: String, valueType: Class<T>): T? {
101             val content: String = getClassPathFileContent(fileName)
102             return readValue(content, valueType)
103         }
104
105         fun objectNodeFromObject(from: kotlin.Any): ObjectNode {
106             return objectMapper.convertValue(from, ObjectNode::class.java)
107         }
108
109         fun jsonNodeFromObject(from: kotlin.Any): JsonNode {
110             return objectMapper.convertValue(from, JsonNode::class.java)
111         }
112
113         fun jsonNodeFromClassPathFile(fileName: String): JsonNode {
114             val content: String = getClassPathFileContent(fileName)
115             return jsonNode(content)
116         }
117
118         fun jsonNodeFromFile(fileName: String): JsonNode {
119             val content: String = getContent(fileName)
120             return jsonNode(content)
121         }
122
123         fun jsonNode(content: String): JsonNode {
124             return jacksonObjectMapper().readTree(content)
125         }
126
127         fun getJson(any: kotlin.Any): String {
128             return getJson(any, false)
129         }
130
131         fun getWrappedJson(wrapper: String, any: kotlin.Any, pretty: Boolean = false): String {
132             val wrapperMap = hashMapOf<String, Any>()
133             wrapperMap[wrapper] = any
134             return getJson(wrapperMap, pretty)
135         }
136
137         fun getJson(any: kotlin.Any, pretty: Boolean = false, includeNull: Boolean = false): String {
138             val objectMapper = jacksonObjectMapper()
139             if (includeNull) {
140                 objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS)
141             } else {
142                 objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
143             }
144             if (pretty) {
145                 objectMapper.enable(SerializationFeature.INDENT_OUTPUT)
146             }
147             return objectMapper.writeValueAsString(any)
148         }
149
150         fun getJsonNode(any: kotlin.Any?, pretty: Boolean = false): JsonNode {
151             val objectMapper = jacksonObjectMapper()
152             objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
153             if (pretty) {
154                 objectMapper.enable(SerializationFeature.INDENT_OUTPUT)
155             }
156             return objectMapper.valueToTree(any)
157         }
158
159         fun <T> getListFromJsonNode(node: JsonNode, valueType: Class<T>): List<T> {
160             return getListFromJson(node.toString(), valueType)
161         }
162
163         fun <T> getListFromJson(content: String, valueType: Class<T>): List<T> {
164             val objectMapper = jacksonObjectMapper()
165             val javaType = objectMapper.typeFactory.constructCollectionType(List::class.java, valueType)
166             return objectMapper.readValue<List<T>>(content, javaType)
167         }
168
169         fun <T> getListFromFile(fileName: String, valueType: Class<T>): List<T> {
170             val content: String = getContent(fileName)
171             return getListFromJson(content, valueType)
172         }
173
174         fun <T> getListFromClassPathFile(fileName: String, valueType: Class<T>): List<T> {
175             val content: String = getClassPathFileContent(fileName)
176             return getListFromJson(content, valueType)
177         }
178
179         fun <T> getMapFromJson(content: String, valueType: Class<T>): MutableMap<String, T> {
180             val objectMapper = jacksonObjectMapper()
181             val mapType = objectMapper.typeFactory.constructMapType(Map::class.java, String::class.java, valueType)
182             return objectMapper.readValue(content, mapType)
183         }
184
185         fun <T> getMapFromFile(file: File, valueType: Class<T>): MutableMap<String, T> = runBlocking {
186             val content: String = file.readNBText()
187             getMapFromJson(content, valueType)
188         }
189
190         fun <T> getMapFromFile(fileName: String, valueType: Class<T>): MutableMap<String, T> = getMapFromFile(File(fileName), valueType)
191
192         fun <T> getInstanceFromMap(properties: MutableMap<String, JsonNode>, classType: Class<T>): T {
193             return readValue(getJson(properties), classType)
194                 ?: throw BluePrintProcessorException("failed to transform content ($properties) to type ($classType)")
195         }
196
197         fun checkJsonNodeValueOfType(type: String, jsonNode: JsonNode): Boolean {
198             if (BluePrintTypes.validPrimitiveTypes().contains(type.toLowerCase())) {
199                 return checkJsonNodeValueOfPrimitiveType(type, jsonNode)
200             } else if (BluePrintTypes.validCollectionTypes().contains(type)) {
201                 return checkJsonNodeValueOfCollectionType(type, jsonNode)
202             }
203             return false
204         }
205
206         fun checkIfPrimitiveType(primitiveType: String): Boolean {
207             return when (primitiveType.toLowerCase()) {
208                 BluePrintConstants.DATA_TYPE_STRING -> true
209                 BluePrintConstants.DATA_TYPE_BOOLEAN -> true
210                 BluePrintConstants.DATA_TYPE_INTEGER -> true
211                 BluePrintConstants.DATA_TYPE_FLOAT -> true
212                 BluePrintConstants.DATA_TYPE_DOUBLE -> true
213                 BluePrintConstants.DATA_TYPE_TIMESTAMP -> true
214                 else -> false
215             }
216         }
217
218         fun checkJsonNodeValueOfPrimitiveType(primitiveType: String, jsonNode: JsonNode): Boolean {
219             return when (primitiveType.toLowerCase()) {
220                 BluePrintConstants.DATA_TYPE_STRING -> jsonNode.isTextual
221                 BluePrintConstants.DATA_TYPE_BOOLEAN -> jsonNode.isBoolean
222                 BluePrintConstants.DATA_TYPE_INTEGER -> jsonNode.isInt
223                 BluePrintConstants.DATA_TYPE_FLOAT -> jsonNode.isDouble
224                 BluePrintConstants.DATA_TYPE_DOUBLE -> jsonNode.isDouble
225                 BluePrintConstants.DATA_TYPE_TIMESTAMP -> jsonNode.isTextual
226                 else -> false
227             }
228         }
229
230         fun checkJsonNodeValueOfCollectionType(type: String, jsonNode: JsonNode): Boolean {
231             return when (type.toLowerCase()) {
232                 BluePrintConstants.DATA_TYPE_LIST -> jsonNode.isArray
233                 else -> false
234             }
235         }
236
237         fun getValue(value: JsonNode): Any {
238             return when (value) {
239                 is BooleanNode -> value.booleanValue()
240                 is IntNode -> value.intValue()
241                 is FloatNode -> value.floatValue()
242                 is DoubleNode -> value.doubleValue()
243                 is TextNode -> value.textValue()
244                 else -> value
245             }
246         }
247
248         fun getValue(value: Any, type: String): Any {
249             return when (type.toLowerCase()) {
250                 BluePrintConstants.DATA_TYPE_BOOLEAN -> (value as BooleanNode).booleanValue()
251                 BluePrintConstants.DATA_TYPE_INTEGER -> (value as IntNode).intValue()
252                 BluePrintConstants.DATA_TYPE_FLOAT -> (value as FloatNode).floatValue()
253                 BluePrintConstants.DATA_TYPE_DOUBLE -> (value as DoubleNode).doubleValue()
254                 BluePrintConstants.DATA_TYPE_STRING -> (value as TextNode).textValue()
255                 else -> (value as JsonNode)
256             }
257         }
258
259         fun populatePrimitiveValues(key: String, value: JsonNode, primitiveType: String, objectNode: ObjectNode) {
260             when (primitiveType.toLowerCase()) {
261                 BluePrintConstants.DATA_TYPE_BOOLEAN,
262                 BluePrintConstants.DATA_TYPE_INTEGER,
263                 BluePrintConstants.DATA_TYPE_FLOAT,
264                 BluePrintConstants.DATA_TYPE_DOUBLE,
265                 BluePrintConstants.DATA_TYPE_TIMESTAMP,
266                 BluePrintConstants.DATA_TYPE_STRING,
267                 BluePrintConstants.DATA_TYPE_NULL ->
268                     objectNode.set(key, value)
269                 else -> throw BluePrintException("populatePrimitiveValues expected only primitive values! Received: ($value)")
270             }
271         }
272
273         fun populatePrimitiveValues(value: JsonNode, primitiveType: String, arrayNode: ArrayNode) {
274             when (primitiveType.toLowerCase()) {
275                 BluePrintConstants.DATA_TYPE_BOOLEAN,
276                 BluePrintConstants.DATA_TYPE_INTEGER,
277                 BluePrintConstants.DATA_TYPE_FLOAT,
278                 BluePrintConstants.DATA_TYPE_DOUBLE,
279                 BluePrintConstants.DATA_TYPE_TIMESTAMP,
280                 BluePrintConstants.DATA_TYPE_STRING,
281                 BluePrintConstants.DATA_TYPE_NULL ->
282                     arrayNode.add(value)
283                 else -> throw BluePrintException("populatePrimitiveValues expected only primitive values! Received: ($value)")
284             }
285         }
286
287         fun populatePrimitiveDefaultValues(key: String, primitiveType: String, objectNode: ObjectNode) {
288             val defaultValue = getDefaultValueOfPrimitiveAsJsonNode(primitiveType)
289                 ?: throw BluePrintException("populatePrimitiveDefaultValues expected only primitive values! Received type ($primitiveType)")
290             objectNode.set<JsonNode>(key, defaultValue)
291         }
292
293         fun populatePrimitiveDefaultValuesForArrayNode(primitiveType: String, arrayNode: ArrayNode) {
294             val defaultValue = getDefaultValueOfPrimitiveAsJsonNode(primitiveType)
295                 ?: throw BluePrintException("populatePrimitiveDefaultValuesForArrayNode expected only primitive values! Received type ($primitiveType)")
296             arrayNode.add(defaultValue)
297         }
298
299         private fun getDefaultValueOfPrimitiveAsJsonNode(primitiveType: String): JsonNode? {
300             return when (primitiveType.toLowerCase()) {
301                 BluePrintConstants.DATA_TYPE_BOOLEAN -> BooleanNode.valueOf(false)
302                 BluePrintConstants.DATA_TYPE_INTEGER -> IntNode.valueOf(0)
303                 BluePrintConstants.DATA_TYPE_FLOAT -> FloatNode.valueOf(0.0f)
304                 BluePrintConstants.DATA_TYPE_DOUBLE -> DoubleNode.valueOf(0.0)
305                 BluePrintConstants.DATA_TYPE_STRING -> MissingNode.getInstance()
306                 else -> null
307             }
308         }
309
310         fun populateJsonNodeValues(key: String, nodeValue: JsonNode?, type: String, objectNode: ObjectNode) {
311             if (nodeValue == null || nodeValue is NullNode) {
312                 objectNode.set<JsonNode>(key, nodeValue)
313             } else if (BluePrintTypes.validPrimitiveTypes().contains(type)) {
314                 populatePrimitiveValues(key, nodeValue, type, objectNode)
315             } else {
316                 objectNode.set<JsonNode>(key, nodeValue)
317             }
318         }
319
320         fun convertPrimitiveResourceValue(type: String, value: String): JsonNode {
321             return when (type.toLowerCase()) {
322                 BluePrintConstants.DATA_TYPE_BOOLEAN -> jsonNodeFromObject(value.toBoolean())
323                 BluePrintConstants.DATA_TYPE_INTEGER -> jsonNodeFromObject(value.toInt())
324                 BluePrintConstants.DATA_TYPE_FLOAT -> jsonNodeFromObject(value.toFloat())
325                 BluePrintConstants.DATA_TYPE_DOUBLE -> jsonNodeFromObject(value.toDouble())
326                 BluePrintConstants.DATA_TYPE_STRING -> jsonNodeFromObject(value)
327                 else -> getJsonNode(value)
328             }
329         }
330     }
331 }