/*
 * Copyright (C) 2015-2018 SoftIndex LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.datakernel.common;

import java.time.Duration;
import java.util.function.Function;

public final class ApplicationSettings {

	public static String getString(Class<?> type, String name, String defValue) {
		String property;
		property = System.getProperty(type.getName() + "." + name);
		if (property != null) return property;
		property = System.getProperty(type.getSimpleName() + "." + name);
		if (property != null) return property;
		return defValue;
	}

	public static <T> T get(Function<String, T> parser, Class<?> type, String name, T defValue) {
		String property = getString(type, name, null);
		if (property != null) {
			return parser.apply(property);
		}
		return defValue;
	}

	public static int getInt(Class<?> type, String name, int defValue) {
		return get(Integer::parseInt, type, name, defValue);
	}

	public static long getLong(Class<?> type, String name, long defValue) {
		return get(Long::parseLong, type, name, defValue);
	}

	public static boolean getBoolean(Class<?> type, String name, boolean defValue) {
		return get(s -> s.trim().isEmpty() || Boolean.parseBoolean(s), type, name, defValue);
	}

	public static double getDouble(Class<?> type, String name, double defValue) {
		return get(Double::parseDouble, type, name, defValue);
	}

	public static Duration getDuration(Class<?> type, String name, Duration defValue) {
		return get(StringFormatUtils::parseDuration, type, name, defValue);
	}

	public static MemSize getMemSize(Class<?> type, String name, MemSize defValue) {
		return get(MemSize::valueOf, type, name, defValue);
	}

}

@@ -639,62 +639,230 @@
 ort 
-java.time.Duration;%0Aimport java.util.function.Function
+org.jetbrains.annotations.Nullable;%0A%0Aimport java.time.Duration;%0Aimport java.util.HashMap;%0Aimport java.util.Map;%0Aimport java.util.Properties;%0Aimport java.util.function.Function;%0A%0Aimport static java.util.Collections.emptyMap
 ;%0A%0Ap
@@ -901,32 +901,32 @@
 tings %7B%0A
-%0A
 %09p
-ublic
+rivate
  static 
 String g
@@ -921,101 +921,121 @@
 tic 
-String getString(Class%3C?%3E type, String name, String defValue) %7B%0A%09%09String p
+final Map%3CClass%3C?%3E, Map%3CString, Object%3E%3E customSettings = new HashMap%3C%3E();%0A%0A%09private static P
 ropert
-y;%0A%09%09
+ies 
 propert
-y
+ies
  = S
@@ -1054,213 +1054,308 @@
 pert
-y(type.getName() + %22.%22 + name);%0A%09%09if (property != null) return property;%0A%09%09property = System.getProperty(type.getSimpleName() + %22.%22 + name);%0A%09%09if (property != null) return property;%0A%09%09return defV
+ies();%0A%0A%09public static void useProperties(Properties properties)%7B%0A%09%09ApplicationSettings.properties = properties;%0A%09%7D%0A%0A%09public static void set(Class%3C?%3E type, String name, Object value) %7B%0A%09%09customSettings.computeIfAbsent(type, $ -%3E new HashMap%3C%3E()).put(name, v
 alue
+)
 ;%0A%09%7D%0A%0A
+%09@SuppressWarnings(%22unchecked%22)%0A
 %09pub
@@ -1445,16 +1445,157 @@
 alue) %7B%0A
+%09%09T customSetting = (T) customSettings.getOrDefault(type, emptyMap()).get(name);%0A%09%09if (customSetting != null) %7B%0A%09%09%09return customSetting;%0A%09%09%7D%0A
 %09%09String
@@ -1609,22 +1609,24 @@
 ty = get
-String
+Property
 (type, n
@@ -1632,14 +1632,8 @@
 name
-, null
 );%0A%09
@@ -1714,24 +1714,164 @@
 fValue;%0A%09%7D%0A%0A
+%09public static String getString(Class%3C?%3E type, String name, String defValue) %7B%0A%09%09return get(Function.identity(), type, name, defValue);%0A%09%7D%0A%0A
 %09public stat
@@ -2730,10 +2730,306 @@
 e);%0A%09%7D%0A%0A
+%09@Nullable%0A%09private static String getProperty(Class%3C?%3E type, String name) %7B%0A%09%09String property;%0A%09%09property = properties.getProperty(type.getName() + %22.%22 + name);%0A%09%09if (property != null) return property;%0A%09%09property = properties.getProperty(type.getSimpleName() + %22.%22 + name);%0A%09%09return property;%0A%09%7D%0A
 %7D%0A

Add ability to set ApplicationSettings directly or by passing properties other than System's