DATAMONGO-1730 - Adapt to API changes in mapping subsystem.

This commit is contained in:
Mark Paluch
2017-06-26 16:42:36 +02:00
parent 028aeb327f
commit 697f5ad7c6
47 changed files with 683 additions and 670 deletions

View File

@@ -17,22 +17,10 @@ package org.springframework.data.mongodb.core;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.query.SerializationUtils.*;
import static org.springframework.data.util.Optionals.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.bson.Document;
@@ -60,11 +48,10 @@ import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Metric;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.BulkOperations.BulkMode;
import org.springframework.data.mongodb.core.DefaultBulkOperations.BulkOperationContext;
@@ -558,8 +545,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
Assert.notNull(mode, "BulkMode must not be null!");
Assert.hasText(collectionName, "Collection name must not be null or empty!");
DefaultBulkOperations operations = new DefaultBulkOperations(this, collectionName,
new BulkOperationContext(mode, getPersistentEntity(entityType), queryMapper, updateMapper));
DefaultBulkOperations operations = new DefaultBulkOperations(this, collectionName, new BulkOperationContext(mode,
Optional.ofNullable(getPersistentEntity(entityType)), queryMapper, updateMapper));
operations.setExceptionTranslator(exceptionTranslator);
operations.setDefaultWriteConcern(writeConcern);
@@ -640,9 +627,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
public <T> T findById(Object id, Class<T> entityClass, String collectionName) {
String idKey = mappingContext.getPersistentEntity(entityClass)//
.flatMap(it -> it.getIdProperty())//
.map(it -> it.getName()).orElse(ID_FIELD);
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entityClass);
String idKey = ID_FIELD;
if (persistentEntity != null) {
if (persistentEntity.getIdProperty() != null) {
idKey = persistentEntity.getIdProperty().getName();
}
}
return doFindOne(collectionName, new Document(idKey, id), null, entityClass);
}
@@ -775,11 +766,11 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
Assert.hasText(collectionName, "Collection name must not be null or empty!");
final Document document = query == null ? null
Document document = query == null ? null
: queryMapper.getMappedObject(query.getQueryObject(),
Optional.ofNullable(entityClass).flatMap(it -> mappingContext.getPersistentEntity(entityClass)));
Optional.ofNullable(entityClass).map(it -> mappingContext.getPersistentEntity(entityClass)));
return execute(collectionName, (CollectionCallback<Long>) collection -> collection.count(document));
return execute(collectionName, collection -> collection.count(document));
}
/*
@@ -896,13 +887,16 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
private void initializeVersionProperty(Object entity) {
Optional<? extends MongoPersistentEntity<?>> persistentEntity = getPersistentEntity(entity.getClass());
MongoPersistentEntity<?> persistentEntity = getPersistentEntity(entity.getClass());
ifAllPresent(persistentEntity, persistentEntity.flatMap(PersistentEntity::getVersionProperty), (l, r) -> {
ConvertingPropertyAccessor accessor = new ConvertingPropertyAccessor(l.getPropertyAccessor(entity),
if (persistentEntity != null && persistentEntity.hasVersionProperty()) {
MongoPersistentProperty versionProperty = persistentEntity.getRequiredVersionProperty();
ConvertingPropertyAccessor accessor = new ConvertingPropertyAccessor(persistentEntity.getPropertyAccessor(entity),
mongoConverter.getConversionService());
accessor.setProperty(r, Optional.of(0));
});
accessor.setProperty(versionProperty, 0);
}
}
public void insert(Collection<? extends Object> batchToSave, Class<?> entityClass) {
@@ -984,12 +978,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
Assert.notNull(objectToSave, "Object to save must not be null!");
Assert.hasText(collectionName, "Collection name must not be null or empty!");
Optional<? extends MongoPersistentEntity<?>> entity = getPersistentEntity(objectToSave.getClass());
Optional<MongoPersistentProperty> versionProperty = entity.flatMap(PersistentEntity::getVersionProperty);
MongoPersistentEntity<?> entity = getPersistentEntity(objectToSave.getClass());
mapIfAllPresent(entity, versionProperty, //
(l, r) -> doSaveVersioned(objectToSave, l, collectionName))//
.orElseGet(() -> doSave(collectionName, objectToSave, this.mongoConverter));
if (entity != null && entity.hasVersionProperty()) {
doSaveVersioned(objectToSave, entity, collectionName);
return;
}
doSave(collectionName, objectToSave, this.mongoConverter);
}
private <T> T doSaveVersioned(T objectToSave, MongoPersistentEntity<?> entity, String collectionName) {
@@ -997,13 +993,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
ConvertingPropertyAccessor convertingAccessor = new ConvertingPropertyAccessor(
entity.getPropertyAccessor(objectToSave), mongoConverter.getConversionService());
Optional<MongoPersistentProperty> versionProperty = entity.getVersionProperty();
Optional<Number> versionNumber = versionProperty.flatMap(it -> convertingAccessor.getProperty(it, Number.class));
MongoPersistentProperty property = entity.getRequiredVersionProperty();
Number number = convertingAccessor.getProperty(property, Number.class);
return mapIfAllPresent(versionProperty, versionNumber, (property, number) -> {
if (number != null) {
// Bump version number
convertingAccessor.setProperty(property, Optional.of(number.longValue() + 1));
convertingAccessor.setProperty(property, number.longValue() + 1);
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
assertUpdateableIdIfNotSet(objectToSave);
@@ -1025,16 +1021,16 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
if (result.getModifiedCount() == 0) {
throw new OptimisticLockingFailureException(
String.format("Cannot save entity %s with version %s to collection %s. Has it been modified meanwhile?", id,
versionNumber, collectionName));
number, collectionName));
}
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, document, collectionName));
return objectToSave;
}).orElseGet(() -> {
doInsert(collectionName, objectToSave, this.mongoConverter);
return objectToSave;
});
}
doInsert(collectionName, objectToSave, this.mongoConverter);
return objectToSave;
}
protected <T> T doSave(String collectionName, T objectToSave, MongoWriter<T> writer) {
@@ -1188,8 +1184,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
public UpdateResult doInCollection(MongoCollection<Document> collection)
throws MongoException, DataAccessException {
Optional<? extends MongoPersistentEntity<?>> entity = entityClass == null ? Optional.empty()
: getPersistentEntity(entityClass);
MongoPersistentEntity<?> entity = entityClass == null ? null : getPersistentEntity(entityClass);
increaseVersionForUpdateIfNecessary(entity, update);
@@ -1235,24 +1230,26 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
});
}
private void increaseVersionForUpdateIfNecessary(Optional<? extends MongoPersistentEntity<?>> persistentEntity,
Update update) {
private void increaseVersionForUpdateIfNecessary(MongoPersistentEntity<?> persistentEntity, Update update) {
ifAllPresent(persistentEntity, persistentEntity.flatMap(PersistentEntity::getVersionProperty),
(entity, property) -> {
String versionFieldName = property.getFieldName();
if (!update.modifies(versionFieldName)) {
update.inc(versionFieldName, 1L);
}
});
if (persistentEntity != null && persistentEntity.hasVersionProperty()) {
String versionFieldName = persistentEntity.getRequiredVersionProperty().getFieldName();
if (!update.modifies(versionFieldName)) {
update.inc(versionFieldName, 1L);
}
}
}
private boolean documentContainsVersionProperty(Document document,
Optional<? extends MongoPersistentEntity<?>> persistentEntity) {
private boolean documentContainsVersionProperty(Document document, MongoPersistentEntity<?> persistentEntity) {
return mapIfAllPresent(persistentEntity, persistentEntity.flatMap(PersistentEntity::getVersionProperty), //
(entity, property) -> document.containsKey(property.getFieldName()))//
.orElse(false);
if (persistentEntity != null && persistentEntity.hasVersionProperty()) {
MongoPersistentProperty property = persistentEntity.getRequiredVersionProperty();
return document.containsKey(property.getFieldName());
}
return false;
}
public DeleteResult remove(Object object) {
@@ -1282,21 +1279,25 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
* @param object
* @return
*/
private Pair<String, Optional<Object>> extractIdPropertyAndValue(Object object) {
private Pair<String, Object> extractIdPropertyAndValue(Object object) {
Assert.notNull(object, "Id cannot be extracted from 'null'.");
Class<?> objectType = object.getClass();
if (object instanceof Document) {
return Pair.of(ID_FIELD, Optional.ofNullable(((Document) object).get(ID_FIELD)));
return Pair.of(ID_FIELD, ((Document) object).get(ID_FIELD));
}
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(objectType);
return mapIfAllPresent(entity, entity.flatMap(it -> it.getIdProperty()), //
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(objectType);
(l, r) -> Pair.of(r.getFieldName(), l.getPropertyAccessor(object).getProperty(r)))//
.orElseThrow(() -> new MappingException("No id property found for object of type " + objectType));
if (entity != null && entity.hasIdProperty()) {
MongoPersistentProperty idProperty = entity.getIdProperty();
return Pair.of(idProperty.getFieldName(), entity.getPropertyAccessor(object).getProperty(idProperty));
}
throw new MappingException("No id property found for object of type " + objectType);
}
/**
@@ -1307,8 +1308,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
*/
private Query getIdQueryFor(Object object) {
Pair<String, Optional<Object>> id = extractIdPropertyAndValue(object);
return new Query(where(id.getFirst()).is(id.getSecond().orElse(null)));
Pair<String, Object> id = extractIdPropertyAndValue(object);
return new Query(where(id.getFirst()).is(id.getSecond()));
}
/**
@@ -1322,13 +1323,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
Assert.notEmpty(objects, "Cannot create Query for empty collection.");
Iterator<?> it = objects.iterator();
Pair<String, Optional<Object>> pair = extractIdPropertyAndValue(it.next());
Pair<String, Object> pair = extractIdPropertyAndValue(it.next());
ArrayList<Object> ids = new ArrayList<Object>(objects.size());
ids.add(pair.getSecond().orElse(null));
ids.add(pair.getSecond());
while (it.hasNext()) {
ids.add(extractIdPropertyAndValue(it.next()).getSecond().orElse(null));
ids.add(extractIdPropertyAndValue(it.next()).getSecond());
}
return new Query(where(pair.getFirst()).in(ids));
@@ -1336,15 +1337,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
private void assertUpdateableIdIfNotSet(Object value) {
Optional<? extends MongoPersistentEntity<?>> persistentEntity = mappingContext
.getPersistentEntity(value.getClass());
Optional<MongoPersistentProperty> idProperty = persistentEntity.flatMap(it -> it.getIdProperty());
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(value.getClass());
Optionals.ifAllPresent(persistentEntity, idProperty, (entity, property) -> {
if (entity != null && entity.hasIdProperty()) {
Optional<Object> propertyValue = entity.getPropertyAccessor(value).getProperty(property);
MongoPersistentProperty property = entity.getRequiredIdProperty();
Object propertyValue = entity.getPropertyAccessor(value).getProperty(property);
if (propertyValue.isPresent()) {
if (propertyValue != null) {
return;
}
@@ -1353,7 +1353,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
String.format("Cannot autogenerate id of type %s for entity of type %s!", property.getType().getName(),
value.getClass().getName()));
}
});
}
}
public DeleteResult remove(Query query, String collectionName) {
@@ -1377,7 +1377,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
Assert.hasText(collectionName, "Collection name must not be null or empty!");
final Document queryObject = query.getQueryObject();
final Optional<? extends MongoPersistentEntity<?>> entity = getPersistentEntity(entityClass);
final MongoPersistentEntity<?> entity = getPersistentEntity(entityClass);
return execute(collectionName, new CollectionCallback<DeleteResult>() {
@@ -1948,7 +1948,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
*/
protected <T> T doFindOne(String collectionName, Document query, Document fields, Class<T> entityClass) {
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
Document mappedQuery = queryMapper.getMappedObject(query, entity);
Document mappedFields = fields == null ? null : queryMapper.getMappedObject(fields, entity);
@@ -1998,7 +1998,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
protected <S, T> List<T> doFind(String collectionName, Document query, Document fields, Class<S> entityClass,
CursorPreparer preparer, DocumentCallback<T> objectCallback) {
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
Document mappedFields = queryMapper.getMappedFields(fields, entity);
Document mappedQuery = queryMapper.getMappedObject(query, entity);
@@ -2069,7 +2069,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
serializeToJsonSafely(query), fields, sort, entityClass, collectionName);
}
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
return executeFindOneInternal(
new FindAndRemoveCallback(queryMapper.getMappedObject(query, entity), fields, sort, collation),
@@ -2085,7 +2085,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
options = new FindAndModifyOptions();
}
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
increaseVersionForUpdateIfNecessary(entity, update);
@@ -2121,17 +2121,19 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
return;
}
getIdPropertyFor(savedObject.getClass()).ifPresent(idProp -> {
MongoPersistentProperty idProperty = getIdPropertyFor(savedObject.getClass());
if (idProperty != null) {
ConversionService conversionService = mongoConverter.getConversionService();
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(savedObject.getClass());
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(savedObject);
Optional<Object> value = accessor.getProperty(idProp);
if (!value.isPresent()) {
new ConvertingPropertyAccessor(accessor, conversionService).setProperty(idProp, Optional.of(id));
Object value = accessor.getProperty(idProperty);
if (value == null) {
new ConvertingPropertyAccessor(accessor, conversionService).setProperty(idProperty, id);
}
});
}
}
private MongoCollection<Document> getAndPrepareCollection(MongoDatabase db, String collectionName) {
@@ -2262,12 +2264,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
return exceptionTranslator;
}
private Optional<? extends MongoPersistentEntity<?>> getPersistentEntity(Class<?> type) {
return Optional.ofNullable(type).flatMap(mappingContext::getPersistentEntity);
private MongoPersistentEntity<?> getPersistentEntity(Class<?> type) {
return type != null ? mappingContext.getPersistentEntity(type) : null;
}
private Optional<MongoPersistentProperty> getIdPropertyFor(Class<?> type) {
return mappingContext.getPersistentEntity(type).flatMap(PersistentEntity::getIdProperty);
private MongoPersistentProperty getIdPropertyFor(Class<?> type) {
MongoPersistentEntity<?> persistentEntity = getPersistentEntity(type);
return persistentEntity != null ? persistentEntity.getIdProperty() : null;
}
private <T> String determineEntityCollectionName(T obj) {

View File

@@ -22,17 +22,8 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.function.Tuple2;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -59,11 +50,10 @@ import org.springframework.data.convert.EntityReader;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.Metric;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory;
import org.springframework.data.mongodb.core.convert.DbRefProxyHandler;
@@ -94,6 +84,7 @@ import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.util.MongoClientVersion;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.Pair;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -615,8 +606,8 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
*/
public <T> Mono<T> findById(Object id, Class<T> entityClass, String collectionName) {
Optional<? extends MongoPersistentEntity<?>> persistentEntity = mappingContext.getPersistentEntity(entityClass);
MongoPersistentProperty idProperty = persistentEntity.flatMap(PersistentEntity::getIdProperty).orElse(null);
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entityClass);
MongoPersistentProperty idProperty = persistentEntity != null ? persistentEntity.getIdProperty() : null;
String idKey = idProperty == null ? ID_FIELD : idProperty.getName();
@@ -764,7 +755,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
final Document Document = query == null ? null
: queryMapper.getMappedObject(query.getQueryObject(),
entityClass == null ? Optional.empty() : mappingContext.getPersistentEntity(entityClass));
entityClass == null ? null : mappingContext.getPersistentEntity(entityClass));
return collection.count(Document);
});
@@ -971,29 +962,28 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
ConvertingPropertyAccessor convertingAccessor = new ConvertingPropertyAccessor(
entity.getPropertyAccessor(objectToSave), mongoConverter.getConversionService());
MongoPersistentProperty idProperty = entity.getIdProperty()
.orElseThrow(() -> new IllegalArgumentException("No id property present!"));
MongoPersistentProperty versionProperty = entity.getVersionProperty()
.orElseThrow(() -> new IllegalArgumentException("No version property present!"));
;
MongoPersistentProperty idProperty = entity.getRequiredIdProperty();
MongoPersistentProperty versionProperty = entity.getRequiredVersionProperty();
Optional<Object> version = convertingAccessor.getProperty(versionProperty);
Optional<Number> versionNumber = convertingAccessor.getProperty(versionProperty, Number.class);
Object version = convertingAccessor.getProperty(versionProperty);
Number versionNumber = convertingAccessor.getProperty(versionProperty, Number.class);
// Fresh instance -> initialize version property
if (!version.isPresent()) {
if (version == null) {
return doInsert(collectionName, objectToSave, mongoConverter);
}
ReactiveMongoTemplate.this.assertUpdateableIdIfNotSet(objectToSave);
assertUpdateableIdIfNotSet(objectToSave);
// Create query for entity with the id and old version
Optional<Object> id = convertingAccessor.getProperty(idProperty);
Query query = new Query(
Criteria.where(idProperty.getName()).is(id.get()).and(versionProperty.getName()).is(version.get()));
Object id = convertingAccessor.getProperty(idProperty);
Query query = new Query(Criteria.where(idProperty.getName()).is(id).and(versionProperty.getName()).is(version));
if (versionNumber == null) {
versionNumber = 0;
}
// Bump version number
convertingAccessor.setProperty(versionProperty, Optional.of(versionNumber.orElse(0).longValue() + 1));
convertingAccessor.setProperty(versionProperty, versionNumber.longValue() + 1);
ReactiveMongoTemplate.this.maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
@@ -1241,7 +1231,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
private void increaseVersionForUpdateIfNecessary(MongoPersistentEntity<?> persistentEntity, Update update) {
if (persistentEntity != null && persistentEntity.hasVersionProperty()) {
String versionFieldName = persistentEntity.getVersionProperty().get().getFieldName();
String versionFieldName = persistentEntity.getRequiredVersionProperty().getFieldName();
if (!update.modifies(versionFieldName)) {
update.inc(versionFieldName, 1L);
}
@@ -1254,7 +1244,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
return false;
}
return document.containsKey(persistentEntity.getVersionProperty().get().getFieldName());
return document.containsKey(persistentEntity.getRequiredIdProperty().getFieldName());
}
/* (non-Javadoc)
@@ -1306,25 +1296,27 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
* @param object
* @return
*/
private Entry<String, Object> extractIdPropertyAndValue(Object object) {
private Pair<String, Object> extractIdPropertyAndValue(Object object) {
Assert.notNull(object, "Id cannot be extracted from 'null'.");
Assert.notNull(object, "Id cannot be extracted from 'null'.");
Class<?> objectType = object.getClass();
if (object instanceof Document) {
return Collections.singletonMap(ID_FIELD, ((Document) object).get(ID_FIELD)).entrySet().iterator().next();
return Pair.of(ID_FIELD, ((Document) object).get(ID_FIELD));
}
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(objectType);
MongoPersistentProperty idProp = entity.flatMap(PersistentEntity::getIdProperty).orElse(null);
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(objectType);
if (idProp == null) {
throw new MappingException("No id property found for object of type " + objectType);
if (entity != null && entity.hasIdProperty()) {
MongoPersistentProperty idProperty = entity.getIdProperty();
return Pair.of(idProperty.getFieldName(), entity.getPropertyAccessor(object).getProperty(idProperty));
}
Optional<Object> idValue = entity.get().getPropertyAccessor(object).getProperty(idProp);
return Collections.singletonMap(idProp.getFieldName(), idValue.get()).entrySet().iterator().next();
throw new MappingException("No id property found for object of type " + objectType);
}
/**
@@ -1335,8 +1327,8 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
*/
private Query getIdQueryFor(Object object) {
Entry<String, Object> id = extractIdPropertyAndValue(object);
return new Query(where(id.getKey()).is(id.getValue()));
Pair<String, Object> id = extractIdPropertyAndValue(object);
return new Query(where(id.getFirst()).is(id.getSecond()));
}
/**
@@ -1350,35 +1342,36 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
Assert.notEmpty(objects, "Cannot create Query for empty collection.");
Iterator<?> it = objects.iterator();
Entry<String, Object> firstEntry = extractIdPropertyAndValue(it.next());
Pair<String, Object> firstEntry = extractIdPropertyAndValue(it.next());
ArrayList<Object> ids = new ArrayList<Object>(objects.size());
ids.add(firstEntry.getValue());
ids.add(firstEntry.getSecond());
while (it.hasNext()) {
ids.add(extractIdPropertyAndValue(it.next()).getValue());
ids.add(extractIdPropertyAndValue(it.next()).getSecond());
}
return new Query(where(firstEntry.getKey()).in(ids));
return new Query(where(firstEntry.getFirst()).in(ids));
}
private void assertUpdateableIdIfNotSet(Object entity) {
private void assertUpdateableIdIfNotSet(Object value) {
Optional<? extends MongoPersistentEntity<?>> persistentEntity = mappingContext
.getPersistentEntity(entity.getClass());
Optional<MongoPersistentProperty> idProperty = persistentEntity.isPresent() ? persistentEntity.get().getIdProperty()
: Optional.empty();
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(value.getClass());
if (!idProperty.isPresent()) {
return;
}
if (entity != null && entity.hasIdProperty()) {
Optional<Object> idValue = persistentEntity.get().getPropertyAccessor(entity).getProperty(idProperty.get());
MongoPersistentProperty property = entity.getRequiredIdProperty();
Object propertyValue = entity.getPropertyAccessor(value).getProperty(property);
if (!idValue.isPresent() && !MongoSimpleTypes.AUTOGENERATED_ID_TYPES.contains(idProperty.get().getType())) {
throw new InvalidDataAccessApiUsageException(
String.format("Cannot autogenerate id of type %s for entity of type %s!",
idProperty.get().getType().getName(), entity.getClass().getName()));
if (propertyValue != null) {
return;
}
if (!MongoSimpleTypes.AUTOGENERATED_ID_TYPES.contains(property.getType())) {
throw new InvalidDataAccessApiUsageException(
String.format("Cannot autogenerate id of type %s for entity of type %s!", property.getType().getName(),
value.getClass().getName()));
}
}
}
@@ -1557,7 +1550,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
protected <T> Mono<T> doFindOne(String collectionName, Document query, Document fields, Class<T> entityClass,
Collation collation) {
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
Document mappedQuery = queryMapper.getMappedObject(query, entity);
Document mappedFields = fields == null ? null : queryMapper.getMappedObject(fields, entity);
@@ -1607,7 +1600,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
protected <S, T> Flux<T> doFind(String collectionName, Document query, Document fields, Class<S> entityClass,
FindPublisherPreparer preparer, DocumentCallback<T> objectCallback) {
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
Document mappedFields = queryMapper.getMappedFields(fields, entity);
Document mappedQuery = queryMapper.getMappedObject(query, entity);
@@ -1654,7 +1647,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
serializeToJsonSafely(query), fields, sort, entityClass, collectionName));
}
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
return executeFindOneInternal(
new FindAndRemoveCallback(queryMapper.getMappedObject(query, entity), fields, sort, collation),
@@ -1666,11 +1659,11 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
FindAndModifyOptions optionsToUse = options != null ? options : new FindAndModifyOptions();
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
return Mono.defer(() -> {
increaseVersionForUpdateIfNecessary(entity.get(), update);
increaseVersionForUpdateIfNecessary(entity, update);
Document mappedQuery = queryMapper.getMappedObject(query, entity);
Document mappedUpdate = updateMapper.getMappedObject(update.getUpdateObject(), entity);
@@ -1721,11 +1714,11 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(savedObject.getClass());
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(savedObject);
if (accessor.getProperty(idProp).isPresent()) {
if (accessor.getProperty(idProp) != null) {
return;
}
new ConvertingPropertyAccessor(accessor, conversionService).setProperty(idProp, Optional.ofNullable(id));
new ConvertingPropertyAccessor(accessor, conversionService).setProperty(idProp, id);
}
private MongoCollection<Document> getAndPrepareCollection(MongoDatabase db, String collectionName) {
@@ -1896,13 +1889,13 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
}
private MongoPersistentEntity<?> getPersistentEntity(Class<?> type) {
return type == null ? null : mappingContext.getPersistentEntity(type).orElse(null);
return type == null ? null : mappingContext.getPersistentEntity(type);
}
private MongoPersistentProperty getIdPropertyFor(Class<?> type) {
Optional<? extends MongoPersistentEntity<?>> persistentEntity = mappingContext.getPersistentEntity(type);
return persistentEntity.flatMap(PersistentEntity::getIdProperty).orElse(null);
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(type);
return persistentEntity != null ? persistentEntity.getIdProperty() : null;
}
private <T> String determineEntityCollectionName(T obj) {
@@ -1976,7 +1969,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
if (mongoPersistentEntity != null && mongoPersistentEntity.hasVersionProperty()) {
ConvertingPropertyAccessor accessor = new ConvertingPropertyAccessor(
mongoPersistentEntity.getPropertyAccessor(entity), mongoConverter.getConversionService());
accessor.setProperty(mongoPersistentEntity.getVersionProperty().get(), Optional.of(0));
accessor.setProperty(mongoPersistentEntity.getRequiredVersionProperty(), 0);
}
}
@@ -2349,9 +2342,9 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
static class NoOpDbRefResolver implements DbRefResolver {
@Override
public Optional<Object> resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
public Object resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
DbRefProxyHandler proxyHandler) {
return Optional.empty();
return null;
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2016 the original author or authors.
* Copyright 2013-2017 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.
@@ -15,10 +15,9 @@
*/
package org.springframework.data.mongodb.core.convert;
import org.bson.Document;
import java.util.List;
import java.util.Optional;
import org.bson.Document;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
@@ -27,7 +26,7 @@ import com.mongodb.DBRef;
/**
* Used to resolve associations annotated with {@link org.springframework.data.mongodb.core.mapping.DBRef}.
*
*
* @author Thomas Darimont
* @author Oliver Gierke
* @author Christoph Strobl
@@ -40,19 +39,19 @@ public interface DbRefResolver {
* Resolves the given {@link DBRef} into an object of the given {@link MongoPersistentProperty}'s type. The method
* might return a proxy object for the {@link DBRef} or resolve it immediately. In both cases the
* {@link DbRefResolverCallback} will be used to obtain the actual backing object.
*
*
* @param property will never be {@literal null}.
* @param dbref the {@link DBRef} to resolve.
* @param callback will never be {@literal null}.
* @return
*/
Optional<Object> resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
Object resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
DbRefProxyHandler proxyHandler);
/**
* Creates a {@link DBRef} instance for the given {@link org.springframework.data.mongodb.core.mapping.DBRef}
* annotation, {@link MongoPersistentEntity} and id.
*
*
* @param annotation will never be {@literal null}.
* @param entity will never be {@literal null}.
* @param id will never be {@literal null}.
@@ -63,7 +62,7 @@ public interface DbRefResolver {
/**
* Actually loads the {@link DBRef} from the datasource.
*
*
* @param dbRef must not be {@literal null}.
* @return
* @since 1.7

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2017 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.
@@ -29,6 +29,7 @@ import com.mongodb.DBRef;
/**
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
*/
class DefaultDbRefProxyHandler implements DbRefProxyHandler {
@@ -50,7 +51,7 @@ class DefaultDbRefProxyHandler implements DbRefProxyHandler {
this.resolver = resolver;
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.DbRefProxyHandler#populateId(com.mongodb.DBRef, java.lang.Object)
*/
@@ -62,8 +63,7 @@ class DefaultDbRefProxyHandler implements DbRefProxyHandler {
}
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(property);
MongoPersistentProperty idProperty = entity.getIdProperty()
.orElseThrow(() -> new IllegalStateException("Couldn't find identifier property!"));
MongoPersistentProperty idProperty = entity.getRequiredIdProperty();
if (idProperty.usePropertyAccess()) {
return proxy;

View File

@@ -26,7 +26,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
@@ -55,7 +54,7 @@ import com.mongodb.client.model.Filters;
/**
* A {@link DbRefResolver} that resolves {@link org.springframework.data.mongodb.core.mapping.DBRef}s by delegating to a
* {@link DbRefResolverCallback} than is able to generate lazy loading proxies.
*
*
* @author Thomas Darimont
* @author Oliver Gierke
* @author Christoph Strobl
@@ -70,7 +69,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
/**
* Creates a new {@link DefaultDbRefResolver} with the given {@link MongoDbFactory}.
*
*
* @param mongoDbFactory must not be {@literal null}.
*/
public DefaultDbRefResolver(MongoDbFactory mongoDbFactory) {
@@ -87,20 +86,20 @@ public class DefaultDbRefResolver implements DbRefResolver {
* @see org.springframework.data.mongodb.core.convert.DbRefResolver#resolveDbRef(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty, org.springframework.data.mongodb.core.convert.DbRefResolverCallback)
*/
@Override
public Optional<Object> resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
public Object resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
DbRefProxyHandler handler) {
Assert.notNull(property, "Property must not be null!");
Assert.notNull(callback, "Callback must not be null!");
if (isLazyDbRef(property)) {
return Optional.of(createLazyLoadingProxy(property, dbref, callback, handler));
return createLazyLoadingProxy(property, dbref, callback, handler);
}
return Optional.ofNullable(callback.resolve(property));
return callback.resolve(property);
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.DbRefResolver#created(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty, org.springframework.data.mongodb.core.mapping.MongoPersistentEntity, java.lang.Object)
*/
@@ -165,7 +164,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
/**
* Creates a proxy for the given {@link MongoPersistentProperty} using the given {@link DbRefResolverCallback} to
* eventually resolve the value of the property.
*
*
* @param property must not be {@literal null}.
* @param dbref can be {@literal null}.
* @param callback must not be {@literal null}.
@@ -200,7 +199,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
/**
* Returns the CGLib enhanced type for the given source type.
*
*
* @param type
* @return
*/
@@ -216,7 +215,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
/**
* Returns whether the property shall be resolved lazily.
*
*
* @param property must not be {@literal null}.
* @return
*/
@@ -228,7 +227,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
* A {@link MethodInterceptor} that is used within a lazy loading proxy. The property resolving is delegated to a
* {@link DbRefResolverCallback}. The resolving process is triggered by a method invocation on the proxy and is
* guaranteed to be performed only once.
*
*
* @author Thomas Darimont
* @author Oliver Gierke
* @author Christoph Strobl
@@ -259,7 +258,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
/**
* Creates a new {@link LazyLoadingInterceptor} for the given {@link MongoPersistentProperty},
* {@link PersistenceExceptionTranslator} and {@link DbRefResolverCallback}.
*
*
* @param property must not be {@literal null}.
* @param dbref can be {@literal null}.
* @param callback must not be {@literal null}.
@@ -286,7 +285,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
return intercept(invocation.getThis(), invocation.getMethod(), invocation.getArguments(), null);
}
/*
/*
* (non-Javadoc)
* @see org.springframework.cglib.proxy.MethodInterceptor#intercept(java.lang.Object, java.lang.reflect.Method, java.lang.Object[], org.springframework.cglib.proxy.MethodProxy)
*/
@@ -332,7 +331,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
/**
* Returns a to string representation for the given {@code proxy}.
*
*
* @param proxy
* @return
*/
@@ -353,7 +352,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
/**
* Returns the hashcode for the given {@code proxy}.
*
*
* @param proxy
* @return
*/
@@ -363,7 +362,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
/**
* Performs an equality check for the given {@code proxy}.
*
*
* @param proxy
* @param that
* @return
@@ -383,7 +382,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
/**
* Will trigger the resolution if the proxy is not resolved already or return a previously resolved result.
*
*
* @return
*/
private Object ensureResolved() {
@@ -398,7 +397,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
/**
* Callback method for serialization.
*
*
* @param out
* @throws IOException
*/
@@ -410,7 +409,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
/**
* Callback method for deserialization.
*
*
* @param in
* @throws IOException
*/
@@ -426,7 +425,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
/**
* Resolves the proxy into its backing object.
*
*
* @return
*/
private synchronized Object resolve() {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2017 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.
@@ -22,9 +22,10 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
/**
* Default implementation of {@link DbRefResolverCallback}.
*
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
*/
class DefaultDbRefResolverCallback implements DbRefResolverCallback {
@@ -36,7 +37,7 @@ class DefaultDbRefResolverCallback implements DbRefResolverCallback {
/**
* Creates a new {@link DefaultDbRefResolverCallback} using the given {@link Document}, {@link ObjectPath},
* {@link ValueResolver} and {@link SpELExpressionEvaluator}.
*
*
* @param surroundingObject must not be {@literal null}.
* @param path must not be {@literal null}.
* @param evaluator must not be {@literal null}.
@@ -51,12 +52,12 @@ class DefaultDbRefResolverCallback implements DbRefResolverCallback {
this.evaluator = evaluator;
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.DbRefResolverCallback#resolve(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty)
*/
@Override
public Object resolve(MongoPersistentProperty property) {
return resolver.getValueInternal(property, surroundingObject, evaluator, path).orElse(null);
return resolver.getValueInternal(property, surroundingObject, evaluator, path);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2016 the original author or authors.
* Copyright 2011-2017 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.
@@ -32,17 +32,17 @@ import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.ObjectUtils;
import com.mongodb.BasicDBList;
import com.mongodb.DBObject;
import org.springframework.util.ObjectUtils;
/**
* Default implementation of {@link MongoTypeMapper} allowing configuration of the key to lookup and store type
* information in {@link Document}. The key defaults to {@link #DEFAULT_TYPE_KEY}. Actual type-to-{@link String}
* conversion and back is done in {@link #getTypeString(TypeInformation)} or {@link #getTypeInformation(String)}
* respectively.
*
*
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
@@ -94,7 +94,7 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<Bson> implements M
return typeKey == null ? false : typeKey.equals(key);
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.MongoTypeMapper#writeTypeRestrictions(java.util.Set)
*/
@@ -111,26 +111,26 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<Bson> implements M
Alias typeAlias = getAliasFor(ClassTypeInformation.from(restrictedType));
if (typeAlias != null && !ObjectUtils.nullSafeEquals(Alias.NONE, typeAlias) && typeAlias.getValue().isPresent()) {
restrictedMappedTypes.add(typeAlias.getValue().get());
if (typeAlias != null && !ObjectUtils.nullSafeEquals(Alias.NONE, typeAlias) && typeAlias.isPresent()) {
restrictedMappedTypes.add(typeAlias.getValue());
}
}
accessor.writeTypeTo(result, new Document("$in", restrictedMappedTypes));
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.convert.DefaultTypeMapper#getFallbackTypeFor(java.lang.Object)
*/
@Override
protected Optional<TypeInformation<?>> getFallbackTypeFor(Bson source) {
return Optional.of(source instanceof BasicDBList ? LIST_TYPE_INFO : MAP_TYPE_INFO);
protected TypeInformation<?> getFallbackTypeFor(Bson source) {
return source instanceof BasicDBList ? LIST_TYPE_INFO : MAP_TYPE_INFO;
}
/**
* {@link TypeAliasAccessor} to store aliases in a {@link Document}.
*
*
* @author Oliver Gierke
*/
public static final class DocumentTypeAliasAccessor implements TypeAliasAccessor<Bson> {
@@ -152,9 +152,9 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<Bson> implements M
}
if (source instanceof Document) {
return Alias.ofOptional(Optional.ofNullable(((Document) source).get(typeKey)));
return Alias.ofNullable(((Document) source).get(typeKey));
} else if (source instanceof DBObject) {
return Alias.ofOptional(Optional.ofNullable(((DBObject) source).get(typeKey)));
return Alias.ofNullable(((DBObject) source).get(typeKey));
}
throw new IllegalArgumentException("Cannot read alias from " + source.getClass());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2016 the original author or authors.
* Copyright 2013-2017 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.
@@ -18,8 +18,6 @@ package org.springframework.data.mongodb.core.convert;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;
import org.bson.Document;
import org.bson.conversions.Bson;
@@ -34,9 +32,10 @@ import com.mongodb.DBObject;
* Wrapper value object for a {@link Document} to be able to access raw values by {@link MongoPersistentProperty}
* references. The accessors will transparently resolve nested document values that a {@link MongoPersistentProperty}
* might refer to through a path expression in field names.
*
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
*/
class DocumentAccessor {
@@ -44,7 +43,7 @@ class DocumentAccessor {
/**
* Creates a new {@link DocumentAccessor} for the given {@link Document}.
*
*
* @param document must be a {@link Document} effectively, must not be {@literal null}.
*/
public DocumentAccessor(Bson document) {
@@ -62,7 +61,7 @@ class DocumentAccessor {
* Puts the given value into the backing {@link Document} based on the coordinates defined through the given
* {@link MongoPersistentProperty}. By default this will be the plain field name. But field names might also consist
* of path traversals so we might need to create intermediate {@link BasicDocument}s.
*
*
* @param prop must not be {@literal null}.
* @param value
*/
@@ -91,20 +90,11 @@ class DocumentAccessor {
}
}
public void computeIfAbsent(MongoPersistentProperty prop, Supplier<Optional<Object>> supplier) {
if (hasValue(prop)) {
return;
}
supplier.get().ifPresent(it -> put(prop, it));
}
/**
* Returns the value the given {@link MongoPersistentProperty} refers to. By default this will be a direct field but
* the method will also transparently resolve nested values the {@link MongoPersistentProperty} might refer to through
* a path expression in the field name metadata.
*
*
* @param property must not be {@literal null}.
* @return
*/
@@ -161,7 +151,7 @@ class DocumentAccessor {
if (this.document instanceof Document) {
source = ((Document) this.document);
}else {
} else {
source = ((DBObject) this.document).toMap();
}
@@ -182,7 +172,7 @@ class DocumentAccessor {
/**
* Returns the given source object as map, i.e. {@link Document}s and maps as is or {@literal null} otherwise.
*
*
* @param source can be {@literal null}.
* @return
*/
@@ -207,7 +197,7 @@ class DocumentAccessor {
/**
* Returns the {@link Document} which either already exists in the given source under the given key, or creates a new
* nested one, registers it with the source and returns it.
*
*
* @param key must not be {@literal null} or empty.
* @param source must not be {@literal null}.
* @return

View File

@@ -15,8 +15,17 @@
*/
package org.springframework.data.mongodb.core.convert;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import org.bson.Document;
import org.bson.conversions.Bson;
@@ -30,14 +39,14 @@ import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.data.convert.EntityInstantiator;
import org.springframework.data.convert.TypeMapper;
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.PreferredConstructor.Parameter;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.model.ParameterValueProvider;
import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider;
import org.springframework.data.mapping.model.PropertyValueProvider;
@@ -52,7 +61,6 @@ import org.springframework.data.mongodb.core.mapping.event.AfterLoadEvent;
import org.springframework.data.mongodb.core.mapping.event.MongoMappingEvent;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
@@ -82,9 +90,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
protected static final Logger LOGGER = LoggerFactory.getLogger(MappingMongoConverter.class);
protected final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
protected final SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
protected final QueryMapper idMapper;
protected final DbRefResolver dbRefResolver;
protected final DefaultDbRefProxyHandler dbRefProxyHandler;
protected ApplicationContext applicationContext;
protected MongoTypeMapper typeMapper;
@@ -112,6 +120,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
this.idMapper = new QueryMapper(this);
this.spELContext = new SpELContext(DocumentPropertyAccessor.INSTANCE);
this.dbRefProxyHandler = new DefaultDbRefProxyHandler(spELContext, mappingContext, MappingMongoConverter.this);
}
/**
@@ -248,66 +257,89 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final Document bson, final ObjectPath path) {
final DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(bson, spELContext);
DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(bson, spELContext);
ParameterValueProvider<MongoPersistentProperty> provider = getParameterProvider(entity, bson, evaluator, path);
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
S instance = instantiator.createInstance(entity, provider);
final PersistentPropertyAccessor accessor = new ConvertingPropertyAccessor(entity.getPropertyAccessor(instance),
PersistentPropertyAccessor accessor = new ConvertingPropertyAccessor(entity.getPropertyAccessor(instance),
conversionService);
final Optional<MongoPersistentProperty> idProperty = entity.getIdProperty();
final S result = instance;
MongoPersistentProperty idProperty = entity.getIdProperty();
DocumentAccessor documentAccessor = new DocumentAccessor(bson);
// make sure id property is set before all other properties
Optional<Object> idValue = idProperty.filter(documentAccessor::hasValue).map(it -> {
Object idValue = null;
Optional<Object> value = getValueInternal(it, bson, evaluator, path);
accessor.setProperty(it, value);
if (idProperty != null && documentAccessor.hasValue(idProperty)) {
return value;
});
idValue = readIdValue(path, evaluator, idProperty, documentAccessor);
accessor.setProperty(idProperty, idValue);
}
final ObjectPath currentPath = path.push(result, entity,
idValue.isPresent() ? idProperty.map(it -> bson.get(it.getFieldName())).orElse(null) : null);
ObjectPath currentPath = path.push(instance, entity, idValue != null ? bson.get(idProperty.getFieldName()) : null);
// Set properties not already set in the constructor
entity.doWithProperties((PropertyHandler<MongoPersistentProperty>) prop -> {
MongoDbPropertyValueProvider valueProvider = new MongoDbPropertyValueProvider(documentAccessor, evaluator,
currentPath);
DbRefResolverCallback callback = new DefaultDbRefResolverCallback(bson, currentPath, evaluator,
MappingMongoConverter.this);
readProperties(entity, accessor, idProperty, documentAccessor, valueProvider, callback);
return instance;
}
private Object readIdValue(ObjectPath path, DefaultSpELExpressionEvaluator evaluator,
MongoPersistentProperty idProperty, DocumentAccessor documentAccessor) {
String expression = idProperty.getSpelExpression();
Object resolvedValue = expression != null ? evaluator.evaluate(expression) : documentAccessor.get(idProperty);
return resolvedValue != null ? readValue(resolvedValue, idProperty.getTypeInformation(), path) : null;
}
private void readProperties(MongoPersistentEntity<?> entity, PersistentPropertyAccessor accessor,
MongoPersistentProperty idProperty, DocumentAccessor documentAccessor,
MongoDbPropertyValueProvider valueProvider, DbRefResolverCallback callback) {
for (MongoPersistentProperty prop : entity) {
if(prop.isAssociation() && !entity.isConstructorArgument(prop)) {
readAssociation(prop.getAssociation(), accessor, documentAccessor, dbRefProxyHandler, callback );
continue;
}
// we skip the id property since it was already set
if (idProperty != null && idProperty.equals(prop)) {
return;
continue;
}
if (entity.isConstructorArgument(prop) || !documentAccessor.hasValue(prop)) {
return;
continue;
}
accessor.setProperty(prop, getValueInternal(prop, bson, evaluator, currentPath));
});
if(prop.isAssociation()) {
readAssociation(prop.getAssociation(), accessor, documentAccessor, dbRefProxyHandler, callback );
continue;
}
// Handle associations
entity.doWithAssociations((AssociationHandler<MongoPersistentProperty>) association -> {
accessor.setProperty(prop, valueProvider.getPropertyValue(prop));
}
}
final MongoPersistentProperty property = association.getInverse();
private void readAssociation(Association<MongoPersistentProperty> association, PersistentPropertyAccessor accessor,
DocumentAccessor documentAccessor, DbRefProxyHandler handler, DbRefResolverCallback callback) {
MongoPersistentProperty property = association.getInverse();
Object value = documentAccessor.get(property);
if (value == null || entity.isConstructorArgument(property)) {
if (value == null) {
return;
}
DBRef dbref = value instanceof DBRef ? (DBRef) value : null;
DbRefProxyHandler handler = new DefaultDbRefProxyHandler(spELContext, mappingContext, MappingMongoConverter.this);
DbRefResolverCallback callback = new DefaultDbRefResolverCallback(bson, currentPath, evaluator,
MappingMongoConverter.this);
accessor.setProperty(property, dbRefResolver.resolveDbRef(property, dbref, callback, handler));
});
return result;
}
/*
@@ -348,8 +380,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
Object target = obj instanceof LazyLoadingProxy ? ((LazyLoadingProxy) obj).getTarget() : obj;
writeInternal(target, bson, Optional.of(type));
if (asMap(bson).containsKey("_is") && asMap(bson).get("_id") == null) {
writeInternal(target, bson, type);
if (asMap(bson).containsKey("_id") && asMap(bson).get("_id") == null) {
removeFromMap(bson, "_id");
}
@@ -366,7 +398,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* @param bson
*/
@SuppressWarnings("unchecked")
protected void writeInternal(final Object obj, final Bson bson, final Optional<TypeInformation<?>> typeHint) {
protected void writeInternal(final Object obj, final Bson bson, final TypeInformation<?> typeHint) {
if (null == obj) {
return;
@@ -387,7 +419,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
if (Collection.class.isAssignableFrom(entityType)) {
writeCollectionInternal((Collection<?>) obj, Optional.of(ClassTypeInformation.LIST), (BasicDBList) bson);
writeCollectionInternal((Collection<?>) obj, ClassTypeInformation.LIST, (BasicDBList) bson);
return;
}
@@ -406,46 +438,65 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
throw new MappingException("No mapping metadata found for entity of type " + obj.getClass().getName());
}
final PersistentPropertyAccessor accessor = entity.getPropertyAccessor(obj);
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(obj);
DocumentAccessor dbObjectAccessor = new DocumentAccessor(bson);
Optional<MongoPersistentProperty> idProperty = entity.getIdProperty();
idProperty.ifPresent(
prop -> dbObjectAccessor.computeIfAbsent(prop, () -> idMapper.convertId(accessor.getProperty(prop))));
MongoPersistentProperty idProperty = entity.getIdProperty();
if (idProperty != null && !dbObjectAccessor.hasValue(idProperty)) {
Object value = idMapper.convertId(accessor.getProperty(idProperty));
if (value != null) {
dbObjectAccessor.put(idProperty, value);
}
}
writeProperties(bson, entity, accessor, dbObjectAccessor, idProperty);
}
private void writeProperties(Bson bson, MongoPersistentEntity<?> entity, PersistentPropertyAccessor accessor,
DocumentAccessor dbObjectAccessor, MongoPersistentProperty idProperty) {
// Write the properties
entity.doWithProperties((PropertyHandler<MongoPersistentProperty>) prop -> {
for (MongoPersistentProperty prop : entity) {
if (idProperty.map(it -> it.equals(prop)).orElse(false) || !prop.isWritable()) {
return;
if (prop.equals(idProperty) || !prop.isWritable()) {
continue;
}
if(prop.isAssociation()) {
writeAssociation(prop.getAssociation(), accessor, dbObjectAccessor);
continue;
}
accessor.getProperty(prop).ifPresent(it -> {
if (!conversions.isSimpleType(it.getClass())) {
Object value = accessor.getProperty(prop);
writePropertyInternal(it, bson, prop);
} else {
writeSimpleInternal(it, bson, prop);
}
});
});
if (value == null) {
continue;
}
entity.doWithAssociations((AssociationHandler<MongoPersistentProperty>) association -> {
if (!conversions.isSimpleType(value.getClass())) {
writePropertyInternal(value, dbObjectAccessor, prop);
} else {
writeSimpleInternal(value, bson, prop);
}
}
}
private void writeAssociation(Association<MongoPersistentProperty> association, PersistentPropertyAccessor accessor,
DocumentAccessor dbObjectAccessor) {
MongoPersistentProperty inverseProp = association.getInverse();
accessor.getProperty(inverseProp).ifPresent(it -> writePropertyInternal(it, bson, inverseProp));
});
writePropertyInternal(accessor.getProperty(inverseProp), dbObjectAccessor, inverseProp);
}
@SuppressWarnings({ "unchecked" })
protected void writePropertyInternal(Object obj, Bson bson, MongoPersistentProperty prop) {
protected void writePropertyInternal(Object obj, DocumentAccessor accessor, MongoPersistentProperty prop) {
if (obj == null) {
return;
}
DocumentAccessor accessor = new DocumentAccessor(bson);
TypeInformation<?> valueType = ClassTypeInformation.from(obj.getClass());
TypeInformation<?> type = prop.getTypeInformation();
@@ -497,14 +548,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return;
}
Object existingValue = accessor.get(prop);
Document document = existingValue instanceof Document ? (Document) existingValue : new Document();
MongoPersistentEntity<?> entity = isSubtype(prop.getType(), obj.getClass())
? mappingContext.getRequiredPersistentEntity(obj.getClass()) : mappingContext.getRequiredPersistentEntity(type);
Object existingValue = accessor.get(prop);
Document document = existingValue instanceof Document ? (Document) existingValue : new Document();
writeInternal(obj, document, entity);
addCustomTypeKeyIfNecessary(Optional.of(ClassTypeInformation.from(prop.getRawType())), obj, document);
addCustomTypeKeyIfNecessary(ClassTypeInformation.from(prop.getRawType()), obj, document);
accessor.put(prop, document);
}
@@ -539,7 +590,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
protected List<Object> createCollection(Collection<?> collection, MongoPersistentProperty property) {
if (!property.isDbReference()) {
return writeCollectionInternal(collection, Optional.of(property.getTypeInformation()), new BasicDBList());
return writeCollectionInternal(collection, property.getTypeInformation(), new BasicDBList());
}
List<Object> dbList = new ArrayList<>(collection.size());
@@ -601,10 +652,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* @param sink the {@link BasicDBList} to write to.
* @return
*/
private BasicDBList writeCollectionInternal(Collection<?> source, Optional<TypeInformation<?>> type,
BasicDBList sink) {
private BasicDBList writeCollectionInternal(Collection<?> source, TypeInformation<?> type, BasicDBList sink) {
Optional<TypeInformation<?>> componentType = type.flatMap(TypeInformation::getComponentType);
TypeInformation<?> componentType = null;
if (type != null) {
componentType = type.getComponentType();
}
for (Object element : source) {
@@ -649,8 +703,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
writeCollectionInternal(asCollection(val), propertyType.getMapValueType(), new BasicDBList()));
} else {
Document document = new Document();
Optional<TypeInformation<?>> valueTypeInfo = propertyType.isMap() ? propertyType.getMapValueType()
: Optional.of(ClassTypeInformation.OBJECT);
TypeInformation<?> valueTypeInfo = propertyType.isMap() ? propertyType.getMapValueType()
: ClassTypeInformation.OBJECT;
writeInternal(val, document, valueTypeInfo);
addToMap(bson, simpleKey, document);
}
@@ -736,10 +790,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* @param value must not be {@literal null}.
* @param bson must not be {@literal null}.
*/
protected void addCustomTypeKeyIfNecessary(Optional<TypeInformation<?>> type, Object value, Bson bson) {
protected void addCustomTypeKeyIfNecessary(TypeInformation<?> type, Object value, Bson bson) {
Optional<Class<?>> actualType = type.map(TypeInformation::getActualType).map(TypeInformation::getType);
Class<?> reference = actualType.orElse(Object.class);
Class<?> reference = type != null ? type.getActualType().getType() : Object.class;
Class<?> valueType = ClassUtils.getUserClass(value.getClass());
boolean notTheSameClass = !valueType.equals(reference);
@@ -779,18 +832,19 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
Optional<Class<?>> customTarget = conversions.getCustomWriteTarget(value.getClass());
return customTarget.map(it -> (Object) conversionService.convert(value, it)).orElseGet(() -> {
if (customTarget.isPresent()) {
return conversionService.convert(value, customTarget.get());
}
if (ObjectUtils.isArray(value)) {
if (ObjectUtils.isArray(value)) {
if (value instanceof byte[]) {
return value;
}
return asCollection(value);
if (value instanceof byte[]) {
return value;
}
return asCollection(value);
}
return Enum.class.isAssignableFrom(value.getClass()) ? ((Enum<?>) value).name() : value;
});
return Enum.class.isAssignableFrom(value.getClass()) ? ((Enum<?>) value).name() : value;
}
/**
@@ -827,30 +881,30 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return (DBRef) target;
}
Optional<? extends MongoPersistentEntity<?>> targetEntity = mappingContext.getPersistentEntity(target.getClass());
targetEntity = targetEntity.isPresent() ? targetEntity : mappingContext.getPersistentEntity(property);
MongoPersistentEntity<?> targetEntity = mappingContext.getPersistentEntity(target.getClass());
targetEntity = targetEntity != null ? targetEntity : mappingContext.getPersistentEntity(property);
if (null == targetEntity) {
throw new MappingException("No mapping metadata found for " + target.getClass());
}
MongoPersistentEntity<?> entity = targetEntity
.orElseThrow(() -> new MappingException("No mapping metadata found for " + target.getClass()));
MongoPersistentEntity<?> entity = targetEntity;
Optional<MongoPersistentProperty> idProperty = entity.getIdProperty();
MongoPersistentProperty idProperty = entity.getIdProperty();
return idProperty.map(it -> {
if (idProperty != null) {
Object id = target.getClass().equals(it.getType()) ? target : entity.getPropertyAccessor(target).getProperty(it);
Object id = target.getClass().equals(idProperty.getType()) ? target
: entity.getPropertyAccessor(target).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(), entity,
idMapper.convertId(id instanceof Optional ? (Optional) id : Optional.ofNullable(id)).orElse(null));
return dbRefResolver.createDbRef(property == null ? null : property.getDBRef(), entity, idMapper.convertId(id));
}
}).orElseThrow(() -> new MappingException("No id property found on class " + entity.getType()));
throw new MappingException("No id property found on class " + entity.getType());
}
/*
@@ -858,7 +912,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* @see org.springframework.data.mongodb.core.convert.ValueResolver#getValueInternal(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty, com.mongodb.Document, org.springframework.data.mapping.model.SpELExpressionEvaluator, java.lang.Object)
*/
@Override
public Optional<Object> getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator,
public Object getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator,
ObjectPath path) {
return new MongoDbPropertyValueProvider(bson, evaluator, path).getPropertyValue(prop);
}
@@ -879,7 +933,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
Class<?> collectionType = targetType.getType();
TypeInformation<?> componentType = targetType.getComponentType().orElse(ClassTypeInformation.OBJECT);
TypeInformation<?> componentType = targetType.getComponentType() != null ? targetType.getComponentType()
: ClassTypeInformation.OBJECT;
Class<?> rawComponentType = componentType.getType();
collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
@@ -941,15 +996,17 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
Class<?> mapType = typeMapper.readType(bson, type).getType();
Optional<TypeInformation<?>> valueType = type.getMapValueType();
Class<?> rawKeyType = type.getComponentType().map(TypeInformation::getType).orElse(null);
Class<?> rawValueType = type.getMapValueType().map(TypeInformation::getType).orElse(null);
TypeInformation<?> keyType = type.getComponentType();
TypeInformation<?> valueType = type.getMapValueType();
Class<?> rawKeyType = keyType != null ? keyType.getType() : null;
Class<?> rawValueType = valueType != null ? valueType.getType() : null;
Map<String, Object> sourceMap = asMap(bson);
Map<Object, Object> map = CollectionFactory.createMap(mapType, rawKeyType, sourceMap.keySet().size());
if (!DBRef.class.equals(rawValueType) && isCollectionOfDbRefWhereBulkFetchIsPossible(sourceMap.values())) {
bulkReadAndConvertDBRefMapIntoTarget(valueType.orElse(null), rawValueType, sourceMap, map);
bulkReadAndConvertDBRefMapIntoTarget(valueType, rawValueType, sourceMap, map);
return map;
}
@@ -961,12 +1018,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
Object key = potentiallyUnescapeMapKey(entry.getKey());
if (rawKeyType != null) {
if (rawKeyType != null && !rawKeyType.isAssignableFrom(key.getClass())) {
key = conversionService.convert(key, rawKeyType);
}
Object value = entry.getValue();
TypeInformation<?> defaultedValueType = valueType.orElse(ClassTypeInformation.OBJECT);
TypeInformation<?> defaultedValueType = valueType != null ? valueType : ClassTypeInformation.OBJECT;
if (value instanceof Document) {
map.put(key, read(defaultedValueType, (Document) value, path));
@@ -976,7 +1033,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
map.put(key, DBRef.class.equals(rawValueType) ? value
: readAndConvertDBRef((DBRef) value, defaultedValueType, ObjectPath.ROOT, rawValueType));
} else if (value instanceof List) {
map.put(key, readCollectionOrArray(valueType.orElse(ClassTypeInformation.LIST), (List) value, path));
map.put(key,
readCollectionOrArray(valueType != null ? valueType : ClassTypeInformation.LIST, (List) value, path));
} else {
map.put(key, getPotentiallyConvertedSimpleRead(value, rawValueType));
}
@@ -1098,7 +1156,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
if (obj instanceof Map) {
Map<Object, Object> converted = new LinkedHashMap<>(((Map) obj).size(), 1);
Document result = new Document();
for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) obj).entrySet()) {
@@ -1199,7 +1256,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
*
* @author Oliver Gierke
*/
private class MongoDbPropertyValueProvider implements PropertyValueProvider<MongoPersistentProperty> {
class MongoDbPropertyValueProvider implements PropertyValueProvider<MongoPersistentProperty> {
private final DocumentAccessor source;
private final SpELExpressionEvaluator evaluator;
@@ -1224,17 +1281,39 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
this.path = path;
}
/**
* Creates a new {@link MongoDbPropertyValueProvider} for the given source, {@link SpELExpressionEvaluator} and
* {@link ObjectPath}.
*
* @param accessor must not be {@literal null}.
* @param evaluator must not be {@literal null}.
* @param path can be {@literal null}.
*/
public MongoDbPropertyValueProvider(DocumentAccessor accessor, SpELExpressionEvaluator evaluator, ObjectPath path) {
Assert.notNull(accessor, "DocumentAccessor must no be null!");
Assert.notNull(evaluator, "SpELExpressionEvaluator must not be null!");
Assert.notNull(path, "ObjectPath must not be null!");
this.source = accessor;
this.evaluator = evaluator;
this.path = path;
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.PropertyValueProvider#getPropertyValue(org.springframework.data.mapping.PersistentProperty)
*/
public <T> Optional<T> getPropertyValue(MongoPersistentProperty property) {
return Optional
public <T> T getPropertyValue(MongoPersistentProperty property) {
.ofNullable(property.getSpelExpression()//
.map(evaluator::evaluate)//
.orElseGet(() -> source.get(property)))//
.map(it -> readValue(it, property.getTypeInformation(), path));
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);
}
}
@@ -1275,7 +1354,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
@SuppressWarnings("unchecked")
private <T> T readValue(Object value, TypeInformation<?> type, ObjectPath path) {
<T> T readValue(Object value, TypeInformation<?> type, ObjectPath path) {
Class<?> rawType = type.getType();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015-2016 the original author or authors.
* Copyright 2015-2017 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.
@@ -15,17 +15,8 @@
*/
package org.springframework.data.mongodb.core.convert;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.Stack;
import java.util.regex.Pattern;
import org.bson.Document;
@@ -41,7 +32,6 @@ import org.springframework.data.mongodb.core.query.MongoRegexCreator;
import org.springframework.data.mongodb.core.query.SerializationUtils;
import org.springframework.data.repository.core.support.ExampleMatcherAccessor;
import org.springframework.data.repository.query.parser.Part.Type;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@@ -99,8 +89,12 @@ public class MongoExampleMapper {
Document reference = (Document) converter.convertToMongoType(example.getProbe());
if(entity.getIdProperty().isPresent() && !entity.getIdentifierAccessor(example.getProbe()).getIdentifier().isPresent()) {
reference.remove(entity.getIdProperty().get().getFieldName());
if (entity.getIdProperty() != null) {
Object identifier = entity.getIdentifierAccessor(example.getProbe()).getIdentifier();
if (identifier == null) {
reference.remove(entity.getIdProperty().getFieldName());
}
}
ExampleMatcherAccessor matcherAccessor = new ExampleMatcherAccessor(example.getMatcher());
@@ -153,7 +147,7 @@ public class MongoExampleMapper {
while (parts.hasNext()) {
String part = parts.next();
MongoPersistentProperty prop = entity.getPersistentProperty(part).orElse(null);
MongoPersistentProperty prop = entity.getPersistentProperty(part);
if (prop == null) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2017 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.
@@ -16,9 +16,7 @@
package org.springframework.data.mongodb.core.convert;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.util.Assert;
@@ -31,34 +29,36 @@ import org.springframework.util.StringUtils;
* <p>
* An immutable ordered set of target objects for {@link Document} 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
* @author Mark Paluch
* @since 1.6
*/
class ObjectPath {
public static final ObjectPath ROOT = new ObjectPath();
private final List<ObjectPathItem> items;
private final ObjectPathItem[] items;
private ObjectPath() {
this.items = Collections.emptyList();
this.items = new ObjectPathItem[0];
}
/**
* 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);
ObjectPathItem[] items = new ObjectPathItem[parent.items.length + 1];
System.arraycopy(parent.items, 0, items, 0, parent.items.length);
items[parent.items.length] = item;
this.items = Collections.unmodifiableList(items);
this.items = items;
}
/**
@@ -81,7 +81,7 @@ class ObjectPath {
/**
* 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
@@ -113,25 +113,25 @@ class ObjectPath {
/**
* Returns the current object of the {@link ObjectPath} or {@literal null} if the path is empty.
*
*
* @return
*/
public Optional<Object> getCurrentObject() {
return items.isEmpty() ? Optional.empty() : Optional.of(items.get(items.size() - 1).getObject());
public Object getCurrentObject() {
return items.length == 0 ? null : items[items.length - 1].getObject();
}
/*
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
if (items.isEmpty()) {
if (items.length == 0) {
return "[empty]";
}
List<String> strings = new ArrayList<String>(items.size());
List<String> strings = new ArrayList<String>(items.length);
for (ObjectPathItem item : items) {
strings.add(item.object.toString());
@@ -142,7 +142,7 @@ class ObjectPath {
/**
* An item in an {@link ObjectPath}.
*
*
* @author Thomas Darimont
* @author Oliver Gierke
*/
@@ -154,7 +154,7 @@ class ObjectPath {
/**
* Creates a new {@link ObjectPathItem}.
*
*
* @param object
* @param idValue
* @param collection

View File

@@ -39,7 +39,7 @@ import org.springframework.data.mapping.PropertyReferenceException;
import org.springframework.data.mapping.context.InvalidPersistentPropertyPath;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.context.PersistentPropertyPath;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter.NestedDocument;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
@@ -122,7 +122,7 @@ public class QueryMapper {
if (Query.isRestrictedTypeKey(key)) {
@SuppressWarnings("unchecked")
Set<Class<?>> restrictedTypes = (Set<Class<?>>) BsonUtils.get(query, key);
Set<Class<?>> restrictedTypes = BsonUtils.get(query, key);
this.converter.getTypeMapper().writeTypeRestrictions(result, restrictedTypes);
continue;
@@ -318,11 +318,11 @@ public class QueryMapper {
String inKey = valueDbo.containsField("$in") ? "$in" : "$nin";
List<Object> ids = new ArrayList<Object>();
for (Object id : (Iterable<?>) valueDbo.get(inKey)) {
ids.add(convertId(id).get());
ids.add(convertId(id));
}
resultDbo.put(inKey, ids);
} else if (valueDbo.containsField("$ne")) {
resultDbo.put("$ne", convertId(valueDbo.get("$ne")).get());
resultDbo.put("$ne", convertId(valueDbo.get("$ne")));
} else {
return getMappedObject(resultDbo, Optional.empty());
}
@@ -337,18 +337,18 @@ public class QueryMapper {
String inKey = valueDbo.containsKey("$in") ? "$in" : "$nin";
List<Object> ids = new ArrayList<Object>();
for (Object id : (Iterable<?>) valueDbo.get(inKey)) {
ids.add(convertId(id).orElse(null));
ids.add(convertId(id));
}
resultDbo.put(inKey, ids);
} else if (valueDbo.containsKey("$ne")) {
resultDbo.put("$ne", convertId(valueDbo.get("$ne")).orElse(null));
resultDbo.put("$ne", convertId(valueDbo.get("$ne")));
} else {
return getMappedObject(resultDbo, Optional.empty());
}
return resultDbo;
} else {
return convertId(value).orElse(null);
return convertId(value);
}
}
@@ -394,7 +394,7 @@ public class QueryMapper {
MongoPersistentEntity<?> entity = documentField.getPropertyEntity();
return entity.hasIdProperty() && (type.equals(DBRef.class)
|| entity.getIdProperty().map(it -> it.getActualType().isAssignableFrom(type)).orElse(false));
|| entity.getRequiredIdProperty().getActualType().isAssignableFrom(type));
}
/**
@@ -461,7 +461,7 @@ public class QueryMapper {
if (source instanceof DBRef) {
DBRef ref = (DBRef) source;
return new DBRef(ref.getCollectionName(), convertId(ref.getId()).get());
return new DBRef(ref.getCollectionName(), convertId(ref.getId()));
}
if (source instanceof Iterable) {
@@ -537,31 +537,28 @@ public class QueryMapper {
return converter.toDBRef(source, property);
}
private Optional<Object> convertId(Object id) {
return convertId(Optional.ofNullable(id));
}
/**
* Converts the given raw id value into either {@link ObjectId} or {@link String}.
*
* @param id
* @return
*/
public Optional<Object> convertId(Optional<Object> id) {
public Object convertId(Object id) {
return id.map(it -> {
if (id == null) {
return null;
}
if (it instanceof String) {
return ObjectId.isValid(it.toString()) ? conversionService.convert(it, ObjectId.class) : it;
}
if (id instanceof String) {
return ObjectId.isValid(id.toString()) ? conversionService.convert(id, ObjectId.class) : id;
}
try {
return conversionService.canConvert(it.getClass(), ObjectId.class)
? conversionService.convert(it, ObjectId.class) : delegateConvertToMongoType(it, null);
} catch (ConversionException o_O) {
return delegateConvertToMongoType(it, null);
}
});
try {
return conversionService.canConvert(id.getClass(), ObjectId.class) ? conversionService.convert(id, ObjectId.class)
: delegateConvertToMongoType(id, null);
} catch (ConversionException o_O) {
return delegateConvertToMongoType(id, null);
}
}
/**
@@ -836,9 +833,13 @@ public class QueryMapper {
@Override
public boolean isIdField() {
return entity.getIdProperty()//
.map(it -> it.getName().equals(name) || it.getFieldName().equals(name))//
.orElseGet(() -> DEFAULT_ID_NAMES.contains(name));
MongoPersistentProperty idProperty = entity.getIdProperty();
if (idProperty != null) {
return idProperty.getName().equals(name) || idProperty.getFieldName().equals(name);
}
return DEFAULT_ID_NAMES.contains(name);
}
/*
@@ -857,7 +858,7 @@ public class QueryMapper {
@Override
public MongoPersistentEntity<?> getPropertyEntity() {
MongoPersistentProperty property = getProperty();
return property == null ? null : mappingContext.getPersistentEntity(property).orElse(null);
return property == null ? null : mappingContext.getPersistentEntity(property);
}
/*
@@ -883,15 +884,15 @@ public class QueryMapper {
*
* @return
*/
private final Association<MongoPersistentProperty> findAssociation() {
private Association<MongoPersistentProperty> findAssociation() {
if (this.path != null) {
for (MongoPersistentProperty p : this.path) {
Optional<Association<MongoPersistentProperty>> association = p.getAssociation();
Association<MongoPersistentProperty> association = p.getAssociation();
if (association.isPresent()) {
return association.get();
if (association != null) {
return association;
}
}
}

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.data.mongodb.core.convert;
import java.util.Optional;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
@@ -24,7 +22,7 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
/**
* Internal API to trigger the resolution of properties.
*
*
* @author Oliver Gierke
* @author Christoph Strobl
*/
@@ -33,13 +31,13 @@ interface ValueResolver {
/**
* Resolves the value for the given {@link MongoPersistentProperty} within the given {@link Document} using the given
* {@link SpELExpressionEvaluator} and {@link ObjectPath}.
*
*
* @param prop
* @param bson
* @param evaluator
* @param parent
* @return
*/
Optional<Object> getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator,
Object getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator,
ObjectPath path);
}

View File

@@ -131,7 +131,7 @@ public class MongoPersistentEntityIndexCreator implements ApplicationListener<Ma
private void checkForAndCreateIndexes(MongoPersistentEntity<?> entity) {
if (entity.findAnnotation(Document.class).isPresent()) {
if (entity.isAnnotationPresent(Document.class)) {
for (IndexDefinitionHolder indexToCreate : indexResolver.resolveIndexFor(entity.getTypeInformation())) {
createIndex(indexToCreate);
}

View File

@@ -23,7 +23,6 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
@@ -33,7 +32,7 @@ import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.TextIndexIncludeOptions.IncludeStrategy;
import org.springframework.data.mongodb.core.index.TextIndexDefinition.TextIndexDefinitionBuilder;
import org.springframework.data.mongodb.core.index.TextIndexDefinition.TextIndexedFieldSpec;
@@ -94,7 +93,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
public List<IndexDefinitionHolder> resolveIndexForEntity(final MongoPersistentEntity<?> root) {
Assert.notNull(root, "Index cannot be resolved for given 'null' entity.");
Document document = root.findAnnotation(Document.class).orElseThrow(() -> new IllegalArgumentException("Given entity is not collection root."));
Document document = root.findAnnotation(Document.class);
Assert.notNull(document, "Given entity is not collection root.");
final List<IndexDefinitionHolder> indexInformation = new ArrayList<MongoPersistentEntityIndexResolver.IndexDefinitionHolder>();
@@ -255,20 +254,20 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
indexDefinitionBuilder.withLanguageOverride(persistentProperty.getFieldName());
}
Optional<TextIndexed> indexed = persistentProperty.findAnnotation(TextIndexed.class);
TextIndexed indexed = persistentProperty.findAnnotation(TextIndexed.class);
if (includeOptions.isForce() || indexed.isPresent()|| persistentProperty.isEntity()) {
if (includeOptions.isForce() || indexed != null || persistentProperty.isEntity()) {
String propertyDotPath = (StringUtils.hasText(dotPath) ? dotPath + "." : "")
+ persistentProperty.getFieldName();
Float weight = indexed.isPresent() ? indexed.get().weight()
Float weight = indexed != null ? indexed.weight()
: (includeOptions.getParentFieldSpec() != null ? includeOptions.getParentFieldSpec().getWeight() : 1.0F);
if (persistentProperty.isEntity()) {
TextIndexIncludeOptions optionsForNestedType = includeOptions;
if (!IncludeStrategy.FORCE.equals(includeOptions.getStrategy()) && indexed.isPresent()) {
if (!IncludeStrategy.FORCE.equals(includeOptions.getStrategy()) && indexed != null) {
optionsForNestedType = new TextIndexIncludeOptions(IncludeStrategy.FORCE,
new TextIndexedFieldSpec(propertyDotPath, weight));
}
@@ -282,7 +281,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
LOGGER.info(String.format("Potentially invalid index structure discovered. Breaking operation for %s.",
entity.getName()), e);
}
} else if (includeOptions.isForce() || indexed.isPresent()) {
} else if (includeOptions.isForce() || indexed != null) {
indexDefinitionBuilder.onField(propertyDotPath, weight);
}
}
@@ -304,18 +303,18 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
MongoPersistentEntity<?> entity) {
List<IndexDefinitionHolder> indexDefinitions = new ArrayList<MongoPersistentEntityIndexResolver.IndexDefinitionHolder>();
Optional<CompoundIndexes> indexes = entity.findAnnotation(CompoundIndexes.class);
CompoundIndexes indexes = entity.findAnnotation(CompoundIndexes.class);
if (indexes.isPresent()) {
for (CompoundIndex index : indexes.get().value()) {
if (indexes != null) {
for (CompoundIndex index : indexes.value()) {
indexDefinitions.add(createCompoundIndexDefinition(dotPath, fallbackCollection, index, entity));
}
}
Optional<CompoundIndex> index = entity.findAnnotation(CompoundIndex.class);
CompoundIndex index = entity.findAnnotation(CompoundIndex.class);
if (index.isPresent()) {
indexDefinitions.add(createCompoundIndexDefinition(dotPath, fallbackCollection, index.get(), entity));
if (index != null) {
indexDefinitions.add(createCompoundIndexDefinition(dotPath, fallbackCollection, index, entity));
}
return indexDefinitions;
@@ -382,33 +381,33 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
protected IndexDefinitionHolder createIndexDefinition(String dotPath, String collection,
MongoPersistentProperty persitentProperty) {
Optional<Indexed> index = persitentProperty.findAnnotation(Indexed.class);
Indexed index = persitentProperty.findAnnotation(Indexed.class);
if(!index.isPresent()){
if (index == null) {
return null;
}
Index indexDefinition = new Index().on(dotPath,
IndexDirection.ASCENDING.equals(index.get().direction()) ? Sort.Direction.ASC : Sort.Direction.DESC);
IndexDirection.ASCENDING.equals(index.direction()) ? Sort.Direction.ASC : Sort.Direction.DESC);
if (!index.get().useGeneratedName()) {
indexDefinition.named(pathAwareIndexName(index.get().name(), dotPath, persitentProperty));
if (!index.useGeneratedName()) {
indexDefinition.named(pathAwareIndexName(index.name(), dotPath, persitentProperty));
}
if (index.get().unique()) {
if (index.unique()) {
indexDefinition.unique();
}
if (index.get().sparse()) {
if (index.sparse()) {
indexDefinition.sparse();
}
if (index.get().background()) {
if (index.background()) {
indexDefinition.background();
}
if (index.get().expireAfterSeconds() >= 0) {
indexDefinition.expire(index.get().expireAfterSeconds(), TimeUnit.SECONDS);
if (index.expireAfterSeconds() >= 0) {
indexDefinition.expire(index.expireAfterSeconds(), TimeUnit.SECONDS);
}
return new IndexDefinitionHolder(dotPath, indexDefinition, collection);
@@ -426,21 +425,21 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
protected IndexDefinitionHolder createGeoSpatialIndexDefinition(String dotPath, String collection,
MongoPersistentProperty persistentProperty) {
Optional<GeoSpatialIndexed> index = persistentProperty.findAnnotation(GeoSpatialIndexed.class);
GeoSpatialIndexed index = persistentProperty.findAnnotation(GeoSpatialIndexed.class);
if(!index.isPresent()) {
if (index == null) {
return null;
}
GeospatialIndex indexDefinition = new GeospatialIndex(dotPath);
indexDefinition.withBits(index.get().bits());
indexDefinition.withMin(index.get().min()).withMax(index.get().max());
indexDefinition.withBits(index.bits());
indexDefinition.withMin(index.min()).withMax(index.max());
if (!index.get().useGeneratedName()) {
indexDefinition.named(pathAwareIndexName(index.get().name(), dotPath, persistentProperty));
if (!index.useGeneratedName()) {
indexDefinition.named(pathAwareIndexName(index.name(), dotPath, persistentProperty));
}
indexDefinition.typed(index.get().type()).withBucketSize(index.get().bucketSize()).withAdditionalField(index.get().additionalField());
indexDefinition.typed(index.type()).withBucketSize(index.bucketSize()).withAdditionalField(index.additionalField());
return new IndexDefinitionHolder(dotPath, indexDefinition, collection);
}

View File

@@ -20,7 +20,6 @@ import java.lang.reflect.Modifier;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
@@ -32,7 +31,7 @@ import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.model.BasicPersistentEntity;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mongodb.MongoCollectionUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.Expression;
@@ -47,7 +46,7 @@ import org.springframework.util.StringUtils;
/**
* MongoDB specific {@link MongoPersistentEntity} implementation that adds Mongo specific meta-data such as the
* collection name and the like.
*
*
* @author Jon Brisbin
* @author Oliver Gierke
* @author Thomas Darimont
@@ -69,23 +68,30 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
/**
* Creates a new {@link BasicMongoPersistentEntity} with the given {@link TypeInformation}. Will default the
* collection name to the entities simple type name.
*
*
* @param typeInformation must not be {@literal null}.
*/
public BasicMongoPersistentEntity(TypeInformation<T> typeInformation) {
super(typeInformation, Optional.of(MongoPersistentPropertyComparator.INSTANCE));
super(typeInformation, MongoPersistentPropertyComparator.INSTANCE);
Class<?> rawType = typeInformation.getType();
String fallback = MongoCollectionUtils.getPreferredCollectionName(rawType);
Optional<Document> document = this.findAnnotation(Document.class);
this.expression = document.map(it -> detectExpression(it)).orElse(null);
this.context = new StandardEvaluationContext();
this.collection = document.filter(it -> StringUtils.hasText(it.collection())).map(it -> it.collection())
.orElse(fallback);
this.language = document.filter(it -> StringUtils.hasText(it.language())).map(it -> it.language()).orElse("");
if (this.isAnnotationPresent(Document.class)) {
Document document = this.findAnnotation(Document.class);
this.collection = StringUtils.hasText(document.collection()) ? document.collection() : fallback;
this.language = StringUtils.hasText(document.language()) ? document.language() : "";
this.expression = document != null ? detectExpression(document) : null;
} else {
this.collection = fallback;
this.language = "";
this.expression = null;
}
}
/*
@@ -122,7 +128,7 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
*/
@Override
public MongoPersistentProperty getTextScoreProperty() {
return getPersistentProperty(TextScore.class).orElse(null);
return getPersistentProperty(TextScore.class);
}
/*
@@ -159,7 +165,7 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
/**
* {@link Comparator} implementation inspecting the {@link MongoPersistentProperty}'s order.
*
*
* @author Oliver Gierke
*/
static enum MongoPersistentPropertyComparator implements Comparator<MongoPersistentProperty> {
@@ -189,7 +195,7 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
* that is annotated with @see {@link Id}. The property id is updated according to the following rules: 1) An id
* property which is defined explicitly takes precedence over an implicitly defined id property. 2) In case of any
* ambiguity a @see {@link MappingException} is thrown.
*
*
* @param property - the new id property candidate
* @return
*/
@@ -202,45 +208,47 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
return null;
}
Optional<MongoPersistentProperty> currentIdProperty = getIdProperty();
MongoPersistentProperty currentIdProperty = getIdProperty();
return currentIdProperty.map(it -> {
boolean currentIdPropertyIsSet = currentIdProperty != null;
@SuppressWarnings("null")
boolean currentIdPropertyIsExplicit = currentIdPropertyIsSet ? currentIdProperty.isExplicitIdProperty() : false;
boolean newIdPropertyIsExplicit = property.isExplicitIdProperty();
boolean currentIdPropertyIsExplicit = it.isExplicitIdProperty();
boolean newIdPropertyIsExplicit = property.isExplicitIdProperty();
Optional<Field> currentIdPropertyField = it.getField();
if (!currentIdPropertyIsSet) {
return property;
if (newIdPropertyIsExplicit && currentIdPropertyIsExplicit) {
throw new MappingException(
String.format(
"Attempt to add explicit id property %s but already have an property %s registered "
+ "as explicit id. Check your mapping configuration!",
property.getField(), currentIdPropertyField));
}
} else if (newIdPropertyIsExplicit && !currentIdPropertyIsExplicit) {
// explicit id property takes precedence over implicit id property
return property;
@SuppressWarnings("null")
Field currentIdPropertyField = currentIdProperty.getField();
} else if (!newIdPropertyIsExplicit && currentIdPropertyIsExplicit) {
// no id property override - current property is explicitly defined
if (newIdPropertyIsExplicit && currentIdPropertyIsExplicit) {
throw new MappingException(
String.format("Attempt to add explicit id property %s but already have an property %s registered "
+ "as explicit id. Check your mapping configuration!", property.getField(), currentIdPropertyField));
} else {
throw new MappingException(
String.format("Attempt to add id property %s but already have an property %s registered "
+ "as id. Check your mapping configuration!", property.getField(), currentIdPropertyField));
}
} else if (newIdPropertyIsExplicit && !currentIdPropertyIsExplicit) {
// explicit id property takes precedence over implicit id property
return property;
return null;
} else if (!newIdPropertyIsExplicit && currentIdPropertyIsExplicit) {
// no id property override - current property is explicitly defined
}).orElse(property);
} else {
throw new MappingException(
String.format("Attempt to add id property %s but already have an property %s registered "
+ "as id. Check your mapping configuration!", property.getField(), currentIdPropertyField));
}
return null;
}
/**
* Returns a SpEL {@link Expression} frór the collection String expressed in the given {@link Document} annotation if
* present or {@literal null} otherwise. Will also return {@literal null} it the collection {@link String} evaluates
* to a {@link LiteralExpression} (indicating that no subsequent evaluation is necessary).
*
*
* @param document can be {@literal null}
* @return
*/
@@ -264,7 +272,7 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
/**
* Handler to collect {@link MongoPersistentProperty} instances and check that each of them is mapped to a distinct
* field name.
*
*
* @author Oliver Gierke
*/
private static class AssertFieldNameUniquenessHandler

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2016 the original author or authors.
* Copyright 2011-2017 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.
@@ -17,7 +17,6 @@ package org.springframework.data.mongodb.core.mapping;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import org.bson.types.ObjectId;
@@ -27,19 +26,20 @@ import org.springframework.data.annotation.Id;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
import org.springframework.data.mapping.model.FieldNamingStrategy;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.util.StringUtils;
/**
* MongoDB specific {@link org.springframework.data.mapping.MongoPersistentProperty} implementation.
*
* MongoDB specific {@link org.springframework.data.mapping.PersistentProperty} implementation.
*
* @author Oliver Gierke
* @author Patryk Wasik
* @author Thomas Darimont
* @author Christoph Strobl
* @author Mark Paluch
*/
public class BasicMongoPersistentProperty extends AnnotationBasedPersistentProperty<MongoPersistentProperty>
implements MongoPersistentProperty {
@@ -65,7 +65,7 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
/**
* Creates a new {@link BasicMongoPersistentProperty}.
*
*
* @param field
* @param propertyDescriptor
* @param owner
@@ -86,7 +86,7 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
/**
* Also considers fields as id that are of supported id type and name.
*
*
* @see #SUPPORTED_ID_PROPERTY_NAMES
* @see #SUPPORTED_ID_TYPES
*/
@@ -113,14 +113,14 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
/**
* Returns the key to be used to store the value of the property inside a Mongo {@link org.bson.Document}.
*
*
* @return
*/
public String getFieldName() {
if (isIdProperty()) {
if (!getOwner().getIdProperty().isPresent()) {
if (getOwner().getIdProperty() == null) {
return ID_FIELD_NAME;
}
@@ -154,13 +154,10 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
private String getAnnotatedFieldName() {
Optional<org.springframework.data.mongodb.core.mapping.Field> annotation = findAnnotation(
org.springframework.data.mongodb.core.mapping.Field annotation = findAnnotation(
org.springframework.data.mongodb.core.mapping.Field.class);
return annotation//
.filter(it -> StringUtils.hasText(it.value()))//
.map(it -> it.value())//
.orElse(null);
return annotation != null ? annotation.value() : null;
}
/*
@@ -169,10 +166,10 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
*/
public int getFieldOrder() {
Optional<org.springframework.data.mongodb.core.mapping.Field> annotation = findAnnotation(
org.springframework.data.mongodb.core.mapping.Field annotation = findAnnotation(
org.springframework.data.mongodb.core.mapping.Field.class);
return annotation.map(it -> it.order()).orElse(Integer.MAX_VALUE);
return annotation != null ? annotation.order() : Integer.MAX_VALUE;
}
/*
@@ -197,7 +194,7 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#getDBRef()
*/
public DBRef getDBRef() {
return findAnnotation(DBRef.class).orElse(null);
return findAnnotation(DBRef.class);
}
/*

View File

@@ -1,37 +0,0 @@
/*
* Copyright 2016 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.mapping;
import lombok.Value;
import java.util.Optional;
import java.util.function.BiConsumer;
import org.springframework.data.util.Optionals;
/**
* @author Oliver Gierke
*/
@Value(staticConstructor = "of")
public class EntityHandler<T extends MongoPersistentEntity<?>> {
Optional<T> entity;
public void doWithVersionProperty(BiConsumer<T, MongoPersistentProperty> consumer) {
Optionals.ifAllPresent(entity, entity.flatMap(it -> it.getVersionProperty()), consumer);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015-2016 the original author or authors.
* Copyright 2015-2017 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.
@@ -15,8 +15,6 @@
*/
package org.springframework.data.mongodb.repository.query;
import java.util.Optional;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.EntityInstantiator;
import org.springframework.data.convert.EntityInstantiators;
@@ -36,6 +34,7 @@ import org.springframework.util.Assert;
* {@link Converter} to instantiate DTOs from fully equipped domain objects.
*
* @author Oliver Gierke
* @author Mark Paluch
*/
class DtoInstantiatingConverter implements Converter<Object, Object> {
@@ -45,7 +44,7 @@ class DtoInstantiatingConverter implements Converter<Object, Object> {
/**
* Creates a new {@link Converter} to instantiate DTOs.
*
*
* @param dtoType must not be {@literal null}.
* @param context must not be {@literal null}.
* @param instantiators must not be {@literal null}.
@@ -63,7 +62,7 @@ class DtoInstantiatingConverter implements Converter<Object, Object> {
this.instantiator = instantiator.getInstantiatorFor(context.getRequiredPersistentEntity(dtoType));
}
/*
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@@ -78,14 +77,14 @@ class DtoInstantiatingConverter implements Converter<Object, Object> {
final PersistentPropertyAccessor sourceAccessor = sourceEntity.getPropertyAccessor(source);
final PersistentEntity<?, ?> targetEntity = context.getRequiredPersistentEntity(targetType);
final PreferredConstructor<?, ? extends PersistentProperty<?>> constructor = targetEntity
.getPersistenceConstructor().get();
.getPersistenceConstructor();
@SuppressWarnings({ "rawtypes", "unchecked" })
Object dto = instantiator.createInstance(targetEntity, new ParameterValueProvider() {
@Override
public Optional<Object> getParameterValue(Parameter parameter) {
return sourceAccessor.getProperty(sourceEntity.getPersistentProperty(parameter.getName().get().toString()).get());
public Object getParameterValue(Parameter parameter) {
return sourceAccessor.getProperty(sourceEntity.getPersistentProperty(parameter.getName().toString()));
}
});
@@ -101,7 +100,7 @@ class DtoInstantiatingConverter implements Converter<Object, Object> {
}
dtoAccessor.setProperty(property,
sourceAccessor.getProperty(sourceEntity.getPersistentProperty(property.getName()).get()));
sourceAccessor.getProperty(sourceEntity.getPersistentProperty(property.getName())));
}
});

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2015 the original author or authors.
* Copyright 2011-2017 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.
@@ -33,7 +33,7 @@ import org.springframework.data.util.TypeInformation;
/**
* Custom extension of {@link Parameters} discovering additional
*
*
* @author Oliver Gierke
* @author Christoph Strobl
*/
@@ -47,7 +47,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
/**
* Creates a new {@link MongoParameters} instance from the given {@link Method} and {@link MongoQueryMethod}.
*
*
* @param method must not be {@literal null}.
* @param queryMethod must not be {@literal null}.
*/
@@ -115,8 +115,8 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
if (this.nearIndex == null && mongoParameter.isManuallyAnnotatedNearParameter()) {
this.nearIndex = mongoParameter.getIndex();
} else if (mongoParameter.isManuallyAnnotatedNearParameter()) {
throw new IllegalStateException(String.format(
"Found multiple @Near annotations ond method %s! Only one allowed!", parameter.getMethod().toString()));
throw new IllegalStateException(String.format("Found multiple @Near annotations ond method %s! Only one allowed!",
parameter.getMethod().toString()));
}
return mongoParameter;
@@ -128,7 +128,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
/**
* Returns the index of the {@link Distance} parameter to be used for max distance in geo queries.
*
*
* @return
* @since 1.7
*/
@@ -138,7 +138,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
/**
* Returns the index of the parameter to be used to start a geo-near query from.
*
*
* @return
*/
public int getNearIndex() {
@@ -147,7 +147,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
/**
* Returns ths inde of the parameter to be used as a textquery param
*
*
* @return
* @since 1.6
*/
@@ -171,7 +171,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
return rangeIndex;
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.Parameters#createFrom(java.util.List)
*/
@@ -190,7 +190,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
if (componentType == null) {
return i;
} else if (componentType.equals(candidate.getComponentType().get().getType())) {
} else if (componentType.equals(candidate.getRequiredComponentType().getType())) {
return i;
}
}
@@ -201,7 +201,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
/**
* Custom {@link Parameter} implementation adding parameters of type {@link Distance} to the special ones.
*
*
* @author Oliver Gierke
*/
class MongoParameter extends Parameter {
@@ -210,7 +210,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
/**
* Creates a new {@link MongoParameter}.
*
*
* @param parameter must not be {@literal null}.
*/
MongoParameter(MethodParameter parameter) {

View File

@@ -51,7 +51,7 @@ import org.springframework.util.ClassUtils;
/**
* Custom query creator to create Mongo criterias.
*
*
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
@@ -68,7 +68,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
/**
* Creates a new {@link MongoQueryCreator} from the given {@link PartTree}, {@link ConvertingParameterAccessor} and
* {@link MappingContext}.
*
*
* @param tree
* @param accessor
* @param context
@@ -81,7 +81,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
/**
* Creates a new {@link MongoQueryCreator} from the given {@link PartTree}, {@link ConvertingParameterAccessor} and
* {@link MappingContext}.
*
*
* @param tree
* @param accessor
* @param context
@@ -163,7 +163,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
/**
* Populates the given {@link CriteriaDefinition} depending on the {@link Part} given.
*
*
* @param part
* @param property
* @param criteria
@@ -272,7 +272,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
/**
* Creates and extends the given criteria with a like-regex if necessary.
*
*
* @param part
* @param property
* @param criteria
@@ -314,7 +314,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
* If the target property of the comparison is of type String, then the operator checks for match using regular
* expression. If the target property of the comparison is a {@link Collection} then the operator evaluates to true if
* it finds an exact match within any member of the {@link Collection}.
*
*
* @param part
* @param property
* @param criteria
@@ -333,7 +333,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
/**
* Creates an appropriate like-regex and appends it to the given criteria.
*
*
* @param criteria
* @param part
* @param value
@@ -368,7 +368,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
/**
* Returns the next element from the given {@link Iterator} expecting it to be of a certain type.
*
*
* @param <T>
* @param iterator
* @param type
@@ -407,7 +407,11 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
private boolean isSpherical(MongoPersistentProperty property) {
Optional<GeoSpatialIndexed> index = property.findAnnotation(GeoSpatialIndexed.class);
return index.isPresent() && index.get().type().equals(GeoSpatialIndexType.GEO_2DSPHERE);
if (property.isAnnotationPresent(GeoSpatialIndexed.class)) {
GeoSpatialIndexed index = property.findAnnotation(GeoSpatialIndexed.class);
return index.type().equals(GeoSpatialIndexType.GEO_2DSPHERE);
}
return false;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016 the original author or authors.
* Copyright 2016-2017 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.
@@ -62,7 +62,7 @@ interface MongoQueryExecution {
/**
* {@link MongoQueryExecution} for collection returning queries.
*
*
* @author Oliver Gierke
*/
@RequiredArgsConstructor
@@ -83,7 +83,7 @@ interface MongoQueryExecution {
/**
* {@link MongoQueryExecution} for {@link Slice} query methods.
*
*
* @author Oliver Gierke
* @author Christoph Strobl
* @since 1.5
@@ -116,7 +116,7 @@ interface MongoQueryExecution {
/**
* {@link MongoQueryExecution} for pagination queries.
*
*
* @author Oliver Gierke
* @author Mark Paluch
*/
@@ -154,7 +154,7 @@ interface MongoQueryExecution {
/**
* {@link MongoQueryExecution} to return a single entity.
*
*
* @author Oliver Gierke
*/
@RequiredArgsConstructor
@@ -217,7 +217,7 @@ interface MongoQueryExecution {
/**
* {@link MongoQueryExecution} to execute geo-near queries.
*
*
* @author Oliver Gierke
*/
@RequiredArgsConstructor
@@ -267,8 +267,8 @@ interface MongoQueryExecution {
return false;
}
Optional<TypeInformation<?>> componentType = returnType.getComponentType();
return componentType.isPresent() && GeoResult.class.equals(componentType.get().getType());
TypeInformation<?> componentType = returnType.getComponentType();
return componentType != null && GeoResult.class.equals(componentType.getType());
}
}
@@ -322,7 +322,7 @@ interface MongoQueryExecution {
/**
* {@link MongoQueryExecution} removing documents matching the query.
*
*
* @since 1.5
*/
@RequiredArgsConstructor
@@ -388,7 +388,7 @@ interface MongoQueryExecution {
private final @NonNull MongoQueryExecution delegate;
private final @NonNull Converter<Object, Object> converter;
/*
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
*/
@@ -411,7 +411,7 @@ interface MongoQueryExecution {
private final @NonNull MongoOperations operations;
private final @NonNull EntityInstantiators instantiators;
/*
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/

View File

@@ -147,14 +147,14 @@ public class MongoQueryMethod extends QueryMethod {
} else {
Optional<? extends MongoPersistentEntity<?>> returnedEntity = mappingContext.getPersistentEntity(returnedObjectType);
MongoPersistentEntity<?> returnedEntity = mappingContext.getPersistentEntity(returnedObjectType);
MongoPersistentEntity<?> managedEntity = mappingContext.getRequiredPersistentEntity(domainClass);
returnedEntity = !returnedEntity.isPresent() || returnedEntity.get().getType().isInterface() ? Optional.of(managedEntity)
returnedEntity = returnedEntity == null || returnedEntity.getType().isInterface() ? managedEntity
: returnedEntity;
MongoPersistentEntity<?> collectionEntity = domainClass.isAssignableFrom(returnedObjectType) ? returnedEntity.get()
MongoPersistentEntity<?> collectionEntity = domainClass.isAssignableFrom(returnedObjectType) ? returnedEntity
: managedEntity;
this.metadata = new SimpleMongoEntityMetadata<Object>((Class<Object>) returnedEntity.get().getType(),
this.metadata = new SimpleMongoEntityMetadata<Object>((Class<Object>) returnedEntity.getType(),
collectionEntity);
}
}
@@ -192,7 +192,7 @@ public class MongoQueryMethod extends QueryMethod {
if (Iterable.class.isAssignableFrom(returnType)) {
TypeInformation<?> from = ClassTypeInformation.fromReturnTypeOf(method);
return GeoResult.class.equals(from.getComponentType().get().getType());
return GeoResult.class.equals(from.getRequiredComponentType().getType());
}
return false;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016 the original author or authors.
* Copyright 2016-2017 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.
@@ -19,8 +19,6 @@ import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import reactor.core.publisher.Flux;
import java.util.Optional;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.EntityInstantiators;
import org.springframework.data.domain.Pageable;
@@ -154,8 +152,8 @@ interface ReactiveMongoQueryExecution {
return false;
}
Optional<TypeInformation<?>> componentType = returnType.getComponentType();
return componentType.isPresent() && GeoResult.class.equals(componentType.get().getType());
TypeInformation<?> componentType = returnType.getComponentType();
return componentType != null && GeoResult.class.equals(componentType.getType());
}
}

View File

@@ -70,8 +70,8 @@ public class ReactiveMongoQueryMethod extends MongoQueryMethod {
boolean multiWrapper = ReactiveWrappers.isMultiValueType(returnType.getType());
boolean singleWrapperWithWrappedPageableResult = ReactiveWrappers.isSingleValueType(returnType.getType())
&& (PAGE_TYPE.isAssignableFrom(returnType.getComponentType().get())
|| SLICE_TYPE.isAssignableFrom(returnType.getComponentType().get()));
&& (PAGE_TYPE.isAssignableFrom(returnType.getRequiredComponentType())
|| SLICE_TYPE.isAssignableFrom(returnType.getRequiredComponentType()));
if (singleWrapperWithWrappedPageableResult) {
throw new InvalidDataAccessApiUsageException(
@@ -94,7 +94,7 @@ public class ReactiveMongoQueryMethod extends MongoQueryMethod {
this.method = method;
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.MongoQueryMethod#createParameters(java.lang.reflect.Method)
*/
@@ -103,7 +103,7 @@ public class ReactiveMongoQueryMethod extends MongoQueryMethod {
return new MongoParameters(method, isGeoNearQuery(method));
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.QueryMethod#isCollectionQuery()
*/
@@ -112,7 +112,7 @@ public class ReactiveMongoQueryMethod extends MongoQueryMethod {
return !(isPageQuery() || isSliceQuery()) && ReactiveWrappers.isMultiValueType(method.getReturnType());
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.MongoQueryMethod#isGeoNearQuery()
*/
@@ -125,13 +125,13 @@ public class ReactiveMongoQueryMethod extends MongoQueryMethod {
if (ReactiveWrappers.supports(method.getReturnType())) {
TypeInformation<?> from = ClassTypeInformation.fromReturnTypeOf(method);
return GeoResult.class.equals(from.getComponentType().get().getType());
return GeoResult.class.equals(from.getRequiredComponentType().getType());
}
return false;
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.QueryMethod#isModifyingQuery()
*/
@@ -140,7 +140,7 @@ public class ReactiveMongoQueryMethod extends MongoQueryMethod {
return super.isModifyingQuery();
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.QueryMethod#isQueryForEntity()
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2015 by the original author(s).
* Copyright 2011-2017 by the original author(s).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,9 +24,10 @@ import org.springframework.data.repository.core.support.PersistentEntityInformat
* {@link MongoEntityInformation} implementation using a {@link MongoPersistentEntity} instance to lookup the necessary
* information. Can be configured with a custom collection to be returned which will trump the one returned by the
* {@link MongoPersistentEntity} if given.
*
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
*/
public class MappingMongoEntityInformation<T, ID> extends PersistentEntityInformation<T, ID>
implements MongoEntityInformation<T, ID> {
@@ -37,7 +38,7 @@ public class MappingMongoEntityInformation<T, ID> extends PersistentEntityInform
/**
* Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity}.
*
*
* @param entity must not be {@literal null}.
*/
public MappingMongoEntityInformation(MongoPersistentEntity<T> entity) {
@@ -47,18 +48,18 @@ public class MappingMongoEntityInformation<T, ID> extends PersistentEntityInform
/**
* Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity} and fallback
* identifier type.
*
*
* @param entity must not be {@literal null}.
* @param fallbackIdType can be {@literal null}.
*/
public MappingMongoEntityInformation(MongoPersistentEntity<T> entity, Class<ID> fallbackIdType) {
this(entity, (String) null, fallbackIdType);
this(entity, null, fallbackIdType);
}
/**
* Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity} and custom
* collection name.
*
*
* @param entity must not be {@literal null}.
* @param customCollectionName can be {@literal null}.
*/
@@ -69,7 +70,7 @@ public class MappingMongoEntityInformation<T, ID> extends PersistentEntityInform
/**
* Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity}, collection name
* and identifier type.
*
*
* @param entity must not be {@literal null}.
* @param customCollectionName can be {@literal null}.
* @param idType can be {@literal null}.
@@ -96,7 +97,7 @@ public class MappingMongoEntityInformation<T, ID> extends PersistentEntityInform
* @see org.springframework.data.mongodb.repository.MongoEntityInformation#getIdAttribute()
*/
public String getIdAttribute() {
return entityMetadata.getIdProperty().get().getName();
return entityMetadata.getRequiredIdProperty().getName();
}
/*

View File

@@ -18,8 +18,6 @@ package org.springframework.data.mongodb.repository.support;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import java.util.Optional;
import org.springframework.data.domain.Persistable;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
@@ -76,10 +74,10 @@ class PersistableMongoEntityInformation<T, ID> implements MongoEntityInformation
*/
@Override
@SuppressWarnings("unchecked")
public Optional<ID> getId(T t) {
public ID getId(T t) {
if (t instanceof Persistable) {
return Optional.ofNullable(((Persistable<ID>) t).getId());
return ((Persistable<ID>) t).getId();
}
return delegate.getId(t);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2016 the original author or authors.
* Copyright 2011-2017 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.
@@ -33,10 +33,10 @@ import org.springframework.util.ClassUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.DBRef;
import com.mongodb.util.JSON;
import com.querydsl.core.types.Constant;
import com.querydsl.core.types.Expression;
import com.querydsl.core.types.Operation;
import com.mongodb.util.JSON;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.PathMetadata;
import com.querydsl.core.types.PathType;
@@ -44,7 +44,7 @@ import com.querydsl.mongodb.MongodbSerializer;
/**
* Custom {@link MongodbSerializer} to take mapping information into account when building keys for constraints.
*
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
@@ -69,7 +69,7 @@ class SpringDataMongodbSerializer extends MongodbSerializer {
/**
* Creates a new {@link SpringDataMongodbSerializer} for the given {@link MappingContext}.
*
*
* @param mappingContext must not be {@literal null}.
*/
public SpringDataMongodbSerializer(MongoConverter converter) {
@@ -108,9 +108,9 @@ class SpringDataMongodbSerializer extends MongodbSerializer {
Path<?> parent = metadata.getParent();
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(parent.getType());
Optional<MongoPersistentProperty> property = entity.getPersistentProperty(metadata.getName());
MongoPersistentProperty property = entity.getPersistentProperty(metadata.getName());
return !property.isPresent() ? super.getKeyForPath(expr, metadata) : property.get().getFieldName();
return property == null ? super.getKeyForPath(expr, metadata) : property.getFieldName();
}
/*
@@ -120,7 +120,7 @@ class SpringDataMongodbSerializer extends MongodbSerializer {
@Override
protected DBObject asDBObject(String key, Object value) {
value = value instanceof Optional ? ((Optional)value).orElse(null) : value;
value = value instanceof Optional ? ((Optional) value).orElse(null) : value;
if (ID_KEY.equals(key)) {
DBObject superIdValue = super.asDBObject(key, value);
@@ -203,8 +203,8 @@ class SpringDataMongodbSerializer extends MongodbSerializer {
return null;
}
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(parent.getType());
return entity.isPresent() ? entity.get().getRequiredPersistentProperty(path.getMetadata().getName()) : null;
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(parent.getType());
return entity != null ? entity.getRequiredPersistentProperty(path.getMetadata().getName()) : null;
}
/**

View File

@@ -46,7 +46,7 @@ import com.mongodb.client.MongoCollection;
/**
* Integration tests for {@link DefaultBulkOperations}.
*
*
* @author Tobias Trelle
* @author Oliver Gierke
* @author Christoph Strobl
@@ -278,7 +278,7 @@ public class DefaultBulkOperationsIntegrationTests {
private BulkOperations createBulkOps(BulkMode mode, Class<?> entityType) {
Optional<? extends MongoPersistentEntity<?>> entity = entityType != null
? operations.getConverter().getMappingContext().getPersistentEntity(entityType) : Optional.empty();
? Optional.of(operations.getConverter().getMappingContext().getPersistentEntity(entityType)) : Optional.empty();
BulkOperationContext bulkOperationContext = new BulkOperationContext(mode, entity,
new QueryMapper(operations.getConverter()), new UpdateMapper(operations.getConverter()));

View File

@@ -23,6 +23,7 @@ import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.query.Query.*;
import java.util.List;
import java.util.Optional;
import org.bson.Document;
import org.junit.Before;
@@ -80,8 +81,9 @@ public class DefaultBulkOperationsUnitTests {
when(template.getCollection(anyString())).thenReturn(collection);
ops = new DefaultBulkOperations(template, "collection-1",
new BulkOperationContext(BulkMode.ORDERED, mappingContext.getPersistentEntity(SomeDomainType.class),
new QueryMapper(converter), new UpdateMapper(converter)));
new BulkOperationContext(BulkMode.ORDERED,
Optional.of(mappingContext.getPersistentEntity(SomeDomainType.class)), new QueryMapper(converter),
new UpdateMapper(converter)));
}
@Test // DATAMONGO-1518

View File

@@ -29,6 +29,7 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.dao.DataAccessException;
import org.springframework.data.geo.Point;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mongodb.core.convert.AbstractMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter;
@@ -210,7 +211,7 @@ public abstract class MongoOperationsUnitTests {
public void doWith(MongoOperations operations) {
operations.findAll(Object.class);
}
}.assertException(IllegalArgumentException.class);
}.assertException(MappingException.class);
}
@Test

View File

@@ -54,7 +54,7 @@ import org.springframework.data.convert.CustomConversions;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
@@ -1498,7 +1498,7 @@ public class MongoTemplateTests {
template.save(map, "maps");
}
@Test(expected = IllegalArgumentException.class) // DATAMONGO-549
@Test(expected = MappingException.class) // DATAMONGO-549, DATAMONGO-1730
public void savesMongoPrimitiveObjectCorrectly() {
template.save(new Object(), "collection");
}
@@ -1517,7 +1517,7 @@ public class MongoTemplateTests {
assertThat(document.containsKey("_id"), is(true));
}
@Test(expected = IllegalArgumentException.class) // DATAMONGO-550
@Test(expected = MappingException.class) // DATAMONGO-550, DATAMONGO-1730
public void rejectsPlainObjectWithOutExplicitCollection() {
org.bson.Document document = new org.bson.Document("foo", "bar");

View File

@@ -51,7 +51,7 @@ import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.geo.Metrics;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mongodb.core.MongoTemplateTests.PersonWithConvertedId;
import org.springframework.data.mongodb.core.MongoTemplateTests.VersionedPerson;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
@@ -86,6 +86,7 @@ public class ReactiveMongoTemplateTests {
StepVerifier
.create(template.dropCollection("people") //
.mergeWith(template.dropCollection("personX")) //
.mergeWith(template.dropCollection("collection")) //
.mergeWith(template.dropCollection(Person.class)) //
.mergeWith(template.dropCollection(Venue.class)) //
@@ -536,11 +537,11 @@ public class ReactiveMongoTemplateTests {
StepVerifier.create(template.save(map, "maps")).expectNextCount(1).verifyComplete();
}
@Test // DATAMONGO-1444
@Test // DATAMONGO-1444, DATAMONGO-1730
public void savesMongoPrimitiveObjectCorrectly() {
StepVerifier.create(template.save(new Object(), "collection")) //
.expectError(IllegalArgumentException.class) //
.expectError(MappingException.class) //
.verify();
}
@@ -554,7 +555,7 @@ public class ReactiveMongoTemplateTests {
assertThat(dbObject.containsKey("_id"), is(true));
}
@Test(expected = IllegalArgumentException.class) // DATAMONGO-1444
@Test(expected = MappingException.class) // DATAMONGO-1444, DATAMONGO-1730
public void rejectsPlainObjectWithOutExplicitCollection() {
Document dbObject = new Document("foo", "bar");
@@ -562,9 +563,8 @@ public class ReactiveMongoTemplateTests {
StepVerifier.create(template.save(dbObject, "collection")).expectNextCount(1).verifyComplete();
StepVerifier.create(template.findById(dbObject.get("_id"), Document.class)) //
.expectError(IllegalArgumentException.class) //
.expectError(MappingException.class) //
.verify();
}
@Test // DATAMONGO-1444

View File

@@ -54,7 +54,7 @@ import org.springframework.dao.DataAccessException;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.geo.Metrics;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mongodb.core.CollectionCallback;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.Venue;

View File

@@ -24,7 +24,7 @@ import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;

View File

@@ -38,7 +38,7 @@ import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.convert.CustomConversions;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.DirectFieldReference;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;

View File

@@ -18,6 +18,7 @@ package org.springframework.data.mongodb.core.convert;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.any;
import static org.springframework.data.mongodb.core.convert.LazyLoadingTestUtils.*;
import java.io.Serializable;
@@ -68,6 +69,7 @@ import com.mongodb.client.MongoDatabase;
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
* @author Mark Paluch
*/
@RunWith(MockitoJUnitRunner.class)
public class DbRefMappingMongoConverterUnitTests {
@@ -483,7 +485,7 @@ public class DbRefMappingMongoConverterUnitTests {
PersistentPropertyAccessor accessor = propertyEntity.getPropertyAccessor(result.dbRefToConcreteType);
MongoPersistentProperty idProperty = mappingContext.getRequiredPersistentEntity(LazyDbRefTarget.class)
.getIdProperty().get();
.getIdProperty();
assertThat(accessor.getProperty(idProperty), is(notNullValue()));
assertProxyIsResolved(result.dbRefToConcreteType, false);

View File

@@ -21,7 +21,6 @@ import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.bson.Document;
import org.junit.Before;
@@ -33,7 +32,7 @@ import org.springframework.data.util.TypeInformation;
/**
* Unit tests for {@link DefaultMongoTypeMapper}.
*
*
* @author Oliver Gierke
*/
public class DefaultMongoTypeMapperUnitTests {
@@ -187,13 +186,13 @@ public class DefaultMongoTypeMapperUnitTests {
private void readsTypeFromField(Document document, Class<?> type) {
Optional<TypeInformation<?>> typeInfo = typeMapper.readType(document);
TypeInformation<?> typeInfo = typeMapper.readType(document);
if (type != null) {
assertThat(typeInfo, is(notNullValue()));
assertThat(typeInfo.get().getType(), is(typeCompatibleWith(type)));
assertThat(typeInfo.getType(), is(typeCompatibleWith(type)));
} else {
assertThat(typeInfo, is(Optional.empty()));
assertThat(typeInfo, is(nullValue()));
}
}

View File

@@ -58,7 +58,7 @@ import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.geo.Polygon;
import org.springframework.data.geo.Shape;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.model.MappingInstantiationException;
import org.springframework.data.mongodb.core.DocumentTestUtils;
import org.springframework.data.mongodb.core.convert.DocumentAccessorUnitTests.NestedType;

View File

@@ -36,7 +36,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
@@ -462,7 +461,7 @@ public class QueryMapperUnitTests {
public void queryMapperShouldNotChangeStateInGivenQueryObjectWhenIdConstrainedByInList() {
BasicMongoPersistentEntity<?> persistentEntity = context.getRequiredPersistentEntity(Sample.class);
String idPropertyName = persistentEntity.getIdProperty().get().getName();
String idPropertyName = persistentEntity.getIdProperty().getName();
org.bson.Document queryObject = query(where(idPropertyName).in("42")).getQueryObject();
Object idValuesBefore = getAsDocument(queryObject, idPropertyName).get("$in");

View File

@@ -45,7 +45,7 @@ import org.springframework.data.convert.WritingConverter;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.DocumentTestUtils;
import org.springframework.data.mongodb.core.mapping.Field;

View File

@@ -30,7 +30,7 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AliasFor;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.util.ClassTypeInformation;
/**

View File

@@ -33,7 +33,7 @@ import org.springframework.core.annotation.AliasFor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.model.FieldNamingStrategy;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
import org.springframework.data.mapping.model.SimpleTypeHolder;

View File

@@ -22,7 +22,6 @@ import java.util.AbstractMap;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import org.junit.Rule;
import org.junit.Test;
@@ -34,16 +33,17 @@ import org.springframework.context.ApplicationContext;
import org.springframework.data.annotation.Id;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.model.FieldNamingStrategy;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.MappingException;
import com.mongodb.DBRef;
/**
* Unit tests for {@link MongoMappingContext}.
*
*
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
* @author Mark Paluch
*/
@RunWith(MockitoJUnitRunner.class)
public class MongoMappingContextUnitTests {
@@ -65,14 +65,14 @@ public class MongoMappingContextUnitTests {
public void doesNotReturnPersistentEntityForMongoSimpleType() {
MongoMappingContext context = new MongoMappingContext();
assertThat(context.getPersistentEntity(DBRef.class), is(Optional.empty()));
assertThat(context.getPersistentEntity(DBRef.class), is(nullValue()));
}
@Test // DATAMONGO-638
public void doesNotCreatePersistentEntityForAbstractMap() {
MongoMappingContext context = new MongoMappingContext();
assertThat(context.getPersistentEntity(AbstractMap.class), is(Optional.empty()));
assertThat(context.getPersistentEntity(AbstractMap.class), is(nullValue()));
}
@Test // DATAMONGO-607

View File

@@ -22,18 +22,7 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -107,9 +96,9 @@ public class ReactivePerformanceTests {
converter = new MappingMongoConverter(new DbRefResolver() {
@Override
public Optional<Object> resolveDbRef(MongoPersistentProperty property, DBRef dbref,
public Object resolveDbRef(MongoPersistentProperty property, DBRef dbref,
DbRefResolverCallback callback, DbRefProxyHandler proxyHandler) {
return Optional.empty();
return null;
}
@Override

View File

@@ -20,13 +20,10 @@ import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.hamcrest.core.Is;
import org.junit.Before;
import org.junit.Test;
@@ -81,7 +78,7 @@ public class AbstractMongoQueryUnitTests {
public void setUp() {
doReturn("persons").when(persitentEntityMock).getCollection();
doReturn(Optional.of(persitentEntityMock)).when(mappingContextMock).getPersistentEntity(Mockito.any(Class.class));
doReturn(persitentEntityMock).when(mappingContextMock).getPersistentEntity(Mockito.any(Class.class));
doReturn(persitentEntityMock).when(mappingContextMock).getRequiredPersistentEntity(Mockito.any(Class.class));
doReturn(Person.class).when(persitentEntityMock).getType();

View File

@@ -24,7 +24,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
@@ -389,8 +388,8 @@ public class SimpleMongoRepositoryTests {
}
@Override
public Optional<String> getId(Person entity) {
return Optional.ofNullable(entity.getId());
public String getId(Person entity) {
return entity.getId();
}
@Override