diff --git a/src/main/java/org/springframework/data/mapping/IdentifierAccessor.java b/src/main/java/org/springframework/data/mapping/IdentifierAccessor.java new file mode 100644 index 000000000..430a3f8b0 --- /dev/null +++ b/src/main/java/org/springframework/data/mapping/IdentifierAccessor.java @@ -0,0 +1,31 @@ +/* + * Copyright 2014 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.mapping; + +/** + * Interface for a component allowing the access of identifier values. + * + * @author Oliver Gierke + */ +public interface IdentifierAccessor { + + /** + * Returns the value of the identifier. + * + * @return + */ + Object getIdentifier(); +} diff --git a/src/main/java/org/springframework/data/mapping/PersistentEntity.java b/src/main/java/org/springframework/data/mapping/PersistentEntity.java index 52ad9cf9e..699afbf77 100644 --- a/src/main/java/org/springframework/data/mapping/PersistentEntity.java +++ b/src/main/java/org/springframework/data/mapping/PersistentEntity.java @@ -179,4 +179,13 @@ public interface PersistentEntity> { * @since 1.10 */ PersistentPropertyAccessor getPropertyAccessor(Object bean); + + /** + * Returns the {@link IdentifierAccessor} for the given bean. + * + * @param bean must not be {@literal null}. + * @return + * @since 1.10 + */ + IdentifierAccessor getIdentifierAccessor(Object bean); } diff --git a/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java b/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java index 8121926c2..01c277965 100644 --- a/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java +++ b/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 by the original author(s). + * Copyright 2011-2014 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. @@ -28,6 +28,7 @@ import org.springframework.core.annotation.AnnotationUtils; import org.springframework.data.annotation.TypeAlias; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.AssociationHandler; +import org.springframework.data.mapping.IdentifierAccessor; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.PersistentPropertyAccessor; @@ -377,6 +378,39 @@ public class BasicPersistentEntity> implement return new BeanWrapper(bean); } + /* + * (non-Javadoc) + * @see org.springframework.data.mapping.PersistentEntity#getIdentifierAccessor(java.lang.Object) + */ + @Override + public IdentifierAccessor getIdentifierAccessor(Object bean) { + + Assert.notNull(bean, "Targte bean must not be null!"); + Assert.isTrue(getType().isInstance(bean), "Target bean is not of type of the persistent entity!"); + + return hasIdProperty() ? new IdPropertyIdentifierAccessor(this, bean) : NullReturningIdentifierAccessor.INSTANCE; + } + + /** + * A null-object implementation of {@link IdentifierAccessor} to be able to return an accessor for entities that do + * not have an identifier property. + * + * @author Oliver Gierke + */ + private static enum NullReturningIdentifierAccessor implements IdentifierAccessor { + + INSTANCE; + + /* + * (non-Javadoc) + * @see org.springframework.data.mapping.IdentifierAccessor#getIdentifier() + */ + @Override + public Object getIdentifier() { + return null; + } + } + /** * Simple {@link Comparator} adaptor to delegate ordering to the inverse properties of the association. * diff --git a/src/main/java/org/springframework/data/mapping/model/IdPropertyIdentifierAccessor.java b/src/main/java/org/springframework/data/mapping/model/IdPropertyIdentifierAccessor.java new file mode 100644 index 000000000..b2f890e89 --- /dev/null +++ b/src/main/java/org/springframework/data/mapping/model/IdPropertyIdentifierAccessor.java @@ -0,0 +1,60 @@ +/* + * Copyright 2014 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.mapping.model; + +import org.springframework.data.mapping.IdentifierAccessor; +import org.springframework.data.mapping.PersistentEntity; +import org.springframework.data.mapping.PersistentProperty; +import org.springframework.data.mapping.PersistentPropertyAccessor; +import org.springframework.util.Assert; + +/** + * Default implementation of {@link IdentifierAccessor}. + * + * @author Christoph Strobl + * @author Oliver Gierke + * @since 1.10 + */ +public class IdPropertyIdentifierAccessor implements IdentifierAccessor { + + private final PersistentPropertyAccessor accessor; + private final PersistentProperty idProperty; + + /** + * Creates a new {@link IdPropertyIdentifierAccessor} for the given {@link PersistentEntity} and + * {@link ConvertingPropertyAccessor}. + * + * @param entity must not be {@literal null}. + * @param target must not be {@literal null}. + */ + + public IdPropertyIdentifierAccessor(PersistentEntity entity, Object target) { + + Assert.notNull(entity, "PersistentEntity must not be 'null'"); + Assert.isTrue(entity.hasIdProperty(), "PersistentEntity does not have an identifier property!"); + + this.idProperty = entity.getIdProperty(); + this.accessor = entity.getPropertyAccessor(target); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.keyvalue.core.IdentifierAccessor#getIdentifier() + */ + public Object getIdentifier() { + return accessor.getProperty(idProperty); + } +} diff --git a/src/main/java/org/springframework/data/repository/core/support/PersistentEntityInformation.java b/src/main/java/org/springframework/data/repository/core/support/PersistentEntityInformation.java index c514000a0..6cc9577ba 100644 --- a/src/main/java/org/springframework/data/repository/core/support/PersistentEntityInformation.java +++ b/src/main/java/org/springframework/data/repository/core/support/PersistentEntityInformation.java @@ -18,7 +18,6 @@ package org.springframework.data.repository.core.support; import java.io.Serializable; import org.springframework.data.mapping.PersistentEntity; -import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.model.BeanWrapper; import org.springframework.data.repository.core.EntityInformation; @@ -50,14 +49,7 @@ public class PersistentEntityInformation extends Abs */ @Override public ID getId(T entity) { - - PersistentProperty property = persistentEntity.getIdProperty(); - - if (property == null) { - return null; - } - - return (ID) persistentEntity.getPropertyAccessor(entity).getProperty(property); + return (ID) persistentEntity.getIdentifierAccessor(entity).getIdentifier(); } /* diff --git a/src/test/java/org/springframework/data/mapping/model/IdPropertyIdentifierAccessorUnitTests.java b/src/test/java/org/springframework/data/mapping/model/IdPropertyIdentifierAccessorUnitTests.java new file mode 100644 index 000000000..f9cb56f92 --- /dev/null +++ b/src/test/java/org/springframework/data/mapping/model/IdPropertyIdentifierAccessorUnitTests.java @@ -0,0 +1,71 @@ +/* + * Copyright 2014 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.mapping.model; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import org.junit.Test; +import org.springframework.data.annotation.Id; +import org.springframework.data.mapping.IdentifierAccessor; +import org.springframework.data.mapping.context.SampleMappingContext; + +/** + * @author Oliver Gierke + */ +public class IdPropertyIdentifierAccessorUnitTests { + + SampleMappingContext mappingContext = new SampleMappingContext(); + + /** + * @see DATACMNS-599 + */ + @Test(expected = IllegalArgumentException.class) + public void rejectsEntityWithoutIdentifierProperty() { + + new IdPropertyIdentifierAccessor(mappingContext.getPersistentEntity(Sample.class), new Sample()); + } + + /** + * @see DATACMNS-599 + */ + @Test(expected = IllegalArgumentException.class) + public void rejectsNullBean() { + + new IdPropertyIdentifierAccessor(mappingContext.getPersistentEntity(SampleWithId.class), null); + } + + /** + * @see DATACMNS-599 + */ + @Test + public void returnsIdentifierValue() { + + SampleWithId sample = new SampleWithId(); + sample.id = 1L; + + IdentifierAccessor accessor = new IdPropertyIdentifierAccessor( + mappingContext.getPersistentEntity(SampleWithId.class), sample); + + assertThat(accessor.getIdentifier(), is((Object) sample.id)); + } + + static class Sample {} + + static class SampleWithId { + @Id Long id; + } +}