db64f7f7fcd5c3e807c0659c7d9e0e0631000549
[sdc.git] / common / onap-common-configuration-management / onap-configuration-management-core / src / main / java / org / onap / config / ConfigurationUtils.java
1 package org.onap.config;
2
3 import com.google.common.collect.ImmutableMap;
4 import com.virtlink.commons.configuration2.jackson.JsonConfiguration;
5 import net.sf.corn.cps.CPScanner;
6 import net.sf.corn.cps.ResourceFilter;
7 import org.apache.commons.configuration2.CompositeConfiguration;
8 import org.apache.commons.configuration2.Configuration;
9 import org.apache.commons.configuration2.FileBasedConfiguration;
10 import org.apache.commons.configuration2.PropertiesConfiguration;
11 import org.apache.commons.configuration2.XMLConfiguration;
12 import org.apache.commons.configuration2.builder.BasicConfigurationBuilder;
13 import org.apache.commons.configuration2.builder.ReloadingFileBasedConfigurationBuilder;
14 import org.apache.commons.configuration2.builder.fluent.Configurations;
15 import org.apache.commons.configuration2.builder.fluent.Parameters;
16 import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
17 import org.apache.commons.configuration2.ex.ConfigurationException;
18 import org.apache.commons.io.IOUtils;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21 import org.onap.config.api.Config;
22 import org.onap.config.api.ConfigurationManager;
23 import org.onap.config.impl.ConfigurationRepository;
24 import org.onap.config.impl.YamlConfiguration;
25 import org.onap.config.impl.AgglomerateConfiguration;
26 import org.onap.config.impl.ConfigurationDataSource;
27 import org.onap.config.type.ConfigurationMode;
28 import org.onap.config.type.ConfigurationType;
29  
30 import javax.sql.DataSource;
31 import java.io.File;
32 import java.lang.reflect.Field;
33 import java.lang.reflect.ParameterizedType;
34 import java.lang.reflect.Type;
35 import java.net.URL;
36 import java.nio.file.Files;
37 import java.nio.file.Path;
38 import java.sql.Connection;
39 import java.sql.PreparedStatement;
40 import java.sql.ResultSet;
41 import java.sql.Statement;
42 import java.util.ArrayDeque;
43 import java.util.ArrayList;
44 import java.util.Arrays;
45 import java.util.Collection;
46 import java.util.Deque;
47 import java.util.HashMap;
48 import java.util.HashSet;
49 import java.util.Iterator;
50 import java.util.LinkedHashMap;
51 import java.util.List;
52 import java.util.Map;
53 import java.util.Optional;
54 import java.util.Queue;
55 import java.util.Set;
56 import java.util.SortedSet;
57 import java.util.TreeSet;
58 import java.util.concurrent.BlockingQueue;
59 import java.util.concurrent.ConcurrentLinkedQueue;
60 import java.util.concurrent.Executors;
61 import java.util.concurrent.LinkedBlockingQueue;
62 import java.util.concurrent.LinkedTransferQueue;
63 import java.util.concurrent.ThreadFactory;
64 import java.util.concurrent.TransferQueue;
65 import java.util.regex.Matcher;
66 import java.util.regex.Pattern;
67 import java.util.stream.Collectors;
68 import java.util.stream.Stream;
69
70 import java.util.concurrent.Executors;
71 import java.util.concurrent.ThreadFactory;
72 import java.util.stream.Collectors;
73 import java.util.stream.Stream;
74
75 import static com.google.common.collect.ImmutableMap.builder;
76
77 import static java.util.Optional.ofNullable;
78 import static org.onap.config.api.Hint.EXTERNAL_LOOKUP;
79 import static org.onap.config.api.Hint.LATEST_LOOKUP;
80 import static org.onap.config.api.Hint.NODE_SPECIFIC;
81
82
83 import static com.google.common.collect.ImmutableMap.builder;
84 import static org.onap.config.api.Hint.*;
85
86 /**
87  * The type Configuration utils.
88  */
89 public class ConfigurationUtils {
90     private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationUtils.class);
91
92     private ConfigurationUtils() {
93     }
94
95     private static ImmutableMap<Class, Class> arrayClassMap;
96
97     static {
98         ImmutableMap.Builder<Class, Class> builder = builder();
99         builder.put(Byte.class, Byte[].class).put(Short.class, Short[].class)
100                 .put(Integer.class, Integer[].class).put(Long.class, Long[].class)
101                 .put(Float.class, Float[].class).put(Double.class, Double[].class)
102                 .put(Boolean.class, Boolean[].class).put(Character.class, Character[].class)
103                 .put(String.class, String[].class);
104         arrayClassMap = builder.build();
105     }
106
107     /**
108      * Gets thread factory.
109      *
110      * @return the thread factory
111      */
112     public static ThreadFactory getThreadFactory() {
113         return (r1) -> {
114             Thread thread = Executors.privilegedThreadFactory().newThread(r1);
115             thread.setDaemon(true);
116             return thread;
117         };
118     }
119
120     /**
121      * Gets all files.
122      *
123      * @param file          the file
124      * @param recursive     the recursive
125      * @param onlyDirectory the only directory
126      * @return the all files
127      */
128     public static Collection<File> getAllFiles(File file, boolean recursive, boolean onlyDirectory) {
129         ArrayList<File> collection = new ArrayList<>();
130         if (file.isDirectory() && file.exists()) {
131             File[] files = file.listFiles();
132             for (File innerFile : files) {
133                 if (innerFile.isFile() && !onlyDirectory) {
134                     collection.add(innerFile);
135                 } else if (innerFile.isDirectory()) {
136                     collection.add(innerFile);
137                     if (recursive) {
138                         collection.addAll(getAllFiles(innerFile, recursive, onlyDirectory));
139                     }
140                 }
141             }
142         }
143         return collection;
144     }
145
146     /**
147      * Gets comma saperated list.
148      *
149      * @param list the list
150      * @return the comma separated list
151      */
152     public static String getCommaSeparatedList(List list) {
153         return ((Stream<String>) list.stream().filter(o -> o != null && !o.toString().trim().isEmpty()).map(o -> o.toString().trim())).collect(Collectors.joining(","));
154     }
155
156     /**
157      * Gets comma saperated list.
158      *
159      * @param list the list
160      * @return the comma saperated list
161      */
162     public static String getCommaSeparatedList(String[] list) {
163         return getCommaSeparatedList(list == null ? Arrays.asList() : Arrays.asList(list));
164     }
165
166     /**
167      * Gets config type.
168      *
169      * @param url the url
170      * @return the config type
171      */
172     public static ConfigurationType getConfigType(URL url) {
173         return Enum.valueOf(ConfigurationType.class,
174                 url.getFile().substring(url.getFile().lastIndexOf('.') + 1).toUpperCase());
175     }
176
177     /**
178      * Gets config type.
179      *
180      * @param file the file
181      * @return the config type
182      */
183     public static ConfigurationType getConfigType(File file) {
184         return Enum.valueOf(ConfigurationType.class,
185                 file.getAbsolutePath().substring(file.getAbsolutePath().lastIndexOf('.') + 1)
186                         .toUpperCase());
187     }
188
189     /**
190      * Is config boolean.
191      *
192      * @param url the url
193      * @return the boolean
194      */
195     public static boolean isConfig(URL url) {
196         return isConfig(url.getFile());
197     }
198
199     /**
200      * Is config boolean.
201      *
202      * @param file the file
203      * @return the boolean
204      */
205     public static boolean isConfig(File file) {
206         return file != null && file.exists() && isConfig(file.getName());
207     }
208
209     /**
210      * Is config boolean.
211      *
212      * @param file the file
213      * @return the boolean
214      */
215     public static boolean isConfig(String file) {
216         file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
217         file = file.substring(file.lastIndexOf('/') + 1);
218         return file.matches(
219                 "CONFIG(-\\w*){0,1}(-" + "(" + ConfigurationMode.OVERRIDE + "|" + ConfigurationMode.MERGE
220                         + "|" + ConfigurationMode.UNION + ")){0,1}" + "\\.("
221                         + ConfigurationType.PROPERTIES.name() + "|" + ConfigurationType.XML.name() + "|"
222                         + ConfigurationType.JSON.name() + "|" + ConfigurationType.YAML.name() + ")$")
223                 || file.matches("CONFIG(.)*\\.(" + ConfigurationType.PROPERTIES.name() + "|"
224                 + ConfigurationType.XML.name() + "|" + ConfigurationType.JSON.name() + "|"
225                 + ConfigurationType.YAML.name() + ")$");
226     }
227
228     /**
229      * Gets namespace.
230      *
231      * @param url the url
232      * @return the namespace
233      */
234     public static String getNamespace(URL url) {
235
236         Optional<String> namespace = getConfiguration(url).flatMap(ConfigurationUtils::getNamespace).map(String::toUpperCase);
237
238         return namespace.orElseGet(() -> getNamespace(url.getFile().toUpperCase()));
239     }
240
241     /**
242      * Gets namespace.
243      *
244      * @param file the file
245      * @return the namespace
246      */
247     public static String getNamespace(File file) {
248         Optional<String> namespace = getConfiguration(file)
249                 .flatMap(ConfigurationUtils::getNamespace)
250                 .map(String::toUpperCase);
251         return namespace.orElseGet(() -> getNamespace(file.getName().toUpperCase()));
252     }
253
254     private static Optional<String> getNamespace(Configuration config) {
255         return ofNullable(config)
256                 .flatMap(configuration -> ofNullable(configuration.getString(Constants.NAMESPACE_KEY)))
257                 .map(String::toUpperCase);
258     }
259
260     /**
261      * Gets namespace.
262      *
263      * @param file the file
264      * @return the namespace
265      */
266     public static String getNamespace(String file) {
267         file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
268         file = file.substring(file.lastIndexOf('/') + 1);
269         Pattern pattern = Pattern.compile(
270                 "CONFIG(-\\w*){0,1}(-" + "(" + ConfigurationMode.OVERRIDE + "|" + ConfigurationMode.MERGE
271                         + "|" + ConfigurationMode.UNION + ")){0,1}" + "\\.("
272                         + ConfigurationType.PROPERTIES.name() + "|" + ConfigurationType.XML.name() + "|"
273                         + ConfigurationType.JSON.name() + "|" + ConfigurationType.YAML.name() + ")$");
274         Matcher matcher = pattern.matcher(file);
275         boolean b1 = matcher.matches();
276         if (b1) {
277             if (matcher.group(1) != null) {
278                 String moduleName = matcher.group(1).substring(1);
279                 return moduleName.equalsIgnoreCase(ConfigurationMode.OVERRIDE.name())
280                         || moduleName.equalsIgnoreCase(ConfigurationMode.UNION.name())
281                         || moduleName.equalsIgnoreCase(ConfigurationMode.MERGE.name())
282                         ? Constants.DEFAULT_NAMESPACE : moduleName;
283             } else {
284                 return Constants.DEFAULT_NAMESPACE;
285             }
286         } else if (isConfig(file)) {
287             return Constants.DEFAULT_NAMESPACE;
288         }
289
290         return null;
291     }
292
293     /**
294      * Gets merge strategy.
295      *
296      * @param url the url
297      * @return the merge strategy
298      */
299     public static ConfigurationMode getMergeStrategy(URL url) {
300         Optional<ConfigurationMode> configurationMode = getConfiguration(url).flatMap(ConfigurationUtils::getMergeStrategy).flatMap(ConfigurationUtils::convertConfigurationMode);
301         return configurationMode.orElseGet(() -> getMergeStrategy(url.getFile().toUpperCase()));
302     }
303
304     private static Optional<ConfigurationMode> convertConfigurationMode(String configMode) {
305         ConfigurationMode configurationMode = null;
306         try {
307             configurationMode = ConfigurationMode.valueOf(configMode);
308         } catch (Exception exception) {
309             LOGGER.error("Could not find convert {} into configuration mode", configMode);
310         }
311         return Optional.ofNullable(configurationMode);
312     }
313
314     private static Optional<String> getMergeStrategy(Configuration config) {
315         return ofNullable(config)
316                 .flatMap(configuration -> ofNullable(configuration.getString(Constants.MODE_KEY)))
317                 .map(String::toUpperCase);
318     }
319
320
321     /**
322      * Gets merge strategy.
323      *
324      * @param file the file
325      * @return the merge strategy
326      */
327     public static ConfigurationMode getMergeStrategy(File file) {
328         Optional<ConfigurationMode> configurationMode = getConfiguration(file).flatMap(ConfigurationUtils::getMergeStrategy).flatMap(ConfigurationUtils::convertConfigurationMode);
329         return configurationMode.orElseGet(() -> getMergeStrategy(file.getName().toUpperCase()));
330     }
331
332     /**
333      * Gets merge strategy.
334      *
335      * @param file the file
336      * @return the merge strategy
337      */
338     public static ConfigurationMode getMergeStrategy(String file) {
339         file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
340         file = file.substring(file.lastIndexOf('/') + 1);
341         Pattern pattern = Pattern.compile(
342                 "CONFIG(-\\w*){0,1}(-" + "(" + ConfigurationMode.OVERRIDE + "|" + ConfigurationMode.MERGE
343                         + "|" + ConfigurationMode.UNION + ")){0,1}" + "\\.("
344                         + ConfigurationType.PROPERTIES.name() + "|" + ConfigurationType.XML.name() + "|"
345                         + ConfigurationType.JSON.name() + "|" + ConfigurationType.YAML.name() + ")$");
346         Matcher matcher = pattern.matcher(file);
347         boolean b1 = matcher.matches();
348         if (b1) {
349             for (int i = 1; i <= matcher.groupCount(); i++) {
350                 String modeName = matcher.group(i);
351                 if (modeName != null) {
352                     modeName = modeName.substring(1);
353                 }
354                 try {
355                     return Enum.valueOf(ConfigurationMode.class, modeName);
356                 } catch (Exception exception) {
357                     //do nothing
358                 }
359             }
360         }
361
362         return null;
363     }
364
365     /**
366      * Gets configuration.
367      *
368      * @param url the url
369      * @return the configuration
370      */
371     public static Optional<FileBasedConfiguration> getConfiguration(URL url) {
372         FileBasedConfiguration builder = null;
373         try {
374             ConfigurationType configType = ConfigurationUtils.getConfigType(url);
375             switch (configType) {
376                 case PROPERTIES:
377                     builder = new Configurations().fileBased(PropertiesConfiguration.class, url);
378                     break;
379                 case XML:
380                     builder = new Configurations().fileBased(XMLConfiguration.class, url);
381                     break;
382                 case JSON:
383                     builder = new Configurations().fileBased(JsonConfiguration.class, url);
384                     break;
385                 case YAML:
386                     builder = new Configurations().fileBased(YamlConfiguration.class, url);
387                     break;
388                 default:
389                     throw new ConfigurationException("Configuration type not supported:" + configType);
390             }
391         } catch (ConfigurationException exception) {
392             exception.printStackTrace();
393         }
394         return ofNullable(builder);
395     }
396
397     /**
398      * Gets configuration.
399      *
400      * @param file the file
401      * @return the configuration
402      */
403     public static Optional<FileBasedConfiguration> getConfiguration(File file) {
404         FileBasedConfiguration builder = null;
405         try {
406             ConfigurationType configType = ConfigurationUtils.getConfigType(file);
407             switch (configType) {
408                 case PROPERTIES:
409                     builder = new Configurations().fileBased(PropertiesConfiguration.class, file);
410                     break;
411                 case XML:
412                     builder = new Configurations().fileBased(XMLConfiguration.class, file);
413                     break;
414                 case JSON:
415                     builder = new Configurations().fileBased(JsonConfiguration.class, file);
416                     break;
417                 case YAML:
418                     builder = new Configurations().fileBased(YamlConfiguration.class, file);
419                     break;
420                 default:
421                     throw new ConfigurationException("Configuration type not supported:" + configType);
422             }
423         } catch (ConfigurationException exception) {
424             exception.printStackTrace();
425         }
426         return ofNullable(builder);
427     }
428
429     /**
430      * Gets collection generic type.
431      *
432      * @param field the field
433      * @return the collection generic type
434      */
435     public static Class getCollectionGenericType(Field field) {
436         Type type = field.getGenericType();
437
438         if (type instanceof ParameterizedType) {
439
440             ParameterizedType paramType = (ParameterizedType) type;
441             Type[] arr = paramType.getActualTypeArguments();
442
443             for (Type tp : arr) {
444                 Class<?> clzz = (Class<?>) tp;
445                 if (isWrapperClass(clzz)) {
446                     return clzz;
447                 } else {
448                     throw new RuntimeException("Collection of type " + clzz.getName() + " not supported.");
449                 }
450             }
451         }
452         return String[].class;
453     }
454
455
456     /**
457      * Gets array class.
458      *
459      * @param clazz the clazz
460      * @return the array class
461      */
462     public static Class getArrayClass(Class clazz) {
463         return arrayClassMap.getOrDefault(clazz, null);
464     }
465
466     /**
467      * Gets all class path resources.
468      *
469      * @return the all class path resources
470      */
471     public static List<URL> getAllClassPathResources() {
472         return CPScanner.scanResources(new ResourceFilter());
473     }
474
475     /**
476      * Execute ddlsql boolean.
477      *
478      * @param sql the sql
479      * @return the boolean
480      * @throws Exception the exception
481      */
482     public static boolean executeDdlSql(String sql) throws Exception {
483         DataSource datasource = ConfigurationDataSource.lookup();
484         if (datasource == null) {
485             System.err.println("DB configuration not found. Configuration management will be using "
486                     + "in-memory persistence.");
487             return false;
488         }
489         try (Connection con = datasource.getConnection(); Statement stmt = con.createStatement()) {
490             stmt.executeQuery(sql);
491         } catch (Exception exception) {
492             System.err.println("Datasource initialization error. Configuration management will be using in-memory persistence.");
493             return false;
494         }
495         return true;
496     }
497
498     /**
499      * Gets configuration builder.
500      *
501      * @param url the url
502      * @return the configuration builder
503      */
504     public static BasicConfigurationBuilder<FileBasedConfiguration> getConfigurationBuilder(URL url) {
505         ConfigurationType configType = ConfigurationUtils.getConfigType(url);
506         ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder = getFileBasedConfigurationReloadingFileBasedConfigurationBuilder(
507                 configType);
508         builder.configure(new Parameters().fileBased().setURL(url)
509                 .setListDelimiterHandler(new DefaultListDelimiterHandler(',')));
510         return builder;
511     }
512
513     /**
514      * Gets configuration builder.
515      *
516      * @param file     the file
517      * @param autoSave the auto save
518      * @return the configuration builder
519      */
520     public static BasicConfigurationBuilder<FileBasedConfiguration> getConfigurationBuilder(File file,
521                                                                                             boolean autoSave) {
522         ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder;
523         ConfigurationType configType = ConfigurationUtils.getConfigType(file);
524         builder = getFileBasedConfigurationReloadingFileBasedConfigurationBuilder(configType);
525         builder.configure(new Parameters().fileBased().setFile(file)
526                 .setListDelimiterHandler(new DefaultListDelimiterHandler(',')));
527         builder.setAutoSave(autoSave);
528         return builder;
529     }
530
531     private static ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> getFileBasedConfigurationReloadingFileBasedConfigurationBuilder(
532             ConfigurationType configType) {
533         ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder;
534         switch (configType) {
535             case PROPERTIES:
536                 builder = new ReloadingFileBasedConfigurationBuilder<>(PropertiesConfiguration.class);
537                 break;
538             case XML:
539                 builder = new ReloadingFileBasedConfigurationBuilder<>(XMLConfiguration.class);
540                 break;
541             case JSON:
542                 builder = new ReloadingFileBasedConfigurationBuilder<>(JsonConfiguration.class);
543                 break;
544             case YAML:
545                 builder = new ReloadingFileBasedConfigurationBuilder<>(YamlConfiguration.class);
546                 break;
547             default:
548                 throw new IllegalArgumentException("Configuration type not supported:" + configType);
549         }
550         return builder;
551     }
552
553
554     /**
555      * Execute select sql collection.
556      *
557      * @param sql    the sql
558      * @param params the params
559      * @return the collection
560      * @throws Exception the exception
561      */
562     public static Collection<String> executeSelectSql(String sql, String[] params) throws Exception {
563         Collection<String> coll = new ArrayList<>();
564         DataSource datasource = ConfigurationDataSource.lookup();
565         try (Connection con = datasource.getConnection();
566              PreparedStatement stmt = con.prepareStatement(sql)) {
567             if (params != null) {
568                 for (int i = 0; i < params.length; i++) {
569                     stmt.setString(i + 1, params[i]);
570                 }
571             }
572
573             try (ResultSet rs = stmt.executeQuery()) {
574
575                 while (rs.next()) {
576                     coll.add(rs.getString(1));
577                 }
578             }
579
580         } catch (Exception exception) {
581             //exception.printStackTrace();
582             return null;
583         }
584
585         return coll;
586     }
587
588     /**
589      * Execute insert sql boolean.
590      *
591      * @param sql    the sql
592      * @param params the params
593      * @return the boolean
594      * @throws Exception the exception
595      */
596     public static boolean executeInsertSql(String sql, Object[] params) throws Exception {
597         DataSource datasource = ConfigurationDataSource.lookup();
598         try (Connection con = datasource.getConnection();
599              PreparedStatement stmt = con.prepareStatement(sql)) {
600             if (params != null) {
601                 int counter = 0;
602                 for (Object obj : params) {
603                     if (obj == null) {
604                         obj = "";
605                     }
606                     switch (obj.getClass().getName()) {
607                         case "java.lang.String":
608                             stmt.setString(++counter, obj.toString());
609                             break;
610                         case "java.lang.Integer":
611                             stmt.setInt(++counter, ((Integer) obj).intValue());
612                             break;
613                         case "java.lang.Long":
614                             stmt.setLong(++counter, ((Long) obj).longValue());
615                             break;
616                         default:
617                             stmt.setString(++counter, obj.toString());
618                             break;
619                     }
620                 }
621             }
622             stmt.executeUpdate();
623             return true;
624         } catch (Exception exception) {
625             exception.printStackTrace();
626         }
627         return false;
628     }
629
630     /**
631      * Read t.
632      *
633      * @param <T>       the type parameter
634      * @param config    the config
635      * @param clazz     the clazz
636      * @param keyPrefix the key prefix
637      * @return the t
638      * @throws Exception the exception
639      */
640     public static <T> T read(Configuration config, Class<T> clazz, String keyPrefix)
641             throws Exception {
642         Config confAnnot =
643                 clazz.getAnnotation(Config.class);
644         if (confAnnot != null) {
645             keyPrefix += (confAnnot.key() + ".");
646         }
647         T objToReturn = clazz.newInstance();
648         for (Field field : clazz.getDeclaredFields()) {
649             Config fieldConfAnnot =
650                     field.getAnnotation(Config.class);
651             if (fieldConfAnnot != null) {
652                 field.setAccessible(true);
653                 field.set(objToReturn, config.getProperty(keyPrefix + fieldConfAnnot.key()));
654             } else if (field.getType().getAnnotation(Config.class) != null) {
655                 field.set(objToReturn, read(config, field.getType(), keyPrefix));
656             }
657         }
658         return objToReturn;
659     }
660
661     /**
662      * Gets db configuration builder.
663      *
664      * @param configName the config name
665      * @return the db configuration builder
666      * @throws Exception the exception
667      */
668     public static BasicConfigurationBuilder<AgglomerateConfiguration> getDbConfigurationBuilder(
669             String configName) throws Exception {
670         Configuration dbConfig = ConfigurationRepository.lookup()
671                 .getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE);
672         BasicConfigurationBuilder<AgglomerateConfiguration> builder =
673                 new BasicConfigurationBuilder<AgglomerateConfiguration>(AgglomerateConfiguration.class);
674         builder.configure(
675                 new Parameters().database()
676                         .setDataSource(ConfigurationDataSource.lookup())
677                         .setTable(dbConfig.getString("config.Table"))
678                         .setKeyColumn(dbConfig.getString("configKey"))
679                         .setValueColumn(dbConfig.getString("configValue"))
680                         .setConfigurationNameColumn(dbConfig.getString("configNameColumn"))
681                         .setConfigurationName(configName)
682                         .setAutoCommit(true)
683         );
684         return builder;
685     }
686
687     /**
688      * Gets property.
689      *
690      * @param config          the config
691      * @param key             the key
692      * @param processingHints the processing hints
693      * @return the property
694      */
695     public static Object getProperty(Configuration config, String key, int processingHints) {
696         if (!isDirectLookup(processingHints)) {
697             if (config instanceof AgglomerateConfiguration) {
698                 return ((AgglomerateConfiguration) config).getPropertyValue(key);
699             } else if (config instanceof CompositeConfiguration) {
700                 CompositeConfiguration conf = (CompositeConfiguration) config;
701                 for (int i = 0; i < conf.getNumberOfConfigurations(); i++) {
702                     if (conf.getConfiguration(i) instanceof AgglomerateConfiguration) {
703                         return ((AgglomerateConfiguration) conf.getConfiguration(i)).getPropertyValue(key);
704                     } else if (isNodeSpecific(processingHints)) {
705                         Object obj = conf.getConfiguration(i).getProperty(key);
706                         if (obj != null) {
707                             return obj;
708                         }
709                     }
710                 }
711             }
712         }
713         return config.getProperty(key);
714     }
715
716     /**
717      * Gets primitive array.
718      *
719      * @param collection the collection
720      * @param clazz      the clazz
721      * @return the primitive array
722      */
723     public static Object getPrimitiveArray(Collection collection, Class clazz) {
724         if (clazz == int.class) {
725             int[] array = new int[collection.size()];
726             Object[] objArray = collection.toArray();
727             for (int i = 0; i < collection.size(); i++) {
728                 array[i] = (int) objArray[i];
729             }
730             return array;
731         }
732         if (clazz == byte.class) {
733             byte[] array = new byte[collection.size()];
734             Object[] objArray = collection.toArray();
735             for (int i = 0; i < collection.size(); i++) {
736                 array[i] = (byte) objArray[i];
737             }
738             return array;
739         }
740         if (clazz == short.class) {
741             short[] array = new short[collection.size()];
742             Object[] objArray = collection.toArray();
743             for (int i = 0; i < collection.size(); i++) {
744                 array[i] = (short) objArray[i];
745             }
746             return array;
747         }
748         if (clazz == long.class) {
749             long[] array = new long[collection.size()];
750             Object[] objArray = collection.toArray();
751             for (int i = 0; i < collection.size(); i++) {
752                 array[i] = (long) objArray[i];
753             }
754             return array;
755         }
756         if (clazz == float.class) {
757             float[] array = new float[collection.size()];
758             Object[] objArray = collection.toArray();
759             for (int i = 0; i < collection.size(); i++) {
760                 array[i] = (float) objArray[i];
761             }
762             return array;
763         }
764         if (clazz == double.class) {
765             double[] array = new double[collection.size()];
766             Object[] objArray = collection.toArray();
767             for (int i = 0; i < collection.size(); i++) {
768                 array[i] = (double) objArray[i];
769             }
770             return array;
771         }
772         if (clazz == boolean.class) {
773             boolean[] array = new boolean[collection.size()];
774             Object[] objArray = collection.toArray();
775             for (int i = 0; i < collection.size(); i++) {
776                 array[i] = (boolean) objArray[i];
777             }
778             return array;
779         }
780         Object obj = null;
781         return obj;
782     }
783
784     /**
785      * Is wrapper class boolean.
786      *
787      * @param clazz the clazz
788      * @return the boolean
789      */
790     public static boolean isWrapperClass(Class clazz) {
791         return clazz == String.class || clazz == Boolean.class || clazz == Character.class
792                 || Number.class.isAssignableFrom(clazz);
793     }
794
795     /**
796      * Gets collection string.
797      *
798      * @param input the input
799      * @return the collection string
800      */
801     public static String getCollectionString(String input) {
802         Pattern pattern = Pattern.compile("^\\[(.*)\\]$");
803         Matcher matcher = pattern.matcher(input);
804         if (matcher.matches()) {
805             input = matcher.group(1);
806         }
807         return input;
808     }
809
810     /**
811      * Is collection boolean.
812      *
813      * @param input the input
814      * @return the boolean
815      */
816     public static boolean isCollection(String input) {
817         Pattern pattern = Pattern.compile("^\\[(.*)\\]$");
818         Matcher matcher = pattern.matcher(input);
819         return matcher.matches();
820     }
821
822     /**
823      * Process variables if present string.
824      *
825      * @param tenant    the tenant
826      * @param namespace the namespace
827      * @param data      the data
828      * @return the string
829      */
830     public static String processVariablesIfPresent(String tenant, String namespace, String data) {
831         Pattern pattern = Pattern.compile("^.*\\$\\{(.*)\\}.*");
832         Matcher matcher = pattern.matcher(data);
833         if (matcher.matches()) {
834             String key = matcher.group(1);
835             if (key.toUpperCase().startsWith("ENV:")) {
836                 String envValue = System.getenv(key.substring(4));
837                 return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "\\}",
838                         envValue == null ? "" : envValue.replace("\\", "\\\\")));
839             } else if (key.toUpperCase().startsWith("SYS:")) {
840                 String sysValue = System.getProperty(key.substring(4));
841                 return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "\\}",
842                         sysValue == null ? "" : sysValue.replace("\\", "\\\\")));
843             } else {
844                 String propertyValue = ConfigurationUtils.getCollectionString(
845                         ConfigurationManager.lookup().getAsStringValues(tenant, namespace, key).toString());
846                 return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "\\}",
847                         propertyValue == null ? "" : propertyValue.replace("\\", "\\\\")));
848             }
849         } else {
850             return data;
851         }
852     }
853
854     /**
855      * Gets file contents.
856      *
857      * @param path the path
858      * @return the file contents
859      */
860     public static String getFileContents(String path) {
861         try {
862             if (path != null) {
863                 return IOUtils.toString(new URL(path));
864             }
865         } catch (Exception exception) {
866             exception.printStackTrace();
867         }
868         return null;
869     }
870
871     /**
872      * Gets file contents.
873      *
874      * @param path the path
875      * @return the file contents
876      */
877     public static String getFileContents(Path path) {
878         try {
879             if (path != null) {
880                 return new String(Files.readAllBytes(path));
881             }
882         } catch (Exception exception) {
883             exception.printStackTrace();
884         }
885         return null;
886     }
887
888     /**
889      * Gets concrete collection.
890      *
891      * @param clazz the clazz
892      * @return the concrete collection
893      */
894     public static Collection getConcreteCollection(Class clazz) {
895         switch (clazz.getName()) {
896             case "java.util.Collection":
897             case "java.util.List":
898                 return new ArrayList<>();
899             case "java.util.Set":
900                 return new HashSet<>();
901             case "java.util.SortedSet":
902                 return new TreeSet<>();
903             case "java.util.Queue":
904                 return new ConcurrentLinkedQueue<>();
905             case "java.util.Deque":
906                 return new ArrayDeque<>();
907             case "java.util.concurrent.TransferQueue":
908                 return new LinkedTransferQueue<>();
909             case "java.util.concurrent.BlockingQueue":
910                 return new LinkedBlockingQueue<>();
911             default:
912                 return null;
913         }
914     }
915
916     /**
917      * Gets default for.
918      *
919      * @param clazz the clazz
920      * @return the default for
921      */
922     public static Object getDefaultFor(Class clazz) {
923         if (byte.class == clazz) {
924             return new Byte("0");
925         } else if (short.class == clazz) {
926             return new Short("0");
927         } else if (int.class == clazz) {
928             return new Integer("0");
929         } else if (float.class == clazz) {
930             return new Float("0");
931         } else if (long.class == clazz) {
932             return new Long("0");
933         } else if (double.class == clazz) {
934             return new Double("0");
935         } else if (boolean.class == clazz) {
936             return Boolean.FALSE;
937         }
938         return (char) 0;
939     }
940
941     /**
942      * Gets compatible collection for abstract def.
943      *
944      * @param clazz the clazz
945      * @return the compatible collection for abstract def
946      */
947     public static Collection getCompatibleCollectionForAbstractDef(Class clazz) {
948         if (BlockingQueue.class.isAssignableFrom(clazz)) {
949             return getConcreteCollection(BlockingQueue.class);
950         }
951         if (TransferQueue.class.isAssignableFrom(clazz)) {
952             return getConcreteCollection(TransferQueue.class);
953         }
954         if (Deque.class.isAssignableFrom(clazz)) {
955             return getConcreteCollection(Deque.class);
956         }
957         if (Queue.class.isAssignableFrom(clazz)) {
958             return getConcreteCollection(Queue.class);
959         }
960         if (SortedSet.class.isAssignableFrom(clazz)) {
961             return getConcreteCollection(SortedSet.class);
962         }
963         if (Set.class.isAssignableFrom(clazz)) {
964             return getConcreteCollection(Set.class);
965         }
966         if (List.class.isAssignableFrom(clazz)) {
967             return getConcreteCollection(List.class);
968         }
969         return null;
970     }
971
972     /**
973      * Gets configuration repository key.
974      *
975      * @param array the array
976      * @return the configuration repository key
977      */
978     public static String getConfigurationRepositoryKey(String[] array) {
979         Deque<String> stack = new ArrayDeque<>();
980         stack.push(Constants.DEFAULT_TENANT);
981         for (String element : array) {
982             stack.push(element);
983         }
984         String toReturn = stack.pop();
985         return stack.pop() + Constants.KEY_ELEMENTS_DELEMETER + toReturn;
986     }
987
988     /**
989      * Gets configuration repository key.
990      *
991      * @param file the file
992      * @return the configuration repository key
993      */
994     public static String getConfigurationRepositoryKey(File file) {
995         return getConfigurationRepositoryKey(
996                 ConfigurationUtils.getNamespace(file).split(Constants.TENANT_NAMESPACE_SAPERATOR));
997     }
998
999     /**
1000      * Gets configuration repository key.
1001      *
1002      * @param url the url
1003      * @return the configuration repository key
1004      */
1005     public static String getConfigurationRepositoryKey(URL url) {
1006         return getConfigurationRepositoryKey(
1007                 ConfigurationUtils.getNamespace(url).split(Constants.TENANT_NAMESPACE_SAPERATOR));
1008     }
1009
1010     /**
1011      * To map linked hash map.
1012      *
1013      * @param config the config
1014      * @return the linked hash map
1015      */
1016     public static LinkedHashMap toMap(Configuration config) {
1017         Iterator<String> iterator = config.getKeys();
1018         LinkedHashMap<String, String> map = new LinkedHashMap<>();
1019         while (iterator.hasNext()) {
1020             String key = iterator.next();
1021             if (!(key.equals(Constants.MODE_KEY) || key.equals(Constants.NAMESPACE_KEY)
1022                     || key.equals(Constants.LOAD_ORDER_KEY))) {
1023                 map.put(key, config.getProperty(key).toString());
1024             }
1025         }
1026
1027         return map;
1028     }
1029
1030     /**
1031      * Diff map.
1032      *
1033      * @param orig   the orig
1034      * @param latest the latest
1035      * @return the map
1036      */
1037     public static Map diff(LinkedHashMap orig, LinkedHashMap latest) {
1038         orig = new LinkedHashMap<>(orig);
1039         latest = new LinkedHashMap<>(latest);
1040         List<String> set = new ArrayList(orig.keySet());
1041         for (String key : set) {
1042             if (latest.remove(key, orig.get(key))) {
1043                 orig.remove(key);
1044             }
1045         }
1046         Set<String> keys = latest.keySet();
1047         for (String key : keys) {
1048             orig.remove(key);
1049         }
1050         set = new ArrayList(orig.keySet());
1051         for (String key : set) {
1052             latest.put(key, "");
1053         }
1054         return new HashMap<>(latest);
1055     }
1056
1057     /**
1058      * Is array boolean.
1059      *
1060      * @param tenant          the tenant
1061      * @param namespace       the namespace
1062      * @param key             the key
1063      * @param processingHints the processing hints
1064      * @return the boolean
1065      * @throws Exception the exception
1066      */
1067     public static boolean isArray(String tenant, String namespace, String key, int processingHints)
1068             throws Exception {
1069         Object obj = ConfigurationUtils
1070                 .getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace), key,
1071                         processingHints);
1072         return (obj != null) && ConfigurationUtils.isCollection(obj.toString());
1073     }
1074
1075     /**
1076      * Is direct lookup boolean.
1077      *
1078      * @param hints the hints
1079      * @return the boolean
1080      */
1081     public static boolean isDirectLookup(int hints) {
1082         return (hints & LATEST_LOOKUP.value()) == LATEST_LOOKUP.value();
1083     }
1084
1085     /**
1086      * Is external lookup boolean.
1087      *
1088      * @param hints the hints
1089      * @return the boolean
1090      */
1091     public static boolean isExternalLookup(int hints) {
1092         return (hints & EXTERNAL_LOOKUP.value()) == EXTERNAL_LOOKUP.value();
1093     }
1094
1095     /**
1096      * Is node specific boolean.
1097      *
1098      * @param hints the hints
1099      * @return the boolean
1100      */
1101     public static boolean isNodeSpecific(int hints) {
1102         return (hints & NODE_SPECIFIC.value()) == NODE_SPECIFIC.value();
1103     }
1104
1105     public static boolean isZeroLengthArray(Class clazz, Object obj) {
1106         if (clazz.isArray() && clazz.getComponentType().isPrimitive()) {
1107             if (clazz.getComponentType() == int.class) {
1108                 return ((int[]) obj).length == 0;
1109             } else if (clazz.getComponentType() == byte.class) {
1110                 return ((byte[]) obj).length == 0;
1111             } else if (clazz.getComponentType() == short.class) {
1112                 return ((short[]) obj).length == 0;
1113             } else if (clazz.getComponentType() == float.class) {
1114                 return ((float[]) obj).length == 0;
1115             } else if (clazz.getComponentType() == boolean.class) {
1116                 return ((boolean[]) obj).length == 0;
1117             } else if (clazz.getComponentType() == double.class) {
1118                 return ((double[]) obj).length == 0;
1119             } else if (clazz.getComponentType() == long.class) {
1120                 return ((long[]) obj).length == 0;
1121             } else {
1122                 return ((Object[]) obj).length == 0;
1123             }
1124         }
1125
1126         return false;
1127     }
1128
1129     /**
1130      * Checks if value is blank
1131      *
1132      * @param value
1133      * @return
1134      */
1135     public static boolean isBlank(String value) {
1136         return value == null || value.trim().length() == 0;
1137     }
1138 }