tech.ydb.yoj.databind.schema.reflect.StdReflector Maven / Gradle / Ivy
Show all versions of yoj-databind Show documentation
package tech.ydb.yoj.databind.schema.reflect;
import com.google.common.reflect.TypeToken;
import lombok.NonNull;
import tech.ydb.yoj.databind.FieldValueType;
import tech.ydb.yoj.databind.schema.configuration.SchemaRegistry;
import java.lang.reflect.Type;
import java.util.List;
import static java.util.Comparator.comparing;
/**
* Standard {@link Reflector} implementation, suitable for most usages. By default, reflecting record classes, Kotlin
* data classes, POJOs and simple types such as {@code int} is supported.
*
* You can override default {@link Reflector} by creating a custom {@link SchemaRegistry} with your own instance of
* {@code StdReflector} with a different set of {@link TypeFactory type factories}, or a wholly different implementation
* altogether. You then have to pass the {@link SchemaRegistry} to {@code *Schema.of(...)} methods to use it instead of
* {@link SchemaRegistry#getDefault() the default one}.
*
* @see Reflector
* @see ReflectType
* @see ReflectField
*/
public final class StdReflector implements Reflector {
public static final Reflector instance = new StdReflector(List.of(
RecordType.FACTORY,
KotlinDataClassTypeFactory.instance,
PojoType.FACTORY,
SimpleType.FACTORY
));
private final List matchers;
public StdReflector(@NonNull List matchers) {
this.matchers = matchers.stream().sorted(comparing(TypeFactory::priority).reversed()).toList();
}
@Override
@SuppressWarnings("unchecked")
public ReflectType reflectRootType(Class type) {
return (ReflectType) reflectFor(type, FieldValueType.COMPOSITE);
}
@Override
public ReflectType reflectFieldType(Type genericType, FieldValueType bindingType) {
return reflectFor(genericType, bindingType);
}
private ReflectType reflectFor(Type type, FieldValueType fvt) {
Class rawType = TypeToken.of(type).getRawType();
for (TypeFactory m : matchers) {
if (m.matches(rawType, fvt)) {
return m.create(this, rawType, fvt);
}
}
throw new IllegalArgumentException("Cannot reflect type: " + type);
}
public interface TypeFactory {
int priority();
boolean matches(Class rawType, FieldValueType fvt);
ReflectType create(Reflector reflector, Class rawType, FieldValueType fvt);
}
}