DATAMONGO-1049 - Check for explicitly declared language field.

We now check for an explicitly declared language field for setting language_override within a text index. Therefore the attribute (even if named with the reserved keyword language) has to be explicitly marked with @Language. Prior to this change having:

@Language String lang;
String language;

would have caused trouble when trying to resolve index structures as one cannot set language override to more than one property.

Original pull request: #224.
This commit is contained in:
Christoph Strobl
2014-09-15 14:43:58 +02:00
committed by Oliver Gierke
parent dc037dfef6
commit 161fd8c09d
4 changed files with 100 additions and 25 deletions

View File

@@ -220,7 +220,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
}
private void appendTextIndexInformation(final String dotPath,
final TextIndexDefinitionBuilder indexDefinitionBuilder, MongoPersistentEntity<?> entity,
final TextIndexDefinitionBuilder indexDefinitionBuilder, final MongoPersistentEntity<?> entity,
final TextIndexIncludeOptions includeOptions, final CycleGuard guard) {
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
@@ -230,7 +230,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
guard.protect(persistentProperty, dotPath);
if (persistentProperty.isLanguageProperty()) {
if (persistentProperty.isExplicitLanguageProperty() && !StringUtils.hasText(dotPath)) {
indexDefinitionBuilder.withLanguageOverride(persistentProperty.getFieldName());
}
@@ -257,6 +257,10 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
mappingContext.getPersistentEntity(persistentProperty.getActualType()), optionsForNestedType, guard);
} catch (CyclicPropertyReferenceException e) {
LOGGER.warn(e.getMessage(), e);
} catch (InvalidDataAccessApiUsageException e) {
LOGGER.warn(
String.format("Potentially invald index structure discovered. Breaking operation for %s.",
entity.getName()), e);
}
} else if (includeOptions.isForce() || indexed != null) {
indexDefinitionBuilder.onField(propertyDotPath, weight);

View File

@@ -190,9 +190,18 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
*/
@Override
public boolean isLanguageProperty() {
return getFieldName().equals(LANGUAGE_FIELD_NAME) || isAnnotationPresent(Language.class);
return getFieldName().equals(LANGUAGE_FIELD_NAME) || isExplicitLanguageProperty();
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#isExplicitLanguageProperty()
*/
@Override
public boolean isExplicitLanguageProperty() {
return isAnnotationPresent(Language.class);
};
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#isTextScoreProperty()

View File

@@ -61,14 +61,22 @@ public interface MongoPersistentProperty extends PersistentProperty<MongoPersist
boolean isExplicitIdProperty();
/**
* Returns whether the property indicates the documents language either by having a {@link #getFieldName()} equal to
* {@literal language} or being annotated with {@link Language}.
* Returns true whether the property indicates the documents language either by having a {@link #getFieldName()} equal
* to {@literal language} or being annotated with {@link Language}.
*
* @return
* @since 1.6
*/
boolean isLanguageProperty();
/**
* Returns true when property being annotated with {@link Language}.
*
* @return
* @since 1.6.1
*/
boolean isExplicitLanguageProperty();
/**
* Returns whether the property holds the documents score calculated by text search. <br/>
* It's marked with {@link TextScore}.

View File

@@ -15,10 +15,7 @@
*/
package org.springframework.data.mongodb.core.index;
import static org.hamcrest.collection.IsCollectionWithSize.*;
import static org.hamcrest.collection.IsEmptyCollection.*;
import static org.hamcrest.core.IsEqual.*;
import static org.hamcrest.core.IsInstanceOf.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
@@ -26,8 +23,6 @@ import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.List;
import org.hamcrest.collection.IsEmptyCollection;
import org.hamcrest.core.IsEqual;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@@ -461,7 +456,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
indexDefinitions.get(0));
DBObject weights = DBObjectTestUtils.getAsDBObject(indexDefinitions.get(0).getIndexOptions(), "weights");
assertThat(weights.get("nested.foo"), IsEqual.<Object> equalTo(5F));
assertThat(weights.get("nested.foo"), is((Object) 5F));
}
/**
@@ -476,8 +471,8 @@ public class MongoPersistentEntityIndexResolverUnitTests {
"textIndexOnNestedWithMostSpecificValueRoot", indexDefinitions.get(0));
DBObject weights = DBObjectTestUtils.getAsDBObject(indexDefinitions.get(0).getIndexOptions(), "weights");
assertThat(weights.get("nested.foo"), IsEqual.<Object> equalTo(5F));
assertThat(weights.get("nested.bar"), IsEqual.<Object> equalTo(10F));
assertThat(weights.get("nested.foo"), is((Object) 5F));
assertThat(weights.get("nested.bar"), is((Object) 10F));
}
/**
@@ -487,17 +482,57 @@ public class MongoPersistentEntityIndexResolverUnitTests {
public void shouldSetDefaultLanguageCorrectly() {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(DocumentWithDefaultLanguage.class);
assertThat(indexDefinitions.get(0).getIndexOptions().get("default_language"), IsEqual.<Object> equalTo("spanish"));
assertThat(indexDefinitions.get(0).getIndexOptions().get("default_language"), is((Object) "spanish"));
}
/**
* @see DATAMONGO-937
* @see DATAMONGO-937, DATAMONGO-1049
*/
@Test
public void shouldResolveTextIndexLanguageOverrideCorrectly() {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(DocumentWithLanguageOverrideOnNestedElementRoot.class);
assertThat(indexDefinitions.get(0).getIndexOptions().get("language_override"), IsEqual.<Object> equalTo("lang"));
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(DocumentWithLanguageOverride.class);
assertThat(indexDefinitions.get(0).getIndexOptions().get("language_override"), is((Object) "lang"));
}
/**
* @see DATAMONGO-1049
*/
@Test
public void shouldIgnoreTextIndexLanguageOverrideOnNestedElements() {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(DocumentWithLanguageOverrideOnNestedElement.class);
assertThat(indexDefinitions.get(0).getIndexOptions().get("language_override"), is(nullValue()));
}
/**
* @see DATAMONGO-1049
*/
@Test
public void shouldNotCreateIndexDefinitionWhenOnlyLanguageButNoTextIndexPresent() {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(DocumentWithNoTextIndexPropertyButReservedFieldLanguage.class);
assertThat(indexDefinitions, is(empty()));
}
/**
* @see DATAMONGO-1049
*/
@Test
public void shouldNotCreateIndexDefinitionWhenOnlyAnnotatedLanguageButNoTextIndexPresent() {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(DocumentWithNoTextIndexPropertyButReservedFieldLanguageAnnotated.class);
assertThat(indexDefinitions, is(empty()));
}
/**
* @see DATAMONGO-1049
*/
@Test
public void shouldPreferExplicitlyAnnotatedLanguageProperty() {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(DocumentWithOverlappingLanguageProps.class);
assertThat(indexDefinitions.get(0).getIndexOptions().get("language_override"), is((Object) "lang"));
}
@Document
@@ -527,14 +562,12 @@ public class MongoPersistentEntityIndexResolverUnitTests {
static class TextIndexOnNested {
String foo;
}
@Document
static class TextIndexOnNestedWithWeightRoot {
@TextIndexed(weight = 5) TextIndexOnNested nested;
}
@Document
@@ -554,18 +587,39 @@ public class MongoPersistentEntityIndexResolverUnitTests {
}
@Document
static class DocumentWithLanguageOverrideOnNestedElementRoot {
static class DocumentWithLanguageOverrideOnNestedElement {
DocumentWithLanguageOverrideOnNestedElement nested;
DocumentWithLanguageOverride nested;
}
static class DocumentWithLanguageOverrideOnNestedElement {
@Document
static class DocumentWithLanguageOverride {
@TextIndexed String foo;
@Language String lang;
}
@Document
static class DocumentWithNoTextIndexPropertyButReservedFieldLanguage {
String language;
}
@Document
static class DocumentWithNoTextIndexPropertyButReservedFieldLanguageAnnotated {
@Field("language") String lang;
}
@Document
static class DocumentWithOverlappingLanguageProps {
@TextIndexed String foo;
String language;
@Language String lang;
}
}
public static class MixedIndexResolutionTests {
@@ -670,7 +724,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
public void shouldDetectSelfCycleViaCollectionTypeCorrectly() {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(SelfCyclingViaCollectionType.class);
assertThat(indexDefinitions, IsEmptyCollection.empty());
assertThat(indexDefinitions, empty());
}
/**
@@ -680,7 +734,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
public void shouldNotDetectCycleWhenTypeIsUsedMoreThanOnce() {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(MultipleObjectsOfSameType.class);
assertThat(indexDefinitions, IsEmptyCollection.empty());
assertThat(indexDefinitions, empty());
}
/**