Configuration file runtime reload
[sdc.git] / common-app-api / src / main / java / org / openecomp / sdc / common / impl / FSConfigurationSource.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  * Modifications copyright (c) 2019 Nokia
20  * ================================================================================
21  */
22
23 package org.openecomp.sdc.common.impl;
24
25 import java.util.Arrays;
26 import java.util.stream.Collectors;
27 import org.openecomp.sdc.common.api.ConfigurationListener;
28 import org.openecomp.sdc.common.api.ConfigurationSource;
29 import org.openecomp.sdc.common.api.Constants;
30 import org.openecomp.sdc.common.api.exception.LoadConfigurationException;
31 import org.openecomp.sdc.common.util.YamlToObjectConverter;
32 import org.openecomp.sdc.exception.YamlConversionException;
33
34 /**
35  * Read configuration from file system
36  * 
37  * @author esofer
38  *
39  */
40 public class FSConfigurationSource implements ConfigurationSource {
41
42     private final YamlToObjectConverter yamlToObjectConverter = new YamlToObjectConverter();
43
44     private final ConfigFileChangeListener changeListener;
45     private final String appConfigDir;
46
47         public FSConfigurationSource(ConfigFileChangeListener changeListener, String appConfigDir) {
48                 super();
49                 this.changeListener = changeListener;
50                 this.appConfigDir = appConfigDir;
51         }
52
53         /*
54          * get and watch configuration changes. The file name we looking for is the lower case of the class name separated by "-".
55          * 
56          * (non-Javadoc)
57          * 
58          * @see org.openecomp.sdc.common.api.ConfigurationSource#getAndWatchConfiguration (java.lang.Class, org.openecomp.sdc.common.api.ConfigurationListener)
59          */
60         public <T> T getAndWatchConfiguration(final Class<T> className, final ConfigurationListener configurationListener) {
61
62                 final String configFileName = calculateFileName(className);
63
64                 T object;
65                 try {
66                         object = yamlToObjectConverter.convert(this.appConfigDir, className, configFileName);
67                 } catch (final YamlConversionException e) {
68                         final String errorMsg =
69                                 String.format("Could not load '%s' in '%s' for class '%s'", configFileName, appConfigDir, className);
70                         throw new LoadConfigurationException(errorMsg, e);
71                 }
72
73                 if (configurationListener != null && changeListener != null) {
74                         changeListener.register(configFileName, configurationListener);
75                 }
76
77                 return object;
78         }
79
80         public <T> void addWatchConfiguration(Class<T> className, ConfigurationListener configurationListener) {
81
82                 String configFileName = calculateFileName(className);
83
84                 if (configurationListener != null) {
85                         changeListener.register(configFileName, configurationListener);
86                 }
87
88         }
89
90         /**
91          * convert camel case string to list of words separated by "-" where each word is in lower case format. For example, MyClass will be calculated to be my-class.yaml .
92          * 
93          * @param className
94          * @return file name based on the class name
95          */
96     static <T> String calculateFileName(Class<T> className) {
97         String[] words = className.getSimpleName().split("(?=\\p{Upper})");
98
99         return Arrays.stream(words)
100             .map(String::toLowerCase)
101             .collect(Collectors.collectingAndThen(
102                 Collectors.joining("-"),
103                 str -> str + Constants.YAML_SUFFIX)
104             );
105     }
106
107 }