コード例 #1
0
  /**
   * Writes the given {@link Map} to the given {@link DBObject} considering the given {@link
   * TypeInformation}.
   *
   * @param obj must not be {@literal null}.
   * @param dbo must not be {@literal null}.
   * @param propertyType must not be {@literal null}.
   * @return
   */
  protected DBObject writeMapInternal(
      Map<Object, Object> obj, DBObject dbo, TypeInformation<?> propertyType) {

    for (Map.Entry<Object, Object> entry : obj.entrySet()) {

      Object key = entry.getKey();
      Object val = entry.getValue();

      if (conversions.isSimpleType(key.getClass())) {

        String simpleKey = prepareMapKey(key);
        if (val == null || conversions.isSimpleType(val.getClass())) {
          writeSimpleInternal(val, dbo, simpleKey);
        } else if (val instanceof Collection || val.getClass().isArray()) {
          dbo.put(
              simpleKey,
              writeCollectionInternal(
                  asCollection(val), propertyType.getMapValueType(), new BasicDBList()));
        } else {
          DBObject newDbo = new BasicDBObject();
          TypeInformation<?> valueTypeInfo =
              propertyType.isMap() ? propertyType.getMapValueType() : ClassTypeInformation.OBJECT;
          writeInternal(val, newDbo, valueTypeInfo);
          dbo.put(simpleKey, newDbo);
        }
      } else {
        throw new MappingException("Cannot use a complex object as a key value.");
      }
    }

    return dbo;
  }
コード例 #2
0
  /**
   * Internal write conversion method which should be used for nested invocations.
   *
   * @param obj
   * @param dbo
   */
  @SuppressWarnings("unchecked")
  protected void writeInternal(
      final Object obj, final DBObject dbo, final TypeInformation<?> typeHint) {

    if (null == obj) {
      return;
    }

    Class<?> entityType = obj.getClass();
    Class<?> customTarget = conversions.getCustomWriteTarget(entityType, DBObject.class);

    if (customTarget != null) {
      DBObject result = conversionService.convert(obj, DBObject.class);
      dbo.putAll(result);
      return;
    }

    if (Map.class.isAssignableFrom(entityType)) {
      writeMapInternal((Map<Object, Object>) obj, dbo, ClassTypeInformation.MAP);
      return;
    }

    if (Collection.class.isAssignableFrom(entityType)) {
      writeCollectionInternal((Collection<?>) obj, ClassTypeInformation.LIST, (BasicDBList) dbo);
      return;
    }

    MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityType);
    writeInternal(obj, dbo, entity);
    addCustomTypeKeyIfNecessary(typeHint, obj, dbo);
  }
コード例 #3
0
  /**
   * 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);
  }
コード例 #4
0
  /**
   * Populates the given {@link BasicDBList} with values from the given {@link Collection}.
   *
   * @param source the collection to create a {@link BasicDBList} for, must not be {@literal null}.
   * @param type the {@link TypeInformation} to consider or {@literal null} if unknown.
   * @param sink the {@link BasicDBList} to write to.
   * @return
   */
  private BasicDBList writeCollectionInternal(
      Collection<?> source, TypeInformation<?> type, BasicDBList sink) {

    TypeInformation<?> componentType = type == null ? null : type.getComponentType();

    for (Object element : source) {

      Class<?> elementType = element == null ? null : element.getClass();

      if (elementType == null || conversions.isSimpleType(elementType)) {
        sink.add(getPotentiallyConvertedSimpleWrite(element));
      } else if (element instanceof Collection || elementType.isArray()) {
        sink.add(writeCollectionInternal(asCollection(element), componentType, new BasicDBList()));
      } else {
        BasicDBObject propDbObj = new BasicDBObject();
        writeInternal(element, propDbObj, componentType);
        sink.add(propDbObj);
      }
    }

    return sink;
  }
コード例 #5
0
  @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);
  }