package carpet.script.annotation; import java.util.HashMap; import java.util.Map; import carpet.script.value.AbstractListValue; import carpet.script.value.BlockValue; import carpet.script.value.BooleanValue; import carpet.script.value.EntityValue; import carpet.script.value.FormattedTextValue; import carpet.script.value.FunctionValue; import carpet.script.value.ListValue; import carpet.script.value.MapValue; import carpet.script.value.NBTSerializableValue; import carpet.script.value.NumericValue; import carpet.script.value.StringValue; import carpet.script.value.ThreadValue; import carpet.script.value.Value; /** *

Simple {@link ValueConverter} implementation that casts a {@link Value} into one of its subclasses, either for use directly in parameters or * converters, or as an already working middle step.

* *

{@link ValueCaster}s are reused whenever asked for one, since they don't have any complexity.

* * @see #register(Class, String) * * @param The {@link Value} subclass this {@link ValueCaster} casts to */ public final class ValueCaster implements ValueConverter // R always extends Value, not explicitly because of type checking { private static final Map, ValueCaster> byResult = new HashMap<>(); static { register(Value.class, "value"); register(BlockValue.class, "block"); register(EntityValue.class, "entity"); register(FormattedTextValue.class, "formatted text"); register(FunctionValue.class, "function"); register(ListValue.class, "list"); register(MapValue.class, "map"); register(AbstractListValue.class, "list or similar"); // For LazyListValue basically? Not sure what should use this register(NBTSerializableValue.class, "nbt object"); register(NumericValue.class, "number"); register(BooleanValue.class, "boolean"); register(StringValue.class, "string"); register(ThreadValue.class, "thread"); } private final Class outputType; private final String typeName; private ValueCaster(Class outputType, String typeName) { this.outputType = outputType; this.typeName = typeName; } @Override public String getTypeName() { return typeName; } /** *

Returns the registered {@link ValueCaster} for the specified outputType.

* * @param The type of the {@link ValueCaster} you are looking for * @param outputType The class of the {@link Value} the returned {@link ValueCaster} casts to * @return The {@link ValueCaster} for the specified outputType */ @SuppressWarnings("unchecked") // Casters are stored with their exact class, for sure since the map is private (&& class has same generic as // caster) public static ValueCaster get(Class outputType) { return (ValueCaster) byResult.get(outputType); } @Override public R convert(Value value) { if (!outputType.isInstance(value)) return null; return outputType.cast(value); } /** *

Registers a new {@link Value} to be able to use it in {@link SimpleTypeConverter}

* * @param The {@link Value} subclass * @param valueClass The class of T * @param typeName A {@link String} representing the name of this type. It will be used in error messages when there is no higher type * required */ public static void register(Class valueClass, String typeName) { ValueCaster caster = new ValueCaster(valueClass, typeName); byResult.putIfAbsent(valueClass, caster); } }