// Path: src/main/java/me/welkinbai/bsonmapper/exception/BsonMapperConverterException.java
// public class BsonMapperConverterException extends RuntimeException {
// 
//     public BsonMapperConverterException() {
//         super();
//     }
// 
//     public BsonMapperConverterException(String message) {
//         super(message);
//     }
// 
//     public BsonMapperConverterException(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public BsonMapperConverterException(Throwable cause) {
//         super(cause);
//     }
// 
// }


import me.welkinbai.bsonmapper.exception.BsonMapperConverterException;
import org.bson.BsonDbPointer;
import org.bson.BsonRegularExpression;
import org.bson.BsonTimestamp;
import org.bson.BsonType;
import org.bson.BsonUndefined;
import org.bson.BsonValue;
import org.bson.codecs.BsonTypeClassMap;
import org.bson.types.Binary;
import org.bson.types.Code;
import org.bson.types.CodeWithScope;
import org.bson.types.Decimal128;
import org.bson.types.MaxKey;
import org.bson.types.MinKey;
import org.bson.types.ObjectId;
import org.bson.types.Symbol;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
        CLASS_BSON_CONVERTER_MAP.put(Long.class, BsonLongConverter.getInstance());
        CLASS_BSON_CONVERTER_MAP.put(long.class, BsonLongConverter.getInstance());
        CLASS_BSON_CONVERTER_MAP.put(BsonTimestamp.class, BsonTimestampConverter.getInstance());
        CLASS_BSON_CONVERTER_MAP.put(Decimal128.class, BsonBigDecimalConverter.getInstance());
        CLASS_BSON_CONVERTER_MAP.put(MinKey.class, BsonMinKeyConverter.getInstance());
        CLASS_BSON_CONVERTER_MAP.put(MaxKey.class, BsonMaxKeyConverter.getInstance());
        CLASS_BSON_CONVERTER_MAP.put(StringObjectId.class, BsonStringObjectIdConverter.getInstance());
    }

    static BsonValueConverter getValueConverterByBsonType(BsonType bsonType) {
        Class<?> clazz = getClazzByBsonType(bsonType);
        return (BsonValueConverter) CLASS_BSON_CONVERTER_MAP.get(clazz);
    }

    static <T, V extends BsonValue> BsonValueConverter<T, V> getValueConverterByClazz(Class<?> clazz) {
        return (BsonValueConverter<T, V>) CLASS_BSON_CONVERTER_MAP.get(clazz);
    }

    static BsonByteIOConverter getByteIOConverterByBsonType(BsonType bsonType) {
        Class<?> clazz = getClazzByBsonType(bsonType);
        return (BsonByteIOConverter) CLASS_BSON_CONVERTER_MAP.get(clazz);
    }

    static <T> BsonByteIOConverter<T> getByteIOConverterByClazz(Class<?> clazz) {
        return (BsonByteIOConverter<T>) CLASS_BSON_CONVERTER_MAP.get(clazz);
    }

    private static Class<?> getClazzByBsonType(BsonType bsonType) {
        Class<?> clazz = BSON_TYPE_CLASS_MAP.get(bsonType);
        if (clazz == null) {
// Path: src/main/java/me/welkinbai/bsonmapper/exception/BsonMapperConverterException.java
// public class BsonMapperConverterException extends RuntimeException {
// 
//     public BsonMapperConverterException() {
//         super();
//     }
// 
//     public BsonMapperConverterException(String message) {
//         super(message);
//     }
// 
//     public BsonMapperConverterException(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public BsonMapperConverterException(Throwable cause) {
//         super(cause);
//     }
// 
// }


// Path: src/main/java/me/welkinbai/bsonmapper/BsonValueConverterRepertory.java
import me.welkinbai.bsonmapper.exception.BsonMapperConverterException;
import org.bson.BsonDbPointer;
import org.bson.BsonRegularExpression;
import org.bson.BsonTimestamp;
import org.bson.BsonType;
import org.bson.BsonUndefined;
import org.bson.BsonValue;
import org.bson.codecs.BsonTypeClassMap;
import org.bson.types.Binary;
import org.bson.types.Code;
import org.bson.types.CodeWithScope;
import org.bson.types.Decimal128;
import org.bson.types.MaxKey;
import org.bson.types.MinKey;
import org.bson.types.ObjectId;
import org.bson.types.Symbol;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

        CLASS_BSON_CONVERTER_MAP.put(Long.class, BsonLongConverter.getInstance());
        CLASS_BSON_CONVERTER_MAP.put(long.class, BsonLongConverter.getInstance());
        CLASS_BSON_CONVERTER_MAP.put(BsonTimestamp.class, BsonTimestampConverter.getInstance());
        CLASS_BSON_CONVERTER_MAP.put(Decimal128.class, BsonBigDecimalConverter.getInstance());
        CLASS_BSON_CONVERTER_MAP.put(MinKey.class, BsonMinKeyConverter.getInstance());
        CLASS_BSON_CONVERTER_MAP.put(MaxKey.class, BsonMaxKeyConverter.getInstance());
        CLASS_BSON_CONVERTER_MAP.put(StringObjectId.class, BsonStringObjectIdConverter.getInstance());
    }

    static BsonValueConverter getValueConverterByBsonType(BsonType bsonType) {
        Class<?> clazz = getClazzByBsonType(bsonType);
        return (BsonValueConverter) CLASS_BSON_CONVERTER_MAP.get(clazz);
    }

    static <T, V extends BsonValue> BsonValueConverter<T, V> getValueConverterByClazz(Class<?> clazz) {
        return (BsonValueConverter<T, V>) CLASS_BSON_CONVERTER_MAP.get(clazz);
    }

    static BsonByteIOConverter getByteIOConverterByBsonType(BsonType bsonType) {
        Class<?> clazz = getClazzByBsonType(bsonType);
        return (BsonByteIOConverter) CLASS_BSON_CONVERTER_MAP.get(clazz);
    }

    static <T> BsonByteIOConverter<T> getByteIOConverterByClazz(Class<?> clazz) {
        return (BsonByteIOConverter<T>) CLASS_BSON_CONVERTER_MAP.get(clazz);
    }

    private static Class<?> getClazzByBsonType(BsonType bsonType) {
        Class<?> clazz = BSON_TYPE_CLASS_MAP.get(bsonType);
        if (clazz == null) {
            throw new BsonMapperConverterException("can not find BsonValueConverter for bsonType:" + bsonType);