Browse Source

DATAMONGO-2200 - Use mapping context where available.

Use the mapping context to get the required fields or fall back to property descriptors if no mapping context is available.

Original pull request: #748.
pull/772/head
Christoph Strobl 7 years ago committed by Mark Paluch
parent
commit
e24c5e0846
  1. 37
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java
  2. 9
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsAggregationOperationContext.java
  3. 9
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/NestedDelegatingExpressionAggregationOperationContext.java
  4. 9
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/PrefixingDelegatingAggregationOperationContext.java
  5. 3
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java
  6. 22
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java
  7. 37
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java

37
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOperationContext.java

@ -15,9 +15,18 @@ @@ -15,9 +15,18 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.bson.Document;
import org.springframework.beans.BeanUtils;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* The context for an {@link AggregationOperation}.
@ -66,4 +75,32 @@ public interface AggregationOperationContext { @@ -66,4 +75,32 @@ public interface AggregationOperationContext {
* @return
*/
FieldReference getReference(String name);
/**
* Returns the {@link Fields} exposed by the type. May be a {@literal class} or an {@literal interface}.
*
* @param type must not be {@literal null}.
* @return never {@literal null}.
* @since 2.2
*/
default Fields getFields(Class<?> type) {
Assert.notNull(type, "Type must not be null!");
List<String> fields = Arrays.stream(BeanUtils.getPropertyDescriptors(type)) //
.filter(it -> { // object and default methods
Method method = it.getReadMethod();
if (method == null) {
return false;
}
if (ReflectionUtils.isObjectMethod(method)) {
return false;
}
return !method.isDefault();
}) //
.map(PropertyDescriptor::getName) //
.collect(Collectors.toList());
return Fields.fields(fields.toArray(new String[0]));
}
}

9
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ExposedFieldsAggregationOperationContext.java

@ -81,6 +81,15 @@ class ExposedFieldsAggregationOperationContext implements AggregationOperationCo @@ -81,6 +81,15 @@ class ExposedFieldsAggregationOperationContext implements AggregationOperationCo
return getReference(null, name);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getFields(java.lang.Class)
*/
@Override
public Fields getFields(Class<?> type) {
return rootContext.getFields(type);
}
/**
* Returns a {@link FieldReference} to the given {@link Field} with the given {@code name}.
*

9
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/NestedDelegatingExpressionAggregationOperationContext.java

@ -78,4 +78,13 @@ class NestedDelegatingExpressionAggregationOperationContext implements Aggregati @@ -78,4 +78,13 @@ class NestedDelegatingExpressionAggregationOperationContext implements Aggregati
public FieldReference getReference(String name) {
return new ExpressionFieldReference(delegate.getReference(name));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getFields(java.lang.Class)
*/
@Override
public Fields getFields(Class<?> type) {
return delegate.getFields(type);
}
}

9
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/PrefixingDelegatingAggregationOperationContext.java

@ -91,6 +91,15 @@ public class PrefixingDelegatingAggregationOperationContext implements Aggregati @@ -91,6 +91,15 @@ public class PrefixingDelegatingAggregationOperationContext implements Aggregati
return delegate.getReference(name);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getFields(java.lang.Class)
*/
@Override
public Fields getFields(Class<?> type) {
return delegate.getFields(type);
}
@SuppressWarnings("unchecked")
private Document doPrefix(Document source) {

3
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java

@ -1737,8 +1737,9 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation { @@ -1737,8 +1737,9 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
public Document toDocument(AggregationOperationContext context) {
Document projections = new Document();
ReflectionUtils.doWithFields(type, it -> projections.append(it.getName(), 1));
Fields fields = context.getFields(type);
fields.asList().forEach(it -> projections.append(it.getName(), 1));
return context.getMappedObject(projections, type);
}
}

22
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContext.java

@ -17,9 +17,12 @@ package org.springframework.data.mongodb.core.aggregation; @@ -17,9 +17,12 @@ package org.springframework.data.mongodb.core.aggregation;
import static org.springframework.data.mongodb.core.aggregation.Fields.*;
import java.util.ArrayList;
import java.util.List;
import org.bson.Document;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.mapping.SimplePropertyHandler;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.DirectFieldReference;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
@ -101,6 +104,23 @@ public class TypeBasedAggregationOperationContext implements AggregationOperatio @@ -101,6 +104,23 @@ public class TypeBasedAggregationOperationContext implements AggregationOperatio
return getReferenceFor(field(name));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getFields(java.lang.Class)
*/
@Override
public Fields getFields(Class<?> type) {
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(type);
if (entity == null) {
return AggregationOperationContext.super.getFields(type);
}
List<String> fields = new ArrayList<>();
entity.doWithProperties((SimplePropertyHandler) it -> fields.add(it.getName()));
return Fields.fields(fields.toArray(new String[fields.size()]));
}
private FieldReference getReferenceFor(Field field) {
PersistentPropertyPath<MongoPersistentProperty> propertyPath = mappingContext

37
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperationUnitTests.java

@ -27,7 +27,6 @@ import lombok.Data; @@ -27,7 +27,6 @@ import lombok.Data;
import java.util.Arrays;
import java.util.List;
import org.assertj.core.api.Assertions;
import org.bson.Document;
import org.junit.Test;
import org.springframework.data.domain.Range;
@ -2114,7 +2113,7 @@ public class ProjectionOperationUnitTests { @@ -2114,7 +2113,7 @@ public class ProjectionOperationUnitTests {
Document document = operation.toDocument(Aggregation.DEFAULT_CONTEXT);
Document projectClause = DocumentTestUtils.getAsDocument(document, PROJECT);
Assertions.assertThat(projectClause) //
assertThat(projectClause) //
.hasSize(2) //
.containsEntry("title", 1) //
.containsEntry("author", 1);
@ -2130,12 +2129,36 @@ public class ProjectionOperationUnitTests { @@ -2130,12 +2129,36 @@ public class ProjectionOperationUnitTests {
.toDocument(new TypeBasedAggregationOperationContext(Book.class, mappingContext, new QueryMapper(converter)));
Document projectClause = DocumentTestUtils.getAsDocument(document, PROJECT);
Assertions.assertThat(projectClause) //
assertThat(projectClause) //
.hasSize(2) //
.containsEntry("ti_tl_e", 1) //
.containsEntry("author", 1);
}
@Test // DATAMONGO-2200
public void typeProjectionShouldIncludeInterfaceProjectionValues() {
ProjectionOperation operation = Aggregation.project(ProjectionInterface.class);
Document document = operation.toDocument(Aggregation.DEFAULT_CONTEXT);
Document projectClause = DocumentTestUtils.getAsDocument(document, PROJECT);
assertThat(projectClause) //
.hasSize(1) //
.containsEntry("title", 1);
}
@Test // DATAMONGO-2200
public void typeProjectionShouldBeEmptyIfNoPropertiesFound() {
ProjectionOperation operation = Aggregation.project(EmptyType.class);
Document document = operation.toDocument(Aggregation.DEFAULT_CONTEXT);
Document projectClause = DocumentTestUtils.getAsDocument(document, PROJECT);
assertThat(projectClause).isEmpty();
}
private static Document exctractOperation(String field, Document fromProjectClause) {
return (Document) fromProjectClause.get(field);
}
@ -2159,4 +2182,12 @@ public class ProjectionOperationUnitTests { @@ -2159,4 +2182,12 @@ public class ProjectionOperationUnitTests {
String middle;
}
interface ProjectionInterface {
String getTitle();
}
static class EmptyType {
}
}

Loading…
Cancel
Save