From 8c9bbf7f91f400a856597577611b741b9c0516c5 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 16 Jan 2017 10:00:12 +0100 Subject: [PATCH] DATAMONGO-1590 - EntityInformation selected now correctly considers Persistable. We now wrap the MappingMongoEntityInformation into one that delegates the methods implemented by Persistable to the actual entity in case it implements said interface. Original pull request: #436. --- .../MongoEntityInformationSupport.java | 55 ++++++++++ .../support/MongoRepositoryFactory.java | 5 +- .../PersistableMongoEntityInformation.java | 102 ++++++++++++++++++ ...appingMongoEntityInformationUnitTests.java | 76 +++++++++++++ 4 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoEntityInformationSupport.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/PersistableMongoEntityInformation.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/PersistableMappingMongoEntityInformationUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoEntityInformationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoEntityInformationSupport.java new file mode 100644 index 000000000..9b2f41b87 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoEntityInformationSupport.java @@ -0,0 +1,55 @@ +/* + * Copyright 2017 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.repository.support; + +import java.io.Serializable; + +import org.springframework.data.domain.Persistable; +import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; +import org.springframework.data.mongodb.repository.query.MongoEntityInformation; +import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; + +/** + * Support class responsible for creating {@link MongoEntityInformation} instances for a given + * {@link MongoPersistentEntity}. + * + * @author Christoph Strobl + * @since 1.10 + */ +final class MongoEntityInformationSupport { + + private MongoEntityInformationSupport() {} + + /** + * Factory method for creating {@link MongoEntityInformation}. + * + * @param entity must not be {@literal null}. + * @param idType can be {@literal null}. + * @return never {@literal null}. + */ + static MongoEntityInformation entityInformationFor( + MongoPersistentEntity entity, Class idType) { + + Assert.notNull(entity, "Entity must not be null!"); + + MappingMongoEntityInformation entityInformation = new MappingMongoEntityInformation( + (MongoPersistentEntity) entity, (Class) idType); + return ClassUtils.isAssignable(Persistable.class, entity.getType()) + ? new PersistableMongoEntityInformation(entityInformation) : entityInformation; + } + +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java index c6bfe3738..85bb6a037 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java @@ -21,6 +21,7 @@ import java.io.Serializable; import java.lang.reflect.Method; import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.data.domain.Persistable; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.model.MappingException; import org.springframework.data.mongodb.core.MongoOperations; @@ -148,8 +149,8 @@ public class MongoRepositoryFactory extends RepositoryFactorySupport { String.format("Could not lookup mapping metadata for domain class %s!", domainClass.getName())); } - return new MappingMongoEntityInformation((MongoPersistentEntity) entity, - information != null ? (Class) information.getIdType() : null); + return MongoEntityInformationSupport. entityInformationFor(entity, + information != null ? information.getIdType() : null); } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/PersistableMongoEntityInformation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/PersistableMongoEntityInformation.java new file mode 100644 index 000000000..a6c63a405 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/PersistableMongoEntityInformation.java @@ -0,0 +1,102 @@ +/* + * Copyright 2017 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.repository.support; + +import java.io.Serializable; + +import org.springframework.data.domain.Persistable; +import org.springframework.data.mongodb.repository.query.MongoEntityInformation; + +/** + * {@link MongoEntityInformation} implementation wrapping an existing {@link MongoEntityInformation} considering + * {@link Persistable} types by delegating {@link #isNew(Object)} and {@link #getId(Object)} to the corresponding + * {@link Persistable#isNew()} and {@link Persistable#getId()} implementations. + * + * @author Christoph Strobl + * @since 1.10 + */ +public class PersistableMongoEntityInformation implements MongoEntityInformation { + + private final MongoEntityInformation delegate; + + public PersistableMongoEntityInformation(MongoEntityInformation delegate) { + this.delegate = delegate; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.repository.MongoEntityInformation#getCollectionName() + */ + @Override + public String getCollectionName() { + return delegate.getCollectionName(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.repository.MongoEntityInformation#getIdAttribute() + */ + @Override + public String getIdAttribute() { + return delegate.getIdAttribute(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.core.EntityInformation#isNew(java.lang.Object) + */ + @Override + public boolean isNew(T t) { + + if (t instanceof Persistable) { + return ((Persistable) t).isNew(); + } + + return delegate.isNew(t); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.core.EntityInformation#getId(java.lang.Object) + */ + @Override + public ID getId(T t) { + + if (t instanceof Persistable) { + return (ID) ((Persistable) t).getId(); + } + + return delegate.getId(t); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.core.support.PersistentEntityInformation#getIdType() + */ + @Override + public Class getIdType() { + return delegate.getIdType(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.core.support.EntityMetadata#getJavaType() + */ + @Override + public Class getJavaType() { + return delegate.getJavaType(); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/PersistableMappingMongoEntityInformationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/PersistableMappingMongoEntityInformationUnitTests.java new file mode 100644 index 000000000..2f03024c2 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/PersistableMappingMongoEntityInformationUnitTests.java @@ -0,0 +1,76 @@ +/* + * Copyright 2017 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.repository.query; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.data.domain.Persistable; +import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; +import org.springframework.data.mongodb.repository.support.MappingMongoEntityInformation; +import org.springframework.data.mongodb.repository.support.PersistableMongoEntityInformation; + +/** + * Tests for {@link PersistableMongoEntityInformation}. + * + * @author Christoph Strobl + */ +@RunWith(MockitoJUnitRunner.class) +public class PersistableMappingMongoEntityInformationUnitTests { + + @Mock MongoPersistentEntity persistableImplementingEntityTypeInfo; + + @Before + public void setUp() { + when(persistableImplementingEntityTypeInfo.getType()).thenReturn(TypeImplementingPersistable.class); + } + + @Test // DATAMONGO-1590 + public void considersPersistableIsNew() { + + PersistableMongoEntityInformation information = new PersistableMongoEntityInformation( + new MappingMongoEntityInformation(persistableImplementingEntityTypeInfo)); + + assertThat(information.isNew(new TypeImplementingPersistable(100L, false)), is(false)); + } + + static class TypeImplementingPersistable implements Persistable { + + final Long id; + final boolean isNew; + + public TypeImplementingPersistable(Long id, boolean isNew) { + this.id = id; + this.isNew = isNew; + } + + @Override + public Long getId() { + return id; + } + + @Override + public boolean isNew() { + return isNew; + } + } +}