diff --git a/common/implementation/src/main/java/com/dfsek/terra/config/preprocessor/MetaValuePreprocessor.java b/common/implementation/src/main/java/com/dfsek/terra/config/preprocessor/MetaValuePreprocessor.java index 81a39bc37..e4480cf44 100644 --- a/common/implementation/src/main/java/com/dfsek/terra/config/preprocessor/MetaValuePreprocessor.java +++ b/common/implementation/src/main/java/com/dfsek/terra/config/preprocessor/MetaValuePreprocessor.java @@ -9,6 +9,9 @@ import com.dfsek.terra.api.config.meta.Meta; import org.jetbrains.annotations.NotNull; import java.lang.reflect.AnnotatedType; +import java.lang.reflect.ParameterizedType; +import java.util.ArrayList; +import java.util.List; import java.util.Map; public class MetaValuePreprocessor implements ValuePreprocessor { @@ -21,24 +24,64 @@ public class MetaValuePreprocessor implements ValuePreprocessor { @SuppressWarnings("unchecked") @Override public @NotNull Result process(AnnotatedType t, T c, ConfigLoader configLoader, Meta annotation) { - if(c instanceof String) { + if(c instanceof String) { // Can we do standard metaconfig? String value = ((String) c).trim(); if(value.startsWith("$")) { // it's a meta value. - String raw = value.substring(1); - int sep = raw.indexOf(':'); - String file = raw.substring(0, sep); - String key = raw.substring(sep + 1); - - if(!configs.containsKey(file)) throw new LoadException("Cannot fetch metavalue: No such config: " + file); - - Configuration config = configs.get(file); - - if(!config.contains(key)) - throw new LoadException("Cannot fetch metavalue: No such key " + key + " in configuration " + config.getName()); - - return (Result) Result.overwrite(config.get(key)); + return (Result) Result.overwrite(getMetaValue(value.substring(1))); } } + + if(t.getType() instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) t.getType(); + if(parameterizedType.getRawType() instanceof Class) { // Should always be true but we check anyways + Class baseClass = (Class) parameterizedType.getRawType(); + + if(List.class.isAssignableFrom(baseClass) && c instanceof List) { // List metaconfig + List list = (List) c; + + int offset = 0; + List newList = new ArrayList<>((List) c); + + for(int i = 0; i < list.size(); i++) { + Object o = list.get(i); + if(!(o instanceof String)) continue; + String s = ((String) o).trim(); + if(!s.startsWith("<< ")) continue; + String meta = s.substring(3); + + Object metaValue = getMetaValue(meta); + + if(!(metaValue instanceof List)) { + throw new LoadException("MetaList injection candidate must be list, is type " + metaValue.getClass().getCanonicalName()); + } + + List metaList = (List) metaValue; + + newList.addAll(i + offset, metaList); + offset += metaList.size(); + } + + return (Result) Result.overwrite(newList); + } + } + } + return Result.noOp(); } + + private Object getMetaValue(String meta) { + int sep = meta.indexOf(':'); + String file = meta.substring(0, sep); + String key = meta.substring(sep + 1); + + if(!configs.containsKey(file)) throw new LoadException("Cannot fetch metavalue: No such config: " + file); + + Configuration config = configs.get(file); + + if(!config.contains(key)) { + throw new LoadException("Cannot fetch metavalue: No such key " + key + " in configuration " + config.getName()); + } + + return config.get(key); + } }