/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jdbi.v3.core.argument;

import java.lang.reflect.Type;
import java.sql.PreparedStatement;
import java.sql.Types;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Optional;
import org.jdbi.v3.core.config.ConfigRegistry;

import static org.jdbi.v3.core.generic.GenericTypes.getErasedType;

class PrimitivesArgumentFactory implements ArgumentFactory {
    private static final Map<Class<?>, ArgBuilder<?>> BUILDERS = createInternalBuilders();

    private static <T> void register(Map<Class<?>, ArgBuilder<?>> map, Class<T> klass, int type, StatementBinder<T> binder) {
        map.put(klass, (ArgBuilder<T>) v -> new BuiltInArgument<>(klass, type, binder, v));
    }

    private static <T> StatementBinder<T> stringifyValue(StatementBinder<String> real) {
        return (p, i, v) -> real.bind(p, i, String.valueOf(v));
    }

    private static Map<Class<?>, ArgBuilder<?>> createInternalBuilders() {
        final Map<Class<?>, ArgBuilder<?>> map = new IdentityHashMap<>();

        register(map, boolean.class, Types.BOOLEAN, PreparedStatement::setBoolean);
        register(map, byte.class, Types.TINYINT, PreparedStatement::setByte);
        register(map, char.class, Types.CHAR, stringifyValue(PreparedStatement::setString));
        register(map, short.class, Types.SMALLINT, PreparedStatement::setShort);
        register(map, int.class, Types.INTEGER, PreparedStatement::setInt);
        register(map, long.class, Types.INTEGER, PreparedStatement::setLong);
        register(map, float.class, Types.FLOAT, PreparedStatement::setFloat);
        register(map, double.class, Types.DOUBLE, PreparedStatement::setDouble);

        return Collections.unmodifiableMap(map);
    }

    @Override
    @SuppressWarnings("unchecked")
    public Optional<Argument> build(Type expectedType, Object value, ConfigRegistry config) {
        Class<?> expectedClass = getErasedType(expectedType);

        if (value != null && expectedClass == Object.class) {
            expectedClass = value.getClass();
        }

        @SuppressWarnings("rawtypes")
        ArgBuilder v = BUILDERS.get(expectedClass);

        return Optional.ofNullable(v).map(f -> f.build(value));
    }
}

@@ -680,38 +680,8 @@
 es;%0A
-import java.util.Collections;%0A
 impo
@@ -948,23 +948,16 @@
 private 
-static 
 final Ma
@@ -987,580 +987,78 @@
 ?%3E%3E 
-BUILDERS = createInternalBuilders();%0A%0A    private static %3CT%3E void register(Map%3CClass%3C?%3E, ArgBuilder%3C?%3E%3E map, Class%3CT%3E klass, int type, StatementBinder%3CT%3E binder) %7B%0A        map.put(klass, (ArgBuilder%3CT%3E) v -%3E new BuiltInArgument%3C%3E(klass, type, binder, v));%0A    %7D
+builders = new IdentityHashMap%3C%3E();
 %0A%0A    
-private static %3CT%3E StatementBinder%3CT%3E stringifyValue(StatementBinder%3CString%3E real) %7B%0A        return (p, i, v) -%3E real.bind(p, i, String.valueOf(v));%0A    %7D%0A%0A    private static Map%3CClass%3C?%3E, ArgBuilder%3C?%3E%3E createInternalBuilders() %7B%0A        final Map%3CClass%3C?%3E, ArgBuilder%3C?%3E%3E map = new IdentityHashMap%3C%3E();%0A
+PrimitivesArgumentFactory() %7B
 %0A   
@@ -1071,21 +1071,16 @@
 egister(
-map, 
 boolean.
@@ -1150,21 +1150,16 @@
 egister(
-map, 
 byte.cla
@@ -1223,21 +1223,16 @@
 egister(
-map, 
 char.cla
@@ -1251,22 +1251,34 @@
 AR, 
-stringifyValue
+new ObjectToStringBinder%3C%3E
 (Pre
@@ -1323,21 +1323,16 @@
 egister(
-map, 
 short.cl
@@ -1399,21 +1399,16 @@
 egister(
-map, 
 int.clas
@@ -1470,21 +1470,16 @@
 egister(
-map, 
 long.cla
@@ -1543,21 +1543,16 @@
 egister(
-map, 
 float.cl
@@ -1620,13 +1620,8 @@
 ter(
-map, 
 doub
@@ -1678,58 +1678,8 @@
 le);
-%0A%0A        return Collections.unmodifiableMap(map);
 %0A   
@@ -2072,16 +2072,16 @@
 v = 
-BUILDERS
+builders
 .get
@@ -2167,11 +2167,183 @@
 );%0A    %7D
+%0A%0A    private %3CT%3E void register(Class%3CT%3E klass, int sqlType, StatementBinder%3CT%3E binder) %7B%0A        builders.put(klass, BinderArgument.builder(klass, sqlType, binder));%0A    %7D
 %0A%7D%0A

simplify PrimitivesArgFactory code to guide refactor