Skip to content

Commit fdec696

Browse files
authored
Merge pull request #75 from BenCodez/codex/simpleapi-config-view-foundation
Extract platform-neutral configuration binding with Bukkit compatibility
2 parents c4a37e5 + fe70bd5 commit fdec696

8 files changed

Lines changed: 1011 additions & 283 deletions

File tree

Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
package com.bencodez.simpleapi.file.annotation;
2+
3+
import java.lang.reflect.Field;
4+
import java.util.ArrayList;
5+
import java.util.HashSet;
6+
import java.util.List;
7+
import java.util.Set;
8+
9+
import java.util.Objects;
10+
import java.util.function.Function;
11+
12+
import com.bencodez.simpleapi.file.config.ConfigView;
13+
14+
import com.bencodez.simpleapi.time.ParsedDuration;
15+
16+
/**
17+
* Platform-neutral implementation of the existing configuration annotations.
18+
*
19+
* <p>This is a compatibility extraction, not a change to the annotation rules.
20+
* Field fallback values, empty-list handling, declared-field-only traversal,
21+
* annotation order and per-field exception isolation are intentionally retained.
22+
* In particular, the legacy zero-default long reflection behavior is unchanged.</p>
23+
*/
24+
public class AnnotationBinder {
25+
26+
private final Function<ConfigView, ?> sectionValue;
27+
28+
/** Creates a binder that assigns ConfigView values to section fields. */
29+
public AnnotationBinder() {
30+
this(view -> view);
31+
}
32+
33+
/**
34+
* Creates a binder with a platform-specific section projection. Only the
35+
* compatibility adapter should unwrap a view to a native section. The
36+
* projection is invoked for present sections, never for an absent section.
37+
*
38+
* @param sectionValue projection used for ConfigDataConfigurationSection
39+
*/
40+
public AnnotationBinder(Function<ConfigView, ?> sectionValue) {
41+
this.sectionValue = Objects.requireNonNull(sectionValue, "sectionValue");
42+
}
43+
44+
@SuppressWarnings("unchecked")
45+
public void load(ConfigView config, Object classToLoad) {
46+
Class<?> clazz = classToLoad.getClass();
47+
48+
for (Field field : clazz.getDeclaredFields()) {
49+
try {
50+
field.setAccessible(true);
51+
52+
ConfigDataString stringAnnotation = field.getAnnotation(ConfigDataString.class);
53+
if (stringAnnotation != null) {
54+
55+
String defaultValue = stringAnnotation.defaultValue();
56+
if (defaultValue.isEmpty()) {
57+
try {
58+
String v = (String) field.get(classToLoad);
59+
defaultValue = v;
60+
} catch (Exception e) {
61+
62+
}
63+
}
64+
String value = "";
65+
if (!stringAnnotation.secondPath().isEmpty()) {
66+
value = config.getString(stringAnnotation.path(),
67+
config.getString(stringAnnotation.secondPath(), defaultValue));
68+
} else {
69+
value = config.getString(stringAnnotation.path(), defaultValue);
70+
}
71+
72+
field.set(classToLoad, value);
73+
74+
}
75+
76+
ConfigDataBoolean booleanAnnotation = field.getAnnotation(ConfigDataBoolean.class);
77+
if (booleanAnnotation != null) {
78+
boolean defaultValue = booleanAnnotation.defaultValue();
79+
if (!defaultValue) {
80+
try {
81+
boolean v = field.getBoolean(classToLoad);
82+
defaultValue = v;
83+
} catch (Exception e) {
84+
85+
}
86+
87+
}
88+
89+
boolean value = defaultValue;
90+
if (config.contains(booleanAnnotation.path())) {
91+
value = config.getBoolean(booleanAnnotation.path(), defaultValue);
92+
} else if (!booleanAnnotation.secondPath().isEmpty()
93+
&& config.contains(booleanAnnotation.secondPath())) {
94+
value = config.getBoolean(booleanAnnotation.secondPath(), defaultValue);
95+
96+
if (booleanAnnotation.secondPathInvert()) {
97+
value = !value;
98+
}
99+
} else {
100+
value = config.getBoolean(booleanAnnotation.path(), defaultValue);
101+
}
102+
103+
field.set(classToLoad, value);
104+
}
105+
106+
ConfigDataInt intAnnotation = field.getAnnotation(ConfigDataInt.class);
107+
if (intAnnotation != null) {
108+
int defaultValue = intAnnotation.defaultValue();
109+
if (defaultValue == 0) {
110+
try {
111+
int v = field.getInt(classToLoad);
112+
defaultValue = v;
113+
} catch (Exception e) {
114+
115+
}
116+
}
117+
int value = 0;
118+
if (!intAnnotation.secondPath().isEmpty()) {
119+
value = config.getInt(intAnnotation.path(),
120+
config.getInt(intAnnotation.secondPath(), defaultValue));
121+
} else {
122+
value = config.getInt(intAnnotation.path(), defaultValue);
123+
}
124+
125+
field.set(classToLoad, value);
126+
}
127+
128+
ConfigDataLong longAnnotation = field.getAnnotation(ConfigDataLong.class);
129+
if (longAnnotation != null) {
130+
long defaultValue = longAnnotation.defaultValue();
131+
if (defaultValue == 0) {
132+
try {
133+
int v = field.getInt(classToLoad);
134+
defaultValue = v;
135+
} catch (Exception e) {
136+
137+
}
138+
}
139+
long value = 0;
140+
if (!longAnnotation.secondPath().isEmpty()) {
141+
value = config.getLong(longAnnotation.path(),
142+
config.getLong(longAnnotation.secondPath(), defaultValue));
143+
} else {
144+
value = config.getLong(longAnnotation.path(), defaultValue);
145+
}
146+
147+
field.set(classToLoad, value);
148+
}
149+
150+
ConfigDataDouble doubleAnnotation = field.getAnnotation(ConfigDataDouble.class);
151+
if (doubleAnnotation != null) {
152+
double defaultValue = doubleAnnotation.defaultValue();
153+
if (defaultValue == 0) {
154+
try {
155+
double v = field.getDouble(classToLoad);
156+
defaultValue = v;
157+
} catch (Exception e) {
158+
159+
}
160+
}
161+
double value = 0;
162+
if (!doubleAnnotation.secondPath().isEmpty()) {
163+
value = config.getDouble(doubleAnnotation.path(),
164+
config.getDouble(doubleAnnotation.secondPath(), defaultValue));
165+
} else {
166+
value = config.getDouble(doubleAnnotation.path(), defaultValue);
167+
}
168+
169+
field.set(classToLoad, value);
170+
}
171+
172+
ConfigDataListString listAnnotation = field.getAnnotation(ConfigDataListString.class);
173+
if (listAnnotation != null) {
174+
ArrayList<String> defaultValue = new ArrayList<>();
175+
try {
176+
ArrayList<String> v = (ArrayList<String>) field.get(classToLoad);
177+
defaultValue = v;
178+
} catch (Exception e) {
179+
180+
}
181+
182+
List<String> list = config.getStringList(listAnnotation.path());
183+
184+
if (list.isEmpty()) {
185+
list = config.getStringList(listAnnotation.secondPath());
186+
}
187+
188+
ArrayList<String> list1 = new ArrayList<>(list);
189+
// use default value
190+
if (list.isEmpty()) {
191+
list1 = defaultValue;
192+
}
193+
194+
field.set(classToLoad, list1);
195+
196+
/*
197+
* ArrayList<String> value = null; if (!listAnnotation.secondPath().isEmpty()) {
198+
* value = (ArrayList<String>) config.getList(listAnnotation.path(),
199+
* config.getList(listAnnotation.secondPath(), defaultValue)); } else { value =
200+
* (ArrayList<String>) config.getList(listAnnotation.path(), defaultValue); }
201+
*
202+
* field.set(classToLoad, value);
203+
*/
204+
}
205+
206+
ConfigDataListInt intListAnnotation = field.getAnnotation(ConfigDataListInt.class);
207+
if (intListAnnotation != null) {
208+
ArrayList<Integer> defaultValue = new ArrayList<>();
209+
try {
210+
ArrayList<Integer> v = (ArrayList<Integer>) field.get(classToLoad);
211+
defaultValue = v;
212+
} catch (Exception e) {
213+
214+
}
215+
216+
List<Integer> list = config.getIntegerList(intListAnnotation.path());
217+
218+
if (list.isEmpty()) {
219+
list = config.getIntegerList(intListAnnotation.secondPath());
220+
}
221+
222+
ArrayList<Integer> list1 = new ArrayList<>(list);
223+
// use default value
224+
if (list.isEmpty()) {
225+
list1 = defaultValue;
226+
}
227+
228+
field.set(classToLoad, list1);
229+
230+
/*
231+
* ArrayList<String> value = null; if (!listAnnotation.secondPath().isEmpty()) {
232+
* value = (ArrayList<String>) config.getList(listAnnotation.path(),
233+
* config.getList(listAnnotation.secondPath(), defaultValue)); } else { value =
234+
* (ArrayList<String>) config.getList(listAnnotation.path(), defaultValue); }
235+
*
236+
* field.set(classToLoad, value);
237+
*/
238+
}
239+
240+
ConfigDataKeys setAnnotation = field.getAnnotation(ConfigDataKeys.class);
241+
if (setAnnotation != null) {
242+
Set<String> value = new HashSet<>();
243+
if (config.isConfigurationSection(setAnnotation.path())) {
244+
value = config.getConfigurationSection(setAnnotation.path()).getKeys(false);
245+
} else if (config.isConfigurationSection(setAnnotation.secondPath())
246+
&& setAnnotation.secondPath().length() > 0) {
247+
value = config.getConfigurationSection(setAnnotation.secondPath()).getKeys(false);
248+
}
249+
if (value != null) {
250+
field.set(classToLoad, value);
251+
}
252+
}
253+
254+
ConfigDataConfigurationSection confAnnotation = field
255+
.getAnnotation(ConfigDataConfigurationSection.class);
256+
if (confAnnotation != null) {
257+
ConfigView value = null;
258+
if (config.isConfigurationSection(confAnnotation.path())) {
259+
value = config.getConfigurationSection(confAnnotation.path());
260+
} else if (config.isConfigurationSection(confAnnotation.secondPath())
261+
&& !confAnnotation.secondPath().isEmpty()) {
262+
value = config.getConfigurationSection(confAnnotation.secondPath());
263+
}
264+
265+
field.set(classToLoad, value == null ? null : sectionValue.apply(value));
266+
}
267+
268+
ConfigDataParsedDuration durationAnnotation = field.getAnnotation(ConfigDataParsedDuration.class);
269+
if (durationAnnotation != null) {
270+
271+
String defaultValue = durationAnnotation.defaultValue();
272+
273+
if (defaultValue.isEmpty()) {
274+
try {
275+
Object v = field.get(classToLoad);
276+
if (v != null) {
277+
defaultValue = v.toString();
278+
}
279+
} catch (Exception e) {
280+
281+
}
282+
}
283+
284+
String value = "";
285+
286+
if (!durationAnnotation.secondPath().isEmpty()) {
287+
value = config.getString(durationAnnotation.path(),
288+
config.getString(durationAnnotation.secondPath(), defaultValue));
289+
} else {
290+
value = config.getString(durationAnnotation.path(), defaultValue);
291+
}
292+
293+
try {
294+
// Assumes ParsedDuration has a constructor or static parse method
295+
Object parsedDuration = ParsedDuration.parse(value, durationAnnotation.defaultTimeUnit());
296+
field.set(classToLoad, parsedDuration);
297+
} catch (Exception e) {
298+
e.printStackTrace();
299+
}
300+
}
301+
302+
} catch (Exception e) {
303+
e.printStackTrace();
304+
}
305+
}
306+
307+
}
308+
309+
}

0 commit comments

Comments
 (0)