Skip to content

Commit 2d3fdfc

Browse files
committed
cleaning and optimization
1 parent 8227e3b commit 2d3fdfc

2 files changed

Lines changed: 101 additions & 86 deletions

File tree

core/src/main/java/net/j4c0b3y/api/config/StaticConfig.java

Lines changed: 82 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,16 @@ public abstract class StaticConfig {
4949
private final ConfigDocument document;
5050

5151
/**
52-
* Maps all config routes to their associated fields.
52+
* Maps all config field routes to their associated fields.
5353
*/
5454
@Getter(AccessLevel.NONE)
5555
private final Map<String, Field> fields = new HashMap<>();
5656

5757
/**
58-
* A list of all routes mapped to if they can't be removed.
58+
* Maps all config class routes to a set of their members.
5959
*/
6060
@Getter(AccessLevel.NONE)
61-
private final Map<String, Boolean> routes = new HashMap<>();
61+
private final Map<String, Set<AnnotatedElement>> sections = new HashMap<>();
6262

6363
/**
6464
* A map of relocation replacements to their target paths.
@@ -102,6 +102,7 @@ public StaticConfig(File file, InputStream defaults, ConfigHandler handler) {
102102
* @param file The file to be used for the configuration document.
103103
* @param handler The config handler to use for config settings.
104104
*/
105+
@SuppressWarnings("unused")
105106
public StaticConfig(File file, ConfigHandler handler) {
106107
this(file, null, handler);
107108
}
@@ -139,7 +140,7 @@ public void load() {
139140

140141
// If fields are empty, perform the initialization.
141142
if (fields.isEmpty()) {
142-
step(getClass(), "", true);
143+
initialize(getClass(), "");
143144
}
144145

145146
// Load and set each field value from the document.
@@ -207,7 +208,7 @@ public void save() {
207208
document.wipeComments(document);
208209

209210
// Recurse through the static fields, setting the values in the document.
210-
step(getClass(), "", false);
211+
step("");
211212

212213
// Set the additional custom comments specified by the user.
213214
setComments();
@@ -219,15 +220,8 @@ public void save() {
219220
}
220221
}
221222

222-
/**
223-
* Recursively steps through each configuration section.
224-
*
225-
* @param parent The parent class of the section.
226-
* @param path The current path.
227-
* @param initialize If this is the initialization phase.
228-
*/
229-
private void step(Class<?> parent, String path, boolean initialize) throws ReflectiveOperationException {
230-
Map<Integer, List<Pair<String, AnnotatedElement>>> members = new TreeMap<>();
223+
private void initialize(Class<?> parent, String path) {
224+
Map<Integer, Set<AnnotatedElement>> priorities = new TreeMap<>();
231225

232226
for (Field field : parent.getDeclaredFields()) {
233227
// Skip field if its modifiers are invalid, or it is marked @Ignore.
@@ -242,17 +236,12 @@ private void step(Class<?> parent, String path, boolean initialize) throws Refle
242236
field.setAccessible(true);
243237

244238
// Get the route by combining the current path and the formatted key.
245-
String route = path + getRoute(field.getAnnotation(Key.class), field.getName());
239+
String route = getRoute(field, path);
246240

247-
// Add the fields and routes if we are in the initialization phase.
248-
if (initialize) {
249-
routes.put(route, true);
250-
fields.put(route, field);
251-
continue;
252-
}
241+
// Add the field to the field map.
242+
fields.put(route, field);
253243

254-
// Add the field to the member priority map.
255-
members.computeIfAbsent(getPriority(field), key -> new ArrayList<>()).add(new Pair<>(route, field));
244+
priorities.computeIfAbsent(getPriority(field), key -> new LinkedHashSet<>()).add(field);
256245
}
257246

258247
Class<?>[] classes = parent.getDeclaredClasses();
@@ -273,64 +262,65 @@ private void step(Class<?> parent, String path, boolean initialize) throws Refle
273262
}
274263

275264
// Get the route by combining the current path and the formatted key.
276-
String route = path + getRoute(clazz.getAnnotation(Key.class), clazz.getSimpleName());
265+
String route = getRoute(clazz, path);
277266

278-
// Add the routes and recurse if we are in the initialization phase.
279-
if (initialize) {
280-
routes.put(route, false);
281-
step(clazz, route + ".", true);
282-
continue;
283-
}
267+
// Initialize the child class.
268+
initialize(clazz, route);
284269

285-
// Add the class to the member priority map.
286-
members.computeIfAbsent(getPriority(clazz), key -> new ArrayList<>()).add(new Pair<>(route, clazz));
270+
priorities.computeIfAbsent(getPriority(clazz), key -> new LinkedHashSet<>()).add(clazz);
287271
}
288272

289-
for (List<Pair<String, AnnotatedElement>> priority : members.values()) {
290-
for (Pair<String, AnnotatedElement> member : priority) {
291-
String route = member.getLeft();
292-
293-
if (member.getRight() instanceof Field) {
294-
Field field = (Field) member.getRight();
273+
for (Set<AnnotatedElement> members : priorities.values()) {
274+
this.sections.computeIfAbsent(path, key -> new LinkedHashSet<>()).addAll(members);
275+
}
276+
}
295277

296-
boolean hidden = field.isAnnotationPresent(Hidden.class);
297-
boolean present = document.contains(route);
278+
/**
279+
* Recursively steps through each configuration section.
280+
*
281+
* @param path The current path.
282+
*/
283+
private void step(String path) throws ReflectiveOperationException {
284+
for (AnnotatedElement member : sections.get(path)) {
285+
String route = getRoute(member, path);
298286

299-
// If this is the initial saving of the value in the document,
300-
// or the field is final, so we have to override the value anyway.
301-
boolean initial = (!present || Modifier.isFinal(field.getModifiers())) && !hidden;
287+
if (member instanceof Field) {
288+
Field field = (Field) member;
302289

303-
// Set the field value in the configuration document.
304-
if (initial || (!hidden || present)) {
305-
set(route, field, field.get(null));
306-
}
290+
boolean hidden = field.isAnnotationPresent(Hidden.class);
291+
boolean present = document.contains(route);
307292

308-
// Set the associated comment for the route's block if present.
309-
document.setComment(document.getBlock(route), field.getAnnotation(Comment.class));
293+
// If this is the initial saving of the value in the document,
294+
// or the field is final, so we have to override the value anyway.
295+
boolean initial = (!present || Modifier.isFinal(field.getModifiers())) && !hidden;
310296

311-
continue;
297+
// Set the field value in the configuration document.
298+
if (initial || (!hidden || present)) {
299+
set(route, field, field.get(null));
312300
}
313301

314-
if (member.getRight() instanceof Class) {
315-
Class<?> clazz = (Class<?>) member.getRight();
302+
// Set the associated comment for the route's block if present.
303+
document.setComment(document.getBlock(route), field.getAnnotation(Comment.class));
304+
continue;
305+
}
316306

317-
// If the class is final, remove it so it is regenerated with default values.
318-
if (Modifier.isFinal(clazz.getModifiers())) {
319-
document.remove(route);
320-
}
307+
if (member instanceof Class) {
308+
// If the class is final, remove it so it is regenerated with default values.
309+
if (Modifier.isFinal(((Class<?>) member).getModifiers())) {
310+
document.remove(route);
311+
}
321312

322-
Section section = document.getSection(route);
313+
Section section = document.getSection(route);
323314

324-
// If the section doesn't exist and is not hidden, create it.
325-
if (section == null && !clazz.isAnnotationPresent(Hidden.class)) {
326-
section = document.createSection(route);
327-
}
315+
// If the section doesn't exist and is not hidden, create it.
316+
if (section == null && !member.isAnnotationPresent(Hidden.class)) {
317+
section = document.createSection(route);
318+
}
328319

329-
// If the section exists, and we shouldn't skip, set the comment and recurse.
330-
if (section != null) {
331-
document.setComment(section, clazz.getAnnotation(Comment.class));
332-
step(clazz, route + ".", false);
333-
}
320+
// If the section exists, and we shouldn't skip, set the comment and recurse.
321+
if (section != null) {
322+
document.setComment(section, member.getAnnotation(Comment.class));
323+
step(route);
334324
}
335325
}
336326
}
@@ -347,11 +337,11 @@ public void format() throws IOException {
347337

348338
// If there is no field for the route,
349339
// but the route is present in the file.
350-
if (!fields.containsKey(route) && !routes.containsKey(route)) {
340+
if (!fields.containsKey(route) && !sections.containsKey(route)) {
351341

352342
// If the route starts with any manual paths,
353343
// prevent it from being flagged for removal.
354-
if (routes.entrySet().stream().anyMatch(entry -> entry.getValue() && route.startsWith(entry.getKey()))) {
344+
if (fields.keySet().stream().anyMatch(route::startsWith)) {
355345
continue;
356346
}
357347

@@ -402,6 +392,7 @@ public void format() throws IOException {
402392
* @param target The old location.
403393
* @param replacement The new location.
404394
*/
395+
@SuppressWarnings("unused")
405396
protected void relocate(String target, String replacement) {
406397
relocations.computeIfAbsent(replacement, key -> new ArrayList<>()).add(target);
407398
}
@@ -437,6 +428,7 @@ private void relocate() {
437428
* @param side If the comment is on the side.
438429
* @param comment The comment.
439430
*/
431+
@SuppressWarnings("SameParameterValue")
440432
protected void setComment(String route, boolean side, String ...comment) {
441433
comments.put(route, new Pair<>(Arrays.asList(comment), side));
442434
}
@@ -447,6 +439,7 @@ protected void setComment(String route, boolean side, String ...comment) {
447439
* @param route The route.
448440
* @param comment The comment.
449441
*/
442+
@SuppressWarnings("unused")
450443
protected void setComment(String route, String ...comment) {
451444
setComment(route, false, comment);
452445
}
@@ -481,16 +474,20 @@ private <T> void set(String key, Field field, T value) {
481474
}
482475

483476
/**
484-
* If the key annotation is present, uses that value.
485-
* Otherwise, uses the member name with the key formatter.
477+
* Gets the route of a field/class and appends it to the path.
486478
*
487-
* @param key The key annotation.
488-
* @param name The name of the member.
479+
* @param member The member key annotation.
480+
* @param path The current path.
489481
* @return The formatted key.
490482
*/
491-
private String getRoute(Key key, String name) {
483+
private String getRoute(AnnotatedElement member, String path) {
484+
Key key = member.getAnnotation(Key.class);
485+
String name = ClassUtils.getName(member);
486+
492487
boolean valid = key != null && !key.value().trim().isEmpty();
493-
return valid ? key.value() : handler.getKeyFormatter().apply(name);
488+
String route = valid ? key.value() : handler.getKeyFormatter().apply(name);
489+
490+
return path + (path.isEmpty() ? "" : ".") + route;
494491
}
495492

496493
/**
@@ -539,11 +536,20 @@ private int getPriority(AnnotatedElement member) {
539536
protected @interface Hidden {
540537
}
541538

539+
/**
540+
* Sets the priority (order) of the entry in the document.
541+
*/
542+
@Retention(RetentionPolicy.RUNTIME)
543+
@Target({ElementType.TYPE, ElementType.FIELD})
544+
public @interface Priority {
545+
int value();
546+
}
547+
542548
/**
543549
* Adds a header comment to the top of the config document.
544550
*/
545551
@Retention(RetentionPolicy.RUNTIME)
546-
@Target({ElementType.TYPE})
552+
@Target(ElementType.TYPE)
547553
public @interface Header {
548554
String[] value();
549555
}
@@ -552,14 +558,8 @@ private int getPriority(AnnotatedElement member) {
552558
* Adds a footer comment to the bottom of the config document.
553559
*/
554560
@Retention(RetentionPolicy.RUNTIME)
555-
@Target({ElementType.TYPE})
561+
@Target(ElementType.TYPE)
556562
public @interface Footer {
557563
String[] value();
558564
}
559-
560-
@Retention(RetentionPolicy.RUNTIME)
561-
@Target({ElementType.TYPE, ElementType.FIELD})
562-
public @interface Priority {
563-
int value();
564-
}
565565
}

core/src/main/java/net/j4c0b3y/api/config/utils/ClassUtils.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33
import lombok.experimental.UtilityClass;
44

55
import java.lang.invoke.MethodType;
6-
import java.lang.reflect.Field;
7-
import java.lang.reflect.Modifier;
8-
import java.lang.reflect.ParameterizedType;
9-
import java.lang.reflect.Type;
6+
import java.lang.reflect.*;
107

118
/**
129
* @author J4C0B3Y
@@ -37,6 +34,24 @@ public <T> Class<T> wrap(Class<T> type) {
3734
return (Class<T>) MethodType.methodType(type).wrap().returnType();
3835
}
3936

37+
/**
38+
* Gets the name of a member.
39+
*
40+
* @param member The member.
41+
* @return The name.
42+
*/
43+
public String getName(AnnotatedElement member) {
44+
if (member instanceof Class) {
45+
return ((Class<?>) member).getSimpleName();
46+
}
47+
48+
if (member instanceof Field) {
49+
return ((Field) member).getName();
50+
}
51+
52+
throw new IllegalArgumentException("Argument 'member' must be a class or field.");
53+
}
54+
4055
public boolean isCompanionClass(Class<?> clazz) {
4156
if (!Modifier.isPublic(clazz.getModifiers())) return false;
4257
if (!Modifier.isStatic(clazz.getModifiers())) return false;

0 commit comments

Comments
 (0)