diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/PersistentEntity.java b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/PersistentEntity.java index a46594332..3c9febb01 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/PersistentEntity.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/PersistentEntity.java @@ -1,7 +1,5 @@ package org.springframework.data.mapping; -import java.util.Collection; - import org.springframework.data.util.TypeInformation; /** @@ -57,13 +55,6 @@ public interface PersistentEntity> { */ TypeInformation getTypeInformation(); - /** - * A list of property names - * - * @return A List of strings - */ - Collection getPersistentPropertyNames(); - /** * Applies the given {@link PropertyHandler} to all {@link PersistentProperty}s contained in this * {@link PersistentEntity}. diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java index fb56c8b6a..a45611114 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java @@ -15,9 +15,10 @@ */ package org.springframework.data.mapping.model; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Set; +import java.util.TreeSet; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.AssociationHandler; @@ -32,25 +33,42 @@ import org.springframework.util.Assert; * Simple value object to capture information of {@link PersistentEntity}s. * * @author Jon Brisbin + * @author Oliver Gierke */ public class BasicPersistentEntity> implements MutablePersistentEntity { - protected final PreferredConstructor preferredConstructor; - protected final TypeInformation information; - protected final Map persistentProperties = new HashMap(); - protected final Map> associations = new HashMap>(); - protected P idProperty; + private final PreferredConstructor preferredConstructor; + private final TypeInformation information; + private final Set

properties; + private final Set> associations; + + private P idProperty; /** * Creates a new {@link BasicPersistentEntity} from the given {@link TypeInformation}. * - * @param information + * @param information must not be {@literal null}. */ public BasicPersistentEntity(TypeInformation information) { + this(information, null); + } + + /** + * Creates a new {@link BasicPersistentEntity} for the given {@link TypeInformation} and {@link Comparator}. The given + * {@link Comparator} will be used to define the order of the {@link PersistentProperty} instances added to the + * entity. + * + * @param information must not be {@literal null} + * @param comparator + */ + public BasicPersistentEntity(TypeInformation information, Comparator

comparator) { Assert.notNull(information); this.information = information; this.preferredConstructor = new PreferredConstructorDiscoverer(information).getConstructor(); + this.properties = comparator == null ? new HashSet

() : new TreeSet

(comparator); + this.associations = comparator == null ? new HashSet>() : new TreeSet>( + new AssociationComparator

(comparator)); } /* @@ -91,14 +109,14 @@ public class BasicPersistentEntity> implement */ public void addPersistentProperty(P property) { Assert.notNull(property); - persistentProperties.put(property.getName(), property); + properties.add(property); } /* (non-Javadoc) * @see org.springframework.data.mapping.MutablePersistentEntity#addAssociation(org.springframework.data.mapping.model.Association) */ public void addAssociation(Association

association) { - associations.put(association.getInverse().getName(), association); + associations.add(association); } /* @@ -106,7 +124,14 @@ public class BasicPersistentEntity> implement * @see org.springframework.data.mapping.PersistentEntity#getPersistentProperty(java.lang.String) */ public P getPersistentProperty(String name) { - return persistentProperties.get(name); + + for (P property : properties) { + if (property.getName().equals(name)) { + return property; + } + } + + return null; } /* @@ -125,21 +150,13 @@ public class BasicPersistentEntity> implement return information; } - /* - * (non-Javadoc) - * @see org.springframework.data.mapping.PersistentEntity#getPersistentPropertyNames() - */ - public Collection getPersistentPropertyNames() { - return persistentProperties.keySet(); - } - /* * (non-Javadoc) * @see org.springframework.data.mapping.PersistentEntity#doWithProperties(org.springframework.data.mapping.PropertyHandler) */ public void doWithProperties(PropertyHandler

handler) { Assert.notNull(handler); - for (P property : persistentProperties.values()) { + for (P property : properties) { if (!property.isTransient() && !property.isAssociation()) { handler.doWithPersistentProperty(property); } @@ -152,7 +169,7 @@ public class BasicPersistentEntity> implement */ public void doWithAssociations(AssociationHandler

handler) { Assert.notNull(handler); - for (Association

association : associations.values()) { + for (Association

association : associations) { handler.doWithAssociation(association); } } @@ -163,4 +180,23 @@ public class BasicPersistentEntity> implement public void verify() { } + + /** + * Simple {@link Comparator} adaptor to delegate ordering to the inverse properties of the association. + * + * @author Oliver Gierke + */ + private static final class AssociationComparator

> implements Comparator> { + + private final Comparator

delegate; + + public AssociationComparator(Comparator

delegate) { + Assert.notNull(delegate); + this.delegate = delegate; + } + + public int compare(Association

left, Association

right) { + return delegate.compare(left.getInverse(), right.getInverse()); + } + } } diff --git a/spring-data-commons-core/src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java b/spring-data-commons-core/src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java index ef109b871..edf617ab7 100644 --- a/spring-data-commons-core/src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java +++ b/spring-data-commons-core/src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java @@ -2,12 +2,19 @@ package org.springframework.data.mapping.model; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.util.Comparator; +import java.util.Iterator; +import java.util.SortedSet; import org.junit.Test; +import org.mockito.Mockito; import org.springframework.data.mapping.PersistentEntitySpec; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.Person; import org.springframework.data.util.ClassTypeInformation; +import org.springframework.test.util.ReflectionTestUtils; /** * Unit test for {@link BasicPersistentEntity}. @@ -18,7 +25,7 @@ public class BasicPersistentEntityUnitTests> { @Test public void assertInvariants() { - PersistentEntitySpec.assertInvariants(createEntity()); + PersistentEntitySpec.assertInvariants(createEntity(null)); } @Test(expected = IllegalArgumentException.class) @@ -28,10 +35,45 @@ public class BasicPersistentEntityUnitTests> { @Test(expected = IllegalArgumentException.class) public void rejectsNullProperty() { - createEntity().addPersistentProperty(null); + createEntity(null).addPersistentProperty(null); + } + + /** + * @see DATACMNS-50 + */ + @Test + @SuppressWarnings("unchecked") + public void considersComparatorForPropertyOrder() { + + BasicPersistentEntity entity = createEntity(new Comparator() { + public int compare(T o1, T o2) { + return o1.getName().compareTo(o2.getName()); + } + }); + + T lastName = (T) Mockito.mock(PersistentProperty.class); + when(lastName.getName()).thenReturn("lastName"); + + T firstName = (T) Mockito.mock(PersistentProperty.class); + when(firstName.getName()).thenReturn("firstName"); + + T ssn = (T) Mockito.mock(PersistentProperty.class); + when(ssn.getName()).thenReturn("ssn"); + + entity.addPersistentProperty(lastName); + entity.addPersistentProperty(firstName); + entity.addPersistentProperty(ssn); + + SortedSet properties = (SortedSet) ReflectionTestUtils.getField(entity, "properties"); + + assertThat(properties.size(), is(3)); + Iterator iterator = properties.iterator(); + assertThat(iterator.next(), is(entity.getPersistentProperty("firstName"))); + assertThat(iterator.next(), is(entity.getPersistentProperty("lastName"))); + assertThat(iterator.next(), is(entity.getPersistentProperty("ssn"))); } - private BasicPersistentEntity createEntity() { - return new BasicPersistentEntity(ClassTypeInformation.from(Person.class)); + private BasicPersistentEntity createEntity(Comparator comparator) { + return new BasicPersistentEntity(ClassTypeInformation.from(Person.class), comparator); } }