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