1010import javax .annotation .Nonnull ;
1111import javax .annotation .Nullable ;
1212import java .io .File ;
13+ import java .lang .annotation .Annotation ;
1314import java .lang .reflect .Field ;
1415import java .lang .reflect .Modifier ;
1516import java .util .*;
@@ -19,6 +20,23 @@ public final class ConfigUtils
1920 private static final String PACKAGE_DEFAULT = "default" ;
2021 private static final Set <Class <?>> LOADED_CONFIG_CLASSES = new HashSet <>();
2122
23+ public static Set <String > reloadAllConfigs ()
24+ {
25+ Set <String > configNames = new TreeSet <>();
26+ for (Class <?> configClass : LOADED_CONFIG_CLASSES )
27+ {
28+ try
29+ {
30+ readConfig (configClass , true );
31+ configNames .add (getConfigName (configClass ));
32+ }
33+ catch (Throwable ignored )
34+ {
35+ }
36+ }
37+ return configNames ;
38+ }
39+
2240 @ Nonnull
2341 public static <T extends Collection <String >> T readStringCollection (
2442 @ Nonnull Configuration cfg ,
@@ -69,138 +87,165 @@ public static void readConfig(@Nonnull Class<?> configClass, @Nonnull String con
6987 {
7088 for (Field field : configClass .getDeclaredFields ())
7189 {
72- int modifiers = field .getModifiers ();
73- if (Modifier .isPublic (modifiers ) && Modifier .isStatic (modifiers ) && !Modifier .isFinal (modifiers ))
90+ try
7491 {
75- Class <?> type = field .getType ();
76- if (type == boolean .class )
77- {
78- ConfigBoolean annotation = field .getAnnotation (ConfigBoolean .class );
79- if (annotation != null )
80- {
81- String name = annotation .name ().isEmpty () ? field .getName () : annotation .name ();
82- tryMoveProperty (cfg , name , annotation .category (), annotation .oldName (), annotation .oldCategory ());
83-
84- boolean defaultValue = field .getBoolean (null );
85- boolean value = cfg .getBoolean (name , annotation .category (), defaultValue , annotation .comment ());
86- field .setBoolean (null , value );
87- }
88- }
89- else if (type == float .class )
90- {
91- ConfigFloat annotation = field .getAnnotation (ConfigFloat .class );
92- if (annotation != null )
93- {
94- String name = annotation .name ().isEmpty () ? field .getName () : annotation .name ();
95- tryMoveProperty (cfg , name , annotation .category (), annotation .oldName (), annotation .oldCategory ());
96-
97- float defaultValue = field .getFloat (null );
98- float value = cfg .getFloat (name , annotation .category (), defaultValue , annotation .min (), annotation .max (), annotation .comment ());
99- field .setFloat (null , value );
100- }
101- }
102- else if (type == int .class )
103- {
104- ConfigInt annotation = field .getAnnotation (ConfigInt .class );
105- if (annotation != null )
106- {
107- String name = annotation .name ().isEmpty () ? field .getName () : annotation .name ();
108- tryMoveProperty (cfg , name , annotation .category (), annotation .oldName (), annotation .oldCategory ());
109-
110- int defaultValue = field .getInt (null );
111- int value = cfg .getInt (name , annotation .category (), defaultValue , annotation .min (), annotation .max (), annotation .comment ());
112- field .setInt (null , value );
113- }
114- }
115- else if (type == String .class )
116- {
117- ConfigString annotation = field .getAnnotation (ConfigString .class );
118- if (annotation != null )
119- {
120- String name = annotation .name ().isEmpty () ? field .getName () : annotation .name ();
121- tryMoveProperty (cfg , name , annotation .category (), annotation .oldName (), annotation .oldCategory ());
122-
123- String defaultValue = (String ) field .get (null );
124- String value = cfg .getString (name , annotation .category (), defaultValue , annotation .comment ());
125- field .set (null , value );
126- }
127- }
128- else if (type == ItemBlockList .class )
129- {
130- ConfigItemBlockList annotation = field .getAnnotation (ConfigItemBlockList .class );
131- if (annotation != null )
132- {
133- String name = annotation .name ().isEmpty () ? field .getName () : annotation .name ();
134- tryMoveProperty (cfg , name , annotation .category (), annotation .oldName (), annotation .oldCategory ());
135-
136- ItemBlockList list = (ItemBlockList ) field .get (null );
137- Objects .requireNonNull (list , "ItemBlockList " + configClass .getName () + '.' + field .getName () + " must not be null" );
138- Set <String > values = readStringCollection (cfg , name , annotation .category (), annotation .comment (), new HashSet <>(list .getRaw ()));
139- list .clear ();
140- list .addRaw (values );
141- }
142- }
143- else if (type == ClassSet .class )
144- {
145- ConfigClassSet annotation = field .getAnnotation (ConfigClassSet .class );
146- if (annotation != null )
147- {
148- String name = annotation .name ().isEmpty () ? field .getName () : annotation .name ();
149- tryMoveProperty (cfg , name , annotation .category (), annotation .oldName (), annotation .oldCategory ());
150-
151- ClassSet <?> classSet = (ClassSet <?>) field .get (null );
152- Objects .requireNonNull (classSet , "ClassSet " + configClass .getName () + '.' + field .getName () + " must not be null" );
153- Set <String > values = readStringCollection (cfg , name , annotation .category (), annotation .comment (), new HashSet <>(classSet .getRaw ()));
154- classSet .clear ();
155- classSet .addRaw (values );
156- }
157- }
158- else if (Enum .class .isAssignableFrom (type ))
159- {
160- ConfigEnum annotation = field .getAnnotation (ConfigEnum .class );
161- if (annotation != null )
162- {
163- String name = annotation .name ().isEmpty () ? field .getName () : annotation .name ();
164- tryMoveProperty (cfg , name , annotation .category (), annotation .oldName (), annotation .oldCategory ());
165-
166- Enum <?> defaultValue = (Enum <?>) field .get (null );
167- Objects .requireNonNull (defaultValue , "Enum " + configClass .getName () + '.' + field .getName () + " must not be null" );
168- String valueName = cfg .getString (name , annotation .category (), defaultValue .name (), annotation .comment ());
169- try
170- {
171- Enum <?> value = Enum .valueOf (defaultValue .getDeclaringClass (), valueName );
172- field .set (null , value );
173- }
174- catch (IllegalArgumentException e )
175- {
176- e .printStackTrace ();
177- }
178- }
179- }
180- else if (Collection .class .isAssignableFrom (type ))
181- {
182- // TODO Check generic type
183- ConfigStringCollection annotation = field .getAnnotation (ConfigStringCollection .class );
184- if (annotation != null )
185- {
186- String name = annotation .name ().isEmpty () ? field .getName () : annotation .name ();
187- tryMoveProperty (cfg , name , annotation .category (), annotation .oldName (), annotation .oldCategory ());
188-
189- Collection <String > collection = (Collection <String >) field .get (null );
190- Objects .requireNonNull (collection , "Collection " + configClass .getName () + '.' + field .getName () + " must not be null" );
191- readStringCollection (cfg , name , annotation .category (), annotation .comment (), collection );
192- }
193- }
92+ readConfigProperty (cfg , field );
93+ }
94+ catch (Throwable throwable )
95+ {
96+ EventHelper .LOGGER .error ("Failed reading property {} in config {}" , field , cfg .getConfigFile ().getName (), throwable );
19497 }
19598 }
19699 }
197100 catch (Throwable throwable )
198101 {
199- EventHelper .LOGGER .error ("Failed reading config " + cfg .getConfigFile ().getName (), throwable );
102+ EventHelper .LOGGER .error ("Failed reading config {}" , cfg .getConfigFile ().getName (), throwable );
200103 }
201104 cfg .save ();
202105 }
203106
107+ private static void readConfigProperty (@ Nonnull Configuration cfg , @ Nonnull Field field )
108+ throws IllegalAccessException
109+ {
110+ if (Modifier .isStatic (field .getModifiers ()))
111+ {
112+ field .setAccessible (true );
113+ for (Annotation declaredAnnotation : field .getDeclaredAnnotations ())
114+ {
115+ // Handle all annotations to throw expection if field have multiple config annotations
116+
117+ Class <? extends Annotation > annotationType = declaredAnnotation .annotationType ();
118+ if (annotationType == ConfigBoolean .class )
119+ {
120+ checkType (field , boolean .class );
121+ checkNotFinal (field );
122+
123+ ConfigBoolean annotation = (ConfigBoolean ) declaredAnnotation ;
124+ String name = annotation .name ().isEmpty () ? field .getName () : annotation .name ();
125+ tryMoveProperty (cfg , name , annotation .category (), annotation .oldName (), annotation .oldCategory ());
126+
127+ boolean defaultValue = field .getBoolean (null );
128+ boolean value = cfg .getBoolean (name , annotation .category (), defaultValue , annotation .comment ());
129+ field .setBoolean (null , value );
130+ }
131+ else if (annotationType == ConfigFloat .class )
132+ {
133+ checkType (field , float .class );
134+ checkNotFinal (field );
135+
136+ ConfigFloat annotation = (ConfigFloat ) declaredAnnotation ;
137+ String name = annotation .name ().isEmpty () ? field .getName () : annotation .name ();
138+ tryMoveProperty (cfg , name , annotation .category (), annotation .oldName (), annotation .oldCategory ());
139+
140+ float defaultValue = field .getFloat (null );
141+ float value = cfg .getFloat (name , annotation .category (), defaultValue , annotation .min (), annotation .max (), annotation .comment ());
142+ field .setFloat (null , value );
143+ }
144+ else if (annotationType == ConfigInt .class )
145+ {
146+ checkType (field , int .class );
147+ checkNotFinal (field );
148+
149+ ConfigInt annotation = (ConfigInt ) declaredAnnotation ;
150+ String name = annotation .name ().isEmpty () ? field .getName () : annotation .name ();
151+ tryMoveProperty (cfg , name , annotation .category (), annotation .oldName (), annotation .oldCategory ());
152+
153+ int defaultValue = field .getInt (null );
154+ int value = cfg .getInt (name , annotation .category (), defaultValue , annotation .min (), annotation .max (), annotation .comment ());
155+ field .setInt (null , value );
156+ }
157+ else if (annotationType == ConfigString .class )
158+ {
159+ checkType (field , String .class );
160+ checkNotFinal (field );
161+
162+ ConfigString annotation = (ConfigString ) declaredAnnotation ;
163+ String name = annotation .name ().isEmpty () ? field .getName () : annotation .name ();
164+ tryMoveProperty (cfg , name , annotation .category (), annotation .oldName (), annotation .oldCategory ());
165+
166+ String defaultValue = (String ) field .get (null );
167+ String value = cfg .getString (name , annotation .category (), defaultValue , annotation .comment ());
168+ field .set (null , value );
169+ }
170+ else if (annotationType == ConfigItemBlockList .class )
171+ {
172+ checkType (field , ItemBlockList .class );
173+
174+ ConfigItemBlockList annotation = (ConfigItemBlockList ) declaredAnnotation ;
175+ String name = annotation .name ().isEmpty () ? field .getName () : annotation .name ();
176+ tryMoveProperty (cfg , name , annotation .category (), annotation .oldName (), annotation .oldCategory ());
177+
178+ ItemBlockList list = (ItemBlockList ) field .get (null );
179+ Objects .requireNonNull (list , field + " value must not be null" );
180+ Set <String > values = readStringCollection (cfg , name , annotation .category (), annotation .comment (), new HashSet <>(list .getRaw ()));
181+ list .clear ();
182+ list .addRaw (values );
183+ }
184+ else if (annotationType == ConfigClassSet .class )
185+ {
186+ checkType (field , ClassSet .class );
187+
188+ ConfigClassSet annotation = (ConfigClassSet ) declaredAnnotation ;
189+ String name = annotation .name ().isEmpty () ? field .getName () : annotation .name ();
190+ tryMoveProperty (cfg , name , annotation .category (), annotation .oldName (), annotation .oldCategory ());
191+
192+ ClassSet <?> classSet = (ClassSet <?>) field .get (null );
193+ Objects .requireNonNull (classSet , field + " value must not be null" );
194+ Set <String > values = readStringCollection (cfg , name , annotation .category (), annotation .comment (), new HashSet <>(classSet .getRaw ()));
195+ classSet .clear ();
196+ classSet .addRaw (values );
197+ }
198+ else if (annotationType == ConfigEnum .class )
199+ {
200+ checkType (field , Enum .class );
201+ checkNotFinal (field );
202+
203+ ConfigEnum annotation = (ConfigEnum ) declaredAnnotation ;
204+ String name = annotation .name ().isEmpty () ? field .getName () : annotation .name ();
205+ tryMoveProperty (cfg , name , annotation .category (), annotation .oldName (), annotation .oldCategory ());
206+
207+ Enum <?> defaultValue = (Enum <?>) field .get (null );
208+ Objects .requireNonNull (defaultValue , field + " value must not be null" );
209+ String valueName = cfg .getString (name , annotation .category (), defaultValue .name (), annotation .comment ());
210+ try
211+ {
212+ Enum <?> value = Enum .valueOf (defaultValue .getDeclaringClass (), valueName );
213+ field .set (null , value );
214+ }
215+ catch (IllegalArgumentException e )
216+ {
217+ e .printStackTrace ();
218+ }
219+ }
220+ else if (annotationType == ConfigStringCollection .class )
221+ {
222+ // TODO Check generic type
223+ checkType (field , Collection .class );
224+
225+ ConfigStringCollection annotation = (ConfigStringCollection ) declaredAnnotation ;
226+ String name = annotation .name ().isEmpty () ? field .getName () : annotation .name ();
227+ tryMoveProperty (cfg , name , annotation .category (), annotation .oldName (), annotation .oldCategory ());
228+
229+ Collection <String > collection = (Collection <String >) field .get (null );
230+ Objects .requireNonNull (collection , field + " value must not be null" );
231+ readStringCollection (cfg , name , annotation .category (), annotation .comment (), collection );
232+ }
233+ }
234+ }
235+ }
236+
237+ private static void checkType (@ Nonnull Field field , @ Nonnull Class <?> expectedType )
238+ {
239+ Class <?> type = field .getType ();
240+ Preconditions .checkArgument (expectedType == type || expectedType .isAssignableFrom (type ), field + " type must be " + expectedType + " ( real type is " + type + ')' );
241+ }
242+
243+ private static void checkNotFinal (@ Nonnull Field field )
244+ {
245+ int modifiers = field .getModifiers ();
246+ Preconditions .checkArgument (!Modifier .isFinal (modifiers ), field + " must not be final" );
247+ }
248+
204249 private static boolean tryMoveProperty (
205250 @ Nonnull Configuration cfg ,
206251 @ Nonnull String newName ,
0 commit comments