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 1f69513de..77e286591 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 @@ -26,6 +26,7 @@ import org.springframework.data.mongodb.core.validation.Validator; import org.springframework.data.util.Optionals; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; import com.mongodb.client.model.ValidationAction; import com.mongodb.client.model.ValidationLevel; @@ -49,8 +50,8 @@ public class CollectionOptions { private @Nullable CollectionChangeStreamOptions changeStreamOptions; private CollectionOptions(@Nullable Long size, @Nullable Long maxDocuments, @Nullable Boolean capped, - @Nullable Collation collation, ValidationOptions validationOptions, - @Nullable TimeSeriesOptions timeSeriesOptions, @Nullable CollectionChangeStreamOptions changeStreamOptions) { + @Nullable Collation collation, ValidationOptions validationOptions, @Nullable TimeSeriesOptions timeSeriesOptions, + @Nullable CollectionChangeStreamOptions changeStreamOptions) { this.maxDocuments = maxDocuments; this.size = size; @@ -104,7 +105,7 @@ public class CollectionOptions { * * @return new instance of {@link CollectionOptions}. * @see #changeStream(CollectionChangeStreamOptions) - * @see CollectionChangeStreamOptions#preAndPostImages(boolean) + * @see CollectionChangeStreamOptions#preAndPostImages(boolean) * @since 4.0 */ public static CollectionOptions emitChangedRevisions() { @@ -119,7 +120,8 @@ public class CollectionOptions { * @since 2.0 */ public CollectionOptions capped() { - return new CollectionOptions(size, maxDocuments, true, collation, validationOptions, timeSeriesOptions, changeStreamOptions); + return new CollectionOptions(size, maxDocuments, true, collation, validationOptions, timeSeriesOptions, + changeStreamOptions); } /** @@ -130,7 +132,8 @@ public class CollectionOptions { * @since 2.0 */ public CollectionOptions maxDocuments(long maxDocuments) { - return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions, changeStreamOptions); + return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions, + changeStreamOptions); } /** @@ -141,7 +144,8 @@ public class CollectionOptions { * @since 2.0 */ public CollectionOptions size(long size) { - return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions, changeStreamOptions); + return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions, + changeStreamOptions); } /** @@ -152,7 +156,8 @@ public class CollectionOptions { * @since 2.0 */ public CollectionOptions collation(@Nullable Collation collation) { - return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions, changeStreamOptions); + return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions, + changeStreamOptions); } /** @@ -272,7 +277,8 @@ public class CollectionOptions { public CollectionOptions validation(ValidationOptions validationOptions) { Assert.notNull(validationOptions, "ValidationOptions must not be null"); - return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions, changeStreamOptions); + return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions, + changeStreamOptions); } /** @@ -285,7 +291,8 @@ public class CollectionOptions { public CollectionOptions timeSeries(TimeSeriesOptions timeSeriesOptions) { Assert.notNull(timeSeriesOptions, "TimeSeriesOptions must not be null"); - return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions, changeStreamOptions); + return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions, + changeStreamOptions); } /** @@ -298,7 +305,8 @@ public class CollectionOptions { public CollectionOptions changeStream(CollectionChangeStreamOptions changeStreamOptions) { Assert.notNull(changeStreamOptions, "ChangeStreamOptions must not be null"); - return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions, changeStreamOptions); + return new CollectionOptions(size, maxDocuments, capped, collation, validationOptions, timeSeriesOptions, + changeStreamOptions); } /** @@ -369,6 +377,60 @@ public class CollectionOptions { return Optional.ofNullable(changeStreamOptions); } + @Override + public String toString() { + return "CollectionOptions{" + "maxDocuments=" + maxDocuments + ", size=" + size + ", capped=" + capped + + ", collation=" + collation + ", validationOptions=" + validationOptions + ", timeSeriesOptions=" + + timeSeriesOptions + ", changeStreamOptions=" + changeStreamOptions + ", disableValidation=" + + disableValidation() + ", strictValidation=" + strictValidation() + ", moderateValidation=" + + moderateValidation() + ", warnOnValidationError=" + warnOnValidationError() + ", failOnValidationError=" + + failOnValidationError() + '}'; + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + CollectionOptions that = (CollectionOptions) o; + + if (!ObjectUtils.nullSafeEquals(maxDocuments, that.maxDocuments)) { + return false; + } + if (!ObjectUtils.nullSafeEquals(size, that.size)) { + return false; + } + if (!ObjectUtils.nullSafeEquals(capped, that.capped)) { + return false; + } + if (!ObjectUtils.nullSafeEquals(collation, that.collation)) { + return false; + } + if (!ObjectUtils.nullSafeEquals(validationOptions, that.validationOptions)) { + return false; + } + if (!ObjectUtils.nullSafeEquals(timeSeriesOptions, that.timeSeriesOptions)) { + return false; + } + return ObjectUtils.nullSafeEquals(changeStreamOptions, that.changeStreamOptions); + } + + @Override + public int hashCode() { + int result = ObjectUtils.nullSafeHashCode(maxDocuments); + result = 31 * result + ObjectUtils.nullSafeHashCode(size); + result = 31 * result + ObjectUtils.nullSafeHashCode(capped); + result = 31 * result + ObjectUtils.nullSafeHashCode(collation); + result = 31 * result + ObjectUtils.nullSafeHashCode(validationOptions); + result = 31 * result + ObjectUtils.nullSafeHashCode(timeSeriesOptions); + result = 31 * result + ObjectUtils.nullSafeHashCode(changeStreamOptions); + return result; + } + /** * Encapsulation of ValidationOptions options. * @@ -463,6 +525,40 @@ public class CollectionOptions { boolean isEmpty() { return !Optionals.isAnyPresent(getValidator(), getValidationAction(), getValidationLevel()); } + + @Override + public String toString() { + + return "ValidationOptions{" + "validator=" + validator + ", validationLevel=" + validationLevel + + ", validationAction=" + validationAction + '}'; + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ValidationOptions that = (ValidationOptions) o; + + if (!ObjectUtils.nullSafeEquals(validator, that.validator)) { + return false; + } + if (validationLevel != that.validationLevel) + return false; + return validationAction == that.validationAction; + } + + @Override + public int hashCode() { + int result = ObjectUtils.nullSafeHashCode(validator); + result = 31 * result + ObjectUtils.nullSafeHashCode(validationLevel); + result = 31 * result + ObjectUtils.nullSafeHashCode(validationAction); + return result; + } } /** @@ -491,6 +587,30 @@ public class CollectionOptions { public boolean getPreAndPostImages() { return preAndPostImages; } + + @Override + public String toString() { + return "CollectionChangeStreamOptions{" + "preAndPostImages=" + preAndPostImages + '}'; + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + CollectionChangeStreamOptions that = (CollectionChangeStreamOptions) o; + + return preAndPostImages == that.preAndPostImages; + } + + @Override + public int hashCode() { + return (preAndPostImages ? 1 : 0); + } } /** @@ -576,5 +696,40 @@ public class CollectionOptions { public GranularityDefinition getGranularity() { return granularity; } + + @Override + public String toString() { + + return "TimeSeriesOptions{" + "timeField='" + timeField + '\'' + ", metaField='" + metaField + '\'' + + ", granularity=" + granularity + '}'; + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + TimeSeriesOptions that = (TimeSeriesOptions) o; + + if (!ObjectUtils.nullSafeEquals(timeField, that.timeField)) { + return false; + } + if (!ObjectUtils.nullSafeEquals(metaField, that.metaField)) { + return false; + } + return ObjectUtils.nullSafeEquals(granularity, that.granularity); + } + + @Override + public int hashCode() { + int result = ObjectUtils.nullSafeHashCode(timeField); + result = 31 * result + ObjectUtils.nullSafeHashCode(metaField); + result = 31 * result + ObjectUtils.nullSafeHashCode(granularity); + return result; + } } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CollectionOptionsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CollectionOptionsUnitTests.java new file mode 100644 index 000000000..e067625c7 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/CollectionOptionsUnitTests.java @@ -0,0 +1,79 @@ +/* + * Copyright 2022 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 + * + * https://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.*; +import static org.springframework.data.mongodb.core.CollectionOptions.*; + +import org.bson.Document; +import org.junit.jupiter.api.Test; +import org.springframework.data.mongodb.core.query.Collation; +import org.springframework.data.mongodb.core.validation.Validator; + +/** + * @author Christoph Strobl + */ +class CollectionOptionsUnitTests { + + @Test // GH-4210 + void emptyEquals() { + assertThat(empty()).isEqualTo(empty()); + } + + @Test // GH-4210 + void collectionProperties() { + assertThat(empty().maxDocuments(10).size(1).disableValidation()) + .isEqualTo(empty().maxDocuments(10).size(1).disableValidation()); + } + + @Test // GH-4210 + void changedRevisionsEquals() { + assertThat(emitChangedRevisions()).isNotEqualTo(empty()).isEqualTo(emitChangedRevisions()); + } + + @Test // GH-4210 + void cappedEquals() { + assertThat(empty().capped()).isNotEqualTo(empty()).isEqualTo(empty().capped()); + } + + @Test // GH-4210 + void collationEquals() { + + assertThat(empty().collation(Collation.of("en_US"))) // + .isEqualTo(empty().collation(Collation.of("en_US"))) // + .isNotEqualTo(empty()) // + .isNotEqualTo(empty().collation(Collation.of("de_AT"))); + } + + @Test // GH-4210 + void timeSeriesEquals() { + + assertThat(empty().timeSeries(TimeSeriesOptions.timeSeries("tf"))) // + .isEqualTo(empty().timeSeries(TimeSeriesOptions.timeSeries("tf"))) // + .isNotEqualTo(empty()) // + .isNotEqualTo(empty().timeSeries(TimeSeriesOptions.timeSeries("other"))); + } + + @Test // GH-4210 + void validatorEquals() { + + assertThat(empty().validator(Validator.document(new Document("one", "two")))) // + .isEqualTo(empty().validator(Validator.document(new Document("one", "two")))) // + .isNotEqualTo(empty()) // + .isNotEqualTo(empty().validator(Validator.document(new Document("three", "four")))) + .isNotEqualTo(empty().validator(Validator.document(new Document("one", "two"))).moderateValidation()); + } +}