package carpet.script.annotation; import java.lang.reflect.AnnotatedParameterizedType; import java.lang.reflect.AnnotatedType; import java.util.Iterator; import java.util.ListIterator; import java.util.Optional; import carpet.script.Context; import carpet.script.value.Value; /** *
{@link ValueConverter} that accepts a parameter to not be present on function call.
* *Note that it will not work properly if it's not at the end of the function, since values are consumed in an ordered way, therefore it will throw
* if the value is not present since it will try to evaluate the next parameter into {@code
Why {@link Optional}?
* *It allows passing three states:
*Returns a new {@link OptionalConverter} to convert to the type in the given {@link AnnotatedType} if there is at least one element left in * the iterator, with any parameters, annotations or anything that was present in there.
* *The given {@link ValueConverter} will be called after ensuring that there is at least one element left in the iterator to the type specified * in the generics of this {@link AnnotatedType}, or return an empty {@link Optional} if there is nothing left or the first value meets * {@link Value#isNull()}. * * @apiNote This method expects the {@link AnnotatedType} to already be of {@link Optional} type, and, while it will technically accept a * non-{@link Optional} {@link AnnotatedType}, it will fail with an {@link ArrayIndexOutOfBoundsException} if it doesn't has at least one * generic parameter. * @param annotatedType The type to get generics information from * @return A new {@link OptionalConverter} for the data specified in the {@link AnnotatedType} */ static OptionalConverter> fromAnnotatedType(AnnotatedType annotatedType) { AnnotatedParameterizedType paramType = (AnnotatedParameterizedType) annotatedType; AnnotatedType wrappedType = paramType.getAnnotatedActualTypeArguments()[0]; return new OptionalConverter<>(wrappedType); } }