/**
   * Reads the given {@link DBObject} into a {@link Map}. will recursively resolve nested {@link
   * Map}s as well.
   *
   * @param type the {@link Map} {@link TypeInformation} to be used to unmarshall this {@link
   *     DBObject}.
   * @param dbObject must not be {@literal null}
   * @param path must not be {@literal null}
   * @return
   */
  @SuppressWarnings("unchecked")
  protected Map<Object, Object> readMap(
      TypeInformation<?> type, DBObject dbObject, ObjectPath path) {

    Assert.notNull(dbObject, "DBObject must not be null!");
    Assert.notNull(path, "Object path must not be null!");

    Class<?> mapType = typeMapper.readType(dbObject, type).getType();

    TypeInformation<?> keyType = type.getComponentType();
    Class<?> rawKeyType = keyType == null ? null : keyType.getType();

    TypeInformation<?> valueType = type.getMapValueType();
    Class<?> rawValueType = valueType == null ? null : valueType.getType();

    Map<Object, Object> map =
        CollectionFactory.createMap(mapType, rawKeyType, dbObject.keySet().size());
    Map<String, Object> sourceMap = dbObject.toMap();

    for (Entry<String, Object> entry : sourceMap.entrySet()) {
      if (typeMapper.isTypeKey(entry.getKey())) {
        continue;
      }

      Object key = potentiallyUnescapeMapKey(entry.getKey());

      if (rawKeyType != null) {
        key = conversionService.convert(key, rawKeyType);
      }

      Object value = entry.getValue();

      if (value instanceof DBObject) {
        map.put(key, read(valueType, (DBObject) value, path));
      } else if (value instanceof DBRef) {
        map.put(
            key,
            DBRef.class.equals(rawValueType) ? value : read(valueType, readRef((DBRef) value)));
      } else {
        Class<?> valueClass = valueType == null ? null : valueType.getType();
        map.put(key, getPotentiallyConvertedSimpleRead(value, valueClass));
      }
    }

    return map;
  }
  /**
   * Removes the type information from the entire conversion result.
   *
   * @param object
   * @param recursively whether to apply the removal recursively
   * @return
   */
  private Object removeTypeInfo(Object object, boolean recursively) {

    if (!(object instanceof DBObject)) {
      return object;
    }

    DBObject dbObject = (DBObject) object;
    String keyToRemove = null;

    for (String key : dbObject.keySet()) {

      if (recursively) {

        Object value = dbObject.get(key);

        if (value instanceof BasicDBList) {
          for (Object element : (BasicDBList) value) {
            removeTypeInfo(element, recursively);
          }
        } else {
          removeTypeInfo(value, recursively);
        }
      }

      if (typeMapper.isTypeKey(key)) {

        keyToRemove = key;

        if (!recursively) {
          break;
        }
      }
    }

    if (keyToRemove != null) {
      dbObject.removeField(keyToRemove);
    }

    return dbObject;
  }