Merge "Improve script file accessing through cache."
[ccsdk/cds.git] / ms / controllerblueprints / modules / blueprint-core / src / main / kotlin / org / onap / ccsdk / cds / controllerblueprints / core / CustomFunctions.kt
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  * Modifications Copyright © 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
18 package org.onap.ccsdk.cds.controllerblueprints.core
19
20 import com.fasterxml.jackson.databind.JsonNode
21 import com.fasterxml.jackson.databind.node.*
22 import org.apache.commons.lang3.ObjectUtils
23 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
24 import org.slf4j.LoggerFactory
25 import org.slf4j.helpers.MessageFormatter
26 import kotlin.reflect.KClass
27
28 /**
29  *
30  *
31  * @author Brinda Santh
32  */
33
34 fun <T : Any> logger(clazz: T) = LoggerFactory.getLogger(clazz.javaClass)!!
35
36 fun <T : KClass<*>> logger(clazz: T) = LoggerFactory.getLogger(clazz.java)!!
37
38
39 fun <T : Any> T.bpClone(): T {
40     return ObjectUtils.clone(this)
41 }
42
43 fun String.isJson(): Boolean {
44     return ((this.startsWith("{") && this.endsWith("}"))
45             || (this.startsWith("[") && this.endsWith("]")))
46 }
47
48 fun Any.asJsonString(intend: Boolean? = false): String {
49     return JacksonUtils.getJson(this, intend!!)
50 }
51
52 fun String.asJsonPrimitive(): TextNode {
53     return TextNode(this)
54 }
55
56 // If you know the string is json content, then use the function directly
57 fun String.jsonAsJsonType(): JsonNode {
58     return JacksonUtils.jsonNode(this.trim())
59 }
60
61 fun Boolean.asJsonPrimitive(): BooleanNode {
62     return BooleanNode.valueOf(this)
63 }
64
65 fun Int.asJsonPrimitive(): IntNode {
66     return IntNode.valueOf(this)
67 }
68
69 fun Double.asJsonPrimitive(): DoubleNode {
70     return DoubleNode.valueOf(this)
71 }
72
73 /**
74  * Utility to convert Primitive object to Json Type Primitive.
75  */
76 fun <T : Any?> T.asJsonPrimitive(): JsonNode {
77     return if (this == null || this is MissingNode || this is NullNode) {
78         NullNode.instance
79     } else {
80         when (this) {
81             is String ->
82                 this.asJsonPrimitive()
83             is Boolean ->
84                 this.asJsonPrimitive()
85             is Int ->
86                 this.asJsonPrimitive()
87             is Double ->
88                 this.asJsonPrimitive()
89             else ->
90                 throw BluePrintException("$this type is not supported")
91         }
92     }
93 }
94
95 /**
96  * Utility to convert Complex or Primitive object to Json Type.
97  */
98 fun <T : Any?> T.asJsonType(): JsonNode {
99     return if (this == null || this is MissingNode || this is NullNode) {
100         NullNode.instance
101     } else {
102         when (this) {
103             is JsonNode ->
104                 this
105             is String -> {
106                 if (this.isJson())
107                     this.jsonAsJsonType()
108                 else
109                     TextNode(this)
110             }
111             is Boolean ->
112                 BooleanNode.valueOf(this)
113             is Int ->
114                 IntNode.valueOf(this.toInt())
115             is Double ->
116                 DoubleNode.valueOf(this.toDouble())
117             else ->
118                 JacksonUtils.jsonNodeFromObject(this)
119         }
120     }
121 }
122
123 fun Map<String, *>.asJsonNode(): JsonNode {
124     return JacksonUtils.jsonNodeFromObject(this)
125 }
126
127 fun Map<String, *>.asObjectNode(): ObjectNode {
128     return JacksonUtils.objectNodeFromObject(this)
129 }
130
131 fun format(message: String, vararg args: Any?): String {
132     if (args != null && args.isNotEmpty()) {
133         return MessageFormatter.arrayFormat(message, args).message
134     }
135     return message
136 }
137
138 fun <T : Any> Map<String, *>.castOptionalValue(key: String, valueType: KClass<T>): T? {
139     return if (containsKey(key)) {
140         get(key) as? T
141     } else {
142         null
143     }
144 }
145
146 fun <T : Any> Map<String, *>.castValue(key: String, valueType: KClass<T>): T {
147     if (containsKey(key)) {
148         return get(key) as T
149     } else {
150         throw BluePrintException("couldn't find the key $key")
151     }
152 }
153
154 fun ArrayNode.asListOfString(): List<String> {
155     return JacksonUtils.getListFromJsonNode(this, String::class.java)
156 }
157
158 fun JsonNode.returnNullIfMissing(): JsonNode? {
159     return if (this is NullNode || this is MissingNode) {
160         null
161     } else this
162 }
163
164 fun <T : JsonNode> T?.isNull(): Boolean {
165     return this == null || this is NullNode || this is MissingNode
166 }
167
168 fun <T : JsonNode> T?.isNotNull(): Boolean {
169     return !(this == null || this is NullNode || this is MissingNode)
170 }
171
172 /**
173  * Convert Json to map of json node, the root fields will be map keys
174  */
175 fun JsonNode.rootFieldsToMap(): MutableMap<String, JsonNode> {
176     if (this is ObjectNode) {
177         val propertyMap: MutableMap<String, JsonNode> = linkedMapOf()
178         this.fields().forEach {
179             propertyMap[it.key] = it.value
180         }
181         return propertyMap
182     } else {
183         throw BluePrintException("json node should be Object Node Type")
184     }
185 }
186
187 fun JsonNode.removeNullNode() {
188     val it = this.iterator()
189     while (it.hasNext()) {
190         val child = it.next()
191         if (child.isNull) {
192             it.remove()
193         } else {
194             child.removeNullNode()
195         }
196     }
197 }
198
199
200 fun MutableMap<String, JsonNode>.putJsonElement(key: String, value: Any) {
201     val convertedValue = value.asJsonType()
202     this[key] = convertedValue
203 }
204
205 fun Map<String, JsonNode>.getAsString(key: String): String {
206     return this[key]?.asText() ?: throw BluePrintException("couldn't find value for key($key)")
207 }
208
209 fun Map<String, JsonNode>.getAsBoolean(key: String): Boolean {
210     return this[key]?.asBoolean() ?: throw BluePrintException("couldn't find value for key($key)")
211 }
212
213 fun Map<String, JsonNode>.getAsInt(key: String): Int {
214     return this[key]?.asInt() ?: throw BluePrintException("couldn't find value for key($key)")
215 }
216
217 fun Map<String, JsonNode>.getAsDouble(key: String): Double {
218     return this[key]?.asDouble() ?: throw BluePrintException("couldn't find value for key($key)")
219 }
220
221 // Checks
222
223 inline fun checkEquals(value1: String?, value2: String?, lazyMessage: () -> Any): Boolean {
224     if (value1.equals(value2, ignoreCase = true)) {
225         return true
226     } else {
227         throw BluePrintException(lazyMessage().toString())
228     }
229 }
230
231 inline fun checkNotEmpty(value: String?, lazyMessage: () -> Any): String {
232     if (value == null || value.isEmpty()) {
233         val message = lazyMessage()
234         throw IllegalStateException(message.toString())
235     } else {
236         return value
237     }
238 }
239
240 inline fun checkNotBlank(value: String?, lazyMessage: () -> Any): String {
241     if (value == null || value.isBlank()) {
242         val message = lazyMessage()
243         throw IllegalStateException(message.toString())
244     } else {
245         return value
246     }
247 }
248
249 fun isNotEmpty(value: String?): Boolean {
250     return value != null && value.isNotEmpty()
251 }
252
253 fun isNotBlank(value: String?): Boolean {
254     return value != null && value.isNotBlank()
255 }
256
257
258 fun nullToEmpty(value: String?): String {
259     return if (isNotEmpty(value)) value!! else ""
260 }
261
262 inline fun <reified T : JsonNode> T.isComplexType(): Boolean {
263     return this is ObjectNode || this is ArrayNode
264 }
265
266