package org.simpleflatmapper.reflect.meta; import org.simpleflatmapper.reflect.ScoredSetter; import org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition; import org.simpleflatmapper.reflect.Getter; import org.simpleflatmapper.reflect.InstantiatorDefinition; import org.simpleflatmapper.reflect.Parameter; import org.simpleflatmapper.reflect.ReflectionService; import org.simpleflatmapper.reflect.ScoredGetter; import org.simpleflatmapper.util.Consumer; import org.simpleflatmapper.util.ErrorHelper; import org.simpleflatmapper.util.Predicate; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.*; public class OptionalClassMeta<T> implements ClassMeta<Optional<T>> { private final ReflectionService reflectionService; private final Type type; private final InstantiatorDefinition instantiatorDefinition; private final ConstructorPropertyMeta<Optional<T>, ?> propertyMeta; private final ClassMeta<T> innerMeta; public OptionalClassMeta(Type type, ReflectionService reflectionService) { this.type = type; this.reflectionService = reflectionService; try { this.instantiatorDefinition = getInstantiatorDefinition(type); this.propertyMeta = new ConstructorPropertyMeta<Optional<T>, Object>("value", type, reflectionService, instantiatorDefinition.getParameters()[0], new ScoredGetter<Optional<T>, Object>(Integer.MAX_VALUE, new OptionalGetter<T>()), ScoredSetter.<Optional<T>, Object>nullSetter(), instantiatorDefinition, null); this.innerMeta = reflectionService.getClassMeta(instantiatorDefinition.getParameters()[0].getGenericType()); } catch(Exception e) { ErrorHelper.rethrow(e); throw new IllegalStateException(); } } private InstantiatorDefinition getInstantiatorDefinition(Type type) throws NoSuchMethodException { ParameterizedType pt = (ParameterizedType) type; InstantiatorDefinition id = new ExecutableInstantiatorDefinition(Optional.class.getMethod("ofNullable", Object.class), new Parameter(0, "value", Object.class, pt.getActualTypeArguments()[0])); return id; } @Override public ReflectionService getReflectionService() { return reflectionService; } @Override public PropertyFinder<Optional<T>> newPropertyFinder(Predicate<PropertyMeta<?, ?>> propertyFilter) { return new OptionalPropertyFinder<T>(this, propertyFilter); } public Type getType() { return type; } public ClassMeta<T> getInnerMeta() { return innerMeta; } public PropertyMeta<Optional<T>, ?> getProperty() { return propertyMeta; } @Override public List<InstantiatorDefinition> getInstantiatorDefinitions() { return Arrays.asList(instantiatorDefinition); } @Override public void forEachProperties(Consumer<? super PropertyMeta<Optional<T>, ?>> consumer) { consumer.accept(propertyMeta); } private static class OptionalGetter<T> implements Getter<Optional<T>, Object> { @Override public Object get(Optional<T> target) throws Exception { return target.orElse(null); } } }