// 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/Utils.java
// public static String getBsonName(Field field) {
//     String bsonName = field.getName();
//     BsonField bsonField = field.getAnnotation(BsonField.class);
//     if (bsonField != null && !isStrEmpty(bsonField.value())) {
//         bsonName = bsonField.value();
//     }
//     return bsonName;
// }
// 
// Path: src/main/java/me/welkinbai/bsonmapper/Utils.java
// public static Object getObjectIdByRealType(Class<?> fieldType, ObjectId objectId) {
//     if (fieldType == String.class || fieldType == StringObjectId.class) {
//         return objectId.toHexString();
//     } else if (fieldType == ObjectId.class) {
//         return objectId;
//     } else {
//         throw new BsonMapperConverterException("BsonValue ObjectId just can be converted to String or ObjectId.");
//     }
// }
// 
// Path: src/main/java/me/welkinbai/bsonmapper/Utils.java
// public static boolean isIgnored(Field field) {
//     BsonIgnore bsonIgnore = field.getAnnotation(BsonIgnore.class);
//     return bsonIgnore != null;
// }


import me.welkinbai.bsonmapper.exception.BsonMapperConverterException;
import org.bson.BsonArray;
import org.bson.BsonDocument;
import org.bson.BsonReader;
import org.bson.BsonType;
import org.bson.BsonValue;
import org.bson.BsonWriter;
import org.bson.types.ObjectId;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import static me.welkinbai.bsonmapper.MapperLayerCounter.MAPPER_LAYER_COUNTER;
import static me.welkinbai.bsonmapper.Utils.getBsonName;
import static me.welkinbai.bsonmapper.Utils.getObjectIdByRealType;
import static me.welkinbai.bsonmapper.Utils.isIgnored;
                Field field = bsonNameFieldInfoMap.get(bsonName);
                if (field == null || bsonReader.getCurrentBsonType() == BsonType.NULL) {
                    bsonReader.skipValue();
                    continue;
                }
                Object javaValue;
                try {
                    javaValue = getJavaValueByBinaryReader(bsonReader, field, bsonMapperConfig);
                } catch (BsonMapperConverterException e) {
                    throw new BsonMapperConverterException("error when try to get java value from Bson.BsonName:" + bsonName, e);
                }
                setJavaValueToField(targetClazz, target, field, javaValue);
            }
            bsonReader.readEndDocument();
            return target;
        } finally {
            MAPPER_LAYER_COUNTER.reduceCount();
        }
    }

    private Object getJavaValueByBinaryReader(BsonReader bsonReader, Field field, BsonMapperConfig bsonMapperConfig) {
        BsonType currentBsonType = bsonReader.getCurrentBsonType();
        if (currentBsonType == BsonType.DOCUMENT) {
            return decode(bsonReader, field.getType(), bsonMapperConfig);
        }
        if (currentBsonType == BsonType.ARRAY) {
            return BsonValueConverterRepertory.getBsonArrayConverter().decode(bsonReader, field, bsonMapperConfig);
        }
        if (currentBsonType == BsonType.OBJECT_ID) {
            ObjectId objectId = (ObjectId) BsonValueConverterRepertory.getByteIOConverterByBsonType(currentBsonType).decode(bsonReader);
// 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/Utils.java
// public static String getBsonName(Field field) {
//     String bsonName = field.getName();
//     BsonField bsonField = field.getAnnotation(BsonField.class);
//     if (bsonField != null && !isStrEmpty(bsonField.value())) {
//         bsonName = bsonField.value();
//     }
//     return bsonName;
// }
// 
// Path: src/main/java/me/welkinbai/bsonmapper/Utils.java
// public static Object getObjectIdByRealType(Class<?> fieldType, ObjectId objectId) {
//     if (fieldType == String.class || fieldType == StringObjectId.class) {
//         return objectId.toHexString();
//     } else if (fieldType == ObjectId.class) {
//         return objectId;
//     } else {
//         throw new BsonMapperConverterException("BsonValue ObjectId just can be converted to String or ObjectId.");
//     }
// }
// 
// Path: src/main/java/me/welkinbai/bsonmapper/Utils.java
// public static boolean isIgnored(Field field) {
//     BsonIgnore bsonIgnore = field.getAnnotation(BsonIgnore.class);
//     return bsonIgnore != null;
// }


// Path: src/main/java/me/welkinbai/bsonmapper/BsonDocumentConverter.java
import me.welkinbai.bsonmapper.exception.BsonMapperConverterException;
import org.bson.BsonArray;
import org.bson.BsonDocument;
import org.bson.BsonReader;
import org.bson.BsonType;
import org.bson.BsonValue;
import org.bson.BsonWriter;
import org.bson.types.ObjectId;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import static me.welkinbai.bsonmapper.MapperLayerCounter.MAPPER_LAYER_COUNTER;
import static me.welkinbai.bsonmapper.Utils.getBsonName;
import static me.welkinbai.bsonmapper.Utils.getObjectIdByRealType;
import static me.welkinbai.bsonmapper.Utils.isIgnored;

                Field field = bsonNameFieldInfoMap.get(bsonName);
                if (field == null || bsonReader.getCurrentBsonType() == BsonType.NULL) {
                    bsonReader.skipValue();
                    continue;
                }
                Object javaValue;
                try {
                    javaValue = getJavaValueByBinaryReader(bsonReader, field, bsonMapperConfig);
                } catch (BsonMapperConverterException e) {
                    throw new BsonMapperConverterException("error when try to get java value from Bson.BsonName:" + bsonName, e);
                }
                setJavaValueToField(targetClazz, target, field, javaValue);
            }
            bsonReader.readEndDocument();
            return target;
        } finally {
            MAPPER_LAYER_COUNTER.reduceCount();
        }
    }

    private Object getJavaValueByBinaryReader(BsonReader bsonReader, Field field, BsonMapperConfig bsonMapperConfig) {
        BsonType currentBsonType = bsonReader.getCurrentBsonType();
        if (currentBsonType == BsonType.DOCUMENT) {
            return decode(bsonReader, field.getType(), bsonMapperConfig);
        }
        if (currentBsonType == BsonType.ARRAY) {
            return BsonValueConverterRepertory.getBsonArrayConverter().decode(bsonReader, field, bsonMapperConfig);
        }
        if (currentBsonType == BsonType.OBJECT_ID) {
            ObjectId objectId = (ObjectId) BsonValueConverterRepertory.getByteIOConverterByBsonType(currentBsonType).decode(bsonReader);
            return getObjectIdByRealType(field.getType(), objectId);