Skip to content

Commit 2024b30

Browse files
a-zinkmp911de
authored andcommitted
DATAMONGO-1322 - Add support for Criteria-based validator for collection creation.
Extended the CollectionOptions with a ValidationOptions property which corresponds to the MongoDB createCollection() parameters. A validator object can be defined using the Criteria API, or by writing a custom provider. Original pull request: spring-projects#511. Related pull request: spring-projects#525. Related ticket: DATACMNS-1835.
1 parent f2bb467 commit 2024b30

File tree

10 files changed

+521
-8
lines changed

10 files changed

+521
-8
lines changed

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

+17-5
Original file line numberDiff line numberDiff line change
@@ -21,6 +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;
2425
import org.springframework.data.util.Optionals;
2526
import org.springframework.lang.Nullable;
2627
import org.springframework.util.Assert;
@@ -34,6 +35,7 @@
3435
* @author Thomas Risberg
3536
* @author Christoph Strobl
3637
* @author Mark Paluch
38+
* @author Andreas Zink
3739
*/
3840
public class CollectionOptions {
3941

@@ -144,7 +146,11 @@ public CollectionOptions collation(@Nullable Collation collation) {
144146
* @since 2.1
145147
*/
146148
public CollectionOptions schema(@Nullable MongoJsonSchema schema) {
147-
return validation(new Validator(schema, validator.validationLevel, validator.validationAction));
149+
return validation(new Validator(schema, null, validator.validationLevel, validator.validationAction));
150+
}
151+
152+
public CollectionOptions validatorDefinition(@Nullable ValidatorDefinition definition) {
153+
return validation(new Validator(null, definition, validator.validationLevel, validator.validationAction));
148154
}
149155

150156
/**
@@ -213,7 +219,7 @@ public CollectionOptions failOnValidationError() {
213219
public CollectionOptions schemaValidationLevel(ValidationLevel validationLevel) {
214220

215221
Assert.notNull(validationLevel, "ValidationLevel must not be null!");
216-
return validation(new Validator(validator.schema, validationLevel, validator.validationAction));
222+
return validation(new Validator(validator.schema, validator.validatorDefinition, validationLevel, validator.validationAction));
217223
}
218224

219225
/**
@@ -227,7 +233,7 @@ public CollectionOptions schemaValidationLevel(ValidationLevel validationLevel)
227233
public CollectionOptions schemaValidationAction(ValidationAction validationAction) {
228234

229235
Assert.notNull(validationAction, "ValidationAction must not be null!");
230-
return validation(new Validator(validator.schema, validator.validationLevel, validationAction));
236+
return validation(new Validator(validator.schema, validator.validatorDefinition, validator.validationLevel, validationAction));
231237
}
232238

233239
/**
@@ -295,14 +301,16 @@ public Optional<Validator> getValidator() {
295301
* Encapsulation of Validator options.
296302
*
297303
* @author Christoph Strobl
304+
* @author Andreas Zink
298305
* @since 2.1
299306
*/
300307
@RequiredArgsConstructor
301308
public static class Validator {
302309

303-
private static final Validator NONE = new Validator(null, null, null);
310+
private static final Validator NONE = new Validator(null, null, null, null);
304311

305312
private final @Nullable MongoJsonSchema schema;
313+
private final @Nullable ValidatorDefinition validatorDefinition;
306314
private final @Nullable ValidationLevel validationLevel;
307315
private final @Nullable ValidationAction validationAction;
308316

@@ -324,6 +332,10 @@ public Optional<MongoJsonSchema> getSchema() {
324332
return Optional.ofNullable(schema);
325333
}
326334

335+
public Optional<ValidatorDefinition> getValidatorDefinition() {
336+
return Optional.ofNullable(validatorDefinition);
337+
}
338+
327339
/**
328340
* Get the {@code validationLevel} to apply.
329341
*
@@ -346,7 +358,7 @@ public Optional<ValidationAction> getValidationAction() {
346358
* @return {@literal true} if no arguments set.
347359
*/
348360
boolean isEmpty() {
349-
return !Optionals.isAnyPresent(getSchema(), getValidationAction(), getValidationLevel());
361+
return !Optionals.isAnyPresent(getSchema(), getValidatorDefinition(), getValidationAction(), getValidationLevel());
350362
}
351363
}
352364
}

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

+8-2
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@
140140
import com.mongodb.client.MongoDatabase;
141141
import com.mongodb.client.MongoIterable;
142142
import com.mongodb.client.model.*;
143+
import com.mongodb.client.model.ValidationAction;
144+
import com.mongodb.client.model.ValidationLevel;
145+
import com.mongodb.client.model.ValidationOptions;
143146
import com.mongodb.client.result.DeleteResult;
144147
import com.mongodb.client.result.UpdateResult;
145148
import com.mongodb.util.JSONParseException;
@@ -165,6 +168,7 @@
165168
* @author Maninder Singh
166169
* @author Borislav Rangelov
167170
* @author duozhilin
171+
* @author Andreas Zink
168172
*/
169173
@SuppressWarnings("deprecation")
170174
public class MongoTemplate implements MongoOperations, ApplicationContextAware, IndexOperationsProvider {
@@ -2374,6 +2378,7 @@ protected Document convertToDocument(@Nullable CollectionOptions collectionOptio
23742378
Document doc = convertToDocument(collectionOptions);
23752379

23762380
if (collectionOptions != null && collectionOptions.getValidator().isPresent()) {
2381+
23772382
Validator v = collectionOptions.getValidator().get();
23782383
v.getSchema().ifPresent(val -> doc.put("validator", schemaMapper.mapSchema(val.toDocument(), targetType)));
23792384
}
@@ -2398,10 +2403,11 @@ protected Document convertToDocument(@Nullable CollectionOptions collectionOptio
23982403

23992404
if (collectionOptions.getValidator().isPresent()) {
24002405
Validator v = collectionOptions.getValidator().get();
2401-
v.getValidationLevel().ifPresent(val -> document.append("validationLevel", val));
2402-
v.getValidationAction().ifPresent(val -> document.append("validationAction", val));
2406+
v.getValidationLevel().ifPresent(val -> document.append("validationLevel", val.getValue()));
2407+
v.getValidationAction().ifPresent(val -> document.append("validationAction", val.getValue()));
24032408
v.getSchema().ifPresent(val -> document.append("validator",
24042409
new MongoJsonSchemaMapper(getConverter()).mapSchema(val.toDocument(), Object.class)));
2410+
v.getValidatorDefinition().ifPresent(val -> document.put("validator", val.toDocument()));
24052411
}
24062412
}
24072413
return document;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright 2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.mongodb.core.validation;
17+
18+
import lombok.EqualsAndHashCode;
19+
20+
import org.bson.Document;
21+
import org.springframework.data.mongodb.core.query.Criteria;
22+
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
23+
import org.springframework.lang.NonNull;
24+
import org.springframework.util.Assert;
25+
26+
/**
27+
* Utility to build a MongoDB {@code validator} based on a {@link CriteriaDefinition}.
28+
*
29+
* @author Andreas Zink
30+
* @since 2.1
31+
* @see Criteria
32+
*/
33+
@EqualsAndHashCode
34+
public class CriteriaValidator implements ValidatorDefinition {
35+
36+
private final Document document;
37+
38+
private CriteriaValidator(Document document) {
39+
Assert.notNull(document, "Document must not be null!");
40+
this.document = document;
41+
}
42+
43+
/**
44+
* Builds a {@code validator} object, which is basically setup of query operators, based on a
45+
* {@link CriteriaDefinition} instance.
46+
*
47+
* @param criteria the criteria to build the {@code validator} from
48+
* @return
49+
*/
50+
public static CriteriaValidator fromCriteria(@NonNull CriteriaDefinition criteria) {
51+
Assert.notNull(criteria, "Criteria must not be null!");
52+
return new CriteriaValidator(criteria.getCriteriaObject());
53+
}
54+
55+
@Override
56+
public Document toDocument() {
57+
return this.document;
58+
}
59+
60+
@Override
61+
public String toString() {
62+
return document.toString();
63+
}
64+
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.mongodb.core.validation;
17+
18+
import lombok.Getter;
19+
20+
/**
21+
* Determines whether to error on invalid documents or just warn about the violations but allow invalid documents to be
22+
* inserted.
23+
*
24+
* @author Andreas Zink
25+
* @since 2.1
26+
* @see <a href="https://docs.mongodb.com/manual/reference/method/db.createCollection/">MongoDB Collection Options</a>
27+
*/
28+
public enum ValidationAction {
29+
30+
/**
31+
* Documents must pass validation before the write occurs. Otherwise, the write operation fails. (MongoDB default)
32+
*/
33+
ERROR("error"),
34+
35+
/**
36+
* Documents do not have to pass validation. If the document fails validation, the write operation logs the validation
37+
* failure.
38+
*/
39+
WARN("warn");
40+
41+
@Getter private String value;
42+
43+
private ValidationAction(String value) {
44+
this.value = value;
45+
}
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.mongodb.core.validation;
17+
18+
import lombok.Getter;
19+
20+
/**
21+
* Determines how strictly MongoDB applies the validation rules to existing documents during an update.
22+
*
23+
* @author Andreas Zink
24+
* @since 2.1
25+
* @see <a href="https://docs.mongodb.com/manual/reference/method/db.createCollection/">MongoDB Collection Options</a>
26+
*/
27+
public enum ValidationLevel {
28+
29+
/**
30+
* No validation for inserts or updates.
31+
*/
32+
OFF("off"),
33+
34+
/**
35+
* Apply validation rules to all inserts and all updates. (MongoDB default)
36+
*/
37+
STRICT("strict"),
38+
39+
/**
40+
* Apply validation rules to inserts and to updates on existing valid documents. Do not apply rules to updates on
41+
* existing invalid documents.
42+
*/
43+
MODERATE("moderate");
44+
45+
@Getter private String value;
46+
47+
private ValidationLevel(String value) {
48+
this.value = value;
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright 2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.mongodb.core.validation;
17+
18+
import lombok.EqualsAndHashCode;
19+
import lombok.ToString;
20+
21+
import java.util.Optional;
22+
23+
import org.springframework.data.mongodb.core.CollectionOptions;
24+
import org.springframework.lang.NonNull;
25+
import org.springframework.lang.Nullable;
26+
import org.springframework.util.Assert;
27+
28+
/**
29+
* Wraps the collection validation options.
30+
*
31+
* @author Andreas Zink
32+
* @since 2.1
33+
* @see {@link CollectionOptions}
34+
* @see <a href="https://docs.mongodb.com/manual/core/document-validation/">MongoDB Document Validation</a>
35+
* @see <a href="https://docs.mongodb.com/manual/reference/method/db.createCollection/">MongoDB Collection Options</a>
36+
*/
37+
@EqualsAndHashCode
38+
@ToString
39+
public class ValidationOptions {
40+
private ValidatorDefinition validator;
41+
private ValidationLevel validationLevel;
42+
private ValidationAction validationAction;
43+
44+
private ValidationOptions(ValidatorDefinition validator) {
45+
Assert.notNull(validator, "ValidatorDefinition must not be null!");
46+
this.validator = validator;
47+
}
48+
49+
public static ValidationOptions validator(@NonNull ValidatorDefinition validator) {
50+
return new ValidationOptions(validator);
51+
}
52+
53+
public ValidationOptions validationLevel(@Nullable ValidationLevel validationLevel) {
54+
this.validationLevel = validationLevel;
55+
return this;
56+
}
57+
58+
public ValidationOptions validationAction(@Nullable ValidationAction validationAction) {
59+
this.validationAction = validationAction;
60+
return this;
61+
}
62+
63+
public ValidatorDefinition getValidator() {
64+
return validator;
65+
}
66+
67+
public Optional<ValidationLevel> getValidationLevel() {
68+
return Optional.ofNullable(validationLevel);
69+
}
70+
71+
public Optional<ValidationAction> getValidationAction() {
72+
return Optional.ofNullable(validationAction);
73+
}
74+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.mongodb.core.validation;
17+
18+
import org.bson.Document;
19+
import org.springframework.lang.NonNull;
20+
21+
/**
22+
* Provides a {@code validator} object to be used for collection validation.
23+
*
24+
* @author Andreas Zink
25+
* @since 2.1
26+
* @see <a href="https://docs.mongodb.com/manual/reference/method/db.createCollection/">MongoDB Collection Options</a>
27+
*/
28+
public interface ValidatorDefinition {
29+
30+
/**
31+
* @return a MongoDB {@code validator} document
32+
*/
33+
public @NonNull Document toDocument();
34+
35+
}

0 commit comments

Comments
 (0)