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 {
65 (this.trim().startsWith("{") && this.trim().endsWith("}")) ||
66 (this.trim().startsWith("[") && this.trim().endsWith("]"))
70 fun Any.asJsonString(intend: Boolean? = false): String {
71 return JacksonUtils.getJson(this, intend!!)
74 fun String.asJsonPrimitive(): TextNode {
78 inline fun <reified T : Any> String.jsonAsType(): T {
79 return JacksonUtils.readValue<T>(this.trim())
82 // If you know the string is json content, then use the function directly
83 fun String.jsonAsJsonType(): JsonNode {
84 return JacksonUtils.jsonNode(this.trim())
87 fun Boolean.asJsonPrimitive(): BooleanNode {
88 return BooleanNode.valueOf(this)
91 fun Int.asJsonPrimitive(): IntNode {
92 return IntNode.valueOf(this)
95 fun Double.asJsonPrimitive(): DoubleNode {
96 return DoubleNode.valueOf(this)
100 * Utility to convert Primitive object to Json Type Primitive.
102 fun <T : Any?> T.asJsonPrimitive(): JsonNode {
103 return if (this == null || this is MissingNode || this is NullNode) {
108 this.asJsonPrimitive()
110 this.asJsonPrimitive()
112 this.asJsonPrimitive()
114 this.asJsonPrimitive()
116 throw BlueprintException("$this type is not supported")
121 /** Based on Blueprint DataType Convert string value to JsonNode Type **/
122 fun String.asJsonType(bpDataType: String): JsonNode {
123 return when (bpDataType.toLowerCase()) {
124 BlueprintConstants.DATA_TYPE_STRING -> this.asJsonPrimitive()
125 BlueprintConstants.DATA_TYPE_BOOLEAN -> this.toBoolean().asJsonPrimitive()
126 BlueprintConstants.DATA_TYPE_INTEGER -> this.toInt().asJsonPrimitive()
127 BlueprintConstants.DATA_TYPE_FLOAT -> this.toFloat().asJsonPrimitive()
128 BlueprintConstants.DATA_TYPE_DOUBLE -> this.toDouble().asJsonPrimitive()
129 // For List, Map and Complex Types.
130 else -> this.jsonAsJsonType()
135 * Utility to convert Complex or Primitive object or ByteArray to Json Type.
137 fun <T : Any?> T.asJsonType(): JsonNode {
138 return if (this == null || this is MissingNode || this is NullNode) {
143 is ByteArray -> JacksonUtils.objectMapper.reader().readTree(this.inputStream())
146 this.jsonAsJsonType()
150 is Boolean -> BooleanNode.valueOf(this)
151 is Int -> IntNode.valueOf(this.toInt())
152 is Double -> DoubleNode.valueOf(this.toDouble())
153 else -> JacksonUtils.jsonNodeFromObject(this)
158 fun Map<String, *>.asJsonNode(): JsonNode {
159 return JacksonUtils.jsonNodeFromObject(this)
162 fun Map<String, *>.asObjectNode(): ObjectNode {
163 return JacksonUtils.objectNodeFromObject(this)
166 fun format(message: String, vararg args: Any?): String {
167 if (args != null && args.isNotEmpty()) {
168 return MessageFormatter.arrayFormat(message, args).message
173 fun <T : Any> Map<String, *>.castOptionalValue(key: String, valueType: KClass<T>): T? {
174 return if (containsKey(key)) {
181 fun <T : Any> Map<String, *>.castValue(key: String, valueType: KClass<T>): T {
182 if (containsKey(key)) {
185 throw BlueprintException("couldn't find the key $key")
189 fun ArrayNode.asListOfString(): List<String> {
190 return JacksonUtils.getListFromJsonNode(this, String::class.java)
193 fun JsonNode.asByteArray(): ByteArray {
194 val writer = JacksonUtils.objectMapper.writer()
195 return writer.writeValueAsBytes(this)
198 fun <T> JsonNode.asType(clazzType: Class<T>): T {
199 return JacksonUtils.readValue(this, clazzType)
200 ?: throw BlueprintException("couldn't convert JsonNode of type $clazzType")
203 fun JsonNode.asListOfString(): List<String> {
204 check(this is ArrayNode) { "JsonNode is not of type ArrayNode" }
205 return this.asListOfString()
208 fun <T : JsonNode> T?.returnNullIfMissing(): JsonNode? {
209 return if (this == null || this is NullNode || this is MissingNode) {
214 fun <T : JsonNode> T?.isNullOrMissing(): Boolean {
215 return this == null || this is NullNode || this is MissingNode
219 * Convert Json to map of json node, the root fields will be map keys
221 fun JsonNode.rootFieldsToMap(): MutableMap<String, JsonNode> {
222 if (this is ObjectNode) {
223 val propertyMap: MutableMap<String, JsonNode> = linkedMapOf()
224 this.fields().forEach {
225 propertyMap[it.key] = it.value
229 throw BlueprintException("json node should be Object Node Type")
233 fun JsonNode.removeNullNode() {
234 val it = this.iterator()
235 while (it.hasNext()) {
236 val child = it.next()
240 child.removeNullNode()
245 fun MutableMap<String, JsonNode>.putJsonElement(key: String, value: Any) {
246 val convertedValue = value.asJsonType()
247 this[key] = convertedValue
250 fun Map<String, JsonNode>.getAsString(key: String): String {
251 return this[key]?.asText() ?: throw BlueprintException("couldn't find value for key($key)")
254 fun Map<String, JsonNode>.getAsBoolean(key: String): Boolean {
255 return this[key]?.asBoolean() ?: throw BlueprintException("couldn't find value for key($key)")
258 fun Map<String, JsonNode>.getAsInt(key: String): Int {
259 return this[key]?.asInt() ?: throw BlueprintException("couldn't find value for key($key)")
262 fun Map<String, JsonNode>.getAsDouble(key: String): Double {
263 return this[key]?.asDouble() ?: throw BlueprintException("couldn't find value for key($key)")
266 fun Map<String, JsonNode>.getOptionalAsString(key: String): String? {
267 return if (this.containsKey(key)) this[key]!!.asText() else null
270 fun Map<String, JsonNode>.getOptionalAsBoolean(key: String): Boolean? {
271 return if (this.containsKey(key)) this[key]!!.asBoolean() else null
274 fun Map<String, JsonNode>.getOptionalAsInt(key: String): Int? {
275 return if (this.containsKey(key)) this[key]!!.asInt() else null
278 fun Map<String, JsonNode>.getOptionalAsDouble(key: String): Double? {
279 return if (this.containsKey(key)) this[key]!!.asDouble() else null
284 inline fun checkEquals(value1: String?, value2: String?, lazyMessage: () -> Any): Boolean {
285 if (value1.equals(value2, ignoreCase = true)) {
288 throw BlueprintException(lazyMessage().toString())
292 inline fun checkNotEmpty(value: String?, lazyMessage: () -> Any): String {
293 if (value == null || value.isEmpty()) {
294 val message = lazyMessage()
295 throw IllegalStateException(message.toString())
301 inline fun checkNotBlank(value: String?, lazyMessage: () -> Any): String {
302 if (value == null || value.isBlank()) {
303 val message = lazyMessage()
304 throw IllegalStateException(message.toString())
310 fun isNotEmpty(value: String?): Boolean {
311 return value != null && value.isNotEmpty()
314 fun isNotBlank(value: String?): Boolean {
315 return value != null && value.isNotBlank()
318 fun <T : String> T?.emptyTONull(): String? {
319 return if (this == null || this.isEmpty()) null else this
322 fun nullToEmpty(value: String?): String {
323 return if (isNotEmpty(value)) value!! else ""
326 inline fun <reified T : JsonNode> T.isComplexType(): Boolean {
327 return this is ObjectNode || this is ArrayNode
330 // Json Parsing Extensions
331 fun JsonNode.jsonPathParse(expression: String): JsonNode {
332 check(this.isComplexType()) { "$this is not complex or array node to apply expression" }
333 return JsonParserUtils.parse(this, expression)
336 // Json Path Extensions
337 fun JsonNode.jsonPaths(expression: String): List<String> {
338 check(this.isComplexType()) { "$this is not complex or array node to apply expression" }
339 return JsonParserUtils.paths(this, expression)