/** * 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; }
/** * Reads the given {@link BasicDBList} into a collection of the given {@link TypeInformation}. * * @param targetType must not be {@literal null}. * @param sourceValue must not be {@literal null}. * @param path must not be {@literal null}. * @return the converted {@link Collection} or array, will never be {@literal null}. */ private Object readCollectionOrArray( TypeInformation<?> targetType, BasicDBList sourceValue, ObjectPath path) { Assert.notNull(targetType, "Target type must not be null!"); Assert.notNull(path, "Object path must not be null!"); Class<?> collectionType = targetType.getType(); if (sourceValue.isEmpty()) { return getPotentiallyConvertedSimpleRead(new HashSet<Object>(), collectionType); } TypeInformation<?> componentType = targetType.getComponentType(); Class<?> rawComponentType = componentType == null ? null : componentType.getType(); collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class; Collection<Object> items = targetType.getType().isArray() ? new ArrayList<Object>() : CollectionFactory.createCollection( collectionType, rawComponentType, sourceValue.size()); for (int i = 0; i < sourceValue.size(); i++) { Object dbObjItem = sourceValue.get(i); if (dbObjItem instanceof DBRef) { items.add( DBRef.class.equals(rawComponentType) ? dbObjItem : read(componentType, readRef((DBRef) dbObjItem), path)); } else if (dbObjItem instanceof DBObject) { items.add(read(componentType, (DBObject) dbObjItem, path)); } else { items.add(getPotentiallyConvertedSimpleRead(dbObjItem, rawComponentType)); } } return getPotentiallyConvertedSimpleRead(items, targetType.getType()); }
/** * 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; }