diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/geo/Box.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/geo/Box.java index 9ef44fe9d..d642b053f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/geo/Box.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/geo/Box.java @@ -15,6 +15,7 @@ */ package org.springframework.data.document.mongodb.geo; +import org.springframework.data.document.mongodb.mapping.Field; import org.springframework.util.Assert; /** @@ -25,7 +26,9 @@ import org.springframework.util.Assert; */ public class Box { + @Field(order = 10) private final Point first; + @Field(order = 20) private final Point second; public Box(Point lowerLeft, Point upperRight) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/geo/Point.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/geo/Point.java index fbac85687..29b3a20b8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/geo/Point.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/geo/Point.java @@ -16,6 +16,7 @@ package org.springframework.data.document.mongodb.geo; import org.springframework.data.annotation.PersistenceConstructor; +import org.springframework.data.document.mongodb.mapping.Field; import org.springframework.util.Assert; /** @@ -26,7 +27,9 @@ import org.springframework.util.Assert; */ public class Point { + @Field(order = 10) private final double x; + @Field(order = 20) private final double y; @PersistenceConstructor diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/BasicMongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/BasicMongoPersistentEntity.java index 8694ea612..d07ea8e5c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/BasicMongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/BasicMongoPersistentEntity.java @@ -16,6 +16,8 @@ package org.springframework.data.document.mongodb.mapping; +import java.util.Comparator; + import org.springframework.data.document.mongodb.MongoCollectionUtils; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.model.BasicPersistentEntity; @@ -44,7 +46,7 @@ public class BasicMongoPersistentEntity extends BasicPersistentEntity typeInformation) { - super(typeInformation); + super(typeInformation, MongoPersistentPropertyComparator.INSTANCE); Class rawType = typeInformation.getType(); String fallback = MongoCollectionUtils.getPreferredCollectionName(rawType); @@ -73,8 +75,35 @@ public class BasicMongoPersistentEntity extends BasicPersistentEntity { + + INSTANCE; + + /* + * (non-Javadoc) + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + */ + public int compare(MongoPersistentProperty o1, MongoPersistentProperty o2) { + + if (o1.getFieldOrder() == Integer.MAX_VALUE) { + return 1; + } + + if (o2.getFieldOrder() == Integer.MAX_VALUE) { + return -1; + } + + return o1.getFieldOrder() - o2.getFieldOrder(); + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/BasicMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/BasicMongoPersistentProperty.java index 7fe84af33..e66d28cf2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/BasicMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/BasicMongoPersistentProperty.java @@ -21,17 +21,19 @@ import java.math.BigInteger; import java.util.HashSet; import java.util.Set; -import com.mongodb.DBObject; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.bson.types.ObjectId; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty; import org.springframework.data.mapping.model.SimpleTypeHolder; +import org.springframework.util.StringUtils; + +import com.mongodb.DBObject; /** * Mongo specific {@link org.springframework.data.mapping.PersistentProperty} implementation. - * + * * @author Oliver Gierke */ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentProperty implements @@ -39,6 +41,7 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope private static final Log LOG = LogFactory.getLog(BasicMongoPersistentProperty.class); + private static final String ID_FIELD_NAME = "_id"; private static final Set> SUPPORTED_ID_TYPES = new HashSet>(); private static final Set SUPPORTED_ID_PROPERTY_NAMES = new HashSet(); @@ -53,7 +56,7 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope /** * Creates a new {@link BasicMongoPersistentProperty}. - * + * * @param field * @param propertyDescriptor * @param owner @@ -63,8 +66,8 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope MongoPersistentEntity owner, SimpleTypeHolder simpleTypeHolder) { super(field, propertyDescriptor, owner, simpleTypeHolder); - if (isIdProperty() && field.isAnnotationPresent(FieldName.class)) { - LOG.warn(String.format("Invalid usage of %s on id property. Field name will not be considered!", FieldName.class)); + if (isIdProperty() && getFieldName() != ID_FIELD_NAME) { + LOG.warn("Customizing field name for id property not allowed! Custom name will not be considered!"); } } @@ -78,7 +81,7 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope /** * Also considers fields as id that are of supported id type and name. - * + * * @see #SUPPORTED_ID_PROPERTY_NAMES * @see #SUPPORTED_ID_TYPES */ @@ -90,22 +93,31 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope // We need to support a wider range of ID types than just the ones that can be converted to an ObjectId return SUPPORTED_ID_PROPERTY_NAMES.contains(field.getName()); - //return SUPPORTED_ID_TYPES.contains(field.getType()) && SUPPORTED_ID_PROPERTY_NAMES.contains(field.getName()); } /** * Returns the key to be used to store the value of the property inside a Mongo {@link DBObject}. - * + * * @return */ public String getFieldName() { if (isIdProperty()) { - return "_id"; + return ID_FIELD_NAME; } - FieldName annotation = getField().getAnnotation(FieldName.class); - return annotation != null ? annotation.value() : getName(); + org.springframework.data.document.mongodb.mapping.Field annotation = getField().getAnnotation( + org.springframework.data.document.mongodb.mapping.Field.class); + return annotation != null && StringUtils.hasText(annotation.value()) ? annotation.value() : field.getName(); + } + + /* (non-Javadoc) + * @see org.springframework.data.document.mongodb.mapping.MongoPersistentProperty#getFieldOrder() + */ + public int getFieldOrder() { + org.springframework.data.document.mongodb.mapping.Field annotation = getField().getAnnotation( + org.springframework.data.document.mongodb.mapping.Field.class); + return annotation != null ? annotation.order() : Integer.MAX_VALUE; } /* (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/Field.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/Field.java new file mode 100644 index 000000000..3a993b415 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/Field.java @@ -0,0 +1,27 @@ +package org.springframework.data.document.mongodb.mapping; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Annotation to define custom metadata for document fields. + * + * @author Oliver Gierke + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +public @interface Field { + + /** + * The key to be used to store the field inside the document. + * @return + */ + String value() default ""; + + /** + * The order in which various fields shall be stored. Has to be a positive integer. + * @return the order the field shall have in the document or -1 if undefined. + */ + int order() default Integer.MAX_VALUE; +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/FieldName.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/FieldName.java deleted file mode 100644 index cbcec956a..000000000 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/FieldName.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2011 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. - * 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.document.mongodb.mapping; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation to allow defining the name of the field a property should use in a Mongo document. This will cause the - * property annotated being persisted to a field with the configured name as wells as being read from it. - * - * @author Oliver Gierke - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ ElementType.FIELD }) -@Documented -public @interface FieldName { - - String value(); -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoPersistentProperty.java index 69cf73861..03bf62a6a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoPersistentProperty.java @@ -30,6 +30,13 @@ public interface MongoPersistentProperty extends PersistentProperty properties = Arrays.asList(firstName, lastName, ssn); + Collections.sort(properties, MongoPersistentPropertyComparator.INSTANCE); + + assertThat(properties.get(0), is(ssn)); + assertThat(properties.get(1), is(firstName)); + assertThat(properties.get(2), is(lastName)); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index e8b60ead5..2d4f6dac8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -9,7 +9,6 @@ import java.util.HashSet; import java.util.List; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -220,7 +219,6 @@ public abstract class AbstractPersonRepositoryIntegrationTests { } @Test - @Ignore public void findsPeopleByLocationWithinBox() { Point point = new Point(-73.99171, 40.738868); dave.setLocation(point);