package org.jdbi.v3.core.argument;
import java.lang.reflect.Type;
import java.sql.Types;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.OptionalLong;
import org.jdbi.v3.core.config.ConfigRegistry;
import static org.jdbi.v3.core.generic.GenericTypes.findGenericParameter;
import static org.jdbi.v3.core.generic.GenericTypes.getErasedType;
class OptionalArgumentFactory extends DelegatingArgumentFactory {
OptionalArgumentFactory() {
register(OptionalInt.class, Types.INTEGER, (p, i, v) -> {
if (v.isPresent()) {
p.setInt(i, v.getAsInt());
} else {
p.setNull(i, Types.INTEGER);
}
});
register(OptionalLong.class, Types.BIGINT, (p, i, v) -> {
if (v.isPresent()) {
p.setLong(i, v.getAsLong());
} else {
p.setNull(i, Types.BIGINT);
}
});
register(OptionalDouble.class, Types.DOUBLE, (p, i, v) -> {
if (v.isPresent()) {
p.setDouble(i, v.getAsDouble());
} else {
p.setNull(i, Types.DOUBLE);
}
});
}
@Override
public Optional<Argument> build(Type expectedType, Object value, ConfigRegistry config) {
if (value instanceof Optional) {
Object nestedValue = ((Optional<?>) value).orElse(null);
Type nestedType = findOptionalType(expectedType, nestedValue);
return config.get(Arguments.class).findFor(nestedType, nestedValue);
} else {
return super.build(expectedType, value, config);
}
}
private static Type findOptionalType(Type wrapperType, Object nestedValue) {
if (getErasedType(wrapperType).equals(Optional.class)) {
Optional<Type> nestedType = findGenericParameter(wrapperType, Optional.class);
if (nestedType.isPresent()) {
return nestedType.get();
}
}
return nestedValue == null ? Object.class : nestedValue.getClass();
}
}