/**
   * Adds custom type information to the given {@link DBObject} if necessary. That is if the value
   * is not the same as the one given. This is usually the case if you store a subtype of the actual
   * declared type of the property.
   *
   * @param type
   * @param value must not be {@literal null}.
   * @param dbObject must not be {@literal null}.
   */
  protected void addCustomTypeKeyIfNecessary(
      TypeInformation<?> type, Object value, DBObject dbObject) {

    TypeInformation<?> actualType = type != null ? type.getActualType() : null;
    Class<?> reference = actualType == null ? Object.class : actualType.getType();
    Class<?> valueType = ClassUtils.getUserClass(value.getClass());

    boolean notTheSameClass = !valueType.equals(reference);
    if (notTheSameClass) {
      typeMapper.writeType(valueType, dbObject);
    }
  }
  /**
   * Root entry method into write conversion. Adds a type discriminator to the {@link DBObject}.
   * Shouldn't be called for nested conversions.
   *
   * @see org.springframework.data.mongodb.core.core.convert.MongoWriter#write(java.lang.Object,
   *     com.mongodb.DBObject)
   */
  public void write(final Object obj, final DBObject dbo) {

    if (null == obj) {
      return;
    }

    Class<?> entityType = obj.getClass();
    boolean handledByCustomConverter =
        conversions.getCustomWriteTarget(entityType, DBObject.class) != null;
    TypeInformation<? extends Object> type = ClassTypeInformation.from(entityType);

    if (!handledByCustomConverter && !(dbo instanceof BasicDBList)) {
      typeMapper.writeType(type, dbo);
    }

    Object target = obj instanceof LazyLoadingProxy ? ((LazyLoadingProxy) obj).getTarget() : obj;

    writeInternal(target, dbo, type);
  }