1 package com.irtimaled.bbor.config;
3 import com.google.common.io.Files;
6 import java.nio.charset.Charset;
7 import java.nio.charset.StandardCharsets;
8 import java.util.HashMap;
12 public class Configuration {
13 public static final String FALLBACK_CATEGORY = "features";
14 private final File file;
16 Configuration(File file) {
21 try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) {
22 writer.write("# Configuration file\n");
23 for (String category : settingsGroup.keySet()) {
25 writer.write(String.format("%s {\n", category));
26 Map<String, Setting<?>> settings = settingsGroup.get(category);
28 for (String settingName : settings.keySet()) {
32 Setting setting = settings.get(settingName);
33 writer.write(String.format(" # %s\n", setting.comment));
34 writer.write(String.format(" %s:%s=%s\n", setting.getType(), settingName, setting.getValue()));
38 } catch (IOException ignored) {
42 private Map<String, Map<String, Setting<?>>> settingsGroup = new HashMap<>();
46 List<String> lines = Files.readLines(file, Charset.forName("utf-8"));
47 String category = null;
48 String lastCommentLine = null;
49 for (String line : lines) {
50 String trimmedLine = line.trim();
51 if (trimmedLine.isEmpty()) {
54 if (trimmedLine.startsWith("#")) {
55 lastCommentLine = trimmedLine.substring(1).trim();
58 if (trimmedLine.equals("}")) {
62 if (category == null && trimmedLine.endsWith("{")) {
63 category = trimmedLine.substring(0, trimmedLine.length() - 1).trim();
64 settingsGroup.put(category, new HashMap<>());
67 if (category != null) {
68 String[] items = trimmedLine.split("[:=]");
69 char type = items[0].charAt(0);
70 String name = items[1];
71 String stringValue = items[2];
72 Setting setting = getTypedSetting(type, stringValue);
73 setting.comment = lastCommentLine;
74 settingsGroup.get(category).put(name, setting);
77 } catch (IOException ignored) {
81 private Setting<?> getTypedSetting(char type, String value) {
84 return new Setting<>(type, Integer.parseInt(value));
86 return new Setting<>(type, value.equals("1") || value.toLowerCase().equals("true"));
88 return new Setting<>(type, value);
91 <T> Setting<T> get(String category, String settingName, T defaultValue) {
92 char type = getType(defaultValue);
93 if (!settingsGroup.containsKey(category)) {
94 settingsGroup.put(category, new HashMap<>());
96 Map<String, Setting<?>> settings = settingsGroup.get(category);
97 Setting<?> setting = settings.get(settingName);
98 if (setting == null && category != FALLBACK_CATEGORY)
99 setting = getFallbackSetting(settingName, settings);
100 if (setting != null && setting.getType() != type) {
103 if (setting == null) {
104 settings.put(settingName, setting = new Setting<>(type, defaultValue));
106 return (Setting<T>) setting;
109 private Setting<?> getFallbackSetting(String settingName, Map<String, Setting<?>> settings) {
110 Map<String, Setting<?>> fallbackSettings = settingsGroup.get(FALLBACK_CATEGORY);
111 if (fallbackSettings == null) return null;
113 Setting<?> setting = fallbackSettings.get(settingName);
114 if (setting != null) {
115 fallbackSettings.remove(settingName);
116 settings.put(settingName, setting);
121 private <T> char getType(T defaultValue) {
122 String[] typeNames = defaultValue.getClass().getName().split("[.]");
123 return typeNames[typeNames.length - 1].charAt(0);
126 void put(Setting<?> setting) {
127 String category = setting.category;
128 if (!settingsGroup.containsKey(category)) {
129 settingsGroup.put(category, new HashMap<>());
131 Map<String, Setting<?>> settings = settingsGroup.get(category);
132 settings.put(setting.name, setting);