diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java index 94fcc7df4..3ca46ed81 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MappingMongoConverterParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2012 the original author or authors. + * Copyright 2011-2013 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. @@ -54,6 +54,7 @@ import org.springframework.data.mapping.context.MappingContextIsNewStrategyFacto import org.springframework.data.mongodb.core.convert.CustomConversions; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator; +import org.springframework.data.mongodb.core.mapping.CamelCaseAbbreviatingFieldNamingStrategy; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener; @@ -200,6 +201,12 @@ public class MappingMongoConverterParser implements BeanDefinitionParser { mappingContextBuilder.addPropertyValue("simpleTypeHolder", simpleTypesDefinition); } + String abbreviateFieldNames = element.getAttribute("abbreviate-field-names"); + if ("true".equals(abbreviateFieldNames)) { + mappingContextBuilder.addPropertyValue("fieldNamingStrategy", new RootBeanDefinition( + CamelCaseAbbreviatingFieldNamingStrategy.class)); + } + ctxRef = converterId + "." + MAPPING_CONTEXT; parserContext.registerBeanComponent(componentDefinitionBuilder.getComponent(mappingContextBuilder, ctxRef)); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java index 1f16d43ab..589e42115 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2012 the original author or authors. + * Copyright 2011-2013 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. @@ -16,13 +16,19 @@ package org.springframework.data.mongodb.core.mapping; import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.expression.BeanFactoryAccessor; import org.springframework.context.expression.BeanFactoryResolver; +import org.springframework.data.mapping.Association; +import org.springframework.data.mapping.AssociationHandler; +import org.springframework.data.mapping.PropertyHandler; import org.springframework.data.mapping.model.BasicPersistentEntity; +import org.springframework.data.mapping.model.MappingException; import org.springframework.data.mongodb.MongoCollectionUtils; import org.springframework.data.util.TypeInformation; import org.springframework.expression.Expression; @@ -41,6 +47,7 @@ import org.springframework.util.StringUtils; public class BasicMongoPersistentEntity extends BasicPersistentEntity implements MongoPersistentEntity, ApplicationContextAware { + private static final String AMBIGUOUS_FIELD_MAPPING = "Ambiguous field mapping detected! Both %s and %s map to the same field name %s! Disambiguate using @Field annotation!"; private final String collection; private final SpelExpressionParser parser; private final StandardEvaluationContext context; @@ -89,6 +96,19 @@ public class BasicMongoPersistentEntity extends BasicPersistentEntity extends BasicPersistentEntity, + AssociationHandler { + + private final Map properties = new HashMap(); + + public void doWithPersistentProperty(MongoPersistentProperty persistentProperty) { + assertUniqueness(persistentProperty); + } + + public void doWithAssociation(Association association) { + assertUniqueness(association.getInverse()); + } + + private void assertUniqueness(MongoPersistentProperty property) { + + String fieldName = property.getFieldName(); + MongoPersistentProperty existingProperty = properties.get(fieldName); + + if (existingProperty != null) { + throw new MappingException(String.format(AMBIGUOUS_FIELD_MAPPING, property.toString(), + existingProperty.toString(), fieldName)); + } + + properties.put(fieldName, property); + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java index b147cc390..55180cc20 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2012 the original author or authors. + * Copyright 2011-2013 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. @@ -26,6 +26,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty; +import org.springframework.data.mapping.model.MappingException; import org.springframework.data.mapping.model.SimpleTypeHolder; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; @@ -60,6 +61,8 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope CAUSE_FIELD = ReflectionUtils.findField(Throwable.class, "cause"); } + private final FieldNamingStrategy fieldNamingStrategy; + /** * Creates a new {@link BasicMongoPersistentProperty}. * @@ -67,10 +70,14 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope * @param propertyDescriptor * @param owner * @param simpleTypeHolder + * @param fieldNamingStrategy */ public BasicMongoPersistentProperty(Field field, PropertyDescriptor propertyDescriptor, - MongoPersistentEntity owner, SimpleTypeHolder simpleTypeHolder) { + MongoPersistentEntity owner, SimpleTypeHolder simpleTypeHolder, FieldNamingStrategy fieldNamingStrategy) { + super(field, propertyDescriptor, owner, simpleTypeHolder); + this.fieldNamingStrategy = fieldNamingStrategy == null ? PropertyNameFieldNamingStrategy.INSTANCE + : fieldNamingStrategy; if (isIdProperty() && getFieldName() != ID_FIELD_NAME) { LOG.warn("Customizing field name for id property not allowed! Custom name will not be considered!"); @@ -113,9 +120,20 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope return ID_FIELD_NAME; } - org.springframework.data.mongodb.core.mapping.Field annotation = getField().getAnnotation( - org.springframework.data.mongodb.core.mapping.Field.class); - return annotation != null && StringUtils.hasText(annotation.value()) ? annotation.value() : field.getName(); + org.springframework.data.mongodb.core.mapping.Field annotation = findAnnotation(org.springframework.data.mongodb.core.mapping.Field.class); + + if (annotation != null && StringUtils.hasText(annotation.value())) { + return annotation.value(); + } + + String fieldName = fieldNamingStrategy.getFieldName(this); + + if (!StringUtils.hasText(fieldName)) { + throw new MappingException(String.format("Invalid (null or empty) field name returned for property %s by %s!", + this, fieldNamingStrategy.getClass())); + } + + return fieldName; } /* diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java index 466303a56..c91a5de5e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2012 the original author or authors. + * Copyright 2011-2013 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. @@ -38,10 +38,11 @@ public class CachingMongoPersistentProperty extends BasicMongoPersistentProperty * @param propertyDescriptor * @param owner * @param simpleTypeHolder + * @param fieldNamingStrategy */ public CachingMongoPersistentProperty(Field field, PropertyDescriptor propertyDescriptor, - MongoPersistentEntity owner, SimpleTypeHolder simpleTypeHolder) { - super(field, propertyDescriptor, owner, simpleTypeHolder); + MongoPersistentEntity owner, SimpleTypeHolder simpleTypeHolder, FieldNamingStrategy fieldNamingStrategy) { + super(field, propertyDescriptor, owner, simpleTypeHolder, fieldNamingStrategy); } /* diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CamelCaseAbbreviatingFieldNamingStrategy.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CamelCaseAbbreviatingFieldNamingStrategy.java new file mode 100644 index 000000000..08dfa9cfe --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CamelCaseAbbreviatingFieldNamingStrategy.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013 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.mapping; + +import java.util.Locale; + +/** + * {@link FieldNamingStrategy} that abbreviates field names by using the very first letter of the camel case parts of + * the {@link MongoPersistentProperty}'s name. + * + * @since 1.3 + * @author Oliver Gierke + */ +public class CamelCaseAbbreviatingFieldNamingStrategy implements FieldNamingStrategy { + + private static final String CAMEL_CASE_PATTERN = "(?, MongoPersistentProperty> implements ApplicationContextAware { + private static final FieldNamingStrategy DEFAULT_NAMING_STRATEGY = PropertyNameFieldNamingStrategy.INSTANCE; + + private FieldNamingStrategy fieldNamingStrategy = DEFAULT_NAMING_STRATEGY; private ApplicationContext context; /** @@ -46,6 +49,17 @@ public class MongoMappingContext extends AbstractMappingContext owner, SimpleTypeHolder simpleTypeHolder) { - return new CachingMongoPersistentProperty(field, descriptor, owner, simpleTypeHolder); + return new CachingMongoPersistentProperty(field, descriptor, owner, simpleTypeHolder, fieldNamingStrategy); } /* diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/PropertyNameFieldNamingStrategy.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/PropertyNameFieldNamingStrategy.java new file mode 100644 index 000000000..cee9c648d --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/PropertyNameFieldNamingStrategy.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013 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.mapping; + +/** + * {@link FieldNamingStrategy} simply using the {@link MongoPersistentProperty}'s name. + * + * @since 1.3 + * @author Oliver Gierke + */ +public enum PropertyNameFieldNamingStrategy implements FieldNamingStrategy { + + INSTANCE; + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.mapping.FieldNamingStrategy#getFieldName(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty) + */ + public String getFieldName(MongoPersistentProperty property) { + return property.getName(); + } +} diff --git a/spring-data-mongodb/src/main/resources/META-INF/spring.schemas b/spring-data-mongodb/src/main/resources/META-INF/spring.schemas index 0e2202232..ebad3c5ac 100644 --- a/spring-data-mongodb/src/main/resources/META-INF/spring.schemas +++ b/spring-data-mongodb/src/main/resources/META-INF/spring.schemas @@ -1,4 +1,5 @@ http\://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd=org/springframework/data/mongodb/config/spring-mongo-1.0.xsd http\://www.springframework.org/schema/data/mongo/spring-mongo-1.1.xsd=org/springframework/data/mongodb/config/spring-mongo-1.1.xsd http\://www.springframework.org/schema/data/mongo/spring-mongo-1.2.xsd=org/springframework/data/mongodb/config/spring-mongo-1.2.xsd -http\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-1.2.xsd +http\://www.springframework.org/schema/data/mongo/spring-mongo-1.3.xsd=org/springframework/data/mongodb/config/spring-mongo-1.3.xsd +http\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-1.3.xsd diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.3.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.3.xsd new file mode 100644 index 000000000..59019663c --- /dev/null +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.3.xsd @@ -0,0 +1,493 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object + + + + + + + + + + + + + + The reference to a MongoTemplate. Will default to 'mongoTemplate'. + + + + + + + Enables creation of indexes for queries that get derived from the method name + and thus reference domain class properties. Defaults to false. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference to a DbFactory. + + + + + + + + + + + + The reference to a Mongo. Will default to 'mongo'. + + + + + + + The reference to a MappingContext. Will default to 'mappingContext'. + + + + + + + The reference to a MongoTemplate. Will default to 'mongoTemplate'. + + + + + + + Disables JSR-303 validation on MongoDB documents before they are saved. By default it is set to false. + + + + + + + + + + Enables abbreviating the field names for domain class properties to the + first character of their camel case names, e.g. fooBar -> fb. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A reference to a custom converter. + + + + + + + + + \ No newline at end of file diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserIntegrationTests.java index 75242761e..cb9af3806 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MappingMongoConverterParserIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2012 the original author or authors. + * Copyright 2011-2013 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. @@ -15,7 +15,7 @@ */ package org.springframework.data.mongodb.config; -import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.util.Collections; @@ -23,6 +23,7 @@ import java.util.Set; import org.junit.Before; import org.junit.Test; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.core.convert.TypeDescriptor; @@ -31,6 +32,7 @@ import org.springframework.core.convert.converter.GenericConverter; import org.springframework.core.io.ClassPathResource; import org.springframework.data.mongodb.core.convert.CustomConversions; import org.springframework.data.mongodb.core.mapping.Account; +import org.springframework.data.mongodb.core.mapping.CamelCaseAbbreviatingFieldNamingStrategy; import org.springframework.data.mongodb.repository.Person; import org.springframework.stereotype.Component; @@ -67,6 +69,20 @@ public class MappingMongoConverterParserIntegrationTests { assertThat(conversions.hasCustomWriteTarget(Account.class), is(true)); } + /** + * @see DATAMONGO-607 + */ + @Test + public void activatesAbbreviatingPropertiesCorrectly() { + + BeanDefinition definition = factory.getBeanDefinition("abbreviatingConverter.mappingContext"); + Object value = definition.getPropertyValues().getPropertyValue("fieldNamingStrategy").getValue(); + + assertThat(value, is(instanceOf(BeanDefinition.class))); + BeanDefinition strategy = (BeanDefinition) value; + assertThat(strategy.getBeanClassName(), is(CamelCaseAbbreviatingFieldNamingStrategy.class.getName())); + } + @Component public static class SampleConverter implements Converter { public DBObject convert(Person source) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java index ce5cd67ad..abf624c6e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntityUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 by the original author(s). + * Copyright 2011-2013 by the original author(s). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,9 +15,9 @@ */ package org.springframework.data.mongodb.core.mapping; -import static org.mockito.Mockito.*; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; +import static org.mockito.Mockito.*; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java index b1c26388f..c8cc202ed 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 by the original author(s). + * Copyright 2011-2013 by the original author(s). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,10 +19,14 @@ import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import java.lang.reflect.Field; +import java.util.Locale; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.springframework.data.annotation.Id; +import org.springframework.data.mapping.model.MappingException; import org.springframework.data.mapping.model.SimpleTypeHolder; import org.springframework.data.util.ClassTypeInformation; import org.springframework.util.ReflectionUtils; @@ -36,6 +40,9 @@ public class BasicMongoPersistentPropertyUnitTests { MongoPersistentEntity entity; + @Rule + public ExpectedException exception = ExpectedException.none(); + @Before public void setup() { entity = new BasicMongoPersistentEntity(ClassTypeInformation.from(Person.class)); @@ -78,8 +85,45 @@ public class BasicMongoPersistentPropertyUnitTests { assertThat(property.usePropertyAccess(), is(true)); } + /** + * @see DATAMONGO-607 + */ + @Test + public void usesCustomFieldNamingStrategyByDefault() throws Exception { + + Field field = ReflectionUtils.findField(Person.class, "lastname"); + + MongoPersistentProperty property = new BasicMongoPersistentProperty(field, null, entity, new SimpleTypeHolder(), + UppercaseFieldNamingStrategy.INSTANCE); + assertThat(property.getFieldName(), is("LASTNAME")); + + field = ReflectionUtils.findField(Person.class, "firstname"); + + property = new BasicMongoPersistentProperty(field, null, entity, new SimpleTypeHolder(), + UppercaseFieldNamingStrategy.INSTANCE); + assertThat(property.getFieldName(), is("foo")); + } + + /** + * @see DATAMONGO-607 + */ + @Test + public void rejectsInvalidValueReturnedByFieldNamingStrategy() { + + Field field = ReflectionUtils.findField(Person.class, "lastname"); + MongoPersistentProperty property = new BasicMongoPersistentProperty(field, null, entity, new SimpleTypeHolder(), + InvalidFieldNamingStrategy.INSTANCE); + + exception.expect(MappingException.class); + exception.expectMessage(InvalidFieldNamingStrategy.class.getName()); + exception.expectMessage(property.toString()); + + property.getFieldName(); + } + private MongoPersistentProperty getPropertyFor(Field field) { - return new BasicMongoPersistentProperty(field, null, entity, new SimpleTypeHolder()); + return new BasicMongoPersistentProperty(field, null, entity, new SimpleTypeHolder(), + PropertyNameFieldNamingStrategy.INSTANCE); } class Person { @@ -94,4 +138,22 @@ public class BasicMongoPersistentPropertyUnitTests { @org.springframework.data.mongodb.core.mapping.Field(order = -20) String ssn; } + + enum UppercaseFieldNamingStrategy implements FieldNamingStrategy { + + INSTANCE; + + public String getFieldName(MongoPersistentProperty property) { + return property.getName().toUpperCase(Locale.US); + } + } + + enum InvalidFieldNamingStrategy implements FieldNamingStrategy { + + INSTANCE; + + public String getFieldName(MongoPersistentProperty property) { + return null; + } + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/CamelCaseAbbreviatingFieldNamingStrategyUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/CamelCaseAbbreviatingFieldNamingStrategyUnitTests.java new file mode 100644 index 000000000..2340e7205 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/CamelCaseAbbreviatingFieldNamingStrategyUnitTests.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013 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.mapping; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +/** + * Unit tests for {@link CamelCaseAbbreviatingFieldNamingStrategy}. + * + * @author Oliver Gierke + */ +@RunWith(MockitoJUnitRunner.class) +public class CamelCaseAbbreviatingFieldNamingStrategyUnitTests { + + FieldNamingStrategy strategy = new CamelCaseAbbreviatingFieldNamingStrategy(); + + @Mock + MongoPersistentProperty property; + + @Test + public void foo() { + assertFieldNameForPropertyName("fooBar", "fb"); + assertFieldNameForPropertyName("fooBARFooBar", "fbfb"); + } + + private void assertFieldNameForPropertyName(String propertyName, String fieldName) { + + when(property.getName()).thenReturn(propertyName); + assertThat(strategy.getFieldName(property), is(fieldName)); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java index 641e4f241..2a3a42c95 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MongoMappingContextUnitTests.java @@ -21,9 +21,12 @@ import static org.junit.Assert.*; import java.lang.reflect.Field; import java.util.AbstractMap; import java.util.Collections; +import java.util.Locale; import java.util.Map; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; @@ -46,6 +49,9 @@ public class MongoMappingContextUnitTests { @Mock ApplicationContext applicationContext; + @Rule + public ExpectedException exception = ExpectedException.none(); + @Test public void addsSelfReferencingPersistentEntityCorrectly() throws Exception { @@ -90,6 +96,41 @@ public class MongoMappingContextUnitTests { assertThat(context.getPersistentEntity(AbstractMap.class), is(nullValue())); } + /** + * @see DATAMONGO-607 + */ + @Test + public void populatesPersistentPropertyWithCustomFieldNamingStrategy() { + + MongoMappingContext context = new MongoMappingContext(); + context.setApplicationContext(applicationContext); + context.setFieldNamingStrategy(new FieldNamingStrategy() { + + public String getFieldName(MongoPersistentProperty property) { + return property.getName().toUpperCase(Locale.US); + } + }); + + MongoPersistentEntity entity = context.getPersistentEntity(Person.class); + assertThat(entity.getPersistentProperty("firstname").getFieldName(), is("FIRSTNAME")); + } + + /** + * @see DATAMONGO-607 + */ + @Test + public void rejectsClassWithAmbiguousFieldMappings() { + + exception.expect(MappingException.class); + exception.expectMessage("firstname"); + exception.expectMessage("lastname"); + exception.expectMessage("foo"); + + MongoMappingContext context = new MongoMappingContext(); + context.setApplicationContext(applicationContext); + context.getPersistentEntity(InvalidPerson.class); + } + class ClassWithMultipleIdProperties { @Id @@ -102,4 +143,15 @@ public class MongoMappingContextUnitTests { Map children; } + + class Person { + + String firstname, lastname; + } + + class InvalidPerson { + + @org.springframework.data.mongodb.core.mapping.Field("foo") + String firstname, lastname; + } } diff --git a/spring-data-mongodb/src/test/resources/namespace/converter.xml b/spring-data-mongodb/src/test/resources/namespace/converter.xml index 45189bcbc..7aef47ceb 100644 --- a/spring-data-mongodb/src/test/resources/namespace/converter.xml +++ b/spring-data-mongodb/src/test/resources/namespace/converter.xml @@ -10,5 +10,7 @@ + +