1 package com.irtimaled.bbor.client.config;
3 import com.google.common.io.Files;
5 import java.io.BufferedWriter;
7 import java.io.FileOutputStream;
8 import java.io.IOException;
9 import java.io.OutputStreamWriter;
10 import java.io.Writer;
11 import java.nio.charset.StandardCharsets;
12 import java.util.HashMap;
13 import java.util.List;
17 private static final String FALLBACK_CATEGORY = "features";
18 private final File file;
20 Configuration(File file) {
25 try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) {
26 writer.write("# Configuration file\n");
27 for (String category : settingsGroup.keySet()) {
29 writer.write(String.format("%s {\n", category));
30 Map<String, Setting<?>> settings = settingsGroup.get(category);
32 for (String settingName : settings.keySet()) {
36 Setting setting = settings.get(settingName);
37 writer.write(String.format(" # %s\n", setting.comment));
38 writer.write(String.format(" %s:%s=%s\n", setting.getType(), settingName, setting.get()));
42 } catch (IOException ignored) {
46 private final Map<String, Map<String, Setting<?>>> settingsGroup = new HashMap<>();
50 List<String> lines = Files.readLines(file, StandardCharsets.UTF_8);
51 String category = null;
52 String lastCommentLine = null;
53 for (String line : lines) {
54 String trimmedLine = line.trim();
55 if (trimmedLine.isEmpty()) {
58 if (trimmedLine.startsWith("#")) {
59 lastCommentLine = trimmedLine.substring(1).trim();
62 if (trimmedLine.equals("}")) {
66 if (category == null && trimmedLine.endsWith("{")) {
67 category = trimmedLine.substring(0, trimmedLine.length() - 1).trim();
68 settingsGroup.put(category, new HashMap<>());
71 if (category != null) {
72 String[] items = trimmedLine.split("[:=]");
73 char type = items[0].charAt(0);
74 String name = items[1];
75 String stringValue = items[2];
76 Setting setting = getTypedSetting(type, stringValue);
77 setting.comment = lastCommentLine;
78 settingsGroup.get(category).put(name, setting);
81 } catch (IOException ignored) {
85 private Setting<?> getTypedSetting(char type, String value) {
88 return new Setting<>(type, Integer.parseInt(value));
90 return new Setting<>(type, value.equals("1") || value.toLowerCase().equals("true"));
92 return new Setting<>(type, HexColor.from(value));
94 return new Setting<>(type, value);
97 <T> Setting<T> get(String category, String settingName, T defaultValue) {
98 char type = getType(defaultValue);
99 if (!settingsGroup.containsKey(category)) {
100 settingsGroup.put(category, new HashMap<>());
102 Map<String, Setting<?>> settings = settingsGroup.get(category);
103 Setting<?> setting = settings.get(settingName);
104 if (setting == null && !category.equals(FALLBACK_CATEGORY))
105 setting = getFallbackSetting(settingName, settings);
106 if (setting != null && setting.getType() != type) {
109 if (setting == null) {
110 settings.put(settingName, setting = new Setting<>(type, defaultValue));
112 return (Setting<T>) setting;
115 private Setting<?> getFallbackSetting(String settingName, Map<String, Setting<?>> settings) {
116 Map<String, Setting<?>> fallbackSettings = settingsGroup.get(FALLBACK_CATEGORY);
117 if (fallbackSettings == null) return null;
119 Setting<?> setting = fallbackSettings.get(settingName);
120 if (setting != null) {
121 fallbackSettings.remove(settingName);
122 settings.put(settingName, setting);
127 private <T> char getType(T defaultValue) {
128 String[] typeNames = defaultValue.getClass().getName().split("[.]");
129 return typeNames[typeNames.length - 1].charAt(0);
132 void put(Setting<?> setting) {
133 String category = setting.category;
134 if (!settingsGroup.containsKey(category)) {
135 settingsGroup.put(category, new HashMap<>());
137 Map<String, Setting<?>> settings = settingsGroup.get(category);
138 settings.put(setting.name, setting);