Skip to content

DATAMONGO-1322 - Add support for validator when creating collection. #511

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.Optional;

import org.springframework.data.mongodb.core.query.Collation;
import org.springframework.data.mongodb.core.validation.ValidationOptions;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

Expand All @@ -27,13 +28,15 @@
* @author Thomas Risberg
* @author Christoph Strobl
* @author Mark Paluch
* @author Andreas Zink
*/
public class CollectionOptions {

private @Nullable Long maxDocuments;
private @Nullable Long size;
private @Nullable Boolean capped;
private @Nullable Collation collation;
private @Nullable ValidationOptions validation;

/**
* Constructs a new <code>CollectionOptions</code> instance.
Expand All @@ -46,16 +49,17 @@ public class CollectionOptions {
*/
@Deprecated
public CollectionOptions(@Nullable Long size, @Nullable Long maxDocuments, @Nullable Boolean capped) {
this(size, maxDocuments, capped, null);
this(size, maxDocuments, capped, null, null);
}

private CollectionOptions(@Nullable Long size, @Nullable Long maxDocuments, @Nullable Boolean capped,
@Nullable Collation collation) {
@Nullable Collation collation, @Nullable ValidationOptions validation) {

this.maxDocuments = maxDocuments;
this.size = size;
this.capped = capped;
this.collation = collation;
this.validation = validation;
}

/**
Expand All @@ -69,7 +73,7 @@ public static CollectionOptions just(Collation collation) {

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

return new CollectionOptions(null, null, null, collation);
return new CollectionOptions(null, null, null, collation, null);
}

/**
Expand All @@ -79,7 +83,7 @@ public static CollectionOptions just(Collation collation) {
* @since 2.0
*/
public static CollectionOptions empty() {
return new CollectionOptions(null, null, null, null);
return new CollectionOptions(null, null, null, null, null);
}

/**
Expand All @@ -90,7 +94,7 @@ public static CollectionOptions empty() {
* @since 2.0
*/
public CollectionOptions capped() {
return new CollectionOptions(size, maxDocuments, true, collation);
return new CollectionOptions(size, maxDocuments, true, collation, validation);
}

/**
Expand All @@ -101,7 +105,7 @@ public CollectionOptions capped() {
* @since 2.0
*/
public CollectionOptions maxDocuments(long maxDocuments) {
return new CollectionOptions(size, maxDocuments, capped, collation);
return new CollectionOptions(size, maxDocuments, capped, collation, validation);
}

/**
Expand All @@ -112,7 +116,7 @@ public CollectionOptions maxDocuments(long maxDocuments) {
* @since 2.0
*/
public CollectionOptions size(long size) {
return new CollectionOptions(size, maxDocuments, capped, collation);
return new CollectionOptions(size, maxDocuments, capped, collation, validation);
}

/**
Expand All @@ -123,7 +127,18 @@ public CollectionOptions size(long size) {
* @since 2.0
*/
public CollectionOptions collation(@Nullable Collation collation) {
return new CollectionOptions(size, maxDocuments, capped, collation);
return new CollectionOptions(size, maxDocuments, capped, collation, validation);
}

/**
* Create new {@link CollectionOptions} with already given settings and {@link ValidationOptions} set to given value.
*
* @param validation can be {@literal null}.
* @return new {@link CollectionOptions}.
* @since 2.1
*/
public CollectionOptions validation(@Nullable ValidationOptions validation) {
return new CollectionOptions(size, maxDocuments, capped, collation, validation);
}

/**
Expand Down Expand Up @@ -163,4 +178,8 @@ public Optional<Boolean> getCapped() {
public Optional<Collation> getCollation() {
return Optional.ofNullable(collation);
}

public Optional<ValidationOptions> getValidation() {
return Optional.ofNullable(validation);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.ReturnDocument;
import com.mongodb.client.model.UpdateOptions;
import com.mongodb.client.model.ValidationAction;
import com.mongodb.client.model.ValidationLevel;
import com.mongodb.client.model.ValidationOptions;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.mongodb.util.JSONParseException;
Expand All @@ -173,6 +176,7 @@
* @author Laszlo Csontos
* @author Maninder Singh
* @author Borislav Rangelov
* @author Andreas Zink
*/
@SuppressWarnings("deprecation")
public class MongoTemplate implements MongoOperations, ApplicationContextAware, IndexOperationsProvider {
Expand Down Expand Up @@ -2160,6 +2164,21 @@ public MongoCollection<Document> doInDB(MongoDatabase db) throws MongoException,
co.collation(IndexConverters.fromDocument(collectionOptions.get("collation", Document.class)));
}

if (collectionOptions.containsKey("validator")) {
ValidationOptions validationOptions = new ValidationOptions();
validationOptions.validator(collectionOptions.get("validator", Document.class));

if (collectionOptions.containsKey("validationLevel")) {
validationOptions
.validationLevel(ValidationLevel.fromString(collectionOptions.get("validationLevel", String.class)));
}
if (collectionOptions.containsKey("validationAction")) {
validationOptions
.validationAction(ValidationAction.fromString(collectionOptions.get("validationAction", String.class)));
}
co.validationOptions(validationOptions);
}

db.createCollection(collectionName, co);

MongoCollection<Document> coll = db.getCollection(collectionName, Document.class);
Expand Down Expand Up @@ -2281,6 +2300,11 @@ protected Document convertToDocument(@Nullable CollectionOptions collectionOptio
collectionOptions.getSize().ifPresent(val -> document.put("size", val));
collectionOptions.getMaxDocuments().ifPresent(val -> document.put("max", val));
collectionOptions.getCollation().ifPresent(val -> document.append("collation", val.toDocument()));
collectionOptions.getValidation().ifPresent(val -> {
document.append("validator", val.getValidator().toDocument());
val.getValidationLevel().ifPresent(level -> document.append("validationLevel", level.getValue()));
val.getValidationAction().ifPresent(action -> document.append("validationAction", action.getValue()));
});
}
return document;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 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.
* 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.validation;

import lombok.EqualsAndHashCode;

import org.bson.Document;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;

/**
* Utility to build a MongoDB {@code validator} based on a {@link CriteriaDefinition}.
*
* @author Andreas Zink
* @since 2.1
* @see Criteria
*/
@EqualsAndHashCode
public class CriteriaValidator implements ValidatorDefinition {

private final Document document;

private CriteriaValidator(Document document) {
Assert.notNull(document, "Document must not be null!");
this.document = document;
}

/**
* Builds a {@code validator} object, which is basically setup of query operators, based on a
* {@link CriteriaDefinition} instance.
*
* @param criteria the criteria to build the {@code validator} from
* @return
*/
public static CriteriaValidator fromCriteria(@NonNull CriteriaDefinition criteria) {
Assert.notNull(criteria, "Criteria must not be null!");
return new CriteriaValidator(criteria.getCriteriaObject());
}

@Override
public Document toDocument() {
return this.document;
}

@Override
public String toString() {
return document.toString();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 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.
* 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.validation;

import lombok.Getter;

/**
* Determines whether to error on invalid documents or just warn about the violations but allow invalid documents to be
* inserted.
*
* @author Andreas Zink
* @since 2.1
* @see <a href="https://docs.mongodb.com/manual/reference/method/db.createCollection/">MongoDB Collection Options</a>
*/
public enum ValidationAction {

/**
* Documents must pass validation before the write occurs. Otherwise, the write operation fails. (MongoDB default)
*/
ERROR("error"),

/**
* Documents do not have to pass validation. If the document fails validation, the write operation logs the validation
* failure.
*/
WARN("warn");

@Getter private String value;

private ValidationAction(String value) {
this.value = value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 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.
* 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.validation;

import lombok.Getter;

/**
* Determines how strictly MongoDB applies the validation rules to existing documents during an update.
*
* @author Andreas Zink
* @since 2.1
* @see <a href="https://docs.mongodb.com/manual/reference/method/db.createCollection/">MongoDB Collection Options</a>
*/
public enum ValidationLevel {

/**
* No validation for inserts or updates.
*/
OFF("off"),

/**
* Apply validation rules to all inserts and all updates. (MongoDB default)
*/
STRICT("strict"),

/**
* Apply validation rules to inserts and to updates on existing valid documents. Do not apply rules to updates on
* existing invalid documents.
*/
MODERATE("moderate");

@Getter private String value;

private ValidationLevel(String value) {
this.value = value;
}
}
Loading