diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionOptions.java index f0cb71f8ab..5aa36164b5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionOptions.java @@ -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; @@ -27,6 +28,7 @@ * @author Thomas Risberg * @author Christoph Strobl * @author Mark Paluch + * @author Andreas Zink */ public class CollectionOptions { @@ -34,6 +36,7 @@ public class CollectionOptions { private @Nullable Long size; private @Nullable Boolean capped; private @Nullable Collation collation; + private @Nullable ValidationOptions validation; /** * Constructs a new CollectionOptions instance. @@ -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; } /** @@ -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); } /** @@ -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); } /** @@ -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); } /** @@ -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); } /** @@ -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); } /** @@ -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); } /** @@ -163,4 +178,8 @@ public Optional getCapped() { public Optional getCollation() { return Optional.ofNullable(collation); } + + public Optional getValidation() { + return Optional.ofNullable(validation); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java index 30cec4d918..e5d83c8702 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java @@ -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; @@ -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 { @@ -2160,6 +2164,21 @@ public MongoCollection 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 coll = db.getCollection(collectionName, Document.class); @@ -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; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/CriteriaValidator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/CriteriaValidator.java new file mode 100644 index 0000000000..c6cc303859 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/CriteriaValidator.java @@ -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(); + } + +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationAction.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationAction.java new file mode 100644 index 0000000000..199e00a7d6 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationAction.java @@ -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 MongoDB Collection Options + */ +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; + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationLevel.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationLevel.java new file mode 100644 index 0000000000..187c63ca15 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationLevel.java @@ -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 MongoDB Collection Options + */ +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; + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationOptions.java new file mode 100644 index 0000000000..ebb9c0baa8 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationOptions.java @@ -0,0 +1,74 @@ +/* + * 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 lombok.ToString; + +import java.util.Optional; + +import org.springframework.data.mongodb.core.CollectionOptions; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * Wraps the collection validation options. + * + * @author Andreas Zink + * @since 2.1 + * @see {@link CollectionOptions} + * @see MongoDB Document Validation + * @see MongoDB Collection Options + */ +@EqualsAndHashCode +@ToString +public class ValidationOptions { + private ValidatorDefinition validator; + private ValidationLevel validationLevel; + private ValidationAction validationAction; + + private ValidationOptions(ValidatorDefinition validator) { + Assert.notNull(validator, "ValidatorDefinition must not be null!"); + this.validator = validator; + } + + public static ValidationOptions validator(@NonNull ValidatorDefinition validator) { + return new ValidationOptions(validator); + } + + public ValidationOptions validationLevel(@Nullable ValidationLevel validationLevel) { + this.validationLevel = validationLevel; + return this; + } + + public ValidationOptions validationAction(@Nullable ValidationAction validationAction) { + this.validationAction = validationAction; + return this; + } + + public ValidatorDefinition getValidator() { + return validator; + } + + public Optional getValidationLevel() { + return Optional.ofNullable(validationLevel); + } + + public Optional getValidationAction() { + return Optional.ofNullable(validationAction); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidatorDefinition.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidatorDefinition.java new file mode 100644 index 0000000000..50bcbb579a --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidatorDefinition.java @@ -0,0 +1,35 @@ +/* + * 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 org.bson.Document; +import org.springframework.lang.NonNull; + +/** + * Provides a {@code validator} object to be used for collection validation. + * + * @author Andreas Zink + * @since 2.1 + * @see MongoDB Collection Options + */ +public interface ValidatorDefinition { + + /** + * @return a MongoDB {@code validator} document + */ + public @NonNull Document toDocument(); + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateValidationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateValidationTests.java new file mode 100644 index 0000000000..79f90724ed --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateValidationTests.java @@ -0,0 +1,194 @@ +/* + * 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; + +import static org.assertj.core.api.Assertions.assertThat; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; + +import org.bson.Document; +import org.junit.Assert; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.config.AbstractMongoConfiguration; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.validation.CriteriaValidator; +import org.springframework.data.mongodb.core.validation.ValidationAction; +import org.springframework.data.mongodb.core.validation.ValidationLevel; +import org.springframework.data.mongodb.core.validation.ValidationOptions; +import org.springframework.data.mongodb.test.util.MongoVersionRule; +import org.springframework.data.util.Version; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.mongodb.MongoClient; + +/** + * @author Andreas Zink + */ +@RunWith(SpringJUnit4ClassRunner.class) +public class MongoTemplateValidationTests { + + public static @ClassRule MongoVersionRule REQUIRES_AT_LEAST_3_2_0 = MongoVersionRule.atLeast(Version.parse("3.2.0")); + public static final String COLLECTION_NAME = "validation-1"; + + @Configuration + static class Config extends AbstractMongoConfiguration { + + @Override + public MongoClient mongoClient() { + return new MongoClient(); + } + + @Override + protected String getDatabaseName() { + return "validation-tests"; + } + } + + @Autowired MongoTemplate template; + + @Before + public void setUp() { + template.dropCollection(COLLECTION_NAME); + } + + @Test // DATAMONGO-1322 + public void testCollectionWithSimpleCriteriaBasedValidation() { + Criteria criteria = Criteria.where("nonNullString").ne(null).type(2).and("rangedInteger").ne(null).type(16).gte(0) + .lte(122); + ValidationOptions validationOptions = ValidationOptions.validator(CriteriaValidator.fromCriteria(criteria)); + template.createCollection(COLLECTION_NAME, CollectionOptions.empty().validation(validationOptions)); + + Document validator = getValidatorInfo(COLLECTION_NAME); + assertThat(validator.get("nonNullString")).isEqualTo(new Document("$ne", null).append("$type", 2)); + assertThat(validator.get("rangedInteger")) + .isEqualTo(new Document("$ne", null).append("$type", 16).append("$gte", 0).append("$lte", 122)); + + template.save(new SimpleBean("hello", 101), COLLECTION_NAME); + try { + template.save(new SimpleBean(null, 101), COLLECTION_NAME); + Assert.fail("The collection validation was setup to check for non-null string"); + } catch (Exception e) { + // ignore + } + try { + template.save(new SimpleBean("hello", -1), COLLECTION_NAME); + Assert.fail("The collection validation was setup to check for non-negative int"); + } catch (Exception e) { + // ignore + } + } + + @Test // DATAMONGO-1322 + public void testCollectionValidationActionError() { + Criteria criteria = Criteria.where("name").type(2); + ValidationOptions validationOptions = ValidationOptions.validator(CriteriaValidator.fromCriteria(criteria)) + .validationAction(ValidationAction.ERROR); + template.createCollection(COLLECTION_NAME, CollectionOptions.empty().validation(validationOptions)); + + String validationAction = getValidationActionInfo(COLLECTION_NAME); + assertThat(ValidationAction.ERROR.getValue()).isEqualTo(validationAction); + } + + @Test // DATAMONGO-1322 + public void testCollectionValidationActionWarn() { + Criteria criteria = Criteria.where("name").type(2); + ValidationOptions validationOptions = ValidationOptions.validator(CriteriaValidator.fromCriteria(criteria)) + .validationAction(ValidationAction.WARN); + template.createCollection(COLLECTION_NAME, CollectionOptions.empty().validation(validationOptions)); + + String validationAction = getValidationActionInfo(COLLECTION_NAME); + assertThat(ValidationAction.WARN.getValue()).isEqualTo(validationAction); + } + + @Test // DATAMONGO-1322 + public void testCollectionValidationLevelOff() { + Criteria criteria = Criteria.where("name").type(2); + ValidationOptions validationOptions = ValidationOptions.validator(CriteriaValidator.fromCriteria(criteria)) + .validationLevel(ValidationLevel.OFF); + template.createCollection(COLLECTION_NAME, CollectionOptions.empty().validation(validationOptions)); + + String validationAction = getValidationLevelInfo(COLLECTION_NAME); + assertThat(ValidationLevel.OFF.getValue()).isEqualTo(validationAction); + } + + @Test // DATAMONGO-1322 + public void testCollectionValidationLevelModerate() { + Criteria criteria = Criteria.where("name").type(2); + ValidationOptions validationOptions = ValidationOptions.validator(CriteriaValidator.fromCriteria(criteria)) + .validationLevel(ValidationLevel.MODERATE); + template.createCollection(COLLECTION_NAME, CollectionOptions.empty().validation(validationOptions)); + + String validationAction = getValidationLevelInfo(COLLECTION_NAME); + assertThat(ValidationLevel.MODERATE.getValue()).isEqualTo(validationAction); + } + + @Test // DATAMONGO-1322 + public void testCollectionValidationLevelStrict() { + Criteria criteria = Criteria.where("name").type(2); + ValidationOptions validationOptions = ValidationOptions.validator(CriteriaValidator.fromCriteria(criteria)) + .validationLevel(ValidationLevel.STRICT); + template.createCollection(COLLECTION_NAME, CollectionOptions.empty().validation(validationOptions)); + + String validationAction = getValidationLevelInfo(COLLECTION_NAME); + assertThat(ValidationLevel.STRICT.getValue()).isEqualTo(validationAction); + } + + private Document getCollectionOptions(String collectionName) { + return getCollectionInfo(collectionName).get("options", Document.class); + } + + private Document getValidatorInfo(String collectionName) { + return getCollectionOptions(collectionName).get("validator", Document.class); + } + + private String getValidationActionInfo(String collectionName) { + return getCollectionOptions(collectionName).get("validationAction", String.class); + } + + private String getValidationLevelInfo(String collectionName) { + return getCollectionOptions(collectionName).get("validationLevel", String.class); + } + + private Document getCollectionInfo(String collectionName) { + return template.execute(db -> { + Document result = db.runCommand( + new Document().append("listCollections", 1).append("filter", new Document("name", collectionName))); + return (Document) result.get("cursor", Document.class).get("firstBatch", List.class).get(0); + }); + } + + @Data + @AllArgsConstructor + @NoArgsConstructor + static class SimpleBean { + @NotNull private String nonNullString; + @NotNull @Min(0) @Max(122) private Integer rangedInteger; + } + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/validation/CriteriaValidatorTest.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/validation/CriteriaValidatorTest.java new file mode 100644 index 0000000000..1279680435 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/validation/CriteriaValidatorTest.java @@ -0,0 +1,43 @@ +/* + * 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 static org.assertj.core.api.Assertions.assertThat; + +import org.bson.Document; +import org.junit.Test; +import org.springframework.data.mongodb.core.query.Criteria; + +/** + * @author Andreas Zink + */ +public class CriteriaValidatorTest { + + @Test // DATAMONGO-1322 + public void testSimpleCriteria() { + Criteria criteria = Criteria.where("nonNullString").ne(null).type(2).and("rangedInteger").type(16).gte(0).lte(122); + Document validator = CriteriaValidator.fromCriteria(criteria).toDocument(); + + assertThat(validator.get("nonNullString")).isEqualTo(new Document("$ne", null).append("$type", 2)); + assertThat(validator.get("rangedInteger")) + .isEqualTo(new Document("$type", 16).append("$gte", 0).append("$lte", 122)); + } + + @Test(expected = IllegalArgumentException.class) // DATAMONGO-1322 + public void testFailOnNull() { + CriteriaValidator.fromCriteria(null); + } +}