2 * Copyright © 2017-2018 AT&T Intellectual Property.
3 * Modifications Copyright © 2019 IBM.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 package org.onap.ccsdk.cds.controllerblueprints.core
20 import com.fasterxml.jackson.databind.JsonNode
21 import com.fasterxml.jackson.databind.node.ArrayNode
22 import com.fasterxml.jackson.databind.node.BooleanNode
23 import com.fasterxml.jackson.databind.node.DoubleNode
24 import com.fasterxml.jackson.databind.node.IntNode
25 import com.fasterxml.jackson.databind.node.MissingNode
26 import com.fasterxml.jackson.databind.node.NullNode
27 import com.fasterxml.jackson.databind.node.ObjectNode
28 import com.fasterxml.jackson.databind.node.TextNode
29 import org.apache.commons.lang3.ObjectUtils
30 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
31 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JsonParserUtils
32 import org.slf4j.LoggerFactory
33 import org.slf4j.helpers.MessageFormatter
35 import kotlin.reflect.KClass
40 * @author Brinda Santh
43 fun <T : Any> logger(clazz: T) = LoggerFactory.getLogger(clazz.javaClass)!!
45 fun <T : KClass<*>> logger(clazz: T) = LoggerFactory.getLogger(clazz.java)!!
47 fun <T : Any> T?.defaultToEmpty(): String {
48 return this?.toString() ?: ""
51 fun <T : Any> T?.defaultToUUID(): String {
52 return this?.toString() ?: UUID.randomUUID().toString()
55 fun <T : Any> T.bpClone(): T {
56 return ObjectUtils.clone(this)
59 fun String.splitCommaAsList(): List<String> {
60 return this.split(",").map { it.trim() }.toList()
63 fun String.isJson(): Boolean {
64 return ((this.trim().startsWith("{") && this.trim().endsWith("}")) ||
65 (this.trim().startsWith("[") && this.trim().endsWith("]")))
68 fun Any.asJsonString(intend: Boolean? = false): String {
69 return JacksonUtils.getJson(this, intend!!)
72 fun String.asJsonPrimitive(): TextNode {
76 inline fun <reified T : Any> String.jsonAsType(): T {
77 return JacksonUtils.readValue<T>(this.trim())
80 // If you know the string is json content, then use the function directly
81 fun String.jsonAsJsonType(): JsonNode {
82 return JacksonUtils.jsonNode(this.trim())
85 fun Boolean.asJsonPrimitive(): BooleanNode {
86 return BooleanNode.valueOf(this)
89 fun Int.asJsonPrimitive(): IntNode {
90 return IntNode.valueOf(this)
93 fun Double.asJsonPrimitive(): DoubleNode {
94 return DoubleNode.valueOf(this)
98 * Utility to convert Primitive object to Json Type Primitive.
100 fun <T : Any?> T.asJsonPrimitive(): JsonNode {
101 return if (this == null || this is MissingNode || this is NullNode) {
106 this.asJsonPrimitive()
108 this.asJsonPrimitive()
110 this.asJsonPrimitive()
112 this.asJsonPrimitive()
114 throw BluePrintException("$this type is not supported")
119 /** Based on Blueprint DataType Convert string value to JsonNode Type **/
120 fun String.asJsonType(bpDataType: String): JsonNode {
121 return when (bpDataType.toLowerCase()) {
122 BluePrintConstants.DATA_TYPE_STRING -> this.asJsonPrimitive()
123 BluePrintConstants.DATA_TYPE_BOOLEAN -> this.toBoolean().asJsonPrimitive()
124 BluePrintConstants.DATA_TYPE_INTEGER -> this.toInt().asJsonPrimitive()
125 BluePrintConstants.DATA_TYPE_FLOAT -> this.toFloat().asJsonPrimitive()
126 BluePrintConstants.DATA_TYPE_DOUBLE -> this.toDouble().asJsonPrimitive()
127 // For List, Map and Complex Types.
128 else -> this.jsonAsJsonType()
133 * Utility to convert Complex or Primitive object or ByteArray to Json Type.
135 fun <T : Any?> T.asJsonType(): JsonNode {
136 return if (this == null || this is MissingNode || this is NullNode) {
141 is ByteArray -> JacksonUtils.objectMapper.reader().readTree(this.inputStream())
144 this.jsonAsJsonType()
148 is Boolean -> BooleanNode.valueOf(this)
149 is Int -> IntNode.valueOf(this.toInt())
150 is Double -> DoubleNode.valueOf(this.toDouble())
151 else -> JacksonUtils.jsonNodeFromObject(this)
156 fun Map<String, *>.asJsonNode(): JsonNode {
157 return JacksonUtils.jsonNodeFromObject(this)
160 fun Map<String, *>.asObjectNode(): ObjectNode {
161 return JacksonUtils.objectNodeFromObject(this)
164 fun format(message: String, vararg args: Any?): String {
165 if (args != null && args.isNotEmpty()) {
166 return MessageFormatter.arrayFormat(message, args).message
171 fun <T : Any> Map<String, *>.castOptionalValue(key: String, valueType: KClass<T>): T? {
172 return if (containsKey(key)) {
179 fun <T : Any> Map<String, *>.castValue(key: String, valueType: KClass<T>): T {
180 if (containsKey(key)) {
183 throw BluePrintException("couldn't find the key $key")
187 fun ArrayNode.asListOfString(): List<String> {
188 return JacksonUtils.getListFromJsonNode(this, String::class.java)
191 fun JsonNode.asByteArray(): ByteArray {
192 val writer = JacksonUtils.objectMapper.writer()
193 return writer.writeValueAsBytes(this)
196 fun <T> JsonNode.asType(clazzType: Class<T>): T {
197 return JacksonUtils.readValue(this, clazzType)
198 ?: throw BluePrintException("couldn't convert JsonNode of type $clazzType")
201 fun JsonNode.asListOfString(): List<String> {
202 check(this is ArrayNode) { "JsonNode is not of type ArrayNode" }
203 return this.asListOfString()
206 fun <T : JsonNode> T?.returnNullIfMissing(): JsonNode? {
207 return if (this == null || this is NullNode || this is MissingNode) {
212 fun <T : JsonNode> T?.isNullOrMissing(): Boolean {
213 return this == null || this is NullNode || this is MissingNode
217 * Convert Json to map of json node, the root fields will be map keys
219 fun JsonNode.rootFieldsToMap(): MutableMap<String, JsonNode> {
220 if (this is ObjectNode) {
221 val propertyMap: MutableMap<String, JsonNode> = linkedMapOf()
222 this.fields().forEach {
223 propertyMap[it.key] = it.value
227 throw BluePrintException("json node should be Object Node Type")
231 fun JsonNode.removeNullNode() {
232 val it = this.iterator()
233 while (it.hasNext()) {
234 val child = it.next()
238 child.removeNullNode()
243 fun MutableMap<String, JsonNode>.putJsonElement(key: String, value: Any) {
244 val convertedValue = value.asJsonType()
245 this[key] = convertedValue
248 fun Map<String, JsonNode>.getAsString(key: String): String {
249 return this[key]?.asText() ?: throw BluePrintException("couldn't find value for key($key)")
252 fun Map<String, JsonNode>.getAsBoolean(key: String): Boolean {
253 return this[key]?.asBoolean() ?: throw BluePrintException("couldn't find value for key($key)")
256 fun Map<String, JsonNode>.getAsInt(key: String): Int {
257 return this[key]?.asInt() ?: throw BluePrintException("couldn't find value for key($key)")
260 fun Map<String, JsonNode>.getAsDouble(key: String): Double {
261 return this[key]?.asDouble() ?: throw BluePrintException("couldn't find value for key($key)")
264 fun Map<String, JsonNode>.getOptionalAsString(key: String): String? {
265 return if (this.containsKey(key)) this[key]!!.asText() else null
268 fun Map<String, JsonNode>.getOptionalAsBoolean(key: String): Boolean? {
269 return if (this.containsKey(key)) this[key]!!.asBoolean() else null
272 fun Map<String, JsonNode>.getOptionalAsInt(key: String): Int? {
273 return if (this.containsKey(key)) this[key]!!.asInt() else null
276 fun Map<String, JsonNode>.getOptionalAsDouble(key: String): Double? {
277 return if (this.containsKey(key)) this[key]!!.asDouble() else null
282 inline fun checkEquals(value1: String?, value2: String?, lazyMessage: () -> Any): Boolean {
283 if (value1.equals(value2, ignoreCase = true)) {
286 throw BluePrintException(lazyMessage().toString())
290 inline fun checkNotEmpty(value: String?, lazyMessage: () -> Any): String {
291 if (value == null || value.isEmpty()) {
292 val message = lazyMessage()
293 throw IllegalStateException(message.toString())
299 inline fun checkNotBlank(value: String?, lazyMessage: () -> Any): String {
300 if (value == null || value.isBlank()) {
301 val message = lazyMessage()
302 throw IllegalStateException(message.toString())
308 fun isNotEmpty(value: String?): Boolean {
309 return value != null && value.isNotEmpty()
312 fun isNotBlank(value: String?): Boolean {
313 return value != null && value.isNotBlank()
316 fun <T : String> T?.emptyTONull(): String? {
317 return if (this == null || this.isEmpty()) null else this
320 fun nullToEmpty(value: String?): String {
321 return if (isNotEmpty(value)) value!! else ""
324 inline fun <reified T : JsonNode> T.isComplexType(): Boolean {
325 return this is ObjectNode || this is ArrayNode
328 // Json Parsing Extensions
329 fun JsonNode.jsonPathParse(expression: String): JsonNode {
330 check(this.isComplexType()) { "$this is not complex or array node to apply expression" }
331 return JsonParserUtils.parse(this, expression)
334 // Json Path Extensions
335 fun JsonNode.jsonPaths(expression: String): List<String> {
336 check(this.isComplexType()) { "$this is not complex or array node to apply expression" }
337 return JsonParserUtils.paths(this, expression)