DATAMONGO-2112 - Polishing.

Align Indexed(expireAfter) default to empty string according to the documentation. Slightly reword Javadoc.

Import DurationStyle to reuse duration parsing until Spring Framework provides a similar utility. Document ISO-8601 duration style. Prevent null index name evaluation to render "null" as String.

Convert assertions from Hamcrest to AssertJ.

Original pull request: #647.
This commit is contained in:
Mark Paluch
2019-02-26 11:22:12 +01:00
parent 8fbaba0a7c
commit 8741b85806
6 changed files with 422 additions and 196 deletions

View File

@@ -0,0 +1,216 @@
/*
* Copyright 2012-2019 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.index;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Duration format styles.
* <p/>
* Fork of {@code org.springframework.boot.convert.DurationStyle}.
*
* @author Phillip Webb
* @since 2.2
*/
enum DurationStyle {
/**
* Simple formatting, for example '1s'.
*/
SIMPLE("^([\\+\\-]?\\d+)([a-zA-Z]{0,2})$") {
@Override
public Duration parse(String value, @Nullable ChronoUnit unit) {
try {
Matcher matcher = matcher(value);
Assert.state(matcher.matches(), "Does not match simple duration pattern");
String suffix = matcher.group(2);
return (StringUtils.hasLength(suffix) ? Unit.fromSuffix(suffix) : Unit.fromChronoUnit(unit))
.parse(matcher.group(1));
} catch (Exception ex) {
throw new IllegalArgumentException("'" + value + "' is not a valid simple duration", ex);
}
}
},
/**
* ISO-8601 formatting.
*/
ISO8601("^[\\+\\-]?P.*$") {
@Override
public Duration parse(String value, @Nullable ChronoUnit unit) {
try {
return Duration.parse(value);
} catch (Exception ex) {
throw new IllegalArgumentException("'" + value + "' is not a valid ISO-8601 duration", ex);
}
}
};
private final Pattern pattern;
DurationStyle(String pattern) {
this.pattern = Pattern.compile(pattern);
}
protected final boolean matches(String value) {
return this.pattern.matcher(value).matches();
}
protected final Matcher matcher(String value) {
return this.pattern.matcher(value);
}
/**
* Parse the given value to a duration.
*
* @param value the value to parse
* @return a duration
*/
public Duration parse(String value) {
return parse(value, null);
}
/**
* Parse the given value to a duration.
*
* @param value the value to parse
* @param unit the duration unit to use if the value doesn't specify one ({@code null} will default to ms)
* @return a duration
*/
public abstract Duration parse(String value, @Nullable ChronoUnit unit);
/**
* Detect the style then parse the value to return a duration.
*
* @param value the value to parse
* @return the parsed duration
* @throws IllegalStateException if the value is not a known style or cannot be parsed
*/
public static Duration detectAndParse(String value) {
return detectAndParse(value, null);
}
/**
* Detect the style then parse the value to return a duration.
*
* @param value the value to parse
* @param unit the duration unit to use if the value doesn't specify one ({@code null} will default to ms)
* @return the parsed duration
* @throws IllegalStateException if the value is not a known style or cannot be parsed
*/
public static Duration detectAndParse(String value, @Nullable ChronoUnit unit) {
return detect(value).parse(value, unit);
}
/**
* Detect the style from the given source value.
*
* @param value the source value
* @return the duration style
* @throws IllegalStateException if the value is not a known style
*/
public static DurationStyle detect(String value) {
Assert.notNull(value, "Value must not be null");
for (DurationStyle candidate : values()) {
if (candidate.matches(value)) {
return candidate;
}
}
throw new IllegalArgumentException("'" + value + "' is not a valid duration");
}
/**
* Units that we support.
*/
enum Unit {
/**
* Milliseconds.
*/
MILLIS(ChronoUnit.MILLIS, "ms", Duration::toMillis),
/**
* Seconds.
*/
SECONDS(ChronoUnit.SECONDS, "s", Duration::getSeconds),
/**
* Minutes.
*/
MINUTES(ChronoUnit.MINUTES, "m", Duration::toMinutes),
/**
* Hours.
*/
HOURS(ChronoUnit.HOURS, "h", Duration::toHours),
/**
* Days.
*/
DAYS(ChronoUnit.DAYS, "d", Duration::toDays);
private final ChronoUnit chronoUnit;
private final String suffix;
private Function<Duration, Long> longValue;
Unit(ChronoUnit chronoUnit, String suffix, Function<Duration, Long> toUnit) {
this.chronoUnit = chronoUnit;
this.suffix = suffix;
this.longValue = toUnit;
}
public Duration parse(String value) {
return Duration.of(Long.valueOf(value), this.chronoUnit);
}
public long longValue(Duration value) {
return this.longValue.apply(value);
}
public static Unit fromChronoUnit(ChronoUnit chronoUnit) {
if (chronoUnit == null) {
return Unit.MILLIS;
}
for (Unit candidate : values()) {
if (candidate.chronoUnit == chronoUnit) {
return candidate;
}
}
throw new IllegalArgumentException("Unknown unit " + chronoUnit);
}
public static Unit fromSuffix(String suffix) {
for (Unit candidate : values()) {
if (candidate.suffix.equalsIgnoreCase(suffix)) {
return candidate;
}
}
throw new IllegalArgumentException("Unknown unit '" + suffix + "'");
}
}
}

View File

@@ -30,6 +30,7 @@ import java.lang.annotation.Target;
* @author Thomas Darimont
* @author Christoph Strobl
* @author Jordi Llach
* @author Mark Paluch
*/
@Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@@ -136,27 +137,32 @@ public @interface Indexed {
int expireAfterSeconds() default -1;
/**
* Alternative for {@link #expireAfterSeconds()} to configure the timeout after which the collection should expire.
* Defaults to an empty String for no expiry. Accepts numeric values followed by their unit of measure (d(ays),
* h(ours), m(inutes), s(seconds)) or a Spring {@literal template expression}. The expression can result in a a valid
* expiration {@link String} following the conventions already mentioned or a {@link java.time.Duration}.
* Alternative for {@link #expireAfterSeconds()} to configure the timeout after which the document should expire.
* Defaults to an empty {@link String} for no expiry. Accepts numeric values followed by their unit of measure:
* <ul>
* <li><b>d</b>: Days</li>
* <li><b>h</b>: Hours</li>
* <li><b>m</b>: Minutes</li>
* <li><b>s</b>: Seconds</li>
* <li>Alternatively: A Spring {@literal template expression}. The expression can result in a
* {@link java.time.Duration} or a valid expiration {@link String} according to the already mentioned
* conventions.</li>
* </ul>
* Supports ISO-8601 style.
*
* <pre>
* <code>
* <pre class="code">
*
* &#0064;Indexed(expireAfter = "10s")
* String expireAfterTenSeconds;
* &#0064;Indexed(expireAfter = "10s") String expireAfterTenSeconds;
*
* &#0064;Indexed(expireAfter = "1d")
* String expireAfterOneDay;
* &#0064;Indexed(expireAfter = "1d") String expireAfterOneDay;
*
* &#0064;Indexed(expireAfter = "#{&#0064;mySpringBean.timeout}")
* String expireAfterTimeoutObtainedFromSpringBean;
* </code>
* &#0064;Indexed(expireAfter = "P2D") String expireAfterTwoDays;
*
* &#0064;Indexed(expireAfter = "#{&#0064;mySpringBean.timeout}") String expireAfterTimeoutObtainedFromSpringBean;
* </pre>
*
* @return {@literal 0s} by default.
* @return empty by default.
* @since 2.2
*/
String expireAfter() default "0s";
String expireAfter() default "";
}

View File

@@ -29,12 +29,11 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.Association;
@@ -62,7 +61,6 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.NumberUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -81,7 +79,6 @@ import org.springframework.util.StringUtils;
public class MongoPersistentEntityIndexResolver implements IndexResolver {
private static final Logger LOGGER = LoggerFactory.getLogger(MongoPersistentEntityIndexResolver.class);
private static final Pattern TIMEOUT_PATTERN = Pattern.compile("(\\d+)(\\W+)?([dhms])");
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
private final MongoMappingContext mappingContext;
@@ -353,7 +350,6 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
return indexDefinitions;
}
@SuppressWarnings("deprecation")
protected IndexDefinitionHolder createCompoundIndexDefinition(String dotPath, String collection, CompoundIndex index,
MongoPersistentEntity<?> entity) {
@@ -390,8 +386,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
return new org.bson.Document(dotPath, 1);
}
Object keyDefToUse = evaluatePotentialTemplateExpression(keyDefinitionString,
getEvaluationContextForProperty(entity));
Object keyDefToUse = evaluate(keyDefinitionString, getEvaluationContextForProperty(entity));
org.bson.Document dbo = (keyDefToUse instanceof org.bson.Document) ? (org.bson.Document) keyDefToUse
: org.bson.Document.parse(ObjectUtils.nullSafeToString(keyDefToUse));
@@ -450,11 +445,11 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
indexDefinition.expire(index.expireAfterSeconds(), TimeUnit.SECONDS);
}
if (!index.expireAfter().isEmpty() && !index.expireAfter().equals("0s")) {
if (StringUtils.hasText(index.expireAfter())) {
if (index.expireAfterSeconds() >= 0) {
throw new IllegalStateException(String.format(
"@Indexed already defines an expiration timeout of %s sec. via Indexed#expireAfterSeconds. Please make to use either expireAfterSeconds or expireAfter.",
"@Indexed already defines an expiration timeout of %s seconds via Indexed#expireAfterSeconds. Please make to use either expireAfterSeconds or expireAfter.",
index.expireAfterSeconds()));
}
@@ -480,7 +475,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
/**
* Get the {@link EvaluationContext} for a given {@link PersistentEntity entity} the default one.
*
*
* @param persistentEntity can be {@literal null}
* @return
*/
@@ -546,10 +541,15 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
private String pathAwareIndexName(String indexName, String dotPath, @Nullable PersistentEntity<?, ?> entity,
@Nullable MongoPersistentProperty property) {
String nameToUse = StringUtils.hasText(indexName)
? ObjectUtils
.nullSafeToString(evaluatePotentialTemplateExpression(indexName, getEvaluationContextForProperty(entity)))
: "";
String nameToUse = "";
if (StringUtils.hasText(indexName)) {
Object result = evaluate(indexName, getEvaluationContextForProperty(entity));
if (result != null) {
nameToUse = ObjectUtils.nullSafeToString(result);
}
}
if (!StringUtils.hasText(dotPath) || (property != null && dotPath.equals(property.getFieldName()))) {
return StringUtils.hasText(nameToUse) ? nameToUse : dotPath;
@@ -607,7 +607,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
*/
private static Duration computeIndexTimeout(String timeoutValue, EvaluationContext evaluationContext) {
Object evaluatedTimeout = evaluatePotentialTemplateExpression(timeoutValue, evaluationContext);
Object evaluatedTimeout = evaluate(timeoutValue, evaluationContext);
if (evaluatedTimeout == null) {
return Duration.ZERO;
@@ -623,30 +623,11 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
return Duration.ZERO;
}
Matcher matcher = TIMEOUT_PATTERN.matcher(val);
if (matcher.find()) {
Long timeout = NumberUtils.parseNumber(matcher.group(1), Long.class);
String unit = matcher.group(3);
switch (unit) {
case "d":
return Duration.ofDays(timeout);
case "h":
return Duration.ofHours(timeout);
case "m":
return Duration.ofMinutes(timeout);
case "s":
return Duration.ofSeconds(timeout);
}
}
throw new IllegalArgumentException(
String.format("Index timeout %s cannot be parsed. Please use the following pattern '\\d+\\W?[dhms]'.", val));
return DurationStyle.detectAndParse(val);
}
@Nullable
private static Object evaluatePotentialTemplateExpression(String value, EvaluationContext evaluationContext) {
private static Object evaluate(String value, EvaluationContext evaluationContext) {
Expression expression = PARSER.parseExpression(value, ParserContext.TEMPLATE_EXPRESSION);
if (expression instanceof LiteralExpression) {

View File

@@ -15,8 +15,7 @@
*/
package org.springframework.data.mongodb.core.index;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.springframework.data.mongodb.test.util.Assertions.*;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@@ -32,6 +31,7 @@ import java.util.Optional;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
@@ -46,7 +46,6 @@ import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.test.util.Assertions;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -99,7 +98,7 @@ public class IndexingIntegrationTests {
operations.getConverter().getMappingContext().getPersistentEntity(IndexedPerson.class);
assertThat(hasIndex("_firstname", IndexedPerson.class), is(true));
assertThat(hasIndex("_firstname", IndexedPerson.class)).isTrue();
}
@Test // DATAMONGO-2188
@@ -114,7 +113,7 @@ public class IndexingIntegrationTests {
template.getConverter().getMappingContext().getPersistentEntity(IndexedPerson.class);
assertThat(hasIndex("_firstname", MongoCollectionUtils.getPreferredCollectionName(IndexedPerson.class)), is(false));
assertThat(hasIndex("_firstname", MongoCollectionUtils.getPreferredCollectionName(IndexedPerson.class))).isFalse();
}
@Test // DATAMONGO-1163
@@ -123,7 +122,7 @@ public class IndexingIntegrationTests {
operations.getConverter().getMappingContext().getPersistentEntity(IndexedPerson.class);
assertThat(hasIndex("_lastname", IndexedPerson.class), is(true));
assertThat(hasIndex("_lastname", IndexedPerson.class)).isTrue();
}
@Test // DATAMONGO-2112
@@ -140,8 +139,8 @@ public class IndexingIntegrationTests {
.findFirst();
});
Assertions.assertThat(indexInfo).isPresent();
Assertions.assertThat(indexInfo.get()).containsEntry("expireAfterSeconds", 11L);
assertThat(indexInfo).isPresent();
assertThat(indexInfo.get()).containsEntry("expireAfterSeconds", 11L);
}
@Target({ ElementType.FIELD })

View File

@@ -15,10 +15,8 @@
*/
package org.springframework.data.mongodb.core.index;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.springframework.data.mongodb.test.util.IsBsonObject.*;
import static org.springframework.data.mongodb.test.util.Assertions.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -27,11 +25,11 @@ import java.lang.annotation.Target;
import java.util.Collections;
import java.util.List;
import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
import org.springframework.core.annotation.AliasFor;
import org.springframework.data.annotation.Id;
import org.springframework.data.geo.Point;
@@ -53,12 +51,15 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.data.util.ClassTypeInformation;
/**
* Tests for {@link MongoPersistentEntityIndexResolver}.
*
* @author Christoph Strobl
* @author Mark Paluch
*/
@RunWith(Suite.class)
@SuiteClasses({ IndexResolutionTests.class, GeoSpatialIndexResolutionTests.class, CompoundIndexResolutionTests.class,
TextIndexedResolutionTests.class, MixedIndexResolutionTests.class })
@SuppressWarnings("unused")
public class MongoPersistentEntityIndexResolverUnitTests {
/**
@@ -75,7 +76,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
IndexOnLevelZero.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection("indexedProperty", "Zero", indexDefinitions.get(0));
}
@@ -84,7 +85,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(IndexOnLevelOne.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection("zero.indexedProperty", "One", indexDefinitions.get(0));
}
@@ -95,7 +96,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
IndexResolver indexResolver = IndexResolver.create(mappingContext);
Iterable<? extends IndexDefinition> definitions = indexResolver.resolveIndexFor(IndexOnLevelOne.class);
assertThat(definitions.iterator().hasNext(), is(true));
assertThat(definitions).isNotEmpty();
}
@Test // DATAMONGO-899
@@ -103,7 +104,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(IndexOnLevelTwo.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection("one.zero.indexedProperty", "Two", indexDefinitions.get(0));
}
@@ -113,7 +114,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
IndexOnLevelOneWithExplicitlyNamedField.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection("customZero.customFieldName", "indexOnLevelOneWithExplicitlyNamedField",
indexDefinitions.get(0));
}
@@ -125,7 +126,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
IndexOnLevelZero.class);
IndexDefinition indexDefinition = indexDefinitions.get(0).getIndexDefinition();
assertThat(indexDefinition.getIndexOptions(), equalTo(new org.bson.Document().append("name", "indexedProperty")));
assertThat(indexDefinition.getIndexOptions()).isEqualTo(new org.bson.Document("name", "indexedProperty"));
}
@Test // DATAMONGO-899
@@ -135,8 +136,8 @@ public class MongoPersistentEntityIndexResolverUnitTests {
WithOptionsOnIndexedProperty.class);
IndexDefinition indexDefinition = indexDefinitions.get(0).getIndexDefinition();
assertThat(indexDefinition.getIndexOptions(), equalTo(new org.bson.Document().append("name", "indexedProperty")
.append("unique", true).append("sparse", true).append("background", true).append("expireAfterSeconds", 10L)));
assertThat(indexDefinition.getIndexOptions()).isEqualTo(new org.bson.Document().append("name", "indexedProperty")
.append("unique", true).append("sparse", true).append("background", true).append("expireAfterSeconds", 10L));
}
@Test // DATAMONGO-1297
@@ -144,9 +145,9 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(WithDbRef.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions.get(0).getCollection(), equalTo("withDbRef"));
assertThat(indexDefinitions.get(0).getIndexKeys(), equalTo(new org.bson.Document().append("indexedDbRef", 1)));
assertThat(indexDefinitions).hasSize(1);
assertThat(indexDefinitions.get(0).getCollection()).isEqualTo("withDbRef");
assertThat(indexDefinitions.get(0).getIndexKeys()).isEqualTo(new org.bson.Document("indexedDbRef", 1));
}
@Test // DATAMONGO-1297
@@ -155,10 +156,9 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
WrapperOfWithDbRef.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions.get(0).getCollection(), equalTo("wrapperOfWithDbRef"));
assertThat(indexDefinitions.get(0).getIndexKeys(),
equalTo(new org.bson.Document().append("nested.indexedDbRef", 1)));
assertThat(indexDefinitions).hasSize(1);
assertThat(indexDefinitions.get(0).getCollection()).isEqualTo("wrapperOfWithDbRef");
assertThat(indexDefinitions.get(0).getIndexKeys()).isEqualTo(new org.bson.Document("nested.indexedDbRef", 1));
}
@Test // DATAMONGO-1163
@@ -167,9 +167,9 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
IndexOnMetaAnnotatedField.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions.get(0).getCollection(), equalTo("indexOnMetaAnnotatedField"));
assertThat(indexDefinitions.get(0).getIndexOptions(), equalTo(new org.bson.Document().append("name", "_name")));
assertThat(indexDefinitions).hasSize(1);
assertThat(indexDefinitions.get(0).getCollection()).isEqualTo("indexOnMetaAnnotatedField");
assertThat(indexDefinitions.get(0).getIndexOptions()).isEqualTo(new org.bson.Document("name", "_name"));
}
@Test // DATAMONGO-1373
@@ -178,13 +178,15 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
IndexedDocumentWithComposedAnnotations.class);
assertThat(indexDefinitions, hasSize(2));
assertThat(indexDefinitions).hasSize(2);
IndexDefinitionHolder indexDefinitionHolder = indexDefinitions.get(1);
assertThat(indexDefinitionHolder.getIndexKeys(), isBsonObject().containing("fieldWithMyIndexName", 1));
assertThat(indexDefinitionHolder.getIndexOptions(),
isBsonObject().containing("sparse", true).containing("unique", true).containing("name", "my_index_name"));
assertThat(indexDefinitionHolder.getIndexKeys()).containsEntry("fieldWithMyIndexName", 1);
assertThat(indexDefinitionHolder.getIndexOptions()) //
.containsEntry("sparse", true) //
.containsEntry("unique", true) //
.containsEntry("name", "my_index_name");
}
@Test // DATAMONGO-1373
@@ -193,13 +195,15 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
IndexedDocumentWithComposedAnnotations.class);
assertThat(indexDefinitions, hasSize(2));
assertThat(indexDefinitions).hasSize(2);
IndexDefinitionHolder indexDefinitionHolder = indexDefinitions.get(0);
assertThat(indexDefinitionHolder.getIndexKeys(), isBsonObject().containing("fieldWithDifferentIndexName", 1));
assertThat(indexDefinitionHolder.getIndexOptions(),
isBsonObject().containing("sparse", true).containing("name", "different_name").notContaining("unique"));
assertThat(indexDefinitionHolder.getIndexKeys()).containsEntry("fieldWithDifferentIndexName", 1);
assertThat(indexDefinitionHolder.getIndexOptions()) //
.containsEntry("sparse", true) //
.containsEntry("name", "different_name") //
.doesNotContainKey("unique");
}
@Test // DATAMONGO-2112
@@ -208,7 +212,16 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
WithExpireAfterAsPlainString.class);
Assertions.assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("expireAfterSeconds", 600L);
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("expireAfterSeconds", 600L);
}
@Test // DATAMONGO-2112
public void shouldResolveTimeoutFromIso8601String() {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
WithIso8601Style.class);
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("expireAfterSeconds", 86400L);
}
@Test // DATAMONGO-2112
@@ -217,7 +230,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
WithExpireAfterAsExpression.class);
Assertions.assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("expireAfterSeconds", 11L);
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("expireAfterSeconds", 11L);
}
@Test // DATAMONGO-2112
@@ -226,7 +239,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
WithExpireAfterAsExpressionResultingInDuration.class);
Assertions.assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("expireAfterSeconds", 100L);
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("expireAfterSeconds", 100L);
}
@Test // DATAMONGO-2112
@@ -235,9 +248,8 @@ public class MongoPersistentEntityIndexResolverUnitTests {
MongoMappingContext mappingContext = prepareMappingContext(WithInvalidExpireAfter.class);
MongoPersistentEntityIndexResolver indexResolver = new MongoPersistentEntityIndexResolver(mappingContext);
Assertions.assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> indexResolver
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> indexResolver
.resolveIndexForEntity(mappingContext.getRequiredPersistentEntity(WithInvalidExpireAfter.class)));
}
@Test // DATAMONGO-2112
@@ -246,7 +258,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
MongoMappingContext mappingContext = prepareMappingContext(WithDuplicateExpiry.class);
MongoPersistentEntityIndexResolver indexResolver = new MongoPersistentEntityIndexResolver(mappingContext);
Assertions.assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> indexResolver
assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> indexResolver
.resolveIndexForEntity(mappingContext.getRequiredPersistentEntity(WithDuplicateExpiry.class)));
}
@@ -256,7 +268,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
WithIndexNameAsExpression.class);
Assertions.assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name", "my1st");
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name", "my1st");
}
@Document("Zero")
@@ -322,13 +334,13 @@ public class MongoPersistentEntityIndexResolverUnitTests {
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
@ComposedIndexedAnnotation(indexName = "different_name", beUnique = false)
static @interface CustomIndexedAnnotation {
@interface CustomIndexedAnnotation {
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Indexed
static @interface ComposedIndexedAnnotation {
@interface ComposedIndexedAnnotation {
@AliasFor(annotation = Indexed.class, attribute = "unique")
boolean beUnique() default true;
@@ -343,7 +355,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@org.springframework.data.mongodb.core.mapping.Field
static @interface ComposedFieldAnnotation {
@interface ComposedFieldAnnotation {
@AliasFor(annotation = org.springframework.data.mongodb.core.mapping.Field.class, attribute = "value")
String name() default "_id";
@@ -354,6 +366,11 @@ public class MongoPersistentEntityIndexResolverUnitTests {
@Indexed(expireAfter = "10m") String withTimeout;
}
@Document
class WithIso8601Style {
@Indexed(expireAfter = "P1D") String withTimeout;
}
@Document
static class WithExpireAfterAsExpression {
@Indexed(expireAfter = "#{10 + 1 + 's'}") String withTimeout;
@@ -384,7 +401,6 @@ public class MongoPersistentEntityIndexResolverUnitTests {
@Retention(RetentionPolicy.RUNTIME)
@Indexed
@interface IndexedFieldAnnotation {
}
@Document
@@ -405,7 +421,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
GeoSpatialIndexOnLevelZero.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection("geoIndexedProperty", "Zero", indexDefinitions.get(0));
}
@@ -415,7 +431,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
GeoSpatialIndexOnLevelOne.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection("zero.geoIndexedProperty", "One", indexDefinitions.get(0));
}
@@ -425,7 +441,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
GeoSpatialIndexOnLevelTwo.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection("one.zero.geoIndexedProperty", "Two", indexDefinitions.get(0));
}
@@ -437,8 +453,8 @@ public class MongoPersistentEntityIndexResolverUnitTests {
IndexDefinition indexDefinition = indexDefinitions.get(0).getIndexDefinition();
assertThat(indexDefinition.getIndexOptions(), equalTo(
new org.bson.Document().append("name", "location").append("min", 1).append("max", 100).append("bits", 2)));
assertThat(indexDefinition.getIndexOptions()).isEqualTo(
new org.bson.Document().append("name", "location").append("min", 1).append("max", 100).append("bits", 2));
}
@Test // DATAMONGO-1373
@@ -449,10 +465,10 @@ public class MongoPersistentEntityIndexResolverUnitTests {
IndexDefinition indexDefinition = indexDefinitions.get(0).getIndexDefinition();
assertThat(indexDefinition.getIndexKeys(),
isBsonObject().containing("location", "geoHaystack").containing("What light?", 1));
assertThat(indexDefinition.getIndexOptions(),
isBsonObject().containing("name", "my_geo_index_name").containing("bucketSize", 2.0));
assertThat(indexDefinition.getIndexKeys()).containsEntry("location", "geoHaystack").containsEntry("What light?",
1);
assertThat(indexDefinition.getIndexOptions()).containsEntry("name", "my_geo_index_name")
.containsEntry("bucketSize", 2.0);
}
@Test // DATAMONGO-2112
@@ -461,7 +477,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
GeoIndexWithNameAsExpression.class);
Assertions.assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name", "my1st");
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name", "my1st");
}
@Document("Zero")
@@ -531,7 +547,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
CompoundIndexOnLevelZero.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection(new String[] { "foo", "bar" }, "CompoundIndexOnLevelZero", indexDefinitions.get(0));
}
@@ -542,9 +558,9 @@ public class MongoPersistentEntityIndexResolverUnitTests {
CompoundIndexOnLevelZero.class);
IndexDefinition indexDefinition = indexDefinitions.get(0).getIndexDefinition();
assertThat(indexDefinition.getIndexOptions(), equalTo(new org.bson.Document().append("name", "compound_index")
.append("unique", true).append("sparse", true).append("background", true)));
assertThat(indexDefinition.getIndexKeys(), equalTo(new org.bson.Document().append("foo", 1).append("bar", -1)));
assertThat(indexDefinition.getIndexOptions()).isEqualTo(new org.bson.Document("name", "compound_index")
.append("unique", true).append("sparse", true).append("background", true));
assertThat(indexDefinition.getIndexKeys()).isEqualTo(new org.bson.Document().append("foo", 1).append("bar", -1));
}
@Test // DATAMONGO-909
@@ -554,9 +570,9 @@ public class MongoPersistentEntityIndexResolverUnitTests {
IndexDefinedOnSuperClass.class);
IndexDefinition indexDefinition = indexDefinitions.get(0).getIndexDefinition();
assertThat(indexDefinition.getIndexOptions(), equalTo(new org.bson.Document().append("name", "compound_index")
.append("unique", true).append("sparse", true).append("background", true)));
assertThat(indexDefinition.getIndexKeys(), equalTo(new org.bson.Document().append("foo", 1).append("bar", -1)));
assertThat(indexDefinition.getIndexOptions()).isEqualTo(new org.bson.Document().append("name", "compound_index")
.append("unique", true).append("sparse", true).append("background", true));
assertThat(indexDefinition.getIndexKeys()).isEqualTo(new org.bson.Document().append("foo", 1).append("bar", -1));
}
@Test // DATAMONGO-827
@@ -566,9 +582,9 @@ public class MongoPersistentEntityIndexResolverUnitTests {
ComountIndexWithAutogeneratedName.class);
IndexDefinition indexDefinition = indexDefinitions.get(0).getIndexDefinition();
assertThat(indexDefinition.getIndexOptions(),
equalTo(new org.bson.Document().append("unique", true).append("sparse", true).append("background", true)));
assertThat(indexDefinition.getIndexKeys(), equalTo(new org.bson.Document().append("foo", 1).append("bar", -1)));
assertThat(indexDefinition.getIndexOptions())
.isEqualTo(new org.bson.Document().append("unique", true).append("sparse", true).append("background", true));
assertThat(indexDefinition.getIndexKeys()).isEqualTo(new org.bson.Document().append("foo", 1).append("bar", -1));
}
@Test // DATAMONGO-929
@@ -577,7 +593,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
CompoundIndexOnLevelOne.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection(new String[] { "zero.foo", "zero.bar" }, "CompoundIndexOnLevelOne",
indexDefinitions.get(0));
}
@@ -588,7 +604,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
CompoundIndexOnLevelOneWithEmptyIndexDefinition.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection(new String[] { "zero" }, "CompoundIndexOnLevelZeroWithEmptyIndexDef",
indexDefinitions.get(0));
}
@@ -599,7 +615,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
SingleCompoundIndex.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection(new String[] { "foo", "bar" }, "CompoundIndexOnLevelZero", indexDefinitions.get(0));
}
@@ -609,10 +625,10 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
CompoundIndexDocumentWithComposedAnnotation.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions.get(0).getIndexKeys(), isBsonObject().containing("foo", 1).containing("bar", -1));
assertThat(indexDefinitions.get(0).getIndexOptions(), isBsonObject().containing("name", "my_compound_index_name")
.containing("unique", true).containing("background", true));
assertThat(indexDefinitions).hasSize(1);
assertThat(indexDefinitions.get(0).getIndexKeys()).containsEntry("foo", 1).containsEntry("bar", -1);
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name", "my_compound_index_name")
.containsEntry("unique", true).containsEntry("background", true);
}
@Test // DATAMONGO-2112
@@ -621,7 +637,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
CompoundIndexWithNameExpression.class);
Assertions.assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name", "cmp2name");
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name", "cmp2name");
}
@Test // DATAMONGO-2112
@@ -630,7 +646,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
CompoundIndexWithDefExpression.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection(new String[] { "foo", "bar" }, "compoundIndexWithDefExpression",
indexDefinitions.get(0));
}
@@ -660,22 +676,16 @@ public class MongoPersistentEntityIndexResolverUnitTests {
unique = true)
static class SingleCompoundIndex {}
static class IndexDefinedOnSuperClass extends CompoundIndexOnLevelZero {
}
static class IndexDefinedOnSuperClass extends CompoundIndexOnLevelZero {}
@Document("ComountIndexWithAutogeneratedName")
@CompoundIndexes({ @CompoundIndex(useGeneratedName = true, def = "{'foo': 1, 'bar': -1}", background = true,
sparse = true, unique = true) })
static class ComountIndexWithAutogeneratedName {
}
static class ComountIndexWithAutogeneratedName {}
@Document("WithComposedAnnotation")
@ComposedCompoundIndex
static class CompoundIndexDocumentWithComposedAnnotation {
}
static class CompoundIndexDocumentWithComposedAnnotation {}
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
@@ -716,7 +726,8 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
TextIndexOnSinglePropertyInRoot.class);
assertThat(indexDefinitions.size(), equalTo(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection("bar", "textIndexOnSinglePropertyInRoot", indexDefinitions.get(0));
}
@@ -725,7 +736,8 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
TextIndexOnMutiplePropertiesInRoot.class);
assertThat(indexDefinitions.size(), equalTo(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection(new String[] { "foo", "bar" }, "textIndexOnMutiplePropertiesInRoot",
indexDefinitions.get(0));
}
@@ -735,7 +747,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
TextIndexOnNestedRoot.class);
assertThat(indexDefinitions.size(), equalTo(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection(new String[] { "nested.foo" }, "textIndexOnNestedRoot", indexDefinitions.get(0));
}
@@ -744,12 +756,12 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
TextIndexOnNestedWithWeightRoot.class);
assertThat(indexDefinitions.size(), equalTo(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection(new String[] { "nested.foo" }, "textIndexOnNestedWithWeightRoot",
indexDefinitions.get(0));
org.bson.Document weights = DocumentTestUtils.getAsDocument(indexDefinitions.get(0).getIndexOptions(), "weights");
assertThat(weights.get("nested.foo"), is((Object) 5F));
assertThat(weights.get("nested.foo")).isEqualTo(5F);
}
@Test // DATAMONGO-937
@@ -757,13 +769,13 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
TextIndexOnNestedWithMostSpecificValueRoot.class);
assertThat(indexDefinitions.size(), equalTo(1));
assertThat(indexDefinitions).hasSize(1);
assertIndexPathAndCollection(new String[] { "nested.foo", "nested.bar" },
"textIndexOnNestedWithMostSpecificValueRoot", indexDefinitions.get(0));
org.bson.Document weights = DocumentTestUtils.getAsDocument(indexDefinitions.get(0).getIndexOptions(), "weights");
assertThat(weights.get("nested.foo"), is((Object) 5F));
assertThat(weights.get("nested.bar"), is((Object) 10F));
assertThat(weights.get("nested.foo")).isEqualTo(5F);
assertThat(weights.get("nested.bar")).isEqualTo(10F);
}
@Test // DATAMONGO-937
@@ -771,7 +783,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
DocumentWithDefaultLanguage.class);
assertThat(indexDefinitions.get(0).getIndexOptions().get("default_language"), is((Object) "spanish"));
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("default_language", "spanish");
}
@Test // DATAMONGO-937, DATAMONGO-1049
@@ -779,7 +791,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
DocumentWithLanguageOverride.class);
assertThat(indexDefinitions.get(0).getIndexOptions().get("language_override"), is((Object) "lang"));
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("language_override", "lang");
}
@Test // DATAMONGO-1049
@@ -787,7 +799,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
DocumentWithLanguageOverrideOnNestedElement.class);
assertThat(indexDefinitions.get(0).getIndexOptions().get("language_override"), is(nullValue()));
assertThat(indexDefinitions.get(0).getIndexOptions().get("language_override")).isNull();
}
@Test // DATAMONGO-1049
@@ -795,7 +807,8 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
DocumentWithNoTextIndexPropertyButReservedFieldLanguage.class);
assertThat(indexDefinitions, is(empty()));
assertThat(indexDefinitions).isEmpty();
}
@Test // DATAMONGO-1049
@@ -803,7 +816,8 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
DocumentWithNoTextIndexPropertyButReservedFieldLanguageAnnotated.class);
assertThat(indexDefinitions, is(empty()));
assertThat(indexDefinitions).isEmpty();
}
@Test // DATAMONGO-1049
@@ -811,7 +825,8 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
DocumentWithOverlappingLanguageProps.class);
assertThat(indexDefinitions.get(0).getIndexOptions().get("language_override"), is((Object) "lang"));
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("language_override", "lang");
}
@Test // DATAMONGO-1373
@@ -821,7 +836,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
TextIndexedDocumentWithComposedAnnotation.class);
org.bson.Document weights = DocumentTestUtils.getAsDocument(indexDefinitions.get(0).getIndexOptions(), "weights");
assertThat(weights, isBsonObject().containing("foo", 99f));
assertThat(weights).containsEntry("foo", 99f);
}
@Document
@@ -919,7 +934,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@TextIndexed
static @interface ComposedTextIndexedAnnotation {
@interface ComposedTextIndexedAnnotation {
@AliasFor(annotation = TextIndexed.class, attribute = "weight")
float heavyweight() default 99f;
@@ -933,25 +948,27 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(MixedIndexRoot.class);
assertThat(indexDefinitions, hasSize(2));
assertThat(indexDefinitions.get(0).getIndexDefinition(), instanceOf(Index.class));
assertThat(indexDefinitions.get(1).getIndexDefinition(), instanceOf(GeospatialIndex.class));
assertThat(indexDefinitions).hasSize(2);
assertThat(indexDefinitions.get(0).getIndexDefinition()).isInstanceOf(Index.class);
assertThat(indexDefinitions.get(1).getIndexDefinition()).isInstanceOf(GeospatialIndex.class);
}
@Test // DATAMONGO-899
public void cyclicPropertyReferenceOverDBRefShouldNotBeTraversed() {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(Inner.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions.get(0).getIndexDefinition().getIndexKeys(),
equalTo(new org.bson.Document().append("outer", 1)));
assertThat(indexDefinitions).hasSize(1);
assertThat(indexDefinitions.get(0).getIndexDefinition().getIndexKeys())
.isEqualTo(new org.bson.Document().append("outer", 1));
}
@Test // DATAMONGO-899
public void associationsShouldNotBeTraversed() {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(Outer.class);
assertThat(indexDefinitions, empty());
assertThat(indexDefinitions).isEmpty();
}
@Test // DATAMONGO-926
@@ -959,7 +976,8 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
CycleStartingInBetween.class);
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions).hasSize(1);
}
@Test // DATAMONGO-926
@@ -968,7 +986,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(CycleLevelZero.class);
assertIndexPathAndCollection("indexedProperty", "cycleLevelZero", indexDefinitions.get(0));
assertIndexPathAndCollection("cyclicReference.indexedProperty", "cycleLevelZero", indexDefinitions.get(1));
assertThat(indexDefinitions, hasSize(2));
assertThat(indexDefinitions).hasSize(2);
}
@Test // DATAMONGO-926
@@ -976,7 +994,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(CycleOnLevelOne.class);
assertIndexPathAndCollection("reference.indexedProperty", "cycleOnLevelOne", indexDefinitions.get(0));
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions).hasSize(1);
}
@Test // DATAMONGO-926
@@ -984,11 +1002,12 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
NoCycleButIdenticallyNamedProperties.class);
assertThat(indexDefinitions).hasSize(3);
assertIndexPathAndCollection("foo", "noCycleButIdenticallyNamedProperties", indexDefinitions.get(0));
assertIndexPathAndCollection("reference.foo", "noCycleButIdenticallyNamedProperties", indexDefinitions.get(1));
assertIndexPathAndCollection("reference.deep.foo", "noCycleButIdenticallyNamedProperties",
indexDefinitions.get(2));
assertThat(indexDefinitions, hasSize(3));
}
@Test // DATAMONGO-949
@@ -997,7 +1016,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
SimilarityHolingBean.class);
assertIndexPathAndCollection("norm", "similarityHolingBean", indexDefinitions.get(0));
assertThat(indexDefinitions, hasSize(1));
assertThat(indexDefinitions).hasSize(1);
}
@Test // DATAMONGO-962
@@ -1005,7 +1024,8 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
SelfCyclingViaCollectionType.class);
assertThat(indexDefinitions, empty());
assertThat(indexDefinitions).isEmpty();
}
@Test // DATAMONGO-962
@@ -1013,14 +1033,15 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
MultipleObjectsOfSameType.class);
assertThat(indexDefinitions, empty());
assertThat(indexDefinitions).isEmpty();
}
@Test // DATAMONGO-962
@SuppressWarnings({ "rawtypes", "unchecked" })
public void shouldCatchCyclicReferenceExceptionOnRoot() {
MongoPersistentEntity entity = new BasicMongoPersistentEntity<Object>(ClassTypeInformation.from(Object.class));
MongoPersistentEntity entity = new BasicMongoPersistentEntity<>(ClassTypeInformation.from(Object.class));
MongoPersistentProperty propertyMock = mock(MongoPersistentProperty.class);
when(propertyMock.isEntity()).thenReturn(true);
@@ -1028,7 +1049,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
when(propertyMock.getActualType()).thenThrow(
new MongoPersistentEntityIndexResolver.CyclicPropertyReferenceException("foo", Object.class, "bar"));
MongoPersistentEntity<SelfCyclingViaCollectionType> selfCyclingEntity = new BasicMongoPersistentEntity<SelfCyclingViaCollectionType>(
MongoPersistentEntity<SelfCyclingViaCollectionType> selfCyclingEntity = new BasicMongoPersistentEntity<>(
ClassTypeInformation.from(SelfCyclingViaCollectionType.class));
new MongoPersistentEntityIndexResolver(prepareMappingContext(SelfCyclingViaCollectionType.class))
@@ -1041,9 +1062,9 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
NoCycleManyPathsToDeepValueObject.class);
assertThat(indexDefinitions).hasSize(2);
assertIndexPathAndCollection("l3.valueObject.value", "rules", indexDefinitions.get(0));
assertIndexPathAndCollection("l2.l3.valueObject.value", "rules", indexDefinitions.get(1));
assertThat(indexDefinitions, hasSize(2));
}
@Test // DATAMONGO-1025
@@ -1051,8 +1072,9 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
DocumentWithNestedDocumentHavingNamedCompoundIndex.class);
assertThat((String) indexDefinitions.get(0).getIndexOptions().get("name"),
equalTo("propertyOfTypeHavingNamedCompoundIndex.c_index"));
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name",
"propertyOfTypeHavingNamedCompoundIndex.c_index");
}
@Test // DATAMONGO-1025
@@ -1060,8 +1082,8 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
DocumentWithNestedTypeHavingNamedCompoundIndex.class);
assertThat((String) indexDefinitions.get(0).getIndexOptions().get("name"),
equalTo("propertyOfTypeHavingNamedCompoundIndex.c_index"));
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name",
"propertyOfTypeHavingNamedCompoundIndex.c_index");
}
@Test // DATAMONGO-1025
@@ -1069,8 +1091,9 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
DocumentWithNestedDocumentHavingNamedIndex.class);
assertThat((String) indexDefinitions.get(0).getIndexOptions().get("name"),
equalTo("propertyOfTypeHavingNamedIndex.property_index"));
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name",
"propertyOfTypeHavingNamedIndex.property_index");
}
@Test // DATAMONGO-1025
@@ -1078,8 +1101,9 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
DocumentWithNestedTypeHavingNamedIndex.class);
assertThat((String) indexDefinitions.get(0).getIndexOptions().get("name"),
equalTo("propertyOfTypeHavingNamedIndex.property_index"));
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name",
"propertyOfTypeHavingNamedIndex.property_index");
}
@Test // DATAMONGO-1025
@@ -1087,7 +1111,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
DocumentWithNamedIndex.class);
assertThat((String) indexDefinitions.get(0).getIndexOptions().get("name"), equalTo("property_index"));
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name", "property_index");
}
@Test // DATAMONGO-1087
@@ -1096,9 +1120,9 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
MultiplePropertiesOfSameTypeWithMatchingStartLetters.class);
assertThat(indexDefinitions, hasSize(2));
assertThat((String) indexDefinitions.get(0).getIndexOptions().get("name"), equalTo("name.component"));
assertThat((String) indexDefinitions.get(1).getIndexOptions().get("name"), equalTo("nameLast.component"));
assertThat(indexDefinitions).hasSize(2);
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name", "name.component");
assertThat(indexDefinitions.get(1).getIndexOptions()).containsEntry("name", "nameLast.component");
}
@Test // DATAMONGO-1087
@@ -1107,9 +1131,9 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
MultiplePropertiesOfSameTypeWithMatchingStartLettersOnNestedProperty.class);
assertThat(indexDefinitions, hasSize(2));
assertThat((String) indexDefinitions.get(0).getIndexOptions().get("name"), equalTo("component.nameLast"));
assertThat((String) indexDefinitions.get(1).getIndexOptions().get("name"), equalTo("component.name"));
assertThat(indexDefinitions).hasSize(2);
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name", "component.nameLast");
assertThat(indexDefinitions.get(1).getIndexOptions()).containsEntry("name", "component.name");
}
@Test // DATAMONGO-1121
@@ -1118,11 +1142,10 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
OuterDocumentReferingToIndexedPropertyViaDifferentNonCyclingPaths.class);
assertThat(indexDefinitions, hasSize(2));
assertThat((String) indexDefinitions.get(0).getIndexOptions().get("name"), equalTo("path1.foo"));
assertThat((String) indexDefinitions.get(1).getIndexOptions().get("name"),
equalTo("path2.propertyWithIndexedStructure.foo"));
assertThat(indexDefinitions).hasSize(2);
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name", "path1.foo");
assertThat(indexDefinitions.get(1).getIndexOptions()).containsEntry("name",
"path2.propertyWithIndexedStructure.foo");
}
@Test // DATAMONGO-1263
@@ -1131,9 +1154,9 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
EntityWithGenericTypeWrapperAsElement.class);
assertThat(indexDefinitions, hasSize(1));
assertThat((String) indexDefinitions.get(0).getIndexOptions().get("name"),
equalTo("listWithGeneircTypeElement.entity.property_index"));
assertThat(indexDefinitions).hasSize(1);
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name",
"listWithGeneircTypeElement.entity.property_index");
}
@Document
@@ -1365,9 +1388,9 @@ public class MongoPersistentEntityIndexResolverUnitTests {
IndexDefinitionHolder holder) {
for (String expectedPath : expectedPaths) {
assertThat(holder.getIndexDefinition().getIndexKeys().containsKey(expectedPath), equalTo(true));
assertThat(holder.getIndexDefinition().getIndexKeys()).containsKey(expectedPath);
}
assertThat(holder.getCollection(), equalTo(expectedCollection));
assertThat(holder.getCollection()).isEqualTo(expectedCollection);
}
}

View File

@@ -14,6 +14,7 @@
* Kotlin extension methods accepting `KClass` are deprecated now in favor of `reified` methods.
* Support of array filters in `Update` operations.
* <<mongo.jsonSchema.generated, JSON Schema generation>> from domain types.
* SpEL support in for expressions in `@Indexed`.
[[new-features.2-1-0]]
== What's New in Spring Data MongoDB 2.1