/** * Writes the given {@link Map} using the given {@link MongoPersistentProperty} information. * * @param map must not {@literal null}. * @param property must not be {@literal null}. * @return */ protected DBObject createMap(Map<Object, Object> map, MongoPersistentProperty property) { Assert.notNull(map, "Given map must not be null!"); Assert.notNull(property, "PersistentProperty must not be null!"); if (!property.isDbReference()) { return writeMapInternal(map, new BasicDBObject(), property.getTypeInformation()); } BasicDBObject dbObject = new BasicDBObject(); for (Map.Entry<Object, Object> entry : map.entrySet()) { Object key = entry.getKey(); Object value = entry.getValue(); if (conversions.isSimpleType(key.getClass())) { String simpleKey = prepareMapKey(key.toString()); dbObject.put(simpleKey, value != null ? createDBRef(value, property) : null); } else { throw new MappingException("Cannot use a complex object as a key value."); } } return dbObject; }
/* * (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); }
/** * Writes the given {@link Collection} using the given {@link MongoPersistentProperty} * information. * * @param collection must not be {@literal null}. * @param property must not be {@literal null}. * @return */ protected DBObject createCollection(Collection<?> collection, MongoPersistentProperty property) { if (!property.isDbReference()) { return writeCollectionInternal(collection, property.getTypeInformation(), new BasicDBList()); } BasicDBList dbList = new BasicDBList(); for (Object element : collection) { if (element == null) { continue; } DBRef dbRef = createDBRef(element, property); dbList.add(dbRef); } return dbList; }
protected DBRef createDBRef(Object target, MongoPersistentProperty property) { Assert.notNull(target); if (target instanceof DBRef) { return (DBRef) target; } MongoPersistentEntity<?> targetEntity = mappingContext.getPersistentEntity(target.getClass()); targetEntity = targetEntity == null ? targetEntity = mappingContext.getPersistentEntity(property) : targetEntity; if (null == targetEntity) { throw new MappingException("No mapping metadata found for " + target.getClass()); } MongoPersistentProperty idProperty = targetEntity.getIdProperty(); if (idProperty == null) { throw new MappingException("No id property found on class " + targetEntity.getType()); } Object id = null; if (target.getClass().equals(idProperty.getType())) { id = target; } else { PersistentPropertyAccessor accessor = targetEntity.getPropertyAccessor(target); id = accessor.getProperty(idProperty); } if (null == id) { throw new MappingException("Cannot create a reference to an object with a NULL id."); } return dbRefResolver.createDbRef( property == null ? null : property.getDBRef(), targetEntity, idMapper.convertId(id)); }
/* * (non-Javadoc) * @see org.springframework.data.mongodb.core.convert.MongoWriter#toDBRef(java.lang.Object, org.springframework.data.mongodb.core.mapping.MongoPersistentProperty) */ public DBRef toDBRef(Object object, MongoPersistentProperty referingProperty) { org.springframework.data.mongodb.core.mapping.DBRef annotation = null; if (referingProperty != null) { annotation = referingProperty.getDBRef(); Assert.isTrue(annotation != null, "The referenced property has to be mapped with @DBRef!"); } // @see DATAMONGO-913 if (object instanceof LazyLoadingProxy) { return ((LazyLoadingProxy) object).toDBRef(); } return createDBRef(object, referingProperty); }
@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); }
private <S extends Object> S read( final MongoPersistentEntity<S> entity, final DBObject dbo, final ObjectPath path) { final DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(dbo, spELContext); ParameterValueProvider<MongoPersistentProperty> provider = getParameterProvider(entity, dbo, evaluator, path); EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity); S instance = instantiator.createInstance(entity, provider); final PersistentPropertyAccessor accessor = new ConvertingPropertyAccessor(entity.getPropertyAccessor(instance), conversionService); final MongoPersistentProperty idProperty = entity.getIdProperty(); final S result = instance; // make sure id property is set before all other properties Object idValue = null; if (idProperty != null) { idValue = getValueInternal(idProperty, dbo, evaluator, path); accessor.setProperty(idProperty, idValue); } final ObjectPath currentPath = path.push(result, entity, idValue != null ? dbo.get(idProperty.getFieldName()) : null); // Set properties not already set in the constructor entity.doWithProperties( new PropertyHandler<MongoPersistentProperty>() { public void doWithPersistentProperty(MongoPersistentProperty prop) { // we skip the id property since it was already set if (idProperty != null && idProperty.equals(prop)) { return; } if (!dbo.containsField(prop.getFieldName()) || entity.isConstructorArgument(prop)) { return; } accessor.setProperty(prop, getValueInternal(prop, dbo, evaluator, currentPath)); } }); // Handle associations entity.doWithAssociations( new AssociationHandler<MongoPersistentProperty>() { public void doWithAssociation(Association<MongoPersistentProperty> association) { final MongoPersistentProperty property = association.getInverse(); Object value = dbo.get(property.getFieldName()); if (value == null || entity.isConstructorArgument(property)) { return; } DBRef dbref = value instanceof DBRef ? (DBRef) value : null; DbRefProxyHandler handler = new DefaultDbRefProxyHandler( spELContext, mappingContext, MappingMongoConverter.this); DbRefResolverCallback callback = new DefaultDbRefResolverCallback( dbo, currentPath, evaluator, MappingMongoConverter.this); accessor.setProperty( property, dbRefResolver.resolveDbRef(property, dbref, callback, handler)); } }); return result; }