Skip to content

Commit

Permalink
removed needless nullability from ConfigValue#evaluator; IConfigSecti…
Browse files Browse the repository at this point in the history
…on is now an abstract class keeping a reference to the baseEnvironment; migrated tests
  • Loading branch information
BlvckBytes committed Sep 19, 2024
1 parent 5b9cc1d commit 5bd97cf
Show file tree
Hide file tree
Showing 23 changed files with 165 additions and 52 deletions.
36 changes: 20 additions & 16 deletions src/main/java/me/blvckbytes/bbconfigmapper/ConfigMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import me.blvckbytes.gpeee.GPEEE;
import me.blvckbytes.gpeee.IExpressionEvaluator;
import me.blvckbytes.gpeee.Tuple;
import me.blvckbytes.gpeee.interpreter.EvaluationEnvironmentBuilder;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.*;
Expand Down Expand Up @@ -69,7 +70,7 @@ public IConfig getConfig() {
}

@Override
public <T extends IConfigSection> T mapSection(@Nullable String root, Class<T> type) throws Exception {
public <T extends AConfigSection> T mapSection(@Nullable String root, Class<T> type) throws Exception {
logger.log(Level.FINEST, () -> DebugLogSource.MAPPER + "At the entry point of mapping path=" + root + " to type=" + type);
return mapSectionSub(root, null, type);
}
Expand All @@ -86,9 +87,9 @@ public <T extends IConfigSection> T mapSection(@Nullable String root, Class<T> t
* @param type Class of the config section to instantiate
* @return Instantiated class with mapped fields
*/
private <T extends IConfigSection> T mapSectionSub(@Nullable String root, @Nullable Map<?, ?> source, Class<T> type) throws Exception {
private <T extends AConfigSection> T mapSectionSub(@Nullable String root, @Nullable Map<?, ?> source, Class<T> type) throws Exception {
logger.log(Level.FINEST, () -> DebugLogSource.MAPPER + "At the subroutine of mapping path=" + root + " to type=" + type + " using source=" + source);
T instance = findDefaultConstructor(type).newInstance();
T instance = findStandardConstructor(type).newInstance(evaluator.getBaseEnvironment());

Tuple<List<Field>, Iterator<Field>> fields = findApplicableFields(type);

Expand Down Expand Up @@ -245,7 +246,7 @@ private Tuple<List<Field>, Iterator<Field>> findApplicableFields(Class<?> type)

/**
* Tries to convert the input object to the specified type, by either stringifying,
* wrapping the value as an {@link IEvaluable} or by parsing a {@link IConfigSection}
* wrapping the value as an {@link IEvaluable} or by parsing a {@link AConfigSection}
* if the input is of type map and returning null otherwise. Unsupported types throw.
* @param input Input object to convert
* @param type Type to convert to
Expand Down Expand Up @@ -280,15 +281,15 @@ private Tuple<List<Field>, Iterator<Field>> findApplicableFields(Class<?> type)
return input;
}

if (IConfigSection.class.isAssignableFrom(type)) {
if (AConfigSection.class.isAssignableFrom(type)) {
logger.log(Level.FINEST, () -> DebugLogSource.MAPPER + "Parsing value as config-section");

if (!(input instanceof Map)) {
logger.log(Level.FINEST, () -> DebugLogSource.MAPPER + "Value was null, falling back on empty section");
input = new HashMap<>();
}

Object value = mapSectionSub(null, (Map<?, ?>) input, type.asSubclass(IConfigSection.class));
Object value = mapSectionSub(null, (Map<?, ?>) input, type.asSubclass(AConfigSection.class));

if (converter != null)
value = converter.apply(value, evaluator);
Expand Down Expand Up @@ -457,9 +458,9 @@ private Object handleResolveArrayField(Field f, Object value) throws Exception {
return null;
}

if (IConfigSection.class.isAssignableFrom(type)) {
if (AConfigSection.class.isAssignableFrom(type)) {
logger.log(Level.FINEST, () -> DebugLogSource.MAPPER + "Type is of another section");
return mapSectionSub(path, source, type.asSubclass(IConfigSection.class));
return mapSectionSub(path, source, type.asSubclass(AConfigSection.class));
}

logger.log(Level.FINEST, () -> DebugLogSource.MAPPER + "Resolving path value as plain object");
Expand Down Expand Up @@ -505,18 +506,21 @@ private String joinPaths(@Nullable String a, @Nullable String b) {
}

/**
* Find the default constructor of a class (no parameters required to instantiate it)
* Find the standard constructor of a class: constructor(EvaluationEnvironmentBuilder)
* or throw a runtime exception otherwise.
* @param type Type of the target class
* @return Default constructor
* @return Standard constructor
*/
private<T> Constructor<T> findDefaultConstructor(Class<T> type) {
private<T> Constructor<T> findStandardConstructor(Class<T> type) {
try {
Constructor<T> ctor = type.getDeclaredConstructor();
ctor.setAccessible(true);
return ctor;
Constructor<T> constructor = type.getDeclaredConstructor(EvaluationEnvironmentBuilder.class);

if (!Modifier.isPublic(constructor.getModifiers()))
throw new IllegalStateException("The standard-constructor of a config-section has to be public");

return constructor;
} catch (NoSuchMethodException e) {
throw new IllegalStateException("Please specify an empty default constructor on " + type);
throw new IllegalStateException("Please specify a standard-constructor taking an EvaluationEnvironmentBuilder on " + type);
}
}

Expand All @@ -541,7 +545,7 @@ private<T> Constructor<T> findDefaultConstructor(Class<T> type) {
}

/**
* Attempts to unwrap a given type to it's raw type class
* Attempts to unwrap a given type to its raw type class
* @param type Type to unwrap
* @return Unwrapped type
*/
Expand Down
12 changes: 6 additions & 6 deletions src/main/java/me/blvckbytes/bbconfigmapper/ConfigValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
public class ConfigValue implements IEvaluable {

protected final @Nullable Object value;
private final @Nullable IExpressionEvaluator evaluator;
private final IExpressionEvaluator evaluator;

public ConfigValue(@Nullable Object value, @Nullable IExpressionEvaluator evaluator) {
public ConfigValue(@Nullable Object value, IExpressionEvaluator evaluator) {
this.value = value;
this.evaluator = evaluator;
}
Expand All @@ -61,7 +61,7 @@ public <T> Set<T> asSet(ScalarType<T> type, IEvaluationEnvironment env) {

@Override
public Object asRawObject(IEvaluationEnvironment env) {
if (value instanceof AExpression && this.evaluator != null)
if (value instanceof AExpression)
return this.evaluator.evaluateExpression((AExpression) value, env);
return value;
}
Expand Down Expand Up @@ -89,7 +89,7 @@ protected <T> T interpretScalar(@Nullable Object input, ScalarType<T> type, IEva
return (T) input;

// The input is an expression which needs to be evaluated first
if (input instanceof AExpression && this.evaluator != null)
if (input instanceof AExpression)
input = this.evaluator.evaluateExpression((AExpression) input, env);

return (T) type.getInterpreter().apply(input, env);
Expand All @@ -110,7 +110,7 @@ protected <T> T interpretScalar(@Nullable Object input, ScalarType<T> type, IEva
@SuppressWarnings("unchecked")
private<T> T interpret(@Nullable Object input, Class<T> type, @Nullable ScalarType<T>[] genericTypes, IEvaluationEnvironment env) {

if (input instanceof AExpression && this.evaluator != null)
if (input instanceof AExpression)
input = this.evaluator.evaluateExpression((AExpression) input, env);

if (type == List.class || type == Set.class) {
Expand Down Expand Up @@ -139,7 +139,7 @@ private<T> T interpret(@Nullable Object input, Class<T> type, @Nullable ScalarTy
// FIXME: This seems hella repetitive to #interpretScalar

// Expression result collections are flattened into the return result collection, if applicable
if (item instanceof AExpression && this.evaluator != null) {
if (item instanceof AExpression) {
Object result = this.evaluator.evaluateExpression((AExpression) item, env);

if (result instanceof Collection) {
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/me/blvckbytes/bbconfigmapper/IConfigMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,20 @@

package me.blvckbytes.bbconfigmapper;

import me.blvckbytes.bbconfigmapper.sections.IConfigSection;
import me.blvckbytes.bbconfigmapper.sections.AConfigSection;
import org.jetbrains.annotations.Nullable;

public interface IConfigMapper {

/**
* Creates an empty instance of the provided type by invoking the default-constructor
* and then traverses it's fields to assign them one after the other with available
* configuration values while making use of the decision methods within {@link IConfigSection}
* configuration values while making use of the decision methods within {@link AConfigSection}
* @param root Root node of this section (null means config root)
* @param type Type of the class to map
* @return Mapped instance of specified type
*/
<T extends IConfigSection> T mapSection(@Nullable String root, Class<T> type) throws Exception;
<T extends AConfigSection> T mapSection(@Nullable String root, Class<T> type) throws Exception;

/**
* Get the underlying configuration instance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,23 @@

package me.blvckbytes.bbconfigmapper.sections;

import me.blvckbytes.gpeee.interpreter.EvaluationEnvironmentBuilder;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Field;
import java.util.List;

public interface IConfigSection {
public abstract class AConfigSection {

private final EvaluationEnvironmentBuilder baseEnvironment;

public AConfigSection(EvaluationEnvironmentBuilder baseEnvironment) {
this.baseEnvironment = baseEnvironment;
}

public EvaluationEnvironmentBuilder getBaseEnvironment() {
return baseEnvironment.duplicate();
}

/**
* Called to decide the type of Object fields at runtime,
Expand All @@ -40,21 +51,23 @@ public interface IConfigSection {
* @param field Target field in question
* @return Decided type, Object.class means skip
*/
default @Nullable Class<?> runtimeDecide(String field) { return null; }
public @Nullable Class<?> runtimeDecide(String field) {
return null;
}

/**
* Called when a field wasn't found within the config and a default could be set
* @param field Target field
* @return Value to use as a default
*/
default @Nullable Object defaultFor(Field field) throws Exception {
public @Nullable Object defaultFor(Field field) throws Exception {
return null;
}

/**
* Called when parsing of the section is completed
* and no more changes will be applied
*/
default void afterParsing(List<Field> fields) throws Exception {}
public void afterParsing(List<Field> fields) throws Exception {}

}
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,9 @@ public void shouldThrowWhenSectionSelfReferences() throws Exception {
}

@Test
public void shouldThrowWhenNoDefaultConstructorAvailable() throws Exception {
public void shouldThrowWhenNoStandardConstructorAvailable() throws Exception {
IConfigMapper mapper = helper.makeMapper("mappings.yml");
helper.assertThrowsWithMsg(IllegalStateException.class, () -> mapper.mapSection(null, NoDefaultConstructorSection.class), "Please specify an empty default constructor");
helper.assertThrowsWithMsg(IllegalStateException.class, () -> mapper.mapSection(null, NoStandardConstructorSection.class), "Please specify a standard-constructor taking an EvaluationEnvironmentBuilder on ");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,20 @@

package me.blvckbytes.bbconfigmapper.sections;

import me.blvckbytes.gpeee.interpreter.EvaluationEnvironmentBuilder;

import java.lang.reflect.Field;
import java.util.List;

public class BlockBreakQuestParameterSection implements IConfigSection {
public class BlockBreakQuestParameterSection extends AConfigSection {

private String material;
private String world;

public BlockBreakQuestParameterSection(EvaluationEnvironmentBuilder baseEnvironment) {
super(baseEnvironment);
}

@Override
public Class<?> runtimeDecide(String field) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,19 @@

package me.blvckbytes.bbconfigmapper.sections;

public class CustomEnumSection implements IConfigSection {
import me.blvckbytes.gpeee.interpreter.EvaluationEnvironmentBuilder;

public class CustomEnumSection extends AConfigSection {

private ECustomEnum customEnumA;
private ECustomEnum customEnumB;
private ECustomEnum customEnumC;
private ECustomEnum customEnumInvalid;

public CustomEnumSection(EvaluationEnvironmentBuilder baseEnvironment) {
super(baseEnvironment);
}

public ECustomEnum getCustomEnumA() {
return customEnumA;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,19 @@
package me.blvckbytes.bbconfigmapper.sections;

import me.blvckbytes.bbconfigmapper.IEvaluable;
import me.blvckbytes.gpeee.interpreter.EvaluationEnvironmentBuilder;

import java.lang.reflect.Field;
import java.util.List;

public class DatabaseSectionEvaluables implements IConfigSection {
public class DatabaseSectionEvaluables extends AConfigSection {

private IEvaluable host, port, database, username, password;

public DatabaseSectionEvaluables(EvaluationEnvironmentBuilder baseEnvironment) {
super(baseEnvironment);
}

@Override
public Class<?> runtimeDecide(String field) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,20 @@

package me.blvckbytes.bbconfigmapper.sections;

import me.blvckbytes.gpeee.interpreter.EvaluationEnvironmentBuilder;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Field;
import java.util.List;

public class DatabaseSectionStrings implements IConfigSection {
public class DatabaseSectionStrings extends AConfigSection {

private String host, port, database, username, password;

public DatabaseSectionStrings(EvaluationEnvironmentBuilder baseEnvironment) {
super(baseEnvironment);
}

@Override
public Class<?> runtimeDecide(String field) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,20 @@

package me.blvckbytes.bbconfigmapper.sections;

import me.blvckbytes.gpeee.interpreter.EvaluationEnvironmentBuilder;

import java.lang.reflect.Field;
import java.util.List;

public class EntityKillQuestParameterSection implements IConfigSection {
public class EntityKillQuestParameterSection extends AConfigSection {

private String entityType;
private String entityName;

public EntityKillQuestParameterSection(EvaluationEnvironmentBuilder baseEnvironment) {
super(baseEnvironment);
}

@Override
public Class<?> runtimeDecide(String field) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@

package me.blvckbytes.bbconfigmapper.sections;

import me.blvckbytes.gpeee.interpreter.EvaluationEnvironmentBuilder;

import java.lang.reflect.Field;
import java.util.List;

public class IgnoreSection implements IConfigSection {
public class IgnoreSection extends AConfigSection {

@CSIgnore
private String ignored1;
Expand All @@ -39,6 +41,10 @@ public class IgnoreSection implements IConfigSection {

private static String ignored4;

public IgnoreSection(EvaluationEnvironmentBuilder baseEnvironment) {
super(baseEnvironment);
}

@Override
public Class<?> runtimeDecide(String field) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@
import java.lang.reflect.Field;
import java.util.List;

public class NoDefaultConstructorSection implements IConfigSection {
public class NoStandardConstructorSection extends AConfigSection {

private String a, b, c;

public NoDefaultConstructorSection(String a, String b, String c) {
public NoStandardConstructorSection(String a, String b, String c) {
super(null);
this.a = a;
this.b = b;
this.c = c;
Expand Down
Loading

0 comments on commit 5bd97cf

Please sign in to comment.