358dab923f98b2f79b50823903e7b77d71a272ef
[sdc.git] /
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         ConfigurationType configType = ConfigurationUtils.getConfigType(url);
495         ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder = getFileBasedConfigurationReloadingFileBasedConfigurationBuilder(
496                 configType);
497         builder.configure(new Parameters().fileBased().setURL(url)
498                 .setListDelimiterHandler(new DefaultListDelimiterHandler(',')));
499         return builder;
500     }
501
502     /**
503      * Gets configuration builder.
504      *
505      * @param file     the file
506      * @param autoSave the auto save
507      * @return the configuration builder
508      */
509     public static BasicConfigurationBuilder<FileBasedConfiguration> getConfigurationBuilder(File file,
510                                                                                             boolean autoSave) {
511         ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder;
512         ConfigurationType configType = ConfigurationUtils.getConfigType(file);
513         builder = getFileBasedConfigurationReloadingFileBasedConfigurationBuilder(configType);
514         builder.configure(new Parameters().fileBased().setFile(file)
515                 .setListDelimiterHandler(new DefaultListDelimiterHandler(',')));
516         builder.setAutoSave(autoSave);
517         return builder;
518     }
519
520     private static ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> getFileBasedConfigurationReloadingFileBasedConfigurationBuilder(
521             ConfigurationType configType) {
522         ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder;
523         switch (configType) {
524             case PROPERTIES:
525                 builder = new ReloadingFileBasedConfigurationBuilder<>(PropertiesConfiguration.class);
526                 break;
527             case XML:
528                 builder = new ReloadingFileBasedConfigurationBuilder<>(XMLConfiguration.class);
529                 break;
530             case JSON:
531                 builder = new ReloadingFileBasedConfigurationBuilder<>(JsonConfiguration.class);
532                 break;
533             case YAML:
534                 builder = new ReloadingFileBasedConfigurationBuilder<>(YamlConfiguration.class);
535                 break;
536             default:
537                 throw new IllegalArgumentException("Configuration type not supported:"+ configType);
538         }
539         return builder;
540     }
541
542
543     /**
544      * Execute select sql collection.
545      *
546      * @param sql    the sql
547      * @param params the params
548      * @return the collection
549      * @throws Exception the exception
550      */
551     public static Collection<String> executeSelectSql(String sql, String[] params) throws Exception {
552         Collection<String> coll = new ArrayList<>();
553         DataSource datasource = ConfigurationDataSource.lookup();
554         try (Connection con = datasource.getConnection();
555              PreparedStatement stmt = con.prepareStatement(sql)) {
556             if (params != null) {
557                 for (int i = 0; i < params.length; i++) {
558                     stmt.setString(i + 1, params[i]);
559                 }
560             }
561
562             try (ResultSet rs = stmt.executeQuery()) {
563
564                 while (rs.next()) {
565                     coll.add(rs.getString(1));
566                 }
567             }
568
569         } catch (Exception exception) {
570             //exception.printStackTrace();
571             return null;
572         }
573
574         return coll;
575     }
576
577     /**
578      * Execute insert sql boolean.
579      *
580      * @param sql    the sql
581      * @param params the params
582      * @return the boolean
583      * @throws Exception the exception
584      */
585     public static boolean executeInsertSql(String sql, Object[] params) throws Exception {
586         DataSource datasource = ConfigurationDataSource.lookup();
587         try (Connection con = datasource.getConnection();
588              PreparedStatement stmt = con.prepareStatement(sql)) {
589             if (params != null) {
590                 int counter = 0;
591                 for (Object obj : params) {
592                     if (obj == null) {
593                         obj = "";
594                     }
595                     switch (obj.getClass().getName()) {
596                         case "java.lang.String":
597                             stmt.setString(++counter, obj.toString());
598                             break;
599                         case "java.lang.Integer":
600                             stmt.setInt(++counter, ((Integer) obj).intValue());
601                             break;
602                         case "java.lang.Long":
603                             stmt.setLong(++counter, ((Long) obj).longValue());
604                             break;
605                         default:
606                             stmt.setString(++counter, obj.toString());
607                             break;
608                     }
609                 }
610             }
611             stmt.executeUpdate();
612             return true;
613         } catch (Exception exception) {
614             exception.printStackTrace();
615         }
616         return false;
617     }
618
619     /**
620      * Read t.
621      *
622      * @param <T>       the type parameter
623      * @param config    the config
624      * @param clazz     the clazz
625      * @param keyPrefix the key prefix
626      * @return the t
627      * @throws Exception the exception
628      */
629     public static <T> T read(Configuration config, Class<T> clazz, String keyPrefix)
630             throws Exception {
631         Config confAnnot =
632                 clazz.getAnnotation(Config.class);
633         if (confAnnot != null) {
634             keyPrefix += (confAnnot.key() + ".");
635         }
636         T objToReturn = clazz.newInstance();
637         for (Field field : clazz.getDeclaredFields()) {
638             Config fieldConfAnnot =
639                     field.getAnnotation(Config.class);
640             if (fieldConfAnnot != null) {
641                 field.setAccessible(true);
642                 field.set(objToReturn, config.getProperty(keyPrefix + fieldConfAnnot.key()));
643             } else if (field.getType().getAnnotation(Config.class) != null) {
644                 field.set(objToReturn, read(config, field.getType(), keyPrefix));
645             }
646         }
647         return objToReturn;
648     }
649
650     /**
651      * Gets db configuration builder.
652      *
653      * @param configName the config name
654      * @return the db configuration builder
655      * @throws Exception the exception
656      */
657     public static BasicConfigurationBuilder<AgglomerateConfiguration> getDbConfigurationBuilder(
658             String configName) throws Exception {
659         Configuration dbConfig = ConfigurationRepository.lookup()
660                 .getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE);
661         BasicConfigurationBuilder<AgglomerateConfiguration> builder =
662                 new BasicConfigurationBuilder<AgglomerateConfiguration>(AgglomerateConfiguration.class);
663         builder.configure(
664                 new Parameters().database()
665                         .setDataSource(ConfigurationDataSource.lookup())
666                         .setTable(dbConfig.getString("config.Table"))
667                         .setKeyColumn(dbConfig.getString("configKey"))
668                         .setValueColumn(dbConfig.getString("configValue"))
669                         .setConfigurationNameColumn(dbConfig.getString("configNameColumn"))
670                         .setConfigurationName(configName)
671                         .setAutoCommit(true)
672         );
673         return builder;
674     }
675
676     /**
677      * Gets property.
678      *
679      * @param config          the config
680      * @param key             the key
681      * @param processingHints the processing hints
682      * @return the property
683      */
684     public static Object getProperty(Configuration config, String key, int processingHints) {
685         if (!isDirectLookup(processingHints)) {
686             if (config instanceof AgglomerateConfiguration) {
687                 return ((AgglomerateConfiguration) config).getPropertyValue(key);
688             } else if (config instanceof CompositeConfiguration) {
689                 CompositeConfiguration conf = (CompositeConfiguration) config;
690                 for (int i = 0; i < conf.getNumberOfConfigurations(); i++) {
691                     if (conf.getConfiguration(i) instanceof AgglomerateConfiguration) {
692                         return ((AgglomerateConfiguration) conf.getConfiguration(i)).getPropertyValue(key);
693                     } else if (isNodeSpecific(processingHints)) {
694                         Object obj = conf.getConfiguration(i).getProperty(key);
695                         if (obj != null) {
696                             return obj;
697                         }
698                     }
699                 }
700             }
701         }
702         return config.getProperty(key);
703     }
704
705     /**
706      * Gets primitive array.
707      *
708      * @param collection the collection
709      * @param clazz      the clazz
710      * @return the primitive array
711      */
712     public static Object getPrimitiveArray(Collection collection, Class clazz) {
713         if (clazz == int.class) {
714             int[] array = new int[collection.size()];
715             Object[] objArray = collection.toArray();
716             for (int i = 0; i < collection.size(); i++) {
717                 array[i] = (int) objArray[i];
718             }
719             return array;
720         }
721         if (clazz == byte.class) {
722             byte[] array = new byte[collection.size()];
723             Object[] objArray = collection.toArray();
724             for (int i = 0; i < collection.size(); i++) {
725                 array[i] = (byte) objArray[i];
726             }
727             return array;
728         }
729         if (clazz == short.class) {
730             short[] array = new short[collection.size()];
731             Object[] objArray = collection.toArray();
732             for (int i = 0; i < collection.size(); i++) {
733                 array[i] = (short) objArray[i];
734             }
735             return array;
736         }
737         if (clazz == long.class) {
738             long[] array = new long[collection.size()];
739             Object[] objArray = collection.toArray();
740             for (int i = 0; i < collection.size(); i++) {
741                 array[i] = (long) objArray[i];
742             }
743             return array;
744         }
745         if (clazz == float.class) {
746             float[] array = new float[collection.size()];
747             Object[] objArray = collection.toArray();
748             for (int i = 0; i < collection.size(); i++) {
749                 array[i] = (float) objArray[i];
750             }
751             return array;
752         }
753         if (clazz == double.class) {
754             double[] array = new double[collection.size()];
755             Object[] objArray = collection.toArray();
756             for (int i = 0; i < collection.size(); i++) {
757                 array[i] = (double) objArray[i];
758             }
759             return array;
760         }
761         if (clazz == boolean.class) {
762             boolean[] array = new boolean[collection.size()];
763             Object[] objArray = collection.toArray();
764             for (int i = 0; i < collection.size(); i++) {
765                 array[i] = (boolean) objArray[i];
766             }
767             return array;
768         }
769         Object obj = null;
770         return obj;
771     }
772
773     /**
774      * Is wrapper class boolean.
775      *
776      * @param clazz the clazz
777      * @return the boolean
778      */
779     public static boolean isWrapperClass(Class clazz) {
780         return clazz == String.class || clazz == Boolean.class || clazz == Character.class
781                 || Number.class.isAssignableFrom(clazz);
782     }
783
784     /**
785      * Gets collection string.
786      *
787      * @param input the input
788      * @return the collection string
789      */
790     public static String getCollectionString(String input) {
791         Pattern pattern = Pattern.compile("^\\[(.*)\\]$");
792         Matcher matcher = pattern.matcher(input);
793         if (matcher.matches()) {
794             input = matcher.group(1);
795         }
796         return input;
797     }
798
799     /**
800      * Is collection boolean.
801      *
802      * @param input the input
803      * @return the boolean
804      */
805     public static boolean isCollection(String input) {
806         Pattern pattern = Pattern.compile("^\\[(.*)\\]$");
807         Matcher matcher = pattern.matcher(input);
808         return matcher.matches();
809     }
810
811     /**
812      * Process variables if present string.
813      *
814      * @param tenant    the tenant
815      * @param namespace the namespace
816      * @param data      the data
817      * @return the string
818      */
819     public static String processVariablesIfPresent(String tenant, String namespace, String data) {
820         Pattern pattern = Pattern.compile("^.*\\$\\{(.*)\\}.*");
821         Matcher matcher = pattern.matcher(data);
822         if (matcher.matches()) {
823             String key = matcher.group(1);
824             if (key.toUpperCase().startsWith("ENV:")) {
825                 String envValue = System.getenv(key.substring(4));
826                 return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "\\}",
827                         envValue == null ? "" : envValue.replace("\\", "\\\\")));
828             } else if (key.toUpperCase().startsWith("SYS:")) {
829                 String sysValue = System.getProperty(key.substring(4));
830                 return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "\\}",
831                         sysValue == null ? "" : sysValue.replace("\\", "\\\\")));
832             } else {
833                 String propertyValue = ConfigurationUtils.getCollectionString(
834                         ConfigurationManager.lookup().getAsStringValues(tenant, namespace, key).toString());
835                 return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "\\}",
836                         propertyValue == null ? "" : propertyValue.replace("\\", "\\\\")));
837             }
838         } else {
839             return data;
840         }
841     }
842
843     /**
844      * Gets file contents.
845      *
846      * @param path the path
847      * @return the file contents
848      */
849     public static String getFileContents(String path) {
850         try {
851             if (path != null) {
852                 return IOUtils.toString(new URL(path));
853             }
854         } catch (Exception exception) {
855             exception.printStackTrace();
856         }
857         return null;
858     }
859
860     /**
861      * Gets file contents.
862      *
863      * @param path the path
864      * @return the file contents
865      */
866     public static String getFileContents(Path path) {
867         try {
868             if (path != null) {
869                 return new String(Files.readAllBytes(path));
870             }
871         } catch (Exception exception) {
872             exception.printStackTrace();
873         }
874         return null;
875     }
876
877     /**
878      * Gets concrete collection.
879      *
880      * @param clazz the clazz
881      * @return the concrete collection
882      */
883     public static Collection getConcreteCollection(Class clazz) {
884         switch (clazz.getName()) {
885             case "java.util.Collection":
886             case "java.util.List":
887                 return new ArrayList<>();
888             case "java.util.Set":
889                 return new HashSet<>();
890             case "java.util.SortedSet":
891                 return new TreeSet<>();
892             case "java.util.Queue":
893                 return new ConcurrentLinkedQueue<>();
894             case "java.util.Deque":
895                 return new ArrayDeque<>();
896             case "java.util.concurrent.TransferQueue":
897                 return new LinkedTransferQueue<>();
898             case "java.util.concurrent.BlockingQueue":
899                 return new LinkedBlockingQueue<>();
900             default:
901                 return null;
902         }
903     }
904
905     /**
906      * Gets default for.
907      *
908      * @param clazz the clazz
909      * @return the default for
910      */
911     public static Object getDefaultFor(Class clazz) {
912         if (byte.class == clazz) {
913             return new Byte("0");
914         } else if (short.class == clazz) {
915             return new Short("0");
916         } else if (int.class == clazz) {
917             return new Integer("0");
918         } else if (float.class == clazz) {
919             return new Float("0");
920         } else if (long.class == clazz) {
921             return new Long("0");
922         } else if (double.class == clazz) {
923             return new Double("0");
924         } else if (boolean.class == clazz) {
925             return Boolean.FALSE;
926         }
927         return (char) 0;
928     }
929
930     /**
931      * Gets compatible collection for abstract def.
932      *
933      * @param clazz the clazz
934      * @return the compatible collection for abstract def
935      */
936     public static Collection getCompatibleCollectionForAbstractDef(Class clazz) {
937         if (BlockingQueue.class.isAssignableFrom(clazz)) {
938             return getConcreteCollection(BlockingQueue.class);
939         }
940         if (TransferQueue.class.isAssignableFrom(clazz)) {
941             return getConcreteCollection(TransferQueue.class);
942         }
943         if (Deque.class.isAssignableFrom(clazz)) {
944             return getConcreteCollection(Deque.class);
945         }
946         if (Queue.class.isAssignableFrom(clazz)) {
947             return getConcreteCollection(Queue.class);
948         }
949         if (SortedSet.class.isAssignableFrom(clazz)) {
950             return getConcreteCollection(SortedSet.class);
951         }
952         if (Set.class.isAssignableFrom(clazz)) {
953             return getConcreteCollection(Set.class);
954         }
955         if (List.class.isAssignableFrom(clazz)) {
956             return getConcreteCollection(List.class);
957         }
958         return null;
959     }
960
961     /**
962      * Gets configuration repository key.
963      *
964      * @param array the array
965      * @return the configuration repository key
966      */
967     public static String getConfigurationRepositoryKey(String[] array) {
968         Deque<String> stack = new ArrayDeque<>();
969         stack.push(Constants.DEFAULT_TENANT);
970         for (String element : array) {
971             stack.push(element);
972         }
973         String toReturn = stack.pop();
974         return stack.pop() + Constants.KEY_ELEMENTS_DELEMETER + toReturn;
975     }
976
977     /**
978      * Gets configuration repository key.
979      *
980      * @param file the file
981      * @return the configuration repository key
982      */
983     public static String getConfigurationRepositoryKey(File file) {
984         return getConfigurationRepositoryKey(
985                 ConfigurationUtils.getNamespace(file).split(Constants.TENANT_NAMESPACE_SAPERATOR));
986     }
987
988     /**
989      * Gets configuration repository key.
990      *
991      * @param url the url
992      * @return the configuration repository key
993      */
994     public static String getConfigurationRepositoryKey(URL url) {
995         return getConfigurationRepositoryKey(
996                 ConfigurationUtils.getNamespace(url).split(Constants.TENANT_NAMESPACE_SAPERATOR));
997     }
998
999     /**
1000      * To map linked hash map.
1001      *
1002      * @param config the config
1003      * @return the linked hash map
1004      */
1005     public static LinkedHashMap toMap(Configuration config) {
1006         Iterator<String> iterator = config.getKeys();
1007         LinkedHashMap<String, String> map = new LinkedHashMap<>();
1008         while (iterator.hasNext()) {
1009             String key = iterator.next();
1010             if (!(key.equals(Constants.MODE_KEY) || key.equals(Constants.NAMESPACE_KEY)
1011                     || key.equals(Constants.LOAD_ORDER_KEY))) {
1012                 map.put(key, config.getProperty(key).toString());
1013             }
1014         }
1015
1016         return map;
1017     }
1018
1019     /**
1020      * Diff map.
1021      *
1022      * @param orig   the orig
1023      * @param latest the latest
1024      * @return the map
1025      */
1026     public static Map diff(LinkedHashMap orig, LinkedHashMap latest) {
1027         orig = new LinkedHashMap<>(orig);
1028         latest = new LinkedHashMap<>(latest);
1029         List<String> set = new ArrayList(orig.keySet());
1030         for (String key : set) {
1031             if (latest.remove(key, orig.get(key))) {
1032                 orig.remove(key);
1033             }
1034         }
1035         Set<String> keys = latest.keySet();
1036         for (String key : keys) {
1037             orig.remove(key);
1038         }
1039         set = new ArrayList(orig.keySet());
1040         for (String key : set) {
1041             latest.put(key, "");
1042         }
1043         return new HashMap<>(latest);
1044     }
1045
1046     /**
1047      * Is array boolean.
1048      *
1049      * @param tenant          the tenant
1050      * @param namespace       the namespace
1051      * @param key             the key
1052      * @param processingHints the processing hints
1053      * @return the boolean
1054      * @throws Exception the exception
1055      */
1056     public static boolean isArray(String tenant, String namespace, String key, int processingHints)
1057             throws Exception {
1058         Object obj = ConfigurationUtils
1059                 .getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace), key,
1060                         processingHints);
1061         return (obj != null) && ConfigurationUtils.isCollection(obj.toString());
1062     }
1063
1064     /**
1065      * Is direct lookup boolean.
1066      *
1067      * @param hints the hints
1068      * @return the boolean
1069      */
1070     public static boolean isDirectLookup(int hints) {
1071         return (hints & LATEST_LOOKUP.value()) == LATEST_LOOKUP.value();
1072     }
1073
1074     /**
1075      * Is external lookup boolean.
1076      *
1077      * @param hints the hints
1078      * @return the boolean
1079      */
1080     public static boolean isExternalLookup(int hints) {
1081         return (hints & EXTERNAL_LOOKUP.value()) == EXTERNAL_LOOKUP.value();
1082     }
1083
1084     /**
1085      * Is node specific boolean.
1086      *
1087      * @param hints the hints
1088      * @return the boolean
1089      */
1090     public static boolean isNodeSpecific(int hints) {
1091         return (hints & NODE_SPECIFIC.value()) == NODE_SPECIFIC.value();
1092     }
1093
1094     public static boolean isZeroLengthArray(Class clazz, Object obj) {
1095         if (clazz.isArray() && clazz.getComponentType().isPrimitive()) {
1096             if (clazz.getComponentType() == int.class) {
1097                 return ((int[]) obj).length == 0;
1098             } else if (clazz.getComponentType() == byte.class) {
1099                 return ((byte[]) obj).length == 0;
1100             } else if (clazz.getComponentType() == short.class) {
1101                 return ((short[]) obj).length == 0;
1102             } else if (clazz.getComponentType() == float.class) {
1103                 return ((float[]) obj).length == 0;
1104             } else if (clazz.getComponentType() == boolean.class) {
1105                 return ((boolean[]) obj).length == 0;
1106             } else if (clazz.getComponentType() == double.class) {
1107                 return ((double[]) obj).length == 0;
1108             } else if (clazz.getComponentType() == long.class) {
1109                 return ((long[]) obj).length == 0;
1110             } else {
1111                 return ((Object[]) obj).length == 0;
1112             }
1113         }
1114
1115         return false;
1116     }
1117
1118     /**
1119      * Checks if value is blank
1120      *
1121      * @param value
1122      * @return
1123      */
1124     public static boolean isBlank(String value) {
1125         return value == null || value.trim().length() == 0;
1126     }
1127 }