2022-08-21 22:34:55 +02:00
package io.gitlab.jfronny.libjf.config.impl.dsl ;
2024-04-18 23:09:35 +02:00
import io.gitlab.jfronny.commons.serialize.SerializeReader ;
2023-07-18 20:11:23 +02:00
import io.gitlab.jfronny.commons.throwable.Coerce ;
2023-07-18 19:15:47 +02:00
import io.gitlab.jfronny.libjf.LibJf ;
2023-08-30 14:14:20 +02:00
import io.gitlab.jfronny.libjf.config.api.v2.* ;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder ;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.Migration ;
import io.gitlab.jfronny.libjf.config.api.v2.type.Type ;
2022-08-21 22:34:55 +02:00
import java.util.* ;
import java.util.function.Consumer ;
import java.util.function.Supplier ;
public class CategoryBuilderImpl < Builder extends CategoryBuilderImpl < Builder > > implements CategoryBuilder < Builder > {
public final List < CategoryBuilder < ? > > categories = new LinkedList < > ( ) ;
public final String id ;
public final String categoryPath ;
public String translationPrefix ;
public final List < EntryInfo < ? > > entries = new LinkedList < > ( ) ;
public final Map < String , Consumer < ConfigCategory > > presets = new LinkedHashMap < > ( ) ;
2022-08-28 18:48:39 +02:00
public final List < Supplier < List < ConfigInstance > > > referencedConfigs = new LinkedList < > ( ) ;
2022-08-21 22:34:55 +02:00
public final List < Consumer < ConfigCategory > > verifiers = new LinkedList < > ( ) ;
2024-04-18 23:09:35 +02:00
@SuppressWarnings ( " rawtypes " ) // recursive types aren't really needed here
public final Map < String , Consumer < SerializeReader > > migrations = new LinkedHashMap < > ( ) ;
2022-08-21 22:34:55 +02:00
private boolean built = false ;
public CategoryBuilderImpl ( String id , String categoryPath ) {
this . id = id ;
this . categoryPath = categoryPath ;
this . translationPrefix = id + " .jfconfig. " + categoryPath ;
2022-12-29 16:22:54 +01:00
addPreset ( CONFIG_PRESET_DEFAULT , ConfigCategory : : reset ) ;
2022-08-21 22:34:55 +02:00
}
@Override
public Builder setTranslationPrefix ( String translationPrefix ) {
checkBuilt ( ) ;
this . translationPrefix = translationPrefix ;
return asBuilder ( ) ;
}
@Override
public String getTranslationPrefix ( ) {
checkBuilt ( ) ;
return translationPrefix ;
}
@Override
public Builder addPreset ( String id , Consumer < ConfigCategory > action ) {
checkBuilt ( ) ;
2023-07-18 19:15:47 +02:00
if ( presets . containsKey ( id ) ) LibJf . LOGGER . warn ( " Duplicate preset registered for " + categoryPath + this . id + " : " + id + " , overriding " ) ;
2022-08-21 22:34:55 +02:00
presets . put ( id , action ) ;
return asBuilder ( ) ;
}
2022-08-26 20:51:00 +02:00
@Override
public Builder addPreset ( String id , Runnable preset ) {
return addPreset ( id , cfg - > preset . run ( ) ) ;
}
2022-12-29 16:22:54 +01:00
@Override
public Builder removePreset ( String id ) {
checkBuilt ( ) ;
if ( presets . remove ( id ) = = null ) throw new NoSuchElementException ( ) ;
return asBuilder ( ) ;
}
2022-08-21 22:34:55 +02:00
@Override
public Builder addVerifier ( Consumer < ConfigCategory > verifier ) {
checkBuilt ( ) ;
verifiers . add ( verifier ) ;
return asBuilder ( ) ;
}
2022-08-26 20:51:00 +02:00
@Override
public Builder addVerifier ( Runnable verifier ) {
return addVerifier ( cfg - > verifier . run ( ) ) ;
}
2022-08-21 22:34:55 +02:00
@Override
public Builder referenceConfig ( String id ) {
2022-08-28 18:48:39 +02:00
return referenceConfig ( ( ) - > List . of ( ConfigHolder . getInstance ( ) . get ( id ) ) ) ;
2022-08-21 22:34:55 +02:00
}
@Override
public Builder referenceConfig ( ConfigInstance config ) {
2022-08-28 18:48:39 +02:00
return referenceConfig ( ( ) - > List . of ( config ) ) ;
}
@Override
public Builder referenceConfig ( Supplier < List < ConfigInstance > > gen ) {
2022-08-21 22:34:55 +02:00
checkBuilt ( ) ;
2022-08-28 18:48:39 +02:00
referencedConfigs . add ( Objects . requireNonNull ( gen ) ) ;
2022-08-21 22:34:55 +02:00
return asBuilder ( ) ;
}
@Override
public Builder category ( String id , CategoryBuilderFunction builder ) {
checkBuilt ( ) ;
2022-08-22 00:12:19 +02:00
categories . add ( builder . apply ( new CategoryBuilderImpl ( id , categoryPath + id + " . " ) . setTranslationPrefix ( translationPrefix + id + " . " ) ) ) ;
2022-08-21 22:34:55 +02:00
return asBuilder ( ) ;
}
@Override
public Builder value ( String id , int def , double min , double max , Supplier < Integer > get , Consumer < Integer > set ) {
checkBuilt ( ) ;
entries . add ( new DslEntryInfo < > ( id , def , get : : get , set : : accept , Type . TInt . INSTANCE , 100 , min , max ) ) ;
return asBuilder ( ) ;
}
2022-08-26 20:51:00 +02:00
@Override
public Builder value ( String id , long def , double min , double max , Supplier < Long > get , Consumer < Long > set ) {
checkBuilt ( ) ;
entries . add ( new DslEntryInfo < > ( id , def , get : : get , set : : accept , Type . TLong . INSTANCE , 100 , min , max ) ) ;
return asBuilder ( ) ;
}
2022-08-21 22:34:55 +02:00
@Override
public Builder value ( String id , float def , double min , double max , Supplier < Float > get , Consumer < Float > set ) {
checkBuilt ( ) ;
entries . add ( new DslEntryInfo < > ( id , def , get : : get , set : : accept , Type . TFloat . INSTANCE , 100 , min , max ) ) ;
return asBuilder ( ) ;
}
@Override
public Builder value ( String id , double def , double min , double max , Supplier < Double > get , Consumer < Double > set ) {
checkBuilt ( ) ;
entries . add ( new DslEntryInfo < > ( id , def , get : : get , set : : accept , Type . TDouble . INSTANCE , 100 , min , max ) ) ;
return asBuilder ( ) ;
}
@Override
public Builder value ( String id , String def , Supplier < String > get , Consumer < String > set ) {
checkBuilt ( ) ;
entries . add ( new DslEntryInfo < > ( id , def , get : : get , set : : accept , Type . TString . INSTANCE ) ) ;
return asBuilder ( ) ;
}
@Override
public Builder value ( String id , boolean def , Supplier < Boolean > get , Consumer < Boolean > set ) {
checkBuilt ( ) ;
entries . add ( new DslEntryInfo < > ( id , def , get : : get , set : : accept , Type . TBool . INSTANCE ) ) ;
return asBuilder ( ) ;
}
@Override
public Builder value ( String id , String def , String [ ] options , Supplier < String > get , Consumer < String > set ) {
checkBuilt ( ) ;
entries . add ( new DslEntryInfo < > ( id , def , get : : get , set : : accept , Type . TEnum . create ( id , options ) ) ) ;
return asBuilder ( ) ;
}
@Override
public < T extends Enum < T > > Builder value ( String id , T def , Class < T > klazz , Supplier < T > get , Consumer < T > set ) {
checkBuilt ( ) ;
entries . add ( new DslEntryInfo < > ( id , def , get : : get , set : : accept , new Type . TEnum < > ( klazz ) ) ) ;
return asBuilder ( ) ;
}
2022-08-26 20:51:00 +02:00
@Override
2022-08-27 20:17:13 +02:00
public < T > Builder value ( String id , T def , double min , double max , Type type , int width , Supplier < T > get , Consumer < T > set ) {
2022-08-26 20:51:00 +02:00
checkBuilt ( ) ;
entries . add ( new DslEntryInfo < > ( id , def , get : : get , set : : accept , type , width , min , max ) ) ;
return asBuilder ( ) ;
}
2022-08-21 22:34:55 +02:00
@Override
public < T > Builder value ( EntryInfo < T > entry ) {
checkBuilt ( ) ;
entries . add ( Objects . requireNonNull ( entry ) ) ;
return asBuilder ( ) ;
}
2023-07-18 19:15:47 +02:00
@Override
2023-07-18 20:11:23 +02:00
public Builder addMigration ( String element , Migration migration ) {
2023-07-18 19:15:47 +02:00
checkBuilt ( ) ;
if ( migrations . containsKey ( element ) ) LibJf . LOGGER . warn ( " Duplicate migration registered for " + categoryPath + id + " : " + element + " , overriding " ) ;
2024-04-18 23:09:35 +02:00
migrations . put ( element , Coerce . < SerializeReader , Exception > consumer ( migration : : apply ) . addHandler ( e - > LibJf . LOGGER . error ( " Could not apply migration for " + element , e ) ) ) ;
2023-07-18 19:15:47 +02:00
return asBuilder ( ) ;
}
2022-08-21 22:34:55 +02:00
@Override
public String getId ( ) {
return id ;
}
protected Builder asBuilder ( ) {
//noinspection unchecked
return ( Builder ) this ;
}
protected void checkBuilt ( ) {
if ( built ) throw new IllegalStateException ( " This builder was already used to build a category! " ) ;
}
protected void markBuilt ( ) {
checkBuilt ( ) ;
built = true ;
}
@Override
public DslConfigCategory build ( Supplier < ConfigInstance > root ) {
markBuilt ( ) ;
2023-07-18 19:15:47 +02:00
Set < String > migrationNames = migrations . keySet ( ) ;
Set < String > entryNames = new HashSet < > ( ) ;
for ( EntryInfo < ? > entry : entries ) {
String name = entry . getName ( ) ;
if ( migrationNames . contains ( name ) ) LibJf . LOGGER . warn ( " Entry conflict: " + categoryPath + id + " contains both a migration and an entry for " + name ) ;
if ( ! entryNames . add ( name ) ) LibJf . LOGGER . warn ( " Entry conflict: " + categoryPath + id + " contains two entries for " + name ) ;
}
Set < String > categoryNames = new HashSet < > ( ) ;
for ( CategoryBuilder < ? > category : categories ) {
String name = category . getId ( ) ;
if ( migrationNames . contains ( name ) ) LibJf . LOGGER . warn ( " Entry conflict: " + categoryPath + id + " contains both a migration and a category for " + name ) ;
if ( entryNames . contains ( name ) ) LibJf . LOGGER . warn ( " Entry conflict: " + categoryPath + id + " contains both an entry and a category for " + name ) ;
if ( ! categoryNames . add ( name ) ) LibJf . LOGGER . warn ( " Entry conflict: " + categoryPath + id + " contains two categories for " + name ) ;
}
return new DslConfigCategory (
id ,
2022-08-21 22:34:55 +02:00
categoryPath ,
translationPrefix ,
entries ,
presets ,
2022-08-31 10:18:31 +02:00
referencedConfigs ,
categories ,
2022-08-21 22:34:55 +02:00
root ,
2023-07-18 19:15:47 +02:00
verifiers ,
migrations
) ;
2022-08-21 22:34:55 +02:00
}
}