26e8f8e7bb620b054d7fc3021d3673f58d3908f8
[sdc.git] / common / openecomp-common-configuration-management / openecomp-configuration-management-core / src / main / java / org / openecomp / config / impl / ConfigurationImpl.java
1 package org.openecomp.config.impl;
2
3 import static org.openecomp.config.ConfigurationUtils.getConfigurationRepositoryKey;
4 import static org.openecomp.config.ConfigurationUtils.getProperty;
5 import static org.openecomp.config.ConfigurationUtils.isExternalLookup;
6 import static org.openecomp.config.ConfigurationUtils.isWrapperClass;
7 import static org.openecomp.config.ConfigurationUtils.isZeroLengthArray;
8
9 import static org.openecomp.config.Constants.DB_NAMESPACE;
10 import static org.openecomp.config.Constants.DEFAULT_NAMESPACE;
11 import static org.openecomp.config.Constants.DEFAULT_TENANT;
12 import static org.openecomp.config.Constants.KEY_ELEMENTS_DELEMETER;
13
14 import org.apache.commons.configuration2.Configuration;
15 import org.apache.commons.configuration2.DatabaseConfiguration;
16 import org.openecomp.config.ConfigurationUtils;
17 import org.openecomp.config.Constants;
18 import org.openecomp.config.NonConfigResource;
19 import org.openecomp.config.api.Config;
20 import org.openecomp.config.api.ConfigurationChangeListener;
21 import org.openecomp.config.api.Hint;
22
23 import java.io.File;
24 import java.lang.reflect.Constructor;
25 import java.lang.reflect.Field;
26 import java.lang.reflect.Modifier;
27 import java.net.URL;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collection;
31 import java.util.HashMap;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.function.Predicate;
37
38 /**
39  * The type Configuration.
40  */
41 public class ConfigurationImpl implements org.openecomp.config.api.Configuration {
42
43   private static ThreadLocal<String> tenant = new ThreadLocal<String>() {
44     protected String initialValue() {
45       return Constants.DEFAULT_TENANT;
46     }
47
48     ;
49   };
50   private static boolean instantiated = false;
51   /**
52    * The Change notifier.
53    */
54   ConfigurationChangeNotifier changeNotifier;
55
56   /**
57    * Instantiates a new Configuration.
58    *
59    * @throws Exception the exception
60    */
61   public ConfigurationImpl() throws Exception {
62     if (instantiated || !CliConfigurationImpl.class.isAssignableFrom(this.getClass())) {
63       throw new RuntimeException("Illegal access to configuration.");
64     }
65     Map<String, AggregateConfiguration> moduleConfigStore = new HashMap<>();
66     List<URL> classpathResources = ConfigurationUtils.getAllClassPathResources();
67     Predicate<URL> predicate = ConfigurationUtils::isConfig;
68     for (URL url : classpathResources) {
69       if (predicate.test(url)) {
70         String moduleName = getConfigurationRepositoryKey(url);
71         AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName);
72         if (moduleConfig == null) {
73           moduleConfig = new AggregateConfiguration();
74           moduleConfigStore.put(moduleName, moduleConfig);
75         }
76         moduleConfig.addConfig(url);
77       } else {
78         NonConfigResource.add(url);
79       }
80     }
81     String configLocation = System.getProperty("config.location");
82     if (configLocation != null && configLocation.trim().length() > 0) {
83       File root = new File(configLocation);
84       Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
85       Predicate<File> filePredicate = ConfigurationUtils::isConfig;
86       for (File file : filesystemResources) {
87         if (filePredicate.test(file)) {
88           String moduleName = getConfigurationRepositoryKey(file);
89           AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName);
90           if (moduleConfig == null) {
91             moduleConfig = new AggregateConfiguration();
92             moduleConfigStore.put(moduleName, moduleConfig);
93           }
94           moduleConfig.addConfig(file);
95         } else {
96           NonConfigResource.add(file);
97         }
98       }
99     }
100     String tenantConfigLocation = System.getProperty("tenant.config.location");
101     if (tenantConfigLocation != null && tenantConfigLocation.trim().length() > 0) {
102       File root = new File(tenantConfigLocation);
103       Collection<File> tenantsRoot = ConfigurationUtils.getAllFiles(root, false, true);
104       Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
105       Predicate<File> filePredicate = ConfigurationUtils::isConfig;
106       for (File file : filesystemResources) {
107         if (filePredicate.test(file)) {
108           String moduleName = ConfigurationUtils.getNamespace(file);
109           for (File tenanatFileRoot : tenantsRoot) {
110             if (file.getAbsolutePath().startsWith(tenanatFileRoot.getAbsolutePath())) {
111               moduleName = getConfigurationRepositoryKey(
112                   (tenanatFileRoot.getName().toUpperCase() + Constants.TENANT_NAMESPACE_SAPERATOR
113                       + moduleName).split(Constants.TENANT_NAMESPACE_SAPERATOR));
114             }
115           }
116           AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName);
117           if (moduleConfig == null) {
118             moduleConfig = new AggregateConfiguration();
119             moduleConfigStore.put(moduleName, moduleConfig);
120           }
121           moduleConfig.addConfig(file);
122         }
123       }
124     }
125     populateFinalConfigurationIncrementally(moduleConfigStore);
126     ConfigurationRepository.lookup().initTenantsAndNamespaces();
127     String nodeConfigLocation = System.getProperty("node.config.location");
128     if (nodeConfigLocation != null && nodeConfigLocation.trim().length() > 0) {
129       File root = new File(nodeConfigLocation);
130       Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
131       Predicate<File> filePredicate = ConfigurationUtils::isConfig;
132       for (File file : filesystemResources) {
133         if (filePredicate.test(file)) {
134           ConfigurationRepository.lookup().populateOverrideConfigurtaion(
135               getConfigurationRepositoryKey(ConfigurationUtils.getNamespace(file)
136                   .split(Constants.TENANT_NAMESPACE_SAPERATOR)), file);
137         }
138       }
139     }
140     instantiated = true;
141     changeNotifier = new ConfigurationChangeNotifier(moduleConfigStore);
142   }
143
144   @Override
145   public void addConfigurationChangeListener(String tenant, String namespace, String key,
146                                              ConfigurationChangeListener myself) {
147     tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
148         : Constants.DEFAULT_TENANT;
149     namespace =
150         ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
151             : Constants.DEFAULT_NAMESPACE;
152     if (key == null || key.trim().length() == 0) {
153       throw new IllegalArgumentException("Key can't be null.");
154     }
155     if (myself == null) {
156       throw new IllegalArgumentException("ConfigurationChangeListener instance is null.");
157     }
158     try {
159       changeNotifier.notifyChangesTowards(tenant, namespace, key, myself);
160     } catch (Exception exception) {
161       exception.printStackTrace();
162     }
163   }
164
165   private void populateFinalConfigurationIncrementally(Map<String, AggregateConfiguration> configs)
166       throws Exception {
167     boolean isDbAccessible = false;
168     if (configs.get(
169         Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE)
170         != null) {
171       ConfigurationRepository.lookup().populateConfigurtaion(
172           Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE,
173           configs.remove(
174               Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE)
175               .getFinalConfiguration());
176       isDbAccessible = ConfigurationUtils.executeDdlSql(ConfigurationRepository.lookup()
177           .getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
178           .getString("createtablecql"));
179       if (isDbAccessible) {
180         ConfigurationUtils.executeDdlSql(ConfigurationRepository.lookup()
181             .getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
182             .getString("createmonitoringtablecql"));
183       }
184     }
185
186     Set<String> modules = configs.keySet();
187     for (String module : modules) {
188       if (isDbAccessible) {
189         DatabaseConfiguration config =
190             ConfigurationUtils.getDbConfigurationBuilder(module).getConfiguration();
191         Configuration currentConfig = configs.get(module).getFinalConfiguration();
192         Iterator<String> keys = currentConfig.getKeys();
193         while (keys.hasNext()) {
194           String currentKey = keys.next();
195           if (!(Constants.MODE_KEY.equals(currentKey)
196               || Constants.NAMESPACE_KEY.equals(currentKey)
197               || Constants.LOAD_ORDER_KEY.equals(currentKey))) {
198             if (!config.containsKey(currentKey)) {
199               Object propValue = currentConfig.getProperty(currentKey);
200               if (propValue instanceof Collection) {
201                 config.addProperty(currentKey, propValue.toString());
202               } else {
203                 config.addProperty(currentKey, propValue);
204               }
205             }
206           }
207         }
208       } else {
209         ConfigurationRepository.lookup()
210             .populateConfigurtaion(module, configs.get(module).getFinalConfiguration());
211       }
212     }
213   }
214
215   @Override
216   public <T> T get(String tenant, String namespace, String key, Class<T> clazz, Hint... hints) {
217
218     String[] tenantNamespaceArrayy = null;
219     if (tenant == null && namespace != null
220         && (tenantNamespaceArrayy = namespace.split(Constants.TENANT_NAMESPACE_SAPERATOR)).length
221         > 1) {
222       tenant = tenantNamespaceArrayy[0];
223       namespace = tenantNamespaceArrayy[1];
224     }
225
226     tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
227         : Constants.DEFAULT_TENANT;
228     namespace =
229         ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
230             : Constants.DEFAULT_NAMESPACE;
231     T returnValue = null;
232     returnValue = (T) getInternal(tenant, namespace, key,
233         clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
234         hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
235             : hints);
236     if ((returnValue == null || isZeroLengthArray(clazz, returnValue))
237         && !Constants.DEFAULT_TENANT.equals(tenant)) {
238       returnValue = (T) getInternal(Constants.DEFAULT_TENANT, namespace, key,
239           clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
240           hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
241               : hints);
242     }
243     if ((returnValue == null || isZeroLengthArray(clazz, returnValue))
244         && !Constants.DEFAULT_NAMESPACE.equals(namespace)) {
245       returnValue = (T) getInternal(tenant, Constants.DEFAULT_NAMESPACE, key,
246           clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
247           hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
248               : hints);
249     }
250     if ((returnValue == null ||isZeroLengthArray(clazz, returnValue))
251         && !Constants.DEFAULT_NAMESPACE.equals(namespace)
252         && !Constants.DEFAULT_TENANT.equals(tenant)) {
253       returnValue = (T) getInternal(Constants.DEFAULT_TENANT, Constants.DEFAULT_NAMESPACE, key,
254           clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
255           hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
256               : hints);
257     }
258     if (returnValue == null && clazz.isPrimitive()) {
259       return (T) ConfigurationUtils.getDefaultFor(clazz);
260     } else {
261       return returnValue;
262     }
263   }
264
265
266   /**
267    * Gets internal.
268    *
269    * @param <T>       the type parameter
270    * @param tenant    the tenant
271    * @param namespace the namespace
272    * @param key       the key
273    * @param clazz     the clazz
274    * @param hints     the hints
275    * @return the internal
276    */
277   protected <T> T getInternal(String tenant, String namespace, String key, Class<T> clazz,
278                               Hint... hints) {
279     int processingHints = Hint.DEFAULT.value();
280     if (hints != null) {
281       for (Hint hint : hints) {
282         processingHints = processingHints | hint.value();
283       }
284     }
285
286     if (tenant == null || tenant.trim().length() == 0) {
287       tenant = this.tenant.get();
288     } else {
289       tenant = tenant.toUpperCase();
290     }
291     if (namespace == null || namespace.trim().length() == 0) {
292       namespace = Constants.DEFAULT_NAMESPACE;
293     } else {
294       namespace = namespace.toUpperCase();
295     }
296     if (key == null || key.trim().length() == 0) {
297       if (!clazz.isAnnotationPresent(Config.class)) {
298         throw new IllegalArgumentException("Key can't be null.");
299       }
300     }
301     if (clazz == null) {
302       throw new IllegalArgumentException("clazz is null.");
303     }
304     if (clazz.isPrimitive()) {
305       clazz = getWrapperClass(clazz);
306     }
307     try {
308       if (isWrapperClass(clazz) || clazz.isPrimitive()) {
309         Object obj =
310             getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace),
311                 key, processingHints);
312         if (obj != null) {
313           if (ConfigurationUtils.isCollection(obj.toString())) {
314             obj = ConfigurationUtils.getCollectionString(obj.toString());
315           }
316           String value = obj.toString().split(",")[0];
317           value = ConfigurationUtils.processVariablesIfPresent(tenant, namespace, value);
318           return (T) getValue(value, clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
319               processingHints);
320         } else {
321           return null;
322         }
323       } else if (clazz.isArray()
324           && (clazz.getComponentType().isPrimitive() || isWrapperClass(clazz.getComponentType()))) {
325         Object obj =
326             getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace),
327                 key, processingHints);
328         if (obj != null) {
329           Class componentClass = clazz.getComponentType();
330           if (clazz.getComponentType().isPrimitive()) {
331             componentClass = getWrapperClass(clazz.getComponentType());
332           }
333           String collString = ConfigurationUtils.getCollectionString(obj.toString());
334           ArrayList<String> tempCollection = new ArrayList<>();
335           for (String itemValue : collString.split(",")) {
336             tempCollection
337                 .add(ConfigurationUtils.processVariablesIfPresent(tenant, namespace, itemValue));
338           }
339           Collection<T> collection = convert(
340               ConfigurationUtils.getCollectionString(Arrays.toString(tempCollection.toArray())),
341               componentClass, processingHints);
342           if (clazz.getComponentType().isPrimitive()) {
343             return (T) ConfigurationUtils.getPrimitiveArray(collection, clazz.getComponentType());
344           } else {
345             return (T) collection
346                 .toArray(getZeroLengthArrayFor(getWrapperClass(clazz.getComponentType())));
347           }
348         } else {
349           return null;
350         }
351       } else if (clazz.isAnnotationPresent(Config.class)) {
352         return read(tenant, namespace, clazz,
353             (key == null || key.trim().length() == 0) ? "" : (key + "."), hints);
354       } else {
355         throw new IllegalArgumentException(
356             "Only pimitive classes, wrapper classes, corresponding array classes and any "
357                 + "class decorated with @org.openecomp.config.api.Config are allowed as argument.");
358       }
359     } catch (Exception exception) {
360       exception.printStackTrace();
361     }
362     return null;
363   }
364
365
366   private <T> T read(String tenant, String namespace, Class<T> clazz, String keyPrefix,
367                      Hint... hints) throws Exception {
368     org.openecomp.config.api.Config confAnnot =
369         clazz.getAnnotation(org.openecomp.config.api.Config.class);
370     if (confAnnot != null && confAnnot.key().length()>0 && !keyPrefix.endsWith(".")) {
371       keyPrefix += (confAnnot.key() + ".");
372     }
373     Constructor<T> constructor = clazz.getDeclaredConstructor();
374     constructor.setAccessible(true);
375     T objToReturn = constructor.newInstance();
376     for (Field field : clazz.getDeclaredFields()) {
377       field.setAccessible(true);
378       org.openecomp.config.api.Config fieldConfAnnot =
379           field.getAnnotation(org.openecomp.config.api.Config.class);
380       if (fieldConfAnnot != null) {
381         if (field.getType().isPrimitive() || isWrapperClass(field.getType())
382             || (field.getType().isArray() && (field.getType().getComponentType().isPrimitive()
383             || isWrapperClass(field.getType().getComponentType())))
384             || field.getType().getAnnotation(org.openecomp.config.api.Config.class) != null) {
385           field.set(objToReturn,
386               get(tenant, namespace, keyPrefix + fieldConfAnnot.key(), field.getType(), hints));
387         } else if (Collection.class.isAssignableFrom(field.getType())) {
388           Object obj = get(tenant, namespace, keyPrefix + fieldConfAnnot.key(),
389               ConfigurationUtils.getArrayClass(ConfigurationUtils.getCollectionGenericType(field)),
390               hints);
391           if (obj != null) {
392             List list = Arrays.asList((Object[]) obj);
393             Class clazzToInstantiate = null;
394             if (field.getType().isInterface()) {
395               clazzToInstantiate =
396                   ConfigurationUtils.getConcreteCollection(field.getType()).getClass();
397             } else if (Modifier.isAbstract(field.getType().getModifiers())) {
398               clazzToInstantiate =
399                   ConfigurationUtils.getCompatibleCollectionForAbstractDef(field.getType())
400                       .getClass();
401             } else {
402               clazzToInstantiate = field.getType();
403             }
404             Constructor construct =
405                 getConstructorWithArguments(clazzToInstantiate, Collection.class);
406             if (construct != null) {
407               construct.setAccessible(true);
408               field.set(objToReturn, construct.newInstance(list));
409             } else if ((construct =
410                 getConstructorWithArguments(clazzToInstantiate, Integer.class, Boolean.class,
411                     Collection.class)) != null) {
412               construct.setAccessible(true);
413               field.set(objToReturn, construct.newInstance(list.size(), true, list));
414             }
415           }
416         }else if (Map.class.isAssignableFrom(field.getType())){
417           field.set(objToReturn, generateMap(tenant, namespace, keyPrefix+fieldConfAnnot.key()));
418         }
419       }
420     }
421     return objToReturn;
422   }
423
424   private Constructor getConstructorWithArguments(Class clazz, Class... classes) {
425     try {
426       return clazz.getDeclaredConstructor(classes);
427     } catch (Exception exception) {
428       return null;
429     }
430   }
431
432   private Class getWrapperClass(Class clazz) {
433     if (byte.class == clazz) {
434       return Byte.class;
435     } else if (short.class == clazz) {
436       return Short.class;
437     } else if (int.class == clazz) {
438       return Integer.class;
439     } else if (long.class == clazz) {
440       return Long.class;
441     } else if (float.class == clazz) {
442       return Float.class;
443     } else if (double.class == clazz) {
444       return Double.class;
445     } else if (char.class == clazz) {
446       return Character.class;
447     } else if (boolean.class == clazz) {
448       return Boolean.class;
449     }
450     return clazz;
451   }
452
453   private <T> T getValue(Object obj, Class<T> clazz, int processingHint) {
454     if (obj == null || obj.toString().trim().length() == 0) {
455       return null;
456     } else {
457       obj = obj.toString().trim();
458     }
459     if (String.class.equals(clazz)) {
460       if (obj.toString().startsWith("@") && isExternalLookup(processingHint)) {
461         String contents = ConfigurationUtils
462             .getFileContents(NonConfigResource.locate(obj.toString().substring(1).trim()));
463         if (contents == null) {
464           contents = ConfigurationUtils.getFileContents(obj.toString().substring(1).trim());
465         }
466         if (contents != null) {
467           obj = contents;
468         }
469       }
470       return (T) obj.toString();
471     } else if (Number.class.isAssignableFrom(clazz)) {
472       Double doubleValue = Double.valueOf(obj.toString());
473       switch (clazz.getName()) {
474         case "java.lang.Byte":
475           Byte byteVal = doubleValue.byteValue();
476           return (T) byteVal;
477         case "java.lang.Short":
478           Short shortVal = doubleValue.shortValue();
479           return (T) shortVal;
480         case "java.lang.Integer":
481           Integer intVal = doubleValue.intValue();
482           return (T) intVal;
483         case "java.lang.Long":
484           Long longVal = doubleValue.longValue();
485           return (T) longVal;
486         case "java.lang.Float":
487           Float floatVal = doubleValue.floatValue();
488           return (T) floatVal;
489         case "java.lang.Double":
490           Double doubleVal = doubleValue.doubleValue();
491           return (T) doubleVal;
492         default:
493       }
494     } else if (Boolean.class.equals(clazz)) {
495       return (T) Boolean.valueOf(obj.toString());
496     } else if (Character.class.equals(clazz)) {
497       return (T) Character.valueOf(obj.toString().charAt(0));
498     }
499     return null;
500   }
501
502   private <T> T[] getZeroLengthArrayFor(Class<T> clazz) {
503     Object obj = null;
504     if (clazz == int.class) {
505       obj = new int[]{};
506     } else if (clazz == byte.class) {
507       obj = new byte[]{};
508     } else if (clazz == short.class) {
509       obj = new short[]{};
510     } else if (clazz == long.class) {
511       obj = new long[]{};
512     } else if (clazz == float.class) {
513       obj = new float[]{};
514     } else if (clazz == double.class) {
515       obj = new double[]{};
516     } else if (clazz == boolean.class) {
517       obj = new boolean[]{};
518     } else if (clazz == char.class) {
519       obj = new char[]{};
520     } else if (clazz == Byte.class) {
521       obj = new Byte[]{};
522     } else if (clazz == Short.class) {
523       obj = new Short[]{};
524     } else if (clazz == Integer.class) {
525       obj = new Integer[]{};
526     } else if (clazz == Long.class) {
527       obj = new Long[]{};
528     } else if (clazz == Float.class) {
529       obj = new Float[]{};
530     } else if (clazz == Double.class) {
531       obj = new Double[]{};
532     } else if (clazz == Boolean.class) {
533       obj = new Boolean[]{};
534     } else if (clazz == Character.class) {
535       obj = new Character[]{};
536     } else if (clazz == String.class) {
537       obj = new String[]{};
538     }
539     return (T[]) obj;
540   }
541
542   private <T> Collection<T> convert(String commaSaperatedValues, Class<T> clazz,
543                                     int processingHints) {
544     ArrayList<T> collection = new ArrayList<>();
545     for (String value : commaSaperatedValues.split(",")) {
546       try {
547         T type1 = getValue(value, clazz, processingHints);
548         if (type1 != null) {
549           collection.add(type1);
550         }
551       } catch (RuntimeException re) {
552         // do nothing
553       }
554     }
555     return collection;
556   }
557
558   /**
559    * Shutdown.
560    */
561   public void shutdown() {
562     if (changeNotifier != null) {
563       try {
564         changeNotifier.shutdown();
565         ConfigurationDataSource.lookup().close();
566       } catch (Exception exception) {
567         exception.printStackTrace();
568       }
569     }
570   }
571
572   @Override
573   public void removeConfigurationChangeListener(String tenant, String namespace, String key,
574                                                 ConfigurationChangeListener myself) {
575     tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
576         : Constants.DEFAULT_TENANT;
577     namespace =
578         ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
579             : Constants.DEFAULT_NAMESPACE;
580     if (key == null || key.trim().length() == 0) {
581       throw new IllegalArgumentException("Key can't be null.");
582     }
583     try {
584       changeNotifier.stopNotificationTowards(tenant, namespace, key, myself);
585     } catch (Exception exception) {
586       exception.printStackTrace();
587     }
588   }
589
590   @Override
591   public <T> Map<String, T> populateMap(String tenantId, String namespace, String key, Class<T> clazz){
592     if (tenantId==null || tenantId.trim().length()==0){
593       tenantId = this.tenant.get();
594     }else{
595       tenantId = tenantId.toUpperCase();
596     }
597     if (namespace==null || namespace.trim().length()==0){
598       namespace = DEFAULT_NAMESPACE;
599     }else{
600       namespace = namespace.toUpperCase();
601     }
602     Map<String, T> map = new HashMap<>();
603     Iterator<String> keys ;
604     try {
605       if (ConfigurationRepository.lookup().isDBAccessible()){
606         keys = ConfigurationUtils.executeSelectSql(ConfigurationRepository.lookup().getConfigurationFor(DEFAULT_TENANT, DB_NAMESPACE).getString("fetchkeysql"), new String[]{tenantId+KEY_ELEMENTS_DELEMETER+namespace}).iterator();
607       }else{
608         keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys(key);
609       }
610       while(keys.hasNext()){
611         String k = keys.next();
612         if (k.startsWith(key+".")){
613           k = k.substring(key.length()+1);
614           String subkey = k.substring(0, k.indexOf("."));
615           if (!map.containsKey(subkey)){
616             map.put(subkey, get(tenantId, namespace, key+"."+subkey, clazz));
617           }
618         }
619       }
620     }catch (Exception e){
621       e.printStackTrace();
622     }
623     return map;
624   }
625
626   @Override
627   public Map generateMap(String tenantId, String namespace, String key){
628     if (tenantId==null || tenantId.trim().length()==0){
629       tenantId = this.tenant.get();
630     }else{
631       tenantId = tenantId.toUpperCase();
632     }
633     if (namespace==null || namespace.trim().length()==0){
634       namespace = DEFAULT_NAMESPACE;
635     }else{
636       namespace = namespace.toUpperCase();
637     }
638     Map map, parentMap = new HashMap<>();
639     Iterator<String> keys ;
640     try {
641       if (ConfigurationRepository.lookup().isDBAccessible()){
642         keys = ConfigurationUtils.executeSelectSql(ConfigurationRepository.lookup().getConfigurationFor(DEFAULT_TENANT, DB_NAMESPACE).getString("fetchkeysql"), new String[]{tenantId+KEY_ELEMENTS_DELEMETER+namespace}).iterator();
643       }else{
644         if (key==null || key.trim().length()==0){
645           keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys();
646         }else{
647           keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys(key);
648         }
649       }
650       while(keys.hasNext()){
651         map = parentMap;
652         String k = keys.next();
653
654         if (key!=null && key.trim().length()!=0 && !k.startsWith(key+".")){
655           continue;
656         }
657         String value = getAsString(tenantId, namespace, k);
658         if (key!=null && key.trim().length()!=0 && k.startsWith(key+".")){
659           k = k.substring(key.trim().length()+1);
660         }
661
662         while(k.contains(".")){
663           if (k.contains(".")){
664             String subkey = k.substring(0, k.indexOf("."));
665             k = k.substring(k.indexOf(".")+1);
666             if (!map.containsKey(subkey)){
667               map.put(subkey, map=new HashMap<>());
668             }else{
669               map = (Map)map.get(subkey);
670             }
671           }
672         }
673         map.put(k, value);
674       }
675     }catch (Exception e){
676       e.printStackTrace();
677     }
678     return parentMap;
679   }
680
681
682
683
684 }