Skip to content

Commit 1bf8eb0

Browse files
DATAMONGO-1550 - Polishing $replaceRoot (aggregation stage).
Original Pull Request: spring-projects#422.
1 parent ae4cfaa commit 1bf8eb0

File tree

2 files changed

+50
-48
lines changed

2 files changed

+50
-48
lines changed

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

Lines changed: 49 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -26,46 +26,52 @@
2626
import org.springframework.util.Assert;
2727

2828
/**
29-
* Encapsulates the aggregation framework {@code $replaceRoot}-operation.
30-
* <p>
29+
* Encapsulates the aggregation framework {@code $replaceRoot}-operation. <br />
3130
* We recommend to use the static factory method {@link Aggregation#replaceRoot(String)} instead of creating instances
3231
* of this class directly.
33-
*
34-
* @see https://docs.mongodb.com/manual/reference/operator/aggregation/replaceRoot/#pipe._S_replaceRoot
32+
*
33+
* @see <a href=
34+
* "https://docs.mongodb.com/manual/reference/operator/aggregation/replaceRoot/">https://docs.mongodb.com/manual/reference/operator/aggregation/replaceRoot/</a>
3535
* @author Mark Paluch
36+
* @author Christoph Strobl
3637
* @since 1.10
3738
*/
3839
public class ReplaceRootOperation implements FieldsExposingAggregationOperation {
3940

4041
private final Replacement replacement;
4142

4243
/**
43-
* Creates a new {@link ReplaceRootOperation} given the {@link as} field name.
44+
* Creates a new {@link ReplaceRootOperation} given the {@link Field} field name.
4445
*
4546
* @param field must not be {@literal null} or empty.
4647
*/
4748
public ReplaceRootOperation(Field field) {
48-
this.replacement = new FieldReplacement(field);
49+
this(new FieldReplacement(field));
4950
}
5051

5152
/**
52-
* Creates a new {@link ReplaceRootOperation} given the {@link as} field name.
53+
* Creates a new {@link ReplaceRootOperation} given the {@link AggregationExpression} pointing to a document.
5354
*
5455
* @param aggregationExpression must not be {@literal null}.
5556
*/
5657
public ReplaceRootOperation(AggregationExpression aggregationExpression) {
57-
58-
Assert.notNull(aggregationExpression, "AggregationExpression must not be null!");
59-
this.replacement = new AggregationExpressionReplacement(aggregationExpression);
58+
this(new AggregationExpressionReplacement(aggregationExpression));
6059
}
6160

62-
protected ReplaceRootOperation(Replacement replacement) {
61+
/**
62+
* Creates a new {@link ReplaceRootOperation} given the {@link Replacement}.
63+
*
64+
* @param replacement must not be {@literal null}.
65+
*/
66+
public ReplaceRootOperation(Replacement replacement) {
67+
68+
Assert.notNull(replacement, "Replacement must not be null!");
6369
this.replacement = replacement;
6470
}
6571

6672
/**
6773
* Creates a new {@link ReplaceRootDocumentOperationBuilder}.
68-
*
74+
*
6975
* @return a new {@link ReplaceRootDocumentOperationBuilder}.
7076
*/
7177
public static ReplaceRootOperationBuilder builder() {
@@ -77,7 +83,7 @@ public static ReplaceRootOperationBuilder builder() {
7783
*/
7884
@Override
7985
public Document toDocument(AggregationOperationContext context) {
80-
return new Document("$replaceRoot", new Document("newRoot", replacement.toObject(context)));
86+
return new Document("$replaceRoot", new Document("newRoot", replacement.toDocumentExpression(context)));
8187
}
8288

8389
/* (non-Javadoc)
@@ -97,7 +103,7 @@ public static class ReplaceRootOperationBuilder {
97103

98104
/**
99105
* Defines a root document replacement based on a {@literal fieldName} that resolves to a document.
100-
*
106+
*
101107
* @param fieldName must not be {@literal null} or empty.
102108
* @return the final {@link ReplaceRootOperation}.
103109
*/
@@ -116,8 +122,7 @@ public ReplaceRootOperation withValueOf(AggregationExpression aggregationExpress
116122
}
117123

118124
/**
119-
* Defines a root document replacement based on a composable document that is empty initially.
120-
* <p>
125+
* Defines a root document replacement based on a composable document that is empty initially. <br />
121126
* {@link ReplaceRootOperation} can be populated with individual entries and derive its values from other, existing
122127
* documents.
123128
*
@@ -128,8 +133,7 @@ public ReplaceRootDocumentOperation withDocument() {
128133
}
129134

130135
/**
131-
* Defines a root document replacement based on a composable document given {@literal document}
132-
* <p>
136+
* Defines a root document replacement based on a composable document given {@literal document}. <br />
133137
* {@link ReplaceRootOperation} can be populated with individual entries and derive its values from other, existing
134138
* documents.
135139
*
@@ -146,8 +150,7 @@ public ReplaceRootOperation withDocument(Document document) {
146150

147151
/**
148152
* Encapsulates the aggregation framework {@code $replaceRoot}-operation to result in a composable replacement
149-
* document.
150-
* <p>
153+
* document. <br />
151154
* Instances of {@link ReplaceRootDocumentOperation} yield empty upon construction and can be populated with single
152155
* values and documents.
153156
*
@@ -173,7 +176,7 @@ private ReplaceRootDocumentOperation(ReplacementDocument replacementDocument) {
173176
/**
174177
* Creates an extended {@link ReplaceRootDocumentOperation} that combines {@link ReplacementDocument}s from the
175178
* {@literal currentOperation} and {@literal extension} operation.
176-
*
179+
*
177180
* @param currentOperation must not be {@literal null}.
178181
* @param extension must not be {@literal null}.
179182
*/
@@ -183,9 +186,9 @@ protected ReplaceRootDocumentOperation(ReplaceRootDocumentOperation currentOpera
183186
}
184187

185188
/**
186-
* Creates a new {@link ReplaceRootDocumentOperationBuilder} to define a field for the {@link AggregationExpression}
187-
* .
188-
*
189+
* Creates a new {@link ReplaceRootDocumentOperationBuilder} to define a field for the
190+
* {@link AggregationExpression}.
191+
*
189192
* @param aggregationExpression must not be {@literal null}.
190193
* @return the {@link ReplaceRootDocumentOperationBuilder}.
191194
*/
@@ -249,47 +252,50 @@ public ReplaceRootDocumentOperation as(String fieldName) {
249252
* Replacement object that results in a replacement document or an expression that results in a document.
250253
*
251254
* @author Mark Paluch
255+
* @author Christoph Strobl
252256
*/
253-
private abstract static class Replacement {
257+
public interface Replacement {
254258

255259
/**
256-
* Renders the current {@link Replacement} into a {@link Document} based on the given
260+
* Renders the current {@link Replacement} into a its MongoDB representation based on the given
257261
* {@link AggregationOperationContext}.
258262
*
259263
* @param context will never be {@literal null}.
260264
* @return a replacement document or an expression that results in a document.
261265
*/
262-
public abstract Object toObject(AggregationOperationContext context);
266+
Object toDocumentExpression(AggregationOperationContext context);
263267
}
264268

265269
/**
266270
* {@link Replacement} that uses a {@link AggregationExpression} that results in a replacement document.
267271
*
268272
* @author Mark Paluch
269273
*/
270-
private static class AggregationExpressionReplacement extends Replacement {
274+
private static class AggregationExpressionReplacement implements Replacement {
271275

272276
private final AggregationExpression aggregationExpression;
273277

274278
protected AggregationExpressionReplacement(AggregationExpression aggregationExpression) {
279+
280+
Assert.notNull(aggregationExpression, "AggregationExpression must not be null!");
275281
this.aggregationExpression = aggregationExpression;
276282
}
277283

278284
/* (non-Javadoc)
279285
* @see org.springframework.data.mongodb.core.aggregation.ReplaceRootOperation.Replacement#toObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
280286
*/
281287
@Override
282-
public Document toObject(AggregationOperationContext context) {
288+
public Document toDocumentExpression(AggregationOperationContext context) {
283289
return aggregationExpression.toDocument(context);
284290
}
285291
}
286292

287293
/**
288294
* {@link Replacement that references a {@link Field} inside the current aggregation pipeline.
289-
*
295+
*
290296
* @author Mark Paluch
291297
*/
292-
private static class FieldReplacement extends Replacement {
298+
private static class FieldReplacement implements Replacement {
293299

294300
private final Field field;
295301

@@ -306,7 +312,7 @@ protected FieldReplacement(Field field) {
306312
* @see org.springframework.data.mongodb.core.aggregation.ReplaceRootOperation.Replacement#toObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
307313
*/
308314
@Override
309-
public Object toObject(AggregationOperationContext context) {
315+
public Object toDocumentExpression(AggregationOperationContext context) {
310316
return context.getReference(field).toString();
311317
}
312318
}
@@ -316,7 +322,7 @@ public Object toObject(AggregationOperationContext context) {
316322
*
317323
* @author Mark Paluch
318324
*/
319-
private static class ReplacementDocument extends Replacement {
325+
private static class ReplacementDocument implements Replacement {
320326

321327
private final Collection<ReplacementContributor> replacements;
322328

@@ -376,7 +382,7 @@ public static ReplacementDocument forSingleValue(String field, Object value) {
376382
* @see org.springframework.data.mongodb.core.aggregation.ReplaceRootOperation.Replacement#toObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
377383
*/
378384
@Override
379-
public Document toObject(AggregationOperationContext context) {
385+
public Document toDocumentExpression(AggregationOperationContext context) {
380386

381387
Document document = new Document();
382388

@@ -401,7 +407,7 @@ public ReplacementDocument extendWith(ReplacementDocument extension) {
401407
ReplacementDocument replacementDocument = new ReplacementDocument();
402408

403409
List<ReplacementContributor> replacements = new ArrayList<ReplacementContributor>(
404-
this.replacements.size() + replacementDocument.replacements.size());
410+
this.replacements.size() + extension.replacements.size());
405411

406412
replacements.addAll(this.replacements);
407413
replacements.addAll(extension.replacements);
@@ -412,10 +418,10 @@ public ReplacementDocument extendWith(ReplacementDocument extension) {
412418

413419
/**
414420
* Partial {@link Document} contributor for document replacement.
415-
*
421+
*
416422
* @author Mark Paluch
417423
*/
418-
private abstract static class ReplacementContributor {
424+
private interface ReplacementContributor extends AggregationExpression {
419425

420426
/**
421427
* Renders the current {@link ReplacementContributor} into a {@link Document} based on the given
@@ -424,17 +430,17 @@ private abstract static class ReplacementContributor {
424430
* @param context will never be {@literal null}.
425431
* @return
426432
*/
427-
public abstract Document toDocument(AggregationOperationContext context);
433+
Document toDocument(AggregationOperationContext context);
428434
}
429435

430436
/**
431-
* {@link ReplacementContributor} to contribute multiple fields based on the input {@literal value}.
432-
* <p>
437+
* {@link ReplacementContributor} to contribute multiple fields based on the input {@literal value}. <br />
433438
* The value object is mapped into a MongoDB {@link Document}.
434-
*
439+
*
435440
* @author Mark Paluch
441+
* @author Christoph Strobl
436442
*/
437-
private static class DocumentContributor extends ReplacementContributor {
443+
private static class DocumentContributor implements ReplacementContributor {
438444

439445
private final Object value;
440446

@@ -467,7 +473,7 @@ public Document toDocument(AggregationOperationContext context) {
467473
*
468474
* @author Mark Paluch
469475
*/
470-
private abstract static class FieldContributorSupport extends ReplacementContributor {
476+
private abstract static class FieldContributorSupport implements ReplacementContributor {
471477

472478
private final ExposedField field;
473479

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,9 @@
2323
import org.springframework.data.mongodb.core.aggregation.AggregationExpressions.VariableOperators;
2424
import org.springframework.data.mongodb.core.aggregation.ReplaceRootOperation.ReplaceRootDocumentOperation;
2525

26-
import com.mongodb.BasicDBObject;
27-
import com.mongodb.DBObject;
28-
import com.mongodb.util.JSON;
29-
3026
/**
3127
* Unit tests for {@link ReplaceRootOperation}.
32-
*
28+
*
3329
* @author Mark Paluch
3430
*/
3531
public class ReplaceRootOperationUnitTests {

0 commit comments

Comments
 (0)