Skip to content

Commit 36614ef

Browse files
christophstroblmp911de
authored andcommitted
DATAMONGO-1322 - Polishing.
Remove ValidationAction/Level and ValidationOptions duplicates. Rename ValidatorDefinition to Validator and Validator to ValidationOptions. Update and rename some of the tests. Also make sure to run the created validator document through the QueryMapper for value conversion and potential field mappings. Streamline Validator usage by providing plain Document and JsonSchema validator options next to the Criteria based one. Finally update the reference documentation. Original pull request: #525. Related pull request: #511. Related ticket: DATACMNS-1835.
1 parent 2024b30 commit 36614ef

16 files changed

+504
-333
lines changed

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

+71-38
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
import org.springframework.data.mongodb.core.query.Collation;
2323
import org.springframework.data.mongodb.core.schema.MongoJsonSchema;
24-
import org.springframework.data.mongodb.core.validation.ValidatorDefinition;
24+
import org.springframework.data.mongodb.core.validation.Validator;
2525
import org.springframework.data.util.Optionals;
2626
import org.springframework.lang.Nullable;
2727
import org.springframework.util.Assert;
@@ -43,7 +43,7 @@ public class CollectionOptions {
4343
private @Nullable Long size;
4444
private @Nullable Boolean capped;
4545
private @Nullable Collation collation;
46-
private Validator validator;
46+
private ValidationOptions validationOptions;
4747

4848
/**
4949
* Constructs a new <code>CollectionOptions</code> instance.
@@ -56,17 +56,17 @@ public class CollectionOptions {
5656
*/
5757
@Deprecated
5858
public CollectionOptions(@Nullable Long size, @Nullable Long maxDocuments, @Nullable Boolean capped) {
59-
this(size, maxDocuments, capped, null, Validator.none());
59+
this(size, maxDocuments, capped, null, ValidationOptions.none());
6060
}
6161

6262
private CollectionOptions(@Nullable Long size, @Nullable Long maxDocuments, @Nullable Boolean capped,
63-
@Nullable Collation collation, Validator validator) {
63+
@Nullable Collation collation, ValidationOptions validationOptions) {
6464

6565
this.maxDocuments = maxDocuments;
6666
this.size = size;
6767
this.capped = capped;
6868
this.collation = collation;
69-
this.validator = validator;
69+
this.validationOptions = validationOptions;
7070
}
7171

7272
/**
@@ -80,7 +80,7 @@ public static CollectionOptions just(Collation collation) {
8080

8181
Assert.notNull(collation, "Collation must not be null!");
8282

83-
return new CollectionOptions(null, null, null, collation, Validator.none());
83+
return new CollectionOptions(null, null, null, collation, ValidationOptions.none());
8484
}
8585

8686
/**
@@ -90,7 +90,7 @@ public static CollectionOptions just(Collation collation) {
9090
* @since 2.0
9191
*/
9292
public static CollectionOptions empty() {
93-
return new CollectionOptions(null, null, null, null, Validator.none());
93+
return new CollectionOptions(null, null, null, null, ValidationOptions.none());
9494
}
9595

9696
/**
@@ -101,7 +101,7 @@ public static CollectionOptions empty() {
101101
* @since 2.0
102102
*/
103103
public CollectionOptions capped() {
104-
return new CollectionOptions(size, maxDocuments, true, collation, validator);
104+
return new CollectionOptions(size, maxDocuments, true, collation, validationOptions);
105105
}
106106

107107
/**
@@ -112,7 +112,7 @@ public CollectionOptions capped() {
112112
* @since 2.0
113113
*/
114114
public CollectionOptions maxDocuments(long maxDocuments) {
115-
return new CollectionOptions(size, maxDocuments, capped, collation, validator);
115+
return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions);
116116
}
117117

118118
/**
@@ -123,7 +123,7 @@ public CollectionOptions maxDocuments(long maxDocuments) {
123123
* @since 2.0
124124
*/
125125
public CollectionOptions size(long size) {
126-
return new CollectionOptions(size, maxDocuments, capped, collation, validator);
126+
return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions);
127127
}
128128

129129
/**
@@ -134,23 +134,31 @@ public CollectionOptions size(long size) {
134134
* @since 2.0
135135
*/
136136
public CollectionOptions collation(@Nullable Collation collation) {
137-
return new CollectionOptions(size, maxDocuments, capped, collation, validator);
137+
return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions);
138138
}
139139

140140
/**
141-
* Create new {@link CollectionOptions} with already given settings and {@code validator} set to given
141+
* Create new {@link CollectionOptions} with already given settings and {@code validationOptions} set to given
142142
* {@link MongoJsonSchema}.
143143
*
144144
* @param schema can be {@literal null}.
145145
* @return new {@link CollectionOptions}.
146146
* @since 2.1
147147
*/
148148
public CollectionOptions schema(@Nullable MongoJsonSchema schema) {
149-
return validation(new Validator(schema, null, validator.validationLevel, validator.validationAction));
149+
return validator(Validator.schema(schema));
150150
}
151151

152-
public CollectionOptions validatorDefinition(@Nullable ValidatorDefinition definition) {
153-
return validation(new Validator(null, definition, validator.validationLevel, validator.validationAction));
152+
/**
153+
* /** Create new {@link CollectionOptions} with already given settings and {@code validationOptions} set to given
154+
* {@link Validator}.
155+
*
156+
* @param validator can be {@literal null}.
157+
* @return new {@link CollectionOptions}.
158+
* @since 2.1
159+
*/
160+
public CollectionOptions validator(@Nullable Validator validator) {
161+
return validation(validationOptions.validator(validator));
154162
}
155163

156164
/**
@@ -219,7 +227,7 @@ public CollectionOptions failOnValidationError() {
219227
public CollectionOptions schemaValidationLevel(ValidationLevel validationLevel) {
220228

221229
Assert.notNull(validationLevel, "ValidationLevel must not be null!");
222-
return validation(new Validator(validator.schema, validator.validatorDefinition, validationLevel, validator.validationAction));
230+
return validation(validationOptions.validationLevel(validationLevel));
223231
}
224232

225233
/**
@@ -233,20 +241,20 @@ public CollectionOptions schemaValidationLevel(ValidationLevel validationLevel)
233241
public CollectionOptions schemaValidationAction(ValidationAction validationAction) {
234242

235243
Assert.notNull(validationAction, "ValidationAction must not be null!");
236-
return validation(new Validator(validator.schema, validator.validatorDefinition, validator.validationLevel, validationAction));
244+
return validation(validationOptions.validationAction(validationAction));
237245
}
238246

239247
/**
240-
* Create new {@link CollectionOptions} with the given {@link Validator}.
248+
* Create new {@link CollectionOptions} with the given {@link ValidationOptions}.
241249
*
242-
* @param validator must not be {@literal null}. Use {@link Validator#none()} to remove validation.
250+
* @param validationOptions must not be {@literal null}. Use {@link ValidationOptions#none()} to remove validation.
243251
* @return new {@link CollectionOptions}.
244252
* @since 2.1
245253
*/
246-
public CollectionOptions validation(Validator validator) {
254+
public CollectionOptions validation(ValidationOptions validationOptions) {
247255

248-
Assert.notNull(validator, "Validator must not be null!");
249-
return new CollectionOptions(size, maxDocuments, capped, collation, validator);
256+
Assert.notNull(validationOptions, "ValidationOptions must not be null!");
257+
return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions);
250258
}
251259

252260
/**
@@ -293,47 +301,72 @@ public Optional<Collation> getCollation() {
293301
* @return {@link Optional#empty()} if not set.
294302
* @since 2.1
295303
*/
296-
public Optional<Validator> getValidator() {
297-
return validator.isEmpty() ? Optional.empty() : Optional.of(validator);
304+
public Optional<ValidationOptions> getValidationOptions() {
305+
return validationOptions.isEmpty() ? Optional.empty() : Optional.of(validationOptions);
298306
}
299307

300308
/**
301-
* Encapsulation of Validator options.
309+
* Encapsulation of ValidationOptions options.
302310
*
303311
* @author Christoph Strobl
304312
* @author Andreas Zink
305313
* @since 2.1
306314
*/
307315
@RequiredArgsConstructor
308-
public static class Validator {
316+
public static class ValidationOptions {
309317

310-
private static final Validator NONE = new Validator(null, null, null, null);
318+
private static final ValidationOptions NONE = new ValidationOptions(null, null, null);
311319

312-
private final @Nullable MongoJsonSchema schema;
313-
private final @Nullable ValidatorDefinition validatorDefinition;
320+
private final @Nullable Validator validator;
314321
private final @Nullable ValidationLevel validationLevel;
315322
private final @Nullable ValidationAction validationAction;
316323

317324
/**
318-
* Create an empty {@link Validator}.
325+
* Create an empty {@link ValidationOptions}.
319326
*
320327
* @return never {@literal null}.
321328
*/
322-
public static Validator none() {
329+
public static ValidationOptions none() {
323330
return NONE;
324331
}
325332

326333
/**
327-
* Get the {@code $jsonSchema} used for validation.
334+
* Define the {@link Validator} to be used for document validation.
328335
*
329-
* @return {@link Optional#empty()} if not set.
336+
* @param validator can be {@literal null}.
337+
* @return new instance of {@link ValidationOptions}.
338+
*/
339+
public ValidationOptions validator(@Nullable Validator validator) {
340+
return new ValidationOptions(validator, validationLevel, validationAction);
341+
}
342+
343+
/**
344+
* Define the validation level to apply.
345+
*
346+
* @param validationLevel can be {@literal null}.
347+
* @return new instance of {@link ValidationOptions}.
348+
*/
349+
public ValidationOptions validationLevel(ValidationLevel validationLevel) {
350+
return new ValidationOptions(validator, validationLevel, validationAction);
351+
}
352+
353+
/**
354+
* Define the validation action to take.
355+
*
356+
* @param validationAction can be {@literal null}.
357+
* @return new instance of {@link ValidationOptions}.
330358
*/
331-
public Optional<MongoJsonSchema> getSchema() {
332-
return Optional.ofNullable(schema);
359+
public ValidationOptions validationAction(ValidationAction validationAction) {
360+
return new ValidationOptions(validator, validationLevel, validationAction);
333361
}
334362

335-
public Optional<ValidatorDefinition> getValidatorDefinition() {
336-
return Optional.ofNullable(validatorDefinition);
363+
/**
364+
* Get the {@link Validator} to use.
365+
*
366+
* @return never {@literal null}.
367+
*/
368+
public Optional<Validator> getValidator() {
369+
return Optional.ofNullable(validator);
337370
}
338371

339372
/**
@@ -358,7 +391,7 @@ public Optional<ValidationAction> getValidationAction() {
358391
* @return {@literal true} if no arguments set.
359392
*/
360393
boolean isEmpty() {
361-
return !Optionals.isAnyPresent(getSchema(), getValidatorDefinition(), getValidationAction(), getValidationLevel());
394+
return !Optionals.isAnyPresent(getValidator(), getValidationAction(), getValidationLevel());
362395
}
363396
}
364397
}

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

+30-12
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
6464
import org.springframework.data.mongodb.MongoDbFactory;
6565
import org.springframework.data.mongodb.core.BulkOperations.BulkMode;
66-
import org.springframework.data.mongodb.core.CollectionOptions.Validator;
66+
import org.springframework.data.mongodb.core.CollectionOptions.ValidationOptions;
6767
import org.springframework.data.mongodb.core.DefaultBulkOperations.BulkOperationContext;
6868
import org.springframework.data.mongodb.core.aggregation.Aggregation;
6969
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;
@@ -108,6 +108,8 @@
108108
import org.springframework.data.mongodb.core.query.NearQuery;
109109
import org.springframework.data.mongodb.core.query.Query;
110110
import org.springframework.data.mongodb.core.query.Update;
111+
import org.springframework.data.mongodb.core.validation.JsonSchemaValidator;
112+
import org.springframework.data.mongodb.core.validation.Validator;
111113
import org.springframework.data.mongodb.util.MongoClientVersion;
112114
import org.springframework.data.projection.ProjectionInformation;
113115
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
@@ -139,10 +141,16 @@
139141
import com.mongodb.client.MongoCursor;
140142
import com.mongodb.client.MongoDatabase;
141143
import com.mongodb.client.MongoIterable;
142-
import com.mongodb.client.model.*;
144+
import com.mongodb.client.model.CountOptions;
145+
import com.mongodb.client.model.CreateCollectionOptions;
146+
import com.mongodb.client.model.DeleteOptions;
147+
import com.mongodb.client.model.Filters;
148+
import com.mongodb.client.model.FindOneAndDeleteOptions;
149+
import com.mongodb.client.model.FindOneAndUpdateOptions;
150+
import com.mongodb.client.model.ReturnDocument;
151+
import com.mongodb.client.model.UpdateOptions;
143152
import com.mongodb.client.model.ValidationAction;
144153
import com.mongodb.client.model.ValidationLevel;
145-
import com.mongodb.client.model.ValidationOptions;
146154
import com.mongodb.client.result.DeleteResult;
147155
import com.mongodb.client.result.UpdateResult;
148156
import com.mongodb.util.JSONParseException;
@@ -2236,7 +2244,7 @@ public MongoCollection<Document> doInDB(MongoDatabase db) throws MongoException,
22362244

22372245
if (collectionOptions.containsKey("validator")) {
22382246

2239-
ValidationOptions options = new ValidationOptions();
2247+
com.mongodb.client.model.ValidationOptions options = new com.mongodb.client.model.ValidationOptions();
22402248

22412249
if (collectionOptions.containsKey("validationLevel")) {
22422250
options.validationLevel(ValidationLevel.fromString(collectionOptions.getString("validationLevel")));
@@ -2377,10 +2385,10 @@ protected Document convertToDocument(@Nullable CollectionOptions collectionOptio
23772385

23782386
Document doc = convertToDocument(collectionOptions);
23792387

2380-
if (collectionOptions != null && collectionOptions.getValidator().isPresent()) {
2388+
if (collectionOptions != null && collectionOptions.getValidationOptions().isPresent()) {
23812389

2382-
Validator v = collectionOptions.getValidator().get();
2383-
v.getSchema().ifPresent(val -> doc.put("validator", schemaMapper.mapSchema(val.toDocument(), targetType)));
2390+
ValidationOptions v = collectionOptions.getValidationOptions().get();
2391+
v.getValidator().ifPresent(val -> doc.put("validator", getMappedValidator(val, targetType)));
23842392
}
23852393
return doc;
23862394
}
@@ -2401,18 +2409,28 @@ protected Document convertToDocument(@Nullable CollectionOptions collectionOptio
24012409
collectionOptions.getMaxDocuments().ifPresent(val -> document.put("max", val));
24022410
collectionOptions.getCollation().ifPresent(val -> document.append("collation", val.toDocument()));
24032411

2404-
if (collectionOptions.getValidator().isPresent()) {
2405-
Validator v = collectionOptions.getValidator().get();
2412+
if (collectionOptions.getValidationOptions().isPresent()) {
2413+
2414+
CollectionOptions.ValidationOptions v = collectionOptions.getValidationOptions().get();
24062415
v.getValidationLevel().ifPresent(val -> document.append("validationLevel", val.getValue()));
24072416
v.getValidationAction().ifPresent(val -> document.append("validationAction", val.getValue()));
2408-
v.getSchema().ifPresent(val -> document.append("validator",
2409-
new MongoJsonSchemaMapper(getConverter()).mapSchema(val.toDocument(), Object.class)));
2410-
v.getValidatorDefinition().ifPresent(val -> document.put("validator", val.toDocument()));
2417+
v.getValidator().ifPresent(val -> document.append("validator", getMappedValidator(val, Object.class)));
24112418
}
24122419
}
24132420
return document;
24142421
}
24152422

2423+
Document getMappedValidator(Validator validator, Class<?> domainType) {
2424+
2425+
Document validationRules = validator.toDocument();
2426+
2427+
if (validator instanceof JsonSchemaValidator || validationRules.containsKey("$jsonSchema")) {
2428+
return schemaMapper.mapSchema(validationRules, domainType);
2429+
}
2430+
2431+
return queryMapper.getMappedObject(validationRules, mappingContext.getPersistentEntity(domainType));
2432+
}
2433+
24162434
/**
24172435
* Map the results of an ad-hoc query on the default MongoDB collection to an object using the template's converter.
24182436
* The first document that matches the query is returned and also removed from the collection in the database.

0 commit comments

Comments
 (0)