c13a3a458a0c75abfa9a892825c144db4c067a84
[sdc.git] /
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * Modifications Copyright (c) 2019 Samsung
17  *
18  */
19
20 package org.onap.config;
21
22 import com.virtlink.commons.configuration2.jackson.JsonConfiguration;
23 import io.github.classgraph.ClassGraph;
24 import io.github.classgraph.ScanResult;
25 import org.apache.commons.configuration2.Configuration;
26 import org.apache.commons.configuration2.CompositeConfiguration;
27 import org.apache.commons.configuration2.FileBasedConfiguration;
28 import org.apache.commons.configuration2.PropertiesConfiguration;
29 import org.apache.commons.configuration2.XMLConfiguration;
30 import org.apache.commons.configuration2.builder.BasicConfigurationBuilder;
31 import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
32 import org.apache.commons.configuration2.builder.ReloadingFileBasedConfigurationBuilder;
33 import org.apache.commons.configuration2.builder.fluent.Configurations;
34 import org.apache.commons.configuration2.builder.fluent.Parameters;
35 import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
36 import org.apache.commons.configuration2.ex.ConfigurationException;
37 import org.apache.commons.io.IOUtils;
38 import org.onap.config.api.Config;
39 import org.onap.config.api.ConfigurationManager;
40 import org.onap.config.impl.YamlConfiguration;
41 import org.onap.config.type.ConfigurationMode;
42 import org.onap.config.type.ConfigurationType;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 import java.io.File;
47 import java.io.IOException;
48 import java.lang.reflect.Array;
49 import java.lang.reflect.Field;
50 import java.lang.reflect.ParameterizedType;
51 import java.lang.reflect.Type;
52 import java.net.MalformedURLException;
53 import java.net.URL;
54 import java.nio.charset.Charset;
55 import java.nio.file.Files;
56 import java.nio.file.FileVisitResult;
57 import java.nio.file.Path;
58 import java.nio.file.SimpleFileVisitor;
59 import java.nio.file.attribute.BasicFileAttributes;
60 import java.util.ArrayDeque;
61 import java.util.ArrayList;
62 import java.util.Arrays;
63 import java.util.Collection;
64 import java.util.Collections;
65 import java.util.Deque;
66 import java.util.HashMap;
67 import java.util.HashSet;
68 import java.util.List;
69 import java.util.Map;
70 import java.util.Objects;
71 import java.util.Optional;
72 import java.util.Queue;
73 import java.util.Set;
74 import java.util.SortedSet;
75 import java.util.TreeSet;
76 import java.util.concurrent.BlockingQueue;
77 import java.util.concurrent.ConcurrentLinkedQueue;
78 import java.util.concurrent.LinkedBlockingQueue;
79 import java.util.concurrent.LinkedTransferQueue;
80 import java.util.concurrent.TransferQueue;
81 import java.util.function.Predicate;
82 import java.util.regex.Matcher;
83 import java.util.regex.Pattern;
84 import java.util.stream.Collectors;
85
86 import static java.util.Optional.ofNullable;
87 import static org.onap.config.api.Hint.EXTERNAL_LOOKUP;
88 import static org.onap.config.api.Hint.LATEST_LOOKUP;
89 import static org.onap.config.api.Hint.NODE_SPECIFIC;
90
91 public class ConfigurationUtils {
92
93     private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationUtils.class);
94
95     private static final String CONFIGURATION_TYPE_NOT_SUPPORTED = "Configuration type not supported:";
96
97     private static final Map<Class<?>, Class<?>> ARRAY_CLASS_MAP;
98
99     private static final String CONFIG_REGEX_TPL_OPT_1 = "CONFIG(-\\w*){0,1}(-(%s|%s|%s)){0,1}\\.(%s|%s|%s|%s)$";
100
101     private static final String CONFIG_REGEX_TPL_OPT_2 = "CONFIG(.)*\\.(%s|%s|%s|%s)$";
102
103     static {
104         Map<Class<?>, Class<?>> arrayTypes = new HashMap<>();
105         arrayTypes.put(Byte.class, Byte[].class);
106         arrayTypes.put(Short.class, Short[].class);
107         arrayTypes.put(Integer.class, Integer[].class);
108         arrayTypes.put(Long.class, Long[].class);
109         arrayTypes.put(Float.class, Float[].class);
110         arrayTypes.put(Double.class, Double[].class);
111         arrayTypes.put(Boolean.class, Boolean[].class);
112         arrayTypes.put(Character.class, Character[].class);
113         arrayTypes.put(String.class, String[].class);
114         ARRAY_CLASS_MAP = Collections.unmodifiableMap(arrayTypes);
115     }
116
117     private ConfigurationUtils() {
118         // prevent instantiation
119     }
120
121     public static Collection<File> getAllFiles(File file, boolean recursive, boolean onlyDirectory) {
122         ArrayList<File> collection = new ArrayList<>();
123         Path rootPath = file.toPath();
124         try {
125             Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
126                 @Override
127                 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
128                     super.preVisitDirectory(dir,attrs);
129                     if (rootPath.equals(dir)) {
130                         return FileVisitResult.CONTINUE;
131                     }
132                     collection.add(dir.toFile());
133                     return recursive? FileVisitResult.CONTINUE : FileVisitResult.SKIP_SUBTREE;
134                 }
135
136                 @Override
137                 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
138                     super.visitFile(file, attrs);
139                     if (!onlyDirectory) {
140                         collection.add(file.toFile());
141                     }
142                     return FileVisitResult.CONTINUE;
143                 }
144             });
145         } catch (IOException e) {
146             LOGGER.error("Failed to walk through directories starting from: {}.", file.toString(), e);
147         }
148         return collection;
149     }
150
151     public static String getCommaSeparatedList(String[] list) {
152         return (list == null) || (list.length == 0) ? "" : getCommaSeparatedList(Arrays.asList(list));
153     }
154
155     public static String getCommaSeparatedList(List<?> list) {
156
157         if ((list == null) || list.isEmpty()) {
158             return "";
159         }
160
161         return list.stream().filter(o -> o != null && !o.toString().trim().isEmpty())
162                 .map(o -> o.toString().trim()).collect(Collectors.joining(","));
163     }
164
165     public static boolean isConfig(URL url) {
166         return isConfig(url.getFile());
167     }
168
169     public static boolean isConfig(String file) {
170         file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
171         file = file.substring(file.lastIndexOf('/') + 1);
172         return file.matches(
173                 String.format(
174                         CONFIG_REGEX_TPL_OPT_1,
175                         ConfigurationMode.OVERRIDE,
176                         ConfigurationMode.MERGE,
177                         ConfigurationMode.UNION,
178                         ConfigurationType.PROPERTIES.name(),
179                         ConfigurationType.XML.name(),
180                         ConfigurationType.JSON.name(),
181                         ConfigurationType.YAML.name()
182                 )
183         ) || file.matches(
184                 String.format(
185                         CONFIG_REGEX_TPL_OPT_2,
186                         ConfigurationType.PROPERTIES.name(),
187                         ConfigurationType.XML.name(),
188                         ConfigurationType.JSON.name(),
189                         ConfigurationType.YAML.name()
190                 )
191         );
192     }
193
194     public static boolean isConfig(File file) {
195         return file != null && file.exists() && isConfig(file.getName());
196     }
197
198     private static Optional<String> readNamespace(Configuration config) {
199         return ofNullable(config).flatMap(configuration -> ofNullable(configuration.getString(Constants.NAMESPACE_KEY)))
200                 .map(String::toUpperCase);
201     }
202
203     private static Optional<String> readMergeStrategy(Configuration config) {
204         return ofNullable(config).flatMap(configuration -> ofNullable(configuration.getString(Constants.MODE_KEY)))
205                 .map(String::toUpperCase);
206     }
207
208     public static ConfigurationMode getMergeStrategy(File file) {
209         Optional<ConfigurationMode> configurationMode =
210                 getConfiguration(file).flatMap(ConfigurationUtils::readMergeStrategy)
211                         .flatMap(ConfigurationUtils::convertConfigurationMode);
212         return configurationMode.orElseGet(() -> getMergeStrategy(file.getName().toUpperCase()));
213     }
214
215     public static ConfigurationMode getMergeStrategy(URL url) {
216         Optional<ConfigurationMode> configurationMode =
217                 getConfiguration(url).flatMap(ConfigurationUtils::readMergeStrategy)
218                         .flatMap(ConfigurationUtils::convertConfigurationMode);
219         return configurationMode.orElseGet(() -> getMergeStrategy(url.getFile().toUpperCase()));
220     }
221
222     public static ConfigurationMode getMergeStrategy(String file) {
223
224         file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
225         file = file.substring(file.lastIndexOf('/') + 1);
226         Pattern pattern = Pattern.compile(
227                 String.format(
228                         CONFIG_REGEX_TPL_OPT_1,
229                         ConfigurationMode.OVERRIDE,
230                         ConfigurationMode.MERGE,
231                         ConfigurationMode.UNION,
232                         ConfigurationType.PROPERTIES.name(),
233                         ConfigurationType.XML.name(),
234                         ConfigurationType.JSON.name(),
235                         ConfigurationType.YAML.name()
236                 )
237         );
238         Matcher matcher = pattern.matcher(file);
239         boolean b1 = matcher.matches();
240         if (b1) {
241             for (int i = 1; i <= matcher.groupCount(); i++) {
242                 String modeName = matcher.group(i);
243                 if (modeName != null) {
244                     modeName = modeName.substring(1);
245                 }
246                 try {
247                     return Enum.valueOf(ConfigurationMode.class, modeName);
248                 } catch (Exception exception) {
249                     LOGGER.debug("Configuration mode for merge strategy '{}' not found", modeName, exception);
250                 }
251             }
252         }
253
254         return null;
255     }
256
257     public static Optional<FileBasedConfiguration> getConfiguration(URL url) {
258
259         try {
260
261             ConfigurationType configType = ConfigurationUtils.getConfigType(url);
262             switch (configType) {
263                 case PROPERTIES:
264                     return Optional.of(new Configurations().fileBased(PropertiesConfiguration.class, url));
265                 case XML:
266                     return Optional.of(new Configurations().fileBased(XMLConfiguration.class, url));
267                 case JSON:
268                     return Optional.of(new Configurations().fileBased(JsonConfiguration.class, url));
269                 case YAML:
270                     return Optional.of(new Configurations().fileBased(YamlConfiguration.class, url));
271                 default:
272                     throw new ConfigurationException(CONFIGURATION_TYPE_NOT_SUPPORTED + configType);
273             }
274         } catch (ConfigurationException exception) {
275             LOGGER.error("Error reading configuration at {}.", url.toString(), exception);
276         }
277
278         return Optional.empty();
279     }
280
281     public static Optional<FileBasedConfiguration> getConfiguration(File file) {
282
283         try {
284             return getConfiguration(file.getAbsoluteFile().toURI().toURL());
285         } catch (MalformedURLException e) {
286             throw new IllegalStateException("Malformed URL: " + file.getAbsolutePath());
287         }
288     }
289
290     public static ConfigurationType getConfigType(File file) {
291         Objects.requireNonNull(file, "File cannot be null");
292         return Enum.valueOf(ConfigurationType.class,
293                 file.getAbsolutePath().substring(file.getAbsolutePath().lastIndexOf('.') + 1).toUpperCase());
294     }
295
296     public static ConfigurationType getConfigType(URL url) {
297         Objects.requireNonNull(url, "URL cannot be null");
298         return Enum.valueOf(ConfigurationType.class,
299                 url.getFile().substring(url.getFile().lastIndexOf('.') + 1).toUpperCase());
300     }
301
302     private static Optional<ConfigurationMode> convertConfigurationMode(String configMode) {
303         ConfigurationMode configurationMode = null;
304         try {
305             configurationMode = ConfigurationMode.valueOf(configMode);
306         } catch (Exception exception) {
307             LOGGER.error("Could not find convert {} into configuration mode.", configMode, exception);
308         }
309         return Optional.ofNullable(configurationMode);
310     }
311
312     public static Class<?> getCollectionGenericType(Field field) {
313         Type type = field.getGenericType();
314
315         if (type instanceof ParameterizedType) {
316
317             ParameterizedType paramType = (ParameterizedType) type;
318             Type[] arr = paramType.getActualTypeArguments();
319             if (arr.length > 0) {
320                 Class<?> clazz = (Class<?>) arr[0];
321                 if (isWrapperClass(clazz)) {
322                     return clazz;
323                 } else {
324                     throw new IllegalArgumentException("Collection of type " + clazz.getName() + " not supported.");
325                 }
326             }
327         }
328
329         return String[].class;
330     }
331
332     public static boolean isWrapperClass(Class<?> clazz) {
333         Predicate<Class<?>> predicateWrapper = type -> type == String.class || type == Boolean.class || type == Character.class
334                 || Number.class.isAssignableFrom(type);
335         return isA(predicateWrapper, clazz);
336     }
337
338     public static boolean isAPrimitive(Class<?> clazz) {
339         return isA(Class::isPrimitive, clazz);
340     }
341
342     /**
343      * Check if clazz implementing Map iface
344      */
345     public static boolean isAMap(Class<?> clazz) {
346         Predicate<Class<?>> predicateMap = Map.class::isAssignableFrom;
347         return isA(predicateMap, clazz);
348     }
349
350     /**
351      * Check if clazz implementing Collection iface
352      */
353     public static boolean isACollection(Class<?> clazz) {
354         Predicate<Class<?>> predicateCollection = Collection.class::isAssignableFrom;
355         return isA(predicateCollection, clazz);
356     }
357
358     /**
359      * Check if clazz is a primitive or primitive wrapper
360      */
361     public static boolean isAPrimitiveOrWrapper(Class<?> clazz) {
362         Predicate<Class<?>> predicatePrimitive = Class::isPrimitive;
363         Predicate<Class<?>> predicateWrapper = ConfigurationUtils::isWrapperClass;
364         return isA(predicatePrimitive.or(predicateWrapper), clazz);
365     }
366
367     /**
368      * Check if clazz is array of primitives or array of primitives wrappers
369      */
370     public static boolean isAPrimitivesOrWrappersArray(Class<?> clazz) {
371         Predicate<Class<?>> predicatePrimitivesOrWrappersArray =
372                 type -> ConfigurationUtils.isAWrappersArray(type) || ConfigurationUtils.isAPrimitivesArray(type);
373         return isA(predicatePrimitivesOrWrappersArray, clazz);
374
375     }
376
377     /**
378      * Check is clazz is array of primitives
379      */
380     public static boolean isAPrimitivesArray(Class<?> clazz) {
381         Predicate<Class<?>> predicateArray = Class::isArray;
382         Predicate<Class<?>> predicateComponentPrimitive = type -> type.getComponentType().isPrimitive();
383         return isA(predicateArray.and(predicateComponentPrimitive), clazz);
384     }
385
386     /**
387      * Check is clazz is array of primitives wrappers
388      */
389     public static boolean isAWrappersArray(Class<?> clazz) {
390         Predicate<Class<?>> predicateArray = Class::isArray;
391         Predicate<Class<?>> predicateComponentWrapper = type -> isWrapperClass(type.getComponentType());
392         return isA(predicateArray.and(predicateComponentWrapper), clazz);
393     }
394
395     private static boolean isA(Predicate<Class<?>> predicate, Class<?> clazz) {
396         return predicate.test(clazz);
397     }
398
399     public static Class<?> getArrayClass(Class<?> clazz) {
400         return ARRAY_CLASS_MAP.getOrDefault(clazz, null);
401     }
402
403     public static List<URL> getAllClassPathResources() {
404         try (ScanResult scanResult = new ClassGraph().scan()) {
405             return scanResult.getAllResources().getURLs();
406         }
407     }
408
409     public static BasicConfigurationBuilder<FileBasedConfiguration> getConfigurationBuilder(File file) {
410         FileBasedConfigurationBuilder<FileBasedConfiguration> builder;
411         ConfigurationType configType = ConfigurationUtils.getConfigType(file);
412         builder = getFileBasedConfigurationBuilder(configType);
413         builder.configure(new Parameters().fileBased().setFile(file)
414                 .setListDelimiterHandler(new DefaultListDelimiterHandler(',')));
415         return builder;
416     }
417
418     public static BasicConfigurationBuilder<FileBasedConfiguration> getConfigurationBuilder(URL url) {
419         ConfigurationType configType = ConfigurationUtils.getConfigType(url);
420         ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder =
421                 getFileBasedConfigurationBuilder(configType);
422         builder.configure(
423                 new Parameters().fileBased().setURL(url).setListDelimiterHandler(new DefaultListDelimiterHandler(',')));
424         return builder;
425     }
426
427     private static ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> getFileBasedConfigurationBuilder(
428             ConfigurationType configType) {
429
430         ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder;
431         switch (configType) {
432             case PROPERTIES:
433                 builder = new ReloadingFileBasedConfigurationBuilder<>(PropertiesConfiguration.class);
434                 break;
435             case XML:
436                 builder = new ReloadingFileBasedConfigurationBuilder<>(XMLConfiguration.class);
437                 break;
438             case JSON:
439                 builder = new ReloadingFileBasedConfigurationBuilder<>(JsonConfiguration.class);
440                 break;
441             case YAML:
442                 builder = new ReloadingFileBasedConfigurationBuilder<>(YamlConfiguration.class);
443                 break;
444             default:
445                 throw new IllegalArgumentException(CONFIGURATION_TYPE_NOT_SUPPORTED + configType);
446         }
447         return builder;
448     }
449
450     public static <T> T read(Configuration config, Class<T> clazz, String keyPrefix) throws Exception {
451         Config confAnnotation = clazz.getAnnotation(Config.class);
452         if (confAnnotation != null) {
453             keyPrefix += (confAnnotation.key() + ".");
454         }
455         T objToReturn = clazz.newInstance();
456         for (Field field : clazz.getDeclaredFields()) {
457             Config fieldAnnotation = field.getAnnotation(Config.class);
458             if (fieldAnnotation != null) {
459                 field.setAccessible(true);
460                 field.set(objToReturn, config.getProperty(keyPrefix + fieldAnnotation.key()));
461             } else if (field.getType().getAnnotation(Config.class) != null) {
462                 field.set(objToReturn, read(config, field.getType(), keyPrefix));
463             }
464         }
465         return objToReturn;
466     }
467
468     public static Object getPrimitiveArray(Collection<?> collection, Class<?> clazz) {
469         switch (clazz.getName()) {
470             case "int":
471                 return getIntsPrimitiveArray(collection);
472             case "byte":
473                 return getBytesPrimitiveArray(collection);
474             case "short":
475                 return getShortsPrimitiveArray(collection);
476             case "long":
477                 return getLongsPrimitiveArray(collection);
478             case "float":
479                 return getFloatsPrimitiveArray(collection);
480             case "double":
481                 return getDoublesPrimitiveArray(collection);
482             case "boolean":
483                 return getBooleansPrimitiveArray(collection);
484             case "char":
485                 return getCharsPrimitiveArray(collection);
486             default:
487                 return null;
488         }
489     }
490
491     public static Object getWrappersArray(Collection<?> collection, Class<?> clazz) {
492         Object array = null;
493         if (isWrapperClass(clazz)){
494             int collectionSize = collection.size();
495             array = Array.newInstance(clazz, collection.size());
496             Object[] objArray = collection.toArray();
497             System.arraycopy(objArray, 0, array, 0, collectionSize);
498         }
499         return array;
500     }
501
502     public static String getCollectionString(String input) {
503         Pattern pattern = Pattern.compile("^\\[(.*)\\]$");
504         Matcher matcher = pattern.matcher(input);
505         if (matcher.matches()) {
506             input = matcher.group(1);
507         }
508         return input;
509     }
510
511     public static String processVariablesIfPresent(String tenant, String namespace, String data) {
512         Pattern pattern = Pattern.compile("^.*\\$\\{(.*)\\}.*");
513         Matcher matcher = pattern.matcher(data);
514         if (matcher.matches()) {
515             final int substringStartIndex = 4;
516             String key = matcher.group(1);
517             String value;
518             if (key.toUpperCase().startsWith("ENV:")) {
519                 value = System.getenv(key.substring(substringStartIndex));
520             } else if (key.toUpperCase().startsWith("SYS:")) {
521                 value = System.getProperty(key.substring(substringStartIndex));
522             } else {
523                 value = ConfigurationUtils.getCollectionString(
524                         ConfigurationManager.lookup().getAsStringValues(tenant, namespace, key).toString());
525             }
526             return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "}",
527                     value == null ? "" : value.replace("\\", "\\\\")));
528         } else {
529             return data;
530         }
531     }
532
533     public static String getFileContents(String path) {
534         try {
535             if (path != null) {
536                 return IOUtils.toString(new URL(path), Charset.defaultCharset());
537             }
538         } catch (Exception exception) {
539             LOGGER.error("Error while getting '{}' content", path, exception);
540         }
541         return null;
542     }
543
544     public static String getFileContents(Path path) {
545         try {
546             if (path != null) {
547                 return new String(Files.readAllBytes(path));
548             }
549         } catch (Exception exception) {
550             LOGGER.error("Error while getting '{}' content", path.toString(), exception);
551         }
552         return null;
553     }
554
555     public static Object getDefaultFor(Class<?> clazz) {
556         if (byte.class == clazz) {
557             return new Byte("0");
558         } else if (short.class == clazz) {
559             return new Short("0");
560         } else if (int.class == clazz) {
561             return new Integer("0");
562         } else if (float.class == clazz) {
563             return new Float("0");
564         } else if (long.class == clazz) {
565             return new Long("0");
566         } else if (double.class == clazz) {
567             return new Double("0");
568         } else if (boolean.class == clazz) {
569             return Boolean.FALSE;
570         }
571         return (char) 0;
572     }
573
574     public static Collection getCompatibleCollectionForAbstractDef(Class<?> clazz) {
575         if (TransferQueue.class.isAssignableFrom(clazz)) {
576             return getConcreteCollection(TransferQueue.class);
577         }
578         if (BlockingQueue.class.isAssignableFrom(clazz)) {
579             return getConcreteCollection(BlockingQueue.class);
580         }
581         if (Deque.class.isAssignableFrom(clazz)) {
582             return getConcreteCollection(Deque.class);
583         }
584         if (Queue.class.isAssignableFrom(clazz)) {
585             return getConcreteCollection(Queue.class);
586         }
587         if (SortedSet.class.isAssignableFrom(clazz)) {
588             return getConcreteCollection(SortedSet.class);
589         }
590         if (Set.class.isAssignableFrom(clazz)) {
591             return getConcreteCollection(Set.class);
592         }
593         if (List.class.isAssignableFrom(clazz)) {
594             return getConcreteCollection(List.class);
595         }
596         throw new IllegalArgumentException("Only corresponding array classes and any are allowed as argument."
597                 + "assignable from TransferQueue, BlockingQueue, Deque, Queue, SortedSet, Set, List class");
598     }
599
600     public static Collection getConcreteCollection(Class<?> clazz) {
601         switch (clazz.getName()) {
602             case "java.util.Collection":
603             case "java.util.List":
604                 return new ArrayList<>();
605             case "java.util.Set":
606                 return new HashSet<>();
607             case "java.util.SortedSet":
608                 return new TreeSet<>();
609             case "java.util.Queue":
610                 return new ConcurrentLinkedQueue<>();
611             case "java.util.Deque":
612                 return new ArrayDeque<>();
613             case "java.util.concurrent.TransferQueue":
614                 return new LinkedTransferQueue<>();
615             case "java.util.concurrent.BlockingQueue":
616                 return new LinkedBlockingQueue<>();
617             default:
618                 throw new IllegalArgumentException("Only corresponding array classes and any are allowed as argument."
619                         + "assignable from TransferQueue, BlockingQueue, Deque, Queue, SortedSet, Set, List class");
620         }
621     }
622
623     public static String getConfigurationRepositoryKey(File file) {
624         return getConfigurationRepositoryKey(
625                 ConfigurationUtils.getNamespace(file).split(Constants.TENANT_NAMESPACE_SEPARATOR));
626     }
627
628     public static String getConfigurationRepositoryKey(URL url) {
629         return getConfigurationRepositoryKey(
630                 ConfigurationUtils.getNamespace(url).split(Constants.TENANT_NAMESPACE_SEPARATOR));
631     }
632
633     public static String getConfigurationRepositoryKey(String[] array) {
634         Deque<String> stack = new ArrayDeque<>();
635         stack.push(Constants.DEFAULT_TENANT);
636         for (String element : array) {
637             stack.push(element);
638         }
639         String toReturn = stack.pop();
640         return stack.pop() + Constants.KEY_ELEMENTS_DELIMITER + toReturn;
641     }
642
643     public static String getNamespace(File file) {
644         Optional<String> namespace =
645                 getConfiguration(file).flatMap(ConfigurationUtils::readNamespace).map(String::toUpperCase);
646         return namespace.orElseGet(() -> getNamespace(file.getName().toUpperCase()));
647     }
648
649     public static String getNamespace(String file) {
650         file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
651         file = file.substring(file.lastIndexOf('/') + 1);
652         Pattern pattern = Pattern.compile(
653                 String.format(
654                         CONFIG_REGEX_TPL_OPT_1,
655                         ConfigurationMode.OVERRIDE,
656                         ConfigurationMode.MERGE,
657                         ConfigurationMode.UNION,
658                         ConfigurationType.PROPERTIES.name(),
659                         ConfigurationType.XML.name(),
660                         ConfigurationType.JSON.name(),
661                         ConfigurationType.YAML.name()
662                 )
663         );
664         Matcher matcher = pattern.matcher(file);
665         boolean b1 = matcher.matches();
666         if (b1) {
667             if (matcher.group(1) != null) {
668                 String moduleName = matcher.group(1).substring(1);
669                 return moduleName.equalsIgnoreCase(ConfigurationMode.OVERRIDE.name()) || moduleName.equalsIgnoreCase(
670                         ConfigurationMode.UNION.name()) || moduleName.equalsIgnoreCase(ConfigurationMode.MERGE.name())
671                         ? Constants.DEFAULT_NAMESPACE : moduleName;
672             } else {
673                 return Constants.DEFAULT_NAMESPACE;
674             }
675         } else if (isConfig(file)) {
676             return Constants.DEFAULT_NAMESPACE;
677         }
678
679         return null;
680     }
681
682     public static String getNamespace(URL url) {
683
684         Optional<String> namespace =
685                 getConfiguration(url).flatMap(ConfigurationUtils::readNamespace).map(String::toUpperCase);
686
687         return namespace.orElseGet(() -> getNamespace(url.getFile().toUpperCase()));
688     }
689
690     public static Object getProperty(Configuration config, String key, int processingHints) {
691         if (!isDirectLookup(processingHints) && isNodeSpecific(processingHints) && (config instanceof CompositeConfiguration)) {
692             CompositeConfiguration conf = (CompositeConfiguration) config;
693             for (int i = 0; i < conf.getNumberOfConfigurations(); i++) {
694                 Object obj = conf.getConfiguration(i).getProperty(key);
695                 if (obj != null) {
696                     return obj;
697                 }
698             }
699         }
700         return config.getProperty(key);
701     }
702
703     public static boolean isCollection(String input) {
704         Pattern pattern = Pattern.compile("^\\[(.*)\\]$");
705         Matcher matcher = pattern.matcher(input);
706         return matcher.matches();
707     }
708
709     public static boolean isDirectLookup(int hints) {
710         return (hints & LATEST_LOOKUP.value()) == LATEST_LOOKUP.value();
711     }
712
713     public static boolean isNodeSpecific(int hints) {
714         return (hints & NODE_SPECIFIC.value()) == NODE_SPECIFIC.value();
715     }
716
717     public static boolean isExternalLookup(int hints) {
718         return (hints & EXTERNAL_LOOKUP.value()) == EXTERNAL_LOOKUP.value();
719     }
720
721     public static boolean isZeroLengthArray(Class<?> clazz, Object obj) {
722         if (isAPrimitivesArray(clazz)) {
723             if (clazz.getComponentType() == int.class) {
724                 return ((int[]) obj).length == 0;
725             } else if (clazz.getComponentType() == byte.class) {
726                 return ((byte[]) obj).length == 0;
727             } else if (clazz.getComponentType() == short.class) {
728                 return ((short[]) obj).length == 0;
729             } else if (clazz.getComponentType() == float.class) {
730                 return ((float[]) obj).length == 0;
731             } else if (clazz.getComponentType() == boolean.class) {
732                 return ((boolean[]) obj).length == 0;
733             } else if (clazz.getComponentType() == double.class) {
734                 return ((double[]) obj).length == 0;
735             } else if (clazz.getComponentType() == long.class) {
736                 return ((long[]) obj).length == 0;
737             } else {
738                 return ((Object[]) obj).length == 0;
739             }
740         }
741
742         return false;
743     }
744
745     public static boolean isBlank(String value) {
746         return value == null || value.trim().isEmpty();
747     }
748
749     // private methods section starts here
750
751     private static int[] getIntsPrimitiveArray(Collection<?> collection) {
752         int collectionSize = collection.size();
753         int[] array = new int[collectionSize];
754         Object[] objArray = collection.toArray();
755         for (int i = 0; i < collectionSize; i++) {
756             array[i] = (int) objArray[i];
757         }
758         return array;
759     }
760
761     private static byte[] getBytesPrimitiveArray(Collection<?> collection) {
762         int collectionSize = collection.size();
763         byte[] array = new byte[collectionSize];
764         Object[] objArray = collection.toArray();
765         for (int i = 0; i < collectionSize; i++) {
766             array[i] = (byte) objArray[i];
767         }
768         return array;
769     }
770
771     private static short[] getShortsPrimitiveArray(Collection<?> collection) {
772         int collectionSize = collection.size();
773         short[] array = new short[collectionSize];
774         Object[] objArray = collection.toArray();
775         for (int i = 0; i < collectionSize; i++) {
776             array[i] = (short) objArray[i];
777         }
778         return array;
779     }
780
781     private static long[] getLongsPrimitiveArray(Collection<?> collection) {
782         int collectionSize = collection.size();
783         long[] array = new long[collectionSize];
784         Object[] objArray = collection.toArray();
785         for (int i = 0; i < collectionSize; i++) {
786             array[i] = (long) objArray[i];
787         }
788         return array;
789     }
790
791     private static float[] getFloatsPrimitiveArray(Collection<?> collection) {
792         int collectionSize = collection.size();
793         float[] array = new float[collectionSize];
794         Object[] objArray = collection.toArray();
795         for (int i = 0; i < collectionSize; i++) {
796             array[i] = (float) objArray[i];
797         }
798         return array;
799     }
800
801     private static double[] getDoublesPrimitiveArray(Collection<?> collection) {
802         int collectionSize = collection.size();
803         double[] array = new double[collectionSize];
804         Object[] objArray = collection.toArray();
805         for (int i = 0; i < collectionSize; i++) {
806             array[i] = (double) objArray[i];
807         }
808         return array;
809     }
810
811     private static boolean[] getBooleansPrimitiveArray(Collection<?> collection) {
812         int collectionSize = collection.size();
813         boolean[] array = new boolean[collectionSize];
814         Object[] objArray = collection.toArray();
815         for (int i = 0; i < collectionSize; i++) {
816             array[i] = (boolean) objArray[i];
817         }
818         return array;
819     }
820
821     private static char[] getCharsPrimitiveArray(Collection<?> collection) {
822         int collectionSize = collection.size();
823         char[] array = new char[collectionSize];
824         Object[] objArray = collection.toArray();
825         for (int i = 0; i < collectionSize; i++) {
826             array[i] = (char) objArray[i];
827         }
828         return array;
829     }
830
831 }