DATAJPA-19 - Added Hades extensions module.

Added DomainClassPropertyEditor and DomainClassConverter to automatically bind domain classes to Spring MVC controller methods. Same applies to PageableArgumentResolver. Polished up some generics.

Introduced RepositoryFactoryInformation interface being implemented by RepositoryFactorySupport that allows the extension components to get access to the raw factories, access EntityInformation of it and then find out about the repository interface to lookup the actual repository instance.
This commit is contained in:
Oliver Gierke
2011-03-11 15:59:15 +01:00
parent dd6e56d013
commit 80359c4d07
24 changed files with 1829 additions and 22 deletions

View File

@@ -89,7 +89,7 @@ public class QueryMethod {
}
public EntityMetadata<?> getEntityMetadata() {
public EntityMetadata<?> getEntityInformation() {
return new EntityMetadata() {

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.repository.support;
import java.io.Serializable;
import org.springframework.util.Assert;
@@ -24,8 +26,8 @@ import org.springframework.util.Assert;
*
* @author Oliver Gierke
*/
public abstract class AbstractEntityInformation<T> implements
EntityInformation<T> {
public abstract class AbstractEntityInformation<T, ID extends Serializable> implements
EntityInformation<T, ID> {
private final Class<T> domainClass;

View File

@@ -15,13 +15,15 @@
*/
package org.springframework.data.repository.support;
import java.io.Serializable;
/**
* Extension of {@link EntityMetadata} to add functionality to query information
* of entity instances.
*
* @author Oliver Gierke
*/
public interface EntityInformation<T> extends EntityMetadata<T> {
public interface EntityInformation<T, ID extends Serializable> extends EntityMetadata<T> {
/**
* Returns whether the given entity is considered to be new.
@@ -38,5 +40,12 @@ public interface EntityInformation<T> extends EntityMetadata<T> {
* @param entity must never be {@literal null}
* @return
*/
Object getId(T entity);
ID getId(T entity);
/**
* Returns the type of the id of the entity.
*
* @return
*/
Class<ID> getIdType();
}

View File

@@ -15,6 +15,9 @@
*/
package org.springframework.data.repository.support;
import java.io.Serializable;
import org.springframework.core.GenericTypeResolver;
import org.springframework.data.domain.Persistable;
@@ -25,18 +28,21 @@ import org.springframework.data.domain.Persistable;
*
* @author Oliver Gierke
*/
@SuppressWarnings("rawtypes")
public class PersistableEntityInformation<T extends Persistable> extends
AbstractEntityInformation<T> {
public class PersistableEntityInformation<T extends Persistable<ID>, ID extends Serializable> extends
AbstractEntityInformation<T, ID> {
private Class<ID> idClass;
/**
* Creates a new {@link PersistableEntityInformation}.
*
* @param domainClass
*/
@SuppressWarnings("unchecked")
public PersistableEntityInformation(Class<T> domainClass) {
super(domainClass);
this.idClass = (Class<ID>) GenericTypeResolver.resolveTypeArgument(domainClass, Persistable.class);
}
@@ -61,8 +67,15 @@ public class PersistableEntityInformation<T extends Persistable> extends
* org.springframework.data.repository.support.IdAware#getId(java.lang.Object
* )
*/
public Object getId(T entity) {
public ID getId(T entity) {
return entity.getId();
}
/* (non-Javadoc)
* @see org.springframework.data.repository.support.EntityInformation#getIdType()
*/
public Class<ID> getIdType() {
return this.idClass;
}
}

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.repository.support;
import java.io.Serializable;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Required;
@@ -31,8 +33,8 @@ import org.springframework.util.Assert;
* @author Oliver Gierke
* @param <T> the type of the repository
*/
public abstract class RepositoryFactoryBeanSupport<T extends Repository<?, ?>>
implements FactoryBean<T>, InitializingBean {
public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>, S, ID extends Serializable>
implements InitializingBean, RepositoryFactoryInformation<S, ID>, FactoryBean<T> {
private RepositoryFactorySupport factory;
@@ -75,6 +77,25 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<?, ?>>
this.customImplementation = customImplementation;
}
/* (non-Javadoc)
* @see org.springframework.data.repository.support.EntityMetadataProvider#getEntityMetadata()
*/
public EntityInformation<S, ID> getEntityInformation() {
RepositoryMetadata repositoryMetadata = factory.getRepositoryMetadata(repositoryInterface);
return (EntityInformation<S, ID>) factory.getEntityInformation(repositoryMetadata.getDomainClass());
}
/* (non-Javadoc)
* @see org.springframework.data.repository.support.RepositoryFactoryInformation#getRepositoryInterface()
*/
@Override
public Class<? extends T> getRepositoryInterface() {
return repositoryInterface;
}
/*
* (non-Javadoc)

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2011 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.repository.support;
import java.io.Serializable;
import org.springframework.data.repository.Repository;
/**
* Interface for components that can provide {@link EntityInformation} this
* interface
*
* @author Oliver Gierke
*/
public interface RepositoryFactoryInformation<T, ID extends Serializable> {
/**
* Returns {@link EntityInformation} the repository factory is using.
*
* @return
*/
EntityInformation<T, ID> getEntityInformation();
/**
* Returns the interface of the {@link Repository} the factory will create.
*
* @return
*/
Class<? extends Repository<T, ID>> getRepositoryInterface();
}

View File

@@ -17,6 +17,7 @@ package org.springframework.data.repository.support;
import static org.springframework.util.ReflectionUtils.*;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
@@ -124,8 +125,7 @@ public abstract class RepositoryFactorySupport {
Object customImplementation) {
RepositoryMetadata metadata =
new DefaultRepositoryMetadata(repositoryInterface,
getRepositoryBaseClass(repositoryInterface));
getRepositoryMetadata(repositoryInterface);
validate(metadata, customImplementation);
@@ -145,6 +145,29 @@ public abstract class RepositoryFactorySupport {
return (T) result.getProxy();
}
/**
* Returns the {@link RepositoryMetadata} for the given repository interface.
*
* @param repositoryInterface
* @return
*/
protected RepositoryMetadata getRepositoryMetadata(Class<?> repositoryInterface) {
return new DefaultRepositoryMetadata(repositoryInterface, getRepositoryBaseClass(repositoryInterface));
}
/**
* Returns the {@link EntityInformation} for the given domain class.
*
* @param <T> the entity type
* @param <ID> the id type
* @param domainClass
* @return
*/
public abstract <T, ID extends Serializable> EntityInformation<T, ID> getEntityInformation(Class<T> domainClass);
/**

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.repository.support;
import java.io.Serializable;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.ListableBeanFactory;
@@ -32,8 +34,8 @@ import org.springframework.util.Assert;
*
* @author Oliver Gierke
*/
public abstract class TransactionalRepositoryFactoryBeanSupport<T extends Repository<?, ?>>
extends RepositoryFactoryBeanSupport<T> implements BeanFactoryAware {
public abstract class TransactionalRepositoryFactoryBeanSupport<T extends Repository<S, ID>, S, ID extends Serializable>
extends RepositoryFactoryBeanSupport<T, S, ID> implements BeanFactoryAware {
private String transactionManagerName = TxUtils.DEFAULT_TRANSACTION_MANAGER;
private RepositoryProxyPostProcessor txPostProcessor;

View File

@@ -18,6 +18,8 @@ package org.springframework.data.repository.support;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import java.io.Serializable;
import org.junit.Test;
@@ -38,14 +40,14 @@ public class AbstractEntityInformationUnitTests {
@Test
public void considersEntityNewIfGetIdReturnsNull() throws Exception {
EntityInformation<Object> metadata =
EntityInformation<Object, Serializable> metadata =
new DummyAbstractEntityInformation(Object.class);
assertThat(metadata.isNew(null), is(true));
assertThat(metadata.isNew(new Object()), is(false));
}
private static class DummyAbstractEntityInformation extends
AbstractEntityInformation<Object> {
AbstractEntityInformation<Object, Serializable> {
public DummyAbstractEntityInformation(Class<Object> domainClass) {
@@ -60,9 +62,18 @@ public class AbstractEntityInformationUnitTests {
* org.springframework.data.repository.support.EntityMetadata#getId(
* java.lang.Object)
*/
public Object getId(Object entity) {
public Serializable getId(Object entity) {
return entity == null ? null : entity.toString();
}
/* (non-Javadoc)
* @see org.springframework.data.repository.support.EntityInformation#getIdType()
*/
@Override
public Class<Serializable> getIdType() {
return Serializable.class;
}
}
}

View File

@@ -35,8 +35,8 @@ import org.springframework.data.domain.Persistable;
public class PersistableEntityInformationUnitTests {
@SuppressWarnings("rawtypes")
static final PersistableEntityInformation<Persistable> metadata =
new PersistableEntityInformation<Persistable>(Persistable.class);
static final PersistableEntityInformation metadata =
new PersistableEntityInformation(Persistable.class);
@Mock
Persistable<Long> persistable;
@@ -64,8 +64,8 @@ public class PersistableEntityInformationUnitTests {
@Test
public void returnsGivenClassAsEntityType() throws Exception {
PersistableEntityInformation<PersistableEntity> info =
new PersistableEntityInformation<PersistableEntity>(
PersistableEntityInformation<PersistableEntity, Long> info =
new PersistableEntityInformation<PersistableEntity, Long>(
PersistableEntity.class);
assertEquals(PersistableEntity.class, info.getJavaType());

View File

@@ -62,6 +62,16 @@ public class RepositoryFactorySupportUnitTests {
}
class DummyRepositoryFactory extends RepositoryFactorySupport {
/* (non-Javadoc)
* @see org.springframework.data.repository.support.RepositoryFactorySupport#getEntityInformation(java.lang.Class)
*/
@Override
public <T, ID extends Serializable> EntityInformation<T, ID> getEntityInformation(
Class<T> domainClass) {
return mock(EntityInformation.class);
}
@Override
protected Object getTargetRepository(RepositoryMetadata metadata) {