// 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;
package me.welkinbai.bsonmapper;




/**
 * Created by baixiaoxuan on 2017/3/23.
 */
final class BsonDocumentConverter {

    private BsonDocumentConverter() {
    }

    static BsonDocumentConverter getInstance() {
        return new BsonDocumentConverter();
    }

    /**
     * 反序列化BsonDocument到POJO/decode BsonDocument->POJO
     *
     * @param bsonDocument
     * @param targetClazz
     * @param bsonMapperConfig
     * @param <T>
     * @return
     */
    <T> T decode(BsonDocument bsonDocument, Class<T> targetClazz, BsonMapperConfig bsonMapperConfig) {
        MAPPER_LAYER_COUNTER.addCount(bsonMapperConfig);
        try {
            List<Field> allField = Utils.getAllField(targetClazz);
            T target = Utils.newInstanceByClazz(targetClazz);
            for (Field field : allField) {
                if (isIgnored(field)) {
                    continue;
                }
// 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;

package me.welkinbai.bsonmapper;




/**
 * Created by baixiaoxuan on 2017/3/23.
 */
final class BsonDocumentConverter {

    private BsonDocumentConverter() {
    }

    static BsonDocumentConverter getInstance() {
        return new BsonDocumentConverter();
    }

    /**
     * 反序列化BsonDocument到POJO/decode BsonDocument->POJO
     *
     * @param bsonDocument
     * @param targetClazz
     * @param bsonMapperConfig
     * @param <T>
     * @return
     */
    <T> T decode(BsonDocument bsonDocument, Class<T> targetClazz, BsonMapperConfig bsonMapperConfig) {
        MAPPER_LAYER_COUNTER.addCount(bsonMapperConfig);
        try {
            List<Field> allField = Utils.getAllField(targetClazz);
            T target = Utils.newInstanceByClazz(targetClazz);
            for (Field field : allField) {
                if (isIgnored(field)) {
                    continue;
                }
                String bsonName = getBsonName(field);