Fix NullpointerException in ErrorCatalogLoadPropertyService
[ccsdk/cds.git] / ms / error-catalog / services / src / main / kotlin / org / onap / ccsdk / cds / error / catalog / services / ErrorCatalogLoadService.kt
1 /*
2  *  Copyright © 2020 IBM, Bell Canada.
3  *  Modifications Copyright © 2019-2020 AT&T Intellectual Property.
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.error.catalog.services
19
20 import org.onap.ccsdk.cds.error.catalog.core.ErrorMessageLibConstants
21 import org.onap.ccsdk.cds.error.catalog.core.logger
22 import org.onap.ccsdk.cds.error.catalog.services.domain.ErrorMessageModel
23 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean
24 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
25 import org.springframework.stereotype.Service
26 import java.io.File
27 import java.io.FileNotFoundException
28 import java.io.IOException
29 import java.io.InputStream
30 import java.nio.file.Paths
31 import java.util.Properties
32
33 interface ErrorCatalogLoadService {
34
35     suspend fun loadErrorCatalog()
36
37     fun getErrorMessage(domain: String, key: String): String?
38
39     fun getErrorMessage(attribute: String): String?
40 }
41
42 /**
43  * Representation of Blueprint Error Message lib from database service to load the properties
44  */
45 @Service
46 @ConditionalOnBean(ErrorCatalogDBService::class)
47 open class ErrorCatalogLoadDBService(
48     private var errorCatalogProperties: ErrorCatalogProperties,
49     private var errorCatalogDBService: ErrorCatalogDBService
50 ) : ErrorCatalogLoadService {
51
52     private var log = logger(ErrorCatalogLoadDBService::class)
53
54     lateinit var errorMessageInDB: Map<String, ErrorMessageModel>
55
56     override suspend fun loadErrorCatalog() {
57         log.info("Application ID: ${errorCatalogProperties.applicationId} > Initializing error catalog message from database...")
58         errorMessageInDB = getErrorMessagesFromDB()
59     }
60
61     override fun getErrorMessage(domain: String, key: String): String? {
62         return getErrorMessage("$domain.${key.toLowerCase()}")
63     }
64
65     override fun getErrorMessage(attribute: String): String? {
66         val errorMessage = findErrorMessage(attribute)
67         return prepareErrorMessage(errorMessage)
68     }
69
70     /**
71      * Parses the error-messages.properties file which contains error messages
72      */
73     private suspend fun getErrorMessagesFromDB(): Map<String, ErrorMessageModel> {
74         return errorCatalogDBService.getAllErrorMessagesByApplication(errorCatalogProperties.applicationId)
75     }
76
77     private fun findErrorMessage(attribute: String): ErrorMessageModel? {
78         return if (errorMessageInDB.containsKey(attribute)) {
79             errorMessageInDB[attribute]
80         } else {
81             null
82         }
83     }
84
85     private fun prepareErrorMessage(errorMessage: ErrorMessageModel?): String? {
86         return if (errorMessage != null) {
87             "cause=${errorMessage.cause}, action=${errorMessage.action}"
88         } else {
89             null
90         }
91     }
92 }
93
94 /**
95  * Representation of Blueprint Error Message lib property service to load the properties
96  */
97 @Service
98 @ConditionalOnProperty(
99     name = [ErrorMessageLibConstants.ERROR_CATALOG_TYPE],
100     havingValue = ErrorMessageLibConstants.ERROR_CATALOG_TYPE_PROPERTIES
101 )
102 open class ErrorCatalogLoadPropertyService(private var errorCatalogProperties: ErrorCatalogProperties) :
103         ErrorCatalogLoadService {
104
105     private val propertyFileName = ErrorMessageLibConstants.ERROR_CATALOG_PROPERTIES_FILENAME
106     private lateinit var propertyFile: File
107
108     private var log = logger(ErrorCatalogLoadPropertyService::class)
109
110     lateinit var properties: Properties
111
112     override suspend fun loadErrorCatalog() {
113         log.info("Application ID: ${errorCatalogProperties.applicationId} > Initializing error catalog message from properties...")
114         val propertyDir = errorCatalogProperties.errorDefinitionDir ?: ErrorMessageLibConstants.ERROR_CATALOG_PROPERTIES_DIRECTORY
115         propertyFile = Paths.get(propertyDir, propertyFileName).toFile().normalize()
116         properties = parseErrorMessagesProps()
117     }
118
119     override fun getErrorMessage(domain: String, key: String): String? {
120         return getErrorMessage("$domain.${key.toLowerCase()}")
121     }
122
123     override fun getErrorMessage(attribute: String): String? {
124         return properties.getProperty(attribute)
125     }
126
127     /**
128      * Parses the error-messages.properties file which contains error messages
129      */
130     private fun parseErrorMessagesProps(): Properties {
131         var inputStream: InputStream? = null
132         val props = Properties()
133         try {
134             inputStream = propertyFile.inputStream()
135             props.load(inputStream)
136         } catch (e: FileNotFoundException) {
137             log.error("Application ID: ${errorCatalogProperties.applicationId} > Property File '$propertyFileName' " +
138                     "not found in the application directory.")
139         } catch (e: IOException) {
140             log.error("Application ID: ${errorCatalogProperties.applicationId} > Fail to load property file " +
141                     "'$propertyFileName' for message errors.")
142         } finally {
143             inputStream?.close()
144         }
145         return props
146     }
147 }