3232import org .comroid .api .data .bind .DataStructure ;
3333import org .comroid .api .data .seri .DataNode ;
3434import org .comroid .api .data .seri .MimeType ;
35+ import org .comroid .api .data .seri .type .ArrayValueType ;
3536import org .comroid .api .func .exc .ThrowingFunction ;
3637import org .comroid .api .func .exc .ThrowingSupplier ;
3738import org .comroid .api .func .ext .Context ;
3839import org .comroid .api .func .ext .Wrap ;
3940import org .comroid .api .func .util .Debug ;
4041import org .comroid .api .func .util .Pair ;
4142import org .comroid .api .io .FileHandle ;
43+ import org .comroid .api .java .Activator ;
4244import org .comroid .api .java .JITAssistant ;
4345import org .comroid .api .text .Capitalization ;
4446import org .comroid .api .tree .UncheckedCloseable ;
4951import java .io .FileInputStream ;
5052import java .io .FileOutputStream ;
5153import java .io .InputStreamReader ;
54+ import java .lang .reflect .Array ;
5255import java .lang .reflect .Field ;
5356import java .nio .charset .StandardCharsets ;
5457import java .time .Instant ;
@@ -89,7 +92,8 @@ public ConfigurationManager(Context context, Class<T> type, String filePath, Mim
8992 }
9093
9194 public T initialize () {
92- if (!file .exists () && (file .getParentFile ().exists () || file .getParentFile ().mkdirs ())) save (); // save default config
95+ if (!file .exists () && (file .getParentFile ().exists () || file .getParentFile ()
96+ .mkdirs ())) save (); // save default config
9397 reload ();
9498 return config ;
9599 }
@@ -103,9 +107,13 @@ public void reload(boolean force) {
103107 if (!force && ftime ().isBefore (timestamp )) return ; // reload is not necessary
104108
105109 DataNode node ;
106- try (var fis = new FileInputStream (file ); var isr = new InputStreamReader (fis ); var br = new BufferedReader (isr )) {
110+ try (
111+ var fis = new FileInputStream (file ); var isr = new InputStreamReader (fis );
112+ var br = new BufferedReader (isr )
113+ ) {
107114 var data = br .lines ().collect (Collectors .joining ());
108- node = Objects .requireNonNull (dataType .getDeserializer (), "No deserializer set for " + dataType ).apply (data );
115+ node = Objects .requireNonNull (dataType .getDeserializer (), "No deserializer set for " + dataType )
116+ .apply (data );
109117 }
110118 Objects .requireNonNull (node , "No data" );
111119
@@ -123,18 +131,30 @@ private void setSelfAndChildrenRecursive(DataStructure<?> struct, Object it, Dat
123131 classes = property .getAnnotation (Adapt .class ).value ();
124132 JITAssistant .prepare (classes );
125133 value = Arrays .stream (classes )
126- .flatMap ($ -> Stream .ofNullable (TypeAdapter .CACHE .getOrDefault (property .getType ().getTargetClass (), null )))
134+ .flatMap ($ -> Stream .ofNullable (TypeAdapter .CACHE .getOrDefault (property .getType ()
135+ .getTargetClass (), null )))
127136 .flatMap (adp -> adp .deserialize (context , adp .parseSerialized (node .asString ())).stream ())
128137 .findAny ()
129138 .orElse (null );
130139 }
131- if (propType .isStandard () || classes != null ) {
140+
141+ if (propType instanceof ArrayValueType <?>) {
142+ var componentType = propType .getTargetClass ().getComponentType ();
143+ var array = (Object []) Array .newInstance (componentType , node .size ());
144+ for (int i = 0 ; i < node .size (); i ++) {
145+ var each = node .get (i );
146+ array [i ] = Activator .get (componentType ).createInstance (each );
147+ }
148+ value = array ;
149+ }
150+
151+ if (propType .isStandard () || propType .isArray () || classes != null ) {
132152 if (propType .isStandard () && value == null ) value = propType .parse (node .asString ());
133153 property .setFor (it , uncheckedCast (value ));
134154 } else //noinspection ConstantValue <- false positive for some reason
135155 if (node != null ) setSelfAndChildrenRecursive (DataStructure .of (propType .getTargetClass ()),
136- property .getFrom (it ),
137- node );
156+ property .getFrom (it ),
157+ node );
138158 }
139159 }
140160
@@ -228,17 +248,23 @@ public void clear() {
228248 @ Override
229249 public void refresh () {
230250 for (var property : struct .getProperties ())
231- if (!property .isAnnotationPresent (Ignore .class )) sendAttributeMessageRecursive (property .getName (), property , config , 1 );
251+ if (!property .isAnnotationPresent (Ignore .class )) sendAttributeMessageRecursive (property .getName (),
252+ property ,
253+ config ,
254+ 1 );
232255 }
233256
234- private void sendAttributeMessageRecursive (String fullName , DataStructure <?>.Property <?> property , Object it , int level ) {
257+ private void sendAttributeMessageRecursive (
258+ String fullName , DataStructure <?>.Property <?> property , Object it , int level ) {
235259 if (it == null ) {
236260 Debug .log (fullName + " is null" );
237261 return ;
238262 }
239263 Debug .log (fullName + " is not null" );
240264
241- var title = IntStream .range (0 , level ).mapToObj ($ -> "#" ).collect (Collectors .joining ()) + " Config Value " + Code .apply (fullName );
265+ var title = IntStream .range (0 , level )
266+ .mapToObj ($ -> "#" )
267+ .collect (Collectors .joining ()) + " Config Value " + Code .apply (fullName );
242268 var desc = property .getDescription ();
243269 var current = property .getFrom (it );
244270 var propType = property .getType ();
@@ -248,7 +274,10 @@ private void sendAttributeMessageRecursive(String fullName, DataStructure<?>.Pro
248274 ```
249275 %s: %s
250276 ```
251- """ .formatted (title , desc .isEmpty () ? "" : "\n > " + String .join ("\n > " , desc ), propType .getTargetClass ().getSimpleName (), current );
277+ """ .formatted (title ,
278+ desc .isEmpty () ? "" : "\n > " + String .join ("\n > " , desc ),
279+ propType .getTargetClass ().getSimpleName (),
280+ current );
252281
253282 ifs :
254283 {
@@ -267,15 +296,20 @@ private void sendAttributeMessageRecursive(String fullName, DataStructure<?>.Pro
267296 if (current instanceof ISnowflake flake ) current = flake .getIdLong ();
268297 if (current != null ) {
269298 var currentId = (long ) current ;
270- if (Channel .class .isAssignableFrom (propClass )) def = EntitySelectMenu .DefaultValue .channel (currentId );
271- else if (User .class .isAssignableFrom (propClass )) def = EntitySelectMenu .DefaultValue .user (currentId );
272- else if (Role .class .isAssignableFrom (propClass )) def = EntitySelectMenu .DefaultValue .role (currentId );
273- else throw new IllegalArgumentException ("Invalid mentionable: " + propClass .getCanonicalName ());
299+ if (Channel .class .isAssignableFrom (propClass )) def = EntitySelectMenu .DefaultValue .channel (
300+ currentId );
301+ else if (User .class .isAssignableFrom (propClass )) def = EntitySelectMenu .DefaultValue .user (
302+ currentId );
303+ else if (Role .class .isAssignableFrom (propClass )) def = EntitySelectMenu .DefaultValue .role (
304+ currentId );
305+ else
306+ throw new IllegalArgumentException ("Invalid mentionable: " + propClass .getCanonicalName ());
274307 builder .setDefaultValues (def );
275308 }
276309
277310 // choose ChannelType if necessary
278- if (target == EntitySelectMenu .SelectTarget .CHANNEL ) builder .setChannelTypes (Arrays .stream (ChannelType .values ())
311+ if (target == EntitySelectMenu .SelectTarget .CHANNEL ) builder .setChannelTypes (Arrays .stream (
312+ ChannelType .values ())
279313 .filter (type -> type .getInterface ().isAssignableFrom (propClass ))
280314 .filter (type -> type != ChannelType .UNKNOWN )
281315 .toList ());
@@ -290,7 +324,8 @@ private void sendAttributeMessageRecursive(String fullName, DataStructure<?>.Pro
290324 .filter (Field ::isEnumConstant )
291325 .forEach (field -> menu .addOption (Aliased .$ (field )
292326 .findAny ()
293- .or (() -> Optional .ofNullable (ThrowingSupplier .sneaky (() -> Named .$ (field .get (null ))).get ()))
327+ .or (() -> Optional .ofNullable (ThrowingSupplier .sneaky (() -> Named .$ (field .get (null )))
328+ .get ()))
294329 .orElseGet (field ::getName ), field .getName (), Annotations .descriptionText (field )));
295330
296331 // send enum selection box
@@ -358,7 +393,8 @@ public void onStringSelectInteraction(@NotNull StringSelectInteractionEvent even
358393 .filter (Field ::isEnumConstant )
359394 .filter (field -> value .equals (Aliased .$ (field )
360395 .findAny ()
361- .or (() -> Optional .ofNullable (ThrowingSupplier .sneaky (() -> Named .$ (field .get (null ))).get ()))
396+ .or (() -> Optional .ofNullable (ThrowingSupplier .sneaky (() -> Named .$ (field .get (
397+ null ))).get ()))
362398 .orElseGet (field ::getName ))))
363399 .findAny ()
364400 .map (ThrowingFunction .sneaky (field -> field .get (null )))
@@ -389,33 +425,44 @@ public void onEntitySelectInteraction(@NotNull EntitySelectInteractionEvent even
389425 private CompletableFuture <?> updateDisplayValue (Message original , InteractionHook hook , Object value ) {
390426 var raw = original .getContentRaw ();
391427 var start = raw .indexOf ("```" );
392- return original .editMessage (raw .substring (0 , start ) + "```\n " + value + "\n ```" ).flatMap ($ -> hook .deleteOriginal ()).submit ();
428+ return original .editMessage (raw .substring (0 , start ) + "```\n " + value + "\n ```" )
429+ .flatMap ($ -> hook .deleteOriginal ())
430+ .submit ();
393431 }
394432
395433 private Pair <DataStructure <?>.Property <?>, Object > descend (String ... path ) {
396434 if (path .length == 0 ) throw new IllegalArgumentException ("Empty path" );
397435 Wrap <DataStructure <?>.Property <?>> wrap = uncheckedCast (struct .getProperty (path [0 ]));
398436 Object holder = config ;
399- if (wrap .test (prop -> !prop .getType ().isStandard ())) holder = wrap .ifPresentMap (prop -> prop .getFrom (config ));
437+ if (wrap .test (prop -> !prop .getType ()
438+ .isStandard ())) holder = wrap .ifPresentMap (prop -> prop .getFrom (config ));
400439 for (var i = 1 ; i < path .length ; i ++) {
401440 final var fi = i ;
402441 final var fh = holder ;
403- wrap = wrap .map (it -> it .getType ().getTargetClass ()).map (DataStructure ::of ).flatMap (struct -> struct .getProperty (path [fi ]));
442+ wrap = wrap .map (it -> it .getType ().getTargetClass ())
443+ .map (DataStructure ::of )
444+ .flatMap (struct -> struct .getProperty (path [fi ]));
404445 if (wrap .test (prop -> !prop .getType ().isStandard () && prop .getType ().getTargetClass ().isInstance (fh ))) {
405446 Object o = wrap .ifPresentMap (prop -> prop .getFrom (fh ));
406447 if (o != null ) holder = o ;
407448 }
408449 }
409450 final var fh = holder ;
410- return wrap .ifPresentMapOrElseThrow (prop -> new Pair <>(prop , fh ), () -> new NoSuchElementException ("No such property: " + String .join ("." , path )));
451+ return wrap .ifPresentMapOrElseThrow (prop -> new Pair <>(prop , fh ),
452+ () -> new NoSuchElementException ("No such property: " + String .join ("." , path )));
411453 }
412454
413455 private static EntitySelectMenu .@ NotNull SelectTarget getSelectTarget (DataStructure <?>.Property <?> property ) {
414456 EntitySelectMenu .SelectTarget target ;
415- if (Channel .class .isAssignableFrom (property .getType ().getTargetClass ())) target = EntitySelectMenu .SelectTarget .CHANNEL ;
416- else if (User .class .isAssignableFrom (property .getType ().getTargetClass ())) target = EntitySelectMenu .SelectTarget .USER ;
417- else if (Role .class .isAssignableFrom (property .getType ().getTargetClass ())) target = EntitySelectMenu .SelectTarget .ROLE ;
418- else throw new IllegalArgumentException ("Invalid mentionable: " + property .getType ().getTargetClass ().getCanonicalName ());
457+ if (Channel .class .isAssignableFrom (property .getType ()
458+ .getTargetClass ())) target = EntitySelectMenu .SelectTarget .CHANNEL ;
459+ else if (User .class .isAssignableFrom (property .getType ()
460+ .getTargetClass ())) target = EntitySelectMenu .SelectTarget .USER ;
461+ else if (Role .class .isAssignableFrom (property .getType ()
462+ .getTargetClass ())) target = EntitySelectMenu .SelectTarget .ROLE ;
463+ else throw new IllegalArgumentException ("Invalid mentionable: " + property .getType ()
464+ .getTargetClass ()
465+ .getCanonicalName ());
419466 return target ;
420467 }
421468 }
0 commit comments