/*
     * (non-Javadoc)
     * @see org.springframework.data.convert.PropertyValueProvider#getPropertyValue(org.springframework.data.mapping.PersistentProperty)
     */
    public <T> T getPropertyValue(MongoPersistentProperty property) {

      String expression = property.getSpelExpression();
      Object value = expression != null ? evaluator.evaluate(expression) : source.get(property);

      if (value == null) {
        return null;
      }

      return readValue(value, property.getTypeInformation(), path);
    }
  @SuppressWarnings({"unchecked"})
  protected void writePropertyInternal(Object obj, DBObject dbo, MongoPersistentProperty prop) {

    if (obj == null) {
      return;
    }

    DBObjectAccessor accessor = new DBObjectAccessor(dbo);

    TypeInformation<?> valueType = ClassTypeInformation.from(obj.getClass());
    TypeInformation<?> type = prop.getTypeInformation();

    if (valueType.isCollectionLike()) {
      DBObject collectionInternal = createCollection(asCollection(obj), prop);
      accessor.put(prop, collectionInternal);
      return;
    }

    if (valueType.isMap()) {
      DBObject mapDbObj = createMap((Map<Object, Object>) obj, prop);
      accessor.put(prop, mapDbObj);
      return;
    }

    if (prop.isDbReference()) {

      DBRef dbRefObj = null;

      /*
       * If we already have a LazyLoadingProxy, we use it's cached DBRef value instead of
       * unnecessarily initializing it only to convert it to a DBRef a few instructions later.
       */
      if (obj instanceof LazyLoadingProxy) {
        dbRefObj = ((LazyLoadingProxy) obj).toDBRef();
      }

      dbRefObj = dbRefObj != null ? dbRefObj : createDBRef(obj, prop);

      if (null != dbRefObj) {
        accessor.put(prop, dbRefObj);
        return;
      }
    }

    /*
     * If we have a LazyLoadingProxy we make sure it is initialized first.
     */
    if (obj instanceof LazyLoadingProxy) {
      obj = ((LazyLoadingProxy) obj).getTarget();
    }

    // Lookup potential custom target type
    Class<?> basicTargetType = conversions.getCustomWriteTarget(obj.getClass(), null);

    if (basicTargetType != null) {
      accessor.put(prop, conversionService.convert(obj, basicTargetType));
      return;
    }

    Object existingValue = accessor.get(prop);
    BasicDBObject propDbObj =
        existingValue instanceof BasicDBObject
            ? (BasicDBObject) existingValue
            : new BasicDBObject();
    addCustomTypeKeyIfNecessary(ClassTypeInformation.from(prop.getRawType()), obj, propDbObj);

    MongoPersistentEntity<?> entity =
        isSubtype(prop.getType(), obj.getClass())
            ? mappingContext.getPersistentEntity(obj.getClass())
            : mappingContext.getPersistentEntity(type);

    writeInternal(obj, propDbObj, entity);
    accessor.put(prop, propDbObj);
  }