DATAMONGO-1005 - Polishing introduction of ObjectPath.
Simplified implementation of ObjectPath to use a static root instance and hand the path further down until final resolution in MappingMongoConverter.readValue(…). This removes a bit of boxing and unboxing code both in ObjectPath and the converter. Introduced ObjectPath.getPathItem(…) to internalize the iteration to find a potentially already resolved object. Renamed parameters and fields of type ObjectPath to path consistently. Removed obsolete method in MappingMongoConverter. Original pull request: #209.
This commit is contained in:
@@ -20,7 +20,6 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -186,11 +185,11 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
protected <S extends Object> S read(TypeInformation<S> type, DBObject dbo) {
|
||||
return read(type, dbo, ObjectPath.toObjectPath(null));
|
||||
return read(type, dbo, ObjectPath.ROOT);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <S extends Object> S read(TypeInformation<S> type, DBObject dbo, ObjectPath objectPath) {
|
||||
private <S extends Object> S read(TypeInformation<S> type, DBObject dbo, ObjectPath path) {
|
||||
|
||||
if (null == dbo) {
|
||||
return null;
|
||||
@@ -208,11 +207,11 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
if (typeToUse.isCollectionLike() && dbo instanceof BasicDBList) {
|
||||
return (S) readCollectionOrArray(typeToUse, (BasicDBList) dbo, objectPath);
|
||||
return (S) readCollectionOrArray(typeToUse, (BasicDBList) dbo, path);
|
||||
}
|
||||
|
||||
if (typeToUse.isMap()) {
|
||||
return (S) readMap(typeToUse, dbo, objectPath);
|
||||
return (S) readMap(typeToUse, dbo, path);
|
||||
}
|
||||
|
||||
// Retrieve persistent entity info
|
||||
@@ -222,47 +221,47 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
throw new MappingException("No mapping metadata found for " + rawType.getName());
|
||||
}
|
||||
|
||||
return read(persistentEntity, dbo, objectPath);
|
||||
return read(persistentEntity, dbo, path);
|
||||
}
|
||||
|
||||
private ParameterValueProvider<MongoPersistentProperty> getParameterProvider(MongoPersistentEntity<?> entity,
|
||||
DBObject source, DefaultSpELExpressionEvaluator evaluator, ObjectPath objectPath) {
|
||||
DBObject source, DefaultSpELExpressionEvaluator evaluator, ObjectPath path) {
|
||||
|
||||
MongoDbPropertyValueProvider provider = new MongoDbPropertyValueProvider(source, evaluator, objectPath);
|
||||
MongoDbPropertyValueProvider provider = new MongoDbPropertyValueProvider(source, evaluator, path);
|
||||
PersistentEntityParameterValueProvider<MongoPersistentProperty> parameterProvider = new PersistentEntityParameterValueProvider<MongoPersistentProperty>(
|
||||
entity, provider, objectPath.getCurrentObject());
|
||||
entity, provider, path.getCurrentObject());
|
||||
|
||||
return new ConverterAwareSpELExpressionParameterValueProvider(evaluator, conversionService, parameterProvider,
|
||||
objectPath.getCurrentObject());
|
||||
return new ConverterAwareSpELExpressionParameterValueProvider(evaluator, conversionService, parameterProvider, path);
|
||||
}
|
||||
|
||||
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final DBObject dbo,
|
||||
final ObjectPath parentPath) {
|
||||
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, parentPath);
|
||||
ParameterValueProvider<MongoPersistentProperty> provider = getParameterProvider(entity, dbo, evaluator, path);
|
||||
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
|
||||
S instance = instantiator.createInstance(entity, provider);
|
||||
|
||||
final BeanWrapper<S> wrapper = BeanWrapper.create(instance, conversionService);
|
||||
final MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
final S result = wrapper.getBean();
|
||||
|
||||
// make sure id property is set before all other properties
|
||||
Object idValue = null;
|
||||
if (entity.getIdProperty() != null) {
|
||||
idValue = getValueInternal(entity.getIdProperty(), dbo, evaluator, parentPath);
|
||||
wrapper.setProperty(entity.getIdProperty(), idValue);
|
||||
|
||||
if (idProperty != null) {
|
||||
idValue = getValueInternal(idProperty, dbo, evaluator, path);
|
||||
wrapper.setProperty(idProperty, idValue);
|
||||
}
|
||||
|
||||
final ObjectPath currentPath = parentPath.push(result, entity, idValue);
|
||||
final ObjectPath currentPath = path.push(result, entity, idValue);
|
||||
|
||||
// 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 (entity.getIdProperty() != null && entity.getIdProperty().equals(prop)) {
|
||||
if (idProperty != null && idProperty.equals(prop)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -815,9 +814,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
protected Object getValueInternal(MongoPersistentProperty prop, DBObject dbo, SpELExpressionEvaluator evaluator,
|
||||
ObjectPath objectPath) {
|
||||
ObjectPath path) {
|
||||
|
||||
return new MongoDbPropertyValueProvider(dbo, evaluator, objectPath).getPropertyValue(prop);
|
||||
return new MongoDbPropertyValueProvider(dbo, evaluator, path).getPropertyValue(prop);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -825,13 +824,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
*
|
||||
* @param targetType must not be {@literal null}.
|
||||
* @param sourceValue must not be {@literal null}.
|
||||
* @param objectPath 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 objectPath) {
|
||||
private Object readCollectionOrArray(TypeInformation<?> targetType, BasicDBList sourceValue, ObjectPath path) {
|
||||
|
||||
Assert.notNull(targetType);
|
||||
Assert.notNull(objectPath);
|
||||
Assert.notNull(targetType, "Target type must not be null!");
|
||||
Assert.notNull(path, "Object path must not be null!");
|
||||
|
||||
Class<?> collectionType = targetType.getType();
|
||||
|
||||
@@ -852,9 +851,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
if (dbObjItem instanceof DBRef) {
|
||||
items.add(DBRef.class.equals(rawComponentType) ? dbObjItem : read(componentType, readRef((DBRef) dbObjItem),
|
||||
objectPath));
|
||||
path));
|
||||
} else if (dbObjItem instanceof DBObject) {
|
||||
items.add(read(componentType, (DBObject) dbObjItem, objectPath));
|
||||
items.add(read(componentType, (DBObject) dbObjItem, path));
|
||||
} else {
|
||||
items.add(getPotentiallyConvertedSimpleRead(dbObjItem, rawComponentType));
|
||||
}
|
||||
@@ -868,14 +867,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
*
|
||||
* @param type the {@link Map} {@link TypeInformation} to be used to unmarshall this {@link DBObject}.
|
||||
* @param dbObject must not be {@literal null}
|
||||
* @param objectPath 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 objectPath) {
|
||||
protected Map<Object, Object> readMap(TypeInformation<?> type, DBObject dbObject, ObjectPath path) {
|
||||
|
||||
Assert.notNull(dbObject);
|
||||
Assert.notNull(objectPath);
|
||||
Assert.notNull(dbObject, "DBObject must not be null!");
|
||||
Assert.notNull(path, "Object path must not be null!");
|
||||
|
||||
Class<?> mapType = typeMapper.readType(dbObject, type).getType();
|
||||
|
||||
@@ -902,7 +901,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
Object value = entry.getValue();
|
||||
|
||||
if (value instanceof DBObject) {
|
||||
map.put(key, read(valueType, (DBObject) value, objectPath));
|
||||
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 {
|
||||
@@ -914,21 +913,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return map;
|
||||
}
|
||||
|
||||
protected <T> List<?> unwrapList(BasicDBList dbList, TypeInformation<T> targetType) {
|
||||
List<Object> rootList = new ArrayList<Object>();
|
||||
for (int i = 0; i < dbList.size(); i++) {
|
||||
Object obj = dbList.get(i);
|
||||
if (obj instanceof BasicDBList) {
|
||||
rootList.add(unwrapList((BasicDBList) obj, targetType.getComponentType()));
|
||||
} else if (obj instanceof DBObject) {
|
||||
rootList.add(read(targetType, (DBObject) obj));
|
||||
} else {
|
||||
rootList.add(obj);
|
||||
}
|
||||
}
|
||||
return rootList;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.MongoWriter#convertToMongoType(java.lang.Object, org.springframework.data.util.TypeInformation)
|
||||
@@ -1048,7 +1032,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
private final DBObjectAccessor source;
|
||||
private final SpELExpressionEvaluator evaluator;
|
||||
private final ObjectPath objectPath;
|
||||
private final ObjectPath path;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoDbPropertyValueProvider} for the given source, {@link SpELExpressionEvaluator} and
|
||||
@@ -1058,14 +1042,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* @param evaluator must not be {@literal null}.
|
||||
* @param parent can be {@literal null}.
|
||||
*/
|
||||
public MongoDbPropertyValueProvider(DBObject source, SpELExpressionEvaluator evaluator, ObjectPath objectPath) {
|
||||
public MongoDbPropertyValueProvider(DBObject source, SpELExpressionEvaluator evaluator, ObjectPath path) {
|
||||
|
||||
Assert.notNull(source);
|
||||
Assert.notNull(evaluator);
|
||||
|
||||
this.source = new DBObjectAccessor(source);
|
||||
this.evaluator = evaluator;
|
||||
this.objectPath = objectPath;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1081,7 +1065,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return null;
|
||||
}
|
||||
|
||||
return readValue(value, property.getTypeInformation(), objectPath);
|
||||
return readValue(value, property.getTypeInformation(), path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1094,7 +1078,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
private class ConverterAwareSpELExpressionParameterValueProvider extends
|
||||
SpELExpressionParameterValueProvider<MongoPersistentProperty> {
|
||||
|
||||
private final Object parent;
|
||||
private final ObjectPath parent;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ConverterAwareSpELExpressionParameterValueProvider}.
|
||||
@@ -1104,7 +1088,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* @param delegate must not be {@literal null}.
|
||||
*/
|
||||
public ConverterAwareSpELExpressionParameterValueProvider(SpELExpressionEvaluator evaluator,
|
||||
ConversionService conversionService, ParameterValueProvider<MongoPersistentProperty> delegate, Object parent) {
|
||||
ConversionService conversionService, ParameterValueProvider<MongoPersistentProperty> delegate, ObjectPath parent) {
|
||||
|
||||
super(evaluator, conversionService, delegate);
|
||||
this.parent = parent;
|
||||
@@ -1121,73 +1105,37 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T readValue(Object value, TypeInformation<?> type, Object parent) {
|
||||
|
||||
ObjectPath objectPath = ObjectPath.toObjectPath(parent);
|
||||
private <T> T readValue(Object value, TypeInformation<?> type, ObjectPath parent) {
|
||||
|
||||
Class<?> rawType = type.getType();
|
||||
|
||||
if (conversions.hasCustomReadTarget(value.getClass(), rawType)) {
|
||||
return (T) conversionService.convert(value, rawType);
|
||||
} else if (value instanceof DBRef) {
|
||||
return potentiallyReadOrResolveDbRef((DBRef) value, type, objectPath, rawType);
|
||||
return potentiallyReadOrResolveDbRef((DBRef) value, type, parent, rawType);
|
||||
} else if (value instanceof BasicDBList) {
|
||||
return (T) readCollectionOrArray(type, (BasicDBList) value, objectPath);
|
||||
return (T) readCollectionOrArray(type, (BasicDBList) value, parent);
|
||||
} else if (value instanceof DBObject) {
|
||||
return (T) read(type, (DBObject) value, objectPath);
|
||||
return (T) read(type, (DBObject) value, parent);
|
||||
} else {
|
||||
return (T) getPotentiallyConvertedSimpleRead(value, rawType);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T potentiallyReadOrResolveDbRef(DBRef dbref, TypeInformation<?> type, ObjectPath objectPath,
|
||||
Class<?> rawType) {
|
||||
private <T> T potentiallyReadOrResolveDbRef(DBRef dbref, TypeInformation<?> type, ObjectPath path, Class<?> rawType) {
|
||||
|
||||
if (rawType.equals(DBRef.class)) {
|
||||
return (T) dbref;
|
||||
}
|
||||
|
||||
Object object = getObjectFromPathForRefOrNull(objectPath, dbref);
|
||||
Object object = dbref == null ? null : path.getPathItem(dbref.getId(), dbref.getRef());
|
||||
|
||||
if (object != null) {
|
||||
return (T) object;
|
||||
}
|
||||
|
||||
return (T) (object != null ? object : read(type, readRef(dbref), objectPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object from the given {@link ObjectPath} iff the given {@link DBRef} points to it or {@literal null}.
|
||||
*
|
||||
* @param path
|
||||
* @param dbref
|
||||
* @return
|
||||
*/
|
||||
private Object getObjectFromPathForRefOrNull(ObjectPath path, DBRef dbref) {
|
||||
|
||||
if (path == null || dbref == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (ObjectPathItem item : path) {
|
||||
|
||||
Object object = item.getObject();
|
||||
|
||||
if (object == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getIdValue() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dbref.getRef().equals(item.getCollection()) && dbref.getId().equals(item.getIdValue())) {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return (T) (object != null ? object : read(type, readRef(dbref), path));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1199,117 +1147,4 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
DBObject readRef(DBRef ref) {
|
||||
return ref.fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* An immutable ordered set of target objects for {@link DBObject} to {@link Object} conversions. Object paths can be
|
||||
* constructed by the {@link #toObjectPath(Object)} method and extended via {@link #push(Object)}.
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
* @since 1.6
|
||||
*/
|
||||
static class ObjectPath implements Iterable<ObjectPathItem> {
|
||||
|
||||
private final List<ObjectPathItem> items;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ObjectPath} from the given parent {@link ObjectPath} by adding the provided
|
||||
* {@link ObjectPathItem} to it.
|
||||
*
|
||||
* @param parent
|
||||
* @param item
|
||||
*/
|
||||
private ObjectPath(ObjectPath parent, ObjectPathItem item) {
|
||||
|
||||
if (parent == null) {
|
||||
this.items = Collections.singletonList(item);
|
||||
return;
|
||||
}
|
||||
|
||||
List<ObjectPathItem> list = new ArrayList<ObjectPathItem>(parent.items);
|
||||
list.add(item);
|
||||
|
||||
this.items = list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the {@link ObjectPath} with the given {@link Object} as current object.
|
||||
*
|
||||
* @param object
|
||||
* @param entity
|
||||
* @param idValue
|
||||
* @return
|
||||
*/
|
||||
public ObjectPath push(Object object, MongoPersistentEntity<?> entity, Object idValue) {
|
||||
return new ObjectPath(this, new ObjectPathItem(object, idValue, entity != null ? entity.getCollection() : null));
|
||||
}
|
||||
|
||||
public Object getRootObject() {
|
||||
return getRoot().getObject();
|
||||
}
|
||||
|
||||
private ObjectPathItem getRoot() {
|
||||
return items.get(0);
|
||||
}
|
||||
|
||||
public Object getCurrentObject() {
|
||||
return getCurrent().getObject();
|
||||
}
|
||||
|
||||
private ObjectPathItem getCurrent() {
|
||||
return items.get(items.size() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ObjectPathItem> iterator() {
|
||||
return items.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link ObjectPath} represented by the given {@link Object} or creates a new {@link ObjectPath}
|
||||
* wrapping the given {@link Object}.
|
||||
*
|
||||
* @param object
|
||||
* @return
|
||||
*/
|
||||
public static ObjectPath toObjectPath(Object object) {
|
||||
return object instanceof ObjectPath ? ((ObjectPath) object) : new ObjectPath(null, new ObjectPathItem(object,
|
||||
null, null));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
static class ObjectPathItem {
|
||||
|
||||
private final Object object;
|
||||
private final Object idValue;
|
||||
private final String collection;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ObjectPathItem}.
|
||||
*
|
||||
* @param object
|
||||
* @param idValue
|
||||
* @param collection
|
||||
*/
|
||||
ObjectPathItem(Object object, Object idValue, String collection) {
|
||||
|
||||
this.object = object;
|
||||
this.idValue = idValue;
|
||||
this.collection = collection;
|
||||
}
|
||||
|
||||
public Object getObject() {
|
||||
return object;
|
||||
}
|
||||
|
||||
public Object getIdValue() {
|
||||
return idValue;
|
||||
}
|
||||
|
||||
public String getCollection() {
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* A path of objects nested into each other. The type allows access to all parent objects currently in creation even
|
||||
* when resolving more nested objects. This allows to avoid re-resolving object instances that are logically equivalent
|
||||
* to already resolved ones.
|
||||
* <p>
|
||||
* An immutable ordered set of target objects for {@link DBObject} to {@link Object} conversions. Object paths can be
|
||||
* constructed by the {@link #toObjectPath(Object)} method and extended via {@link #push(Object)}.
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
* @since 1.6
|
||||
*/
|
||||
class ObjectPath {
|
||||
|
||||
public static final ObjectPath ROOT = new ObjectPath();
|
||||
|
||||
private final List<ObjectPathItem> items;
|
||||
|
||||
private ObjectPath() {
|
||||
this.items = Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ObjectPath} from the given parent {@link ObjectPath} by adding the provided
|
||||
* {@link ObjectPathItem} to it.
|
||||
*
|
||||
* @param parent can be {@literal null}.
|
||||
* @param item
|
||||
*/
|
||||
private ObjectPath(ObjectPath parent, ObjectPath.ObjectPathItem item) {
|
||||
|
||||
List<ObjectPath.ObjectPathItem> items = new ArrayList<ObjectPath.ObjectPathItem>(parent.items);
|
||||
items.add(item);
|
||||
|
||||
this.items = Collections.unmodifiableList(items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the {@link ObjectPath} with the given {@link Object} as current object.
|
||||
*
|
||||
* @param object must not be {@literal null}.
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param id must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public ObjectPath push(Object object, MongoPersistentEntity<?> entity, Object id) {
|
||||
|
||||
Assert.notNull(object, "Object must not be null!");
|
||||
Assert.notNull(entity, "MongoPersistentEntity must not be null!");
|
||||
|
||||
ObjectPathItem item = new ObjectPathItem(object, id, entity.getCollection());
|
||||
return new ObjectPath(this, item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object with the given id and stored in the given collection if it's contained in the {@link ObjectPath}
|
||||
* .
|
||||
*
|
||||
* @param id must not be {@literal null}.
|
||||
* @param collection must not be {@literal null} or empty.
|
||||
* @return
|
||||
*/
|
||||
public Object getPathItem(Object id, String collection) {
|
||||
|
||||
Assert.notNull(id, "Id must not be null!");
|
||||
Assert.hasText(collection, "Collection name must not be null!");
|
||||
|
||||
for (ObjectPathItem item : items) {
|
||||
|
||||
Object object = item.getObject();
|
||||
|
||||
if (object == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getIdValue() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (collection.equals(item.getCollection()) && id.equals(item.getIdValue())) {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current object of the {@link ObjectPath} or {@literal null} if the path is empty.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Object getCurrentObject() {
|
||||
return items.isEmpty() ? null : items.get(items.size() - 1).getObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* An item in an {@link ObjectPath}.
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class ObjectPathItem {
|
||||
|
||||
private final Object object;
|
||||
private final Object idValue;
|
||||
private final String collection;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ObjectPathItem}.
|
||||
*
|
||||
* @param object
|
||||
* @param idValue
|
||||
* @param collection
|
||||
*/
|
||||
ObjectPathItem(Object object, Object idValue, String collection) {
|
||||
|
||||
this.object = object;
|
||||
this.idValue = idValue;
|
||||
this.collection = collection;
|
||||
}
|
||||
|
||||
public Object getObject() {
|
||||
return object;
|
||||
}
|
||||
|
||||
public Object getIdValue() {
|
||||
return idValue;
|
||||
}
|
||||
|
||||
public String getCollection() {
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user