Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2021 the original author or authors.
* Copyright 2011-2022 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.
Expand Down Expand Up @@ -27,29 +27,48 @@
*
* @author Oliver Gierke
* @author Mark Paluch
* @author Alessandro Nistico
*/
public interface RepositoryMetadata {

/**
* Returns the id class the given class is declared for.
* Returns the id {@link TypeInformation} the given class is declared for.
*
* @return the id class of the entity managed by the repository.
* @return the {@link TypeInformation} class of the entity managed by the repository.
*/
Class<?> getIdType();
TypeInformation<?> getIdTypeInformation();

/**
* Returns the domain class the repository is declared for.
* Returns the domain {@link TypeInformation} the repository is declared for.
*
* @return the domain class the repository is handling.
*/
Class<?> getDomainType();

TypeInformation<?> getDomainTypeInformation();
/**
* Returns the repository interface.
*
* @return
*/
Class<?> getRepositoryInterface();

/**
* Returns the raw id class the given class is declared for.
*
* @return the raw id class of the entity managed by the repository.
*/
default Class<?> getIdType() {
return getIdTypeInformation().getType();
}

/**
* Returns the raw domain class the repository is declared for.
*
* @return the raw domain class the repository is handling.
*/
default Class<?> getDomainType() {
return getDomainTypeInformation().getType();
}

/**
* Returns the type {@link Method} return type as it is declared in the repository. Considers suspended methods and
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2021 the original author or authors.
* Copyright 2011-2022 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.
Expand All @@ -18,6 +18,8 @@
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.repository.RepositoryDefinition;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;

/**
Expand All @@ -27,14 +29,15 @@
* @author Oliver Gierke
* @author Thomas Darimont
* @author Xeno Amess
* @author Alessandro Nistico
*/
public class AnnotationRepositoryMetadata extends AbstractRepositoryMetadata {

private static final String NO_ANNOTATION_FOUND = String.format("Interface %%s must be annotated with @%s!",
RepositoryDefinition.class.getName());

private final Class<?> idType;
private final Class<?> domainType;
private final TypeInformation<?> idType;
private final TypeInformation<?> domainType;

/**
* Creates a new {@link AnnotationRepositoryMetadata} instance looking up repository types from a
Expand All @@ -58,7 +61,7 @@ public AnnotationRepositoryMetadata(Class<?> repositoryInterface) {
* @see org.springframework.data.repository.core.RepositoryMetadata#getIdType()
*/
@Override
public Class<?> getIdType() {
public TypeInformation<?> getIdTypeInformation() {
return this.idType;
}

Expand All @@ -67,29 +70,29 @@ public Class<?> getIdType() {
* @see org.springframework.data.repository.core.RepositoryMetadata#getDomainType()
*/
@Override
public Class<?> getDomainType() {
public TypeInformation<?> getDomainTypeInformation() {
return this.domainType;
}

private Class<?> resolveIdType(Class<?> repositoryInterface) {
private TypeInformation<?> resolveIdType(Class<?> repositoryInterface) {

RepositoryDefinition annotation = AnnotationUtils.findAnnotation(repositoryInterface, RepositoryDefinition.class);

if (annotation == null || annotation.idClass() == null) {
throw new IllegalArgumentException(String.format("Could not resolve id type of %s!", repositoryInterface));
}

return annotation.idClass();
return ClassTypeInformation.from(annotation.idClass());
}

private Class<?> resolveDomainType(Class<?> repositoryInterface) {
private TypeInformation<?> resolveDomainType(Class<?> repositoryInterface) {

RepositoryDefinition annotation = AnnotationUtils.findAnnotation(repositoryInterface, RepositoryDefinition.class);

if (annotation == null || annotation.domainClass() == null) {
throw new IllegalArgumentException(String.format("Could not resolve domain type of %s!", repositoryInterface));
}

return annotation.domainClass();
return ClassTypeInformation.from(annotation.domainClass());
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2021 the original author or authors.
* Copyright 2011-2022 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.
Expand Down Expand Up @@ -43,6 +43,7 @@
* @author Thomas Darimont
* @author Mark Paluch
* @author Christoph Strobl
* @author Alessandro Nistico
*/
class DefaultRepositoryInformation implements RepositoryInformation {

Expand Down Expand Up @@ -80,17 +81,17 @@ public DefaultRepositoryInformation(RepositoryMetadata metadata, Class<?> reposi
* @see org.springframework.data.repository.support.RepositoryMetadata#getDomainClass()
*/
@Override
public Class<?> getDomainType() {
return metadata.getDomainType();
public TypeInformation<?> getDomainTypeInformation() {
return metadata.getDomainTypeInformation();
}

/*
* (non-Javadoc)
* @see org.springframework.data.repository.support.RepositoryMetadata#getIdClass()
*/
@Override
public Class<?> getIdType() {
return metadata.getIdType();
public TypeInformation<?> getIdTypeInformation() {
return metadata.getIdTypeInformation();
}

/*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2021 the original author or authors.
* Copyright 2011-2022 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.
Expand Down Expand Up @@ -30,14 +30,15 @@
*
* @author Oliver Gierke
* @author Thomas Darimont
* @author Alessandro Nistico
*/
public class DefaultRepositoryMetadata extends AbstractRepositoryMetadata {

private static final String MUST_BE_A_REPOSITORY = String.format("Given type must be assignable to %s!",
Repository.class);

private final Class<?> idType;
private final Class<?> domainType;
private final TypeInformation<?> idType;
private final TypeInformation<?> domainType;

/**
* Creates a new {@link DefaultRepositoryMetadata} for the given repository interface.
Expand All @@ -49,31 +50,32 @@ public DefaultRepositoryMetadata(Class<?> repositoryInterface) {
super(repositoryInterface);
Assert.isTrue(Repository.class.isAssignableFrom(repositoryInterface), MUST_BE_A_REPOSITORY);

List<TypeInformation<?>> arguments = ClassTypeInformation.from(repositoryInterface) //
List<TypeInformation<?>> arguments = ClassTypeInformation.from(repositoryInterface)//
.getRequiredSuperTypeInformation(Repository.class)//
.getTypeArguments();

this.domainType = resolveTypeParameter(arguments, 0,
() -> String.format("Could not resolve domain type of %s!", repositoryInterface));

this.idType = resolveTypeParameter(arguments, 1,
() -> String.format("Could not resolve id type of %s!", repositoryInterface));
}

private static Class<?> resolveTypeParameter(List<TypeInformation<?>> arguments, int index,
private static TypeInformation<?> resolveTypeParameter(List<TypeInformation<?>> arguments, int index,
Supplier<String> exceptionMessage) {

if (arguments.size() <= index || arguments.get(index) == null) {
throw new IllegalArgumentException(exceptionMessage.get());
}

return arguments.get(index).getType();
return arguments.get(index).getGenericTypeInformation();
}

public Class<?> getIdType() {
public TypeInformation<?> getIdTypeInformation() {
return this.idType;
}

public Class<?> getDomainType() {
public TypeInformation<?> getDomainTypeInformation() {
return this.domainType;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2021 the original author or authors.
* Copyright 2017-2022 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.
Expand Down Expand Up @@ -45,6 +45,7 @@
*
* @author Mark Paluch
* @author Oliver Gierke
* @author Alessandro Nistico
* @since 2.0
*/
interface MethodLookups {
Expand Down Expand Up @@ -120,8 +121,8 @@ public RepositoryAwareMethodLookup(RepositoryMetadata repositoryMetadata) {

Assert.notNull(repositoryMetadata, "Repository metadata must not be null!");

this.entityType = ResolvableType.forClass(repositoryMetadata.getDomainType());
this.idType = ResolvableType.forClass(repositoryMetadata.getIdType());
this.entityType = ResolvableType.forType(repositoryMetadata.getDomainTypeInformation().getGenericType());
this.idType = ResolvableType.forType(repositoryMetadata.getIdTypeInformation().getGenericType());
this.repositoryInterface = repositoryMetadata.getRepositoryInterface();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2008-2021 the original author or authors.
* Copyright 2008-2022 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.
Expand All @@ -21,6 +21,7 @@

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.ConditionalGenericConverter;
Expand All @@ -29,6 +30,7 @@
import org.springframework.data.repository.core.EntityInformation;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
Expand All @@ -42,6 +44,7 @@
*
* @author Oliver Gierke
* @author Thomas Darimont
* @author Alessandro Nistico
*/
public class DomainClassConverter<T extends ConversionService & ConverterRegistry>
implements ConditionalGenericConverter, ApplicationContextAware {
Expand Down Expand Up @@ -117,6 +120,12 @@ public void setApplicationContext(ApplicationContext context) {
return repositories;
});
}


private static TypeDescriptor getIdTypeDescriptor(RepositoryInformation information) {
TypeInformation<?> idType = information.getIdTypeInformation();
return new TypeDescriptor(ResolvableType.forType(idType.getGenericType()), null, idType.getType().getAnnotations());
}

/**
* Converter to create domain types from any source that can be converted into the domain types identifier type.
Expand Down Expand Up @@ -172,8 +181,9 @@ public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDe
Class<?> domainType = targetType.getType();
RepositoryInvoker invoker = repositoryInvokerFactory.getInvokerFor(domainType);
RepositoryInformation information = repositories.getRequiredRepositoryInformation(domainType);
TypeDescriptor idTypeDescriptor = getIdTypeDescriptor(information);

Object id = conversionService.convert(source, information.getIdType());
Object id = conversionService.convert(source, sourceType, idTypeDescriptor);

return id == null ? null : invoker.invokeFindById(id).orElse(null);
}
Expand All @@ -199,10 +209,10 @@ public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {

return repositoryInformation.map(it -> {

Class<?> rawIdType = it.getIdType();
TypeDescriptor idTypeDescriptor = getIdTypeDescriptor(it);

return sourceType.equals(TypeDescriptor.valueOf(rawIdType))
|| conversionService.canConvert(sourceType.getType(), rawIdType);
return sourceType.equals(idTypeDescriptor)
|| conversionService.canConvert(sourceType, idTypeDescriptor);
}).orElseThrow(
() -> new IllegalStateException(String.format("Couldn't find RepositoryInformation for %s!", domainType)));
}
Expand Down Expand Up @@ -254,8 +264,8 @@ public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDe
Class<?> domainType = sourceType.getType();

EntityInformation<Object, ?> entityInformation = repositories.getEntityInformationFor(domainType);

return conversionService.convert(entityInformation.getId(source), targetType.getType());
Object id = entityInformation.getId(source);
return conversionService.convert(id, TypeDescriptor.forObject(id), targetType);
}

/*
Expand All @@ -279,10 +289,10 @@ public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {

return information.map(it -> {

Class<?> rawIdType = it.getIdType();
TypeDescriptor idTypeDescriptor = getIdTypeDescriptor(it);

return targetType.equals(TypeDescriptor.valueOf(rawIdType))
|| conversionService.canConvert(rawIdType, targetType.getType());
return targetType.equals(idTypeDescriptor)
|| conversionService.canConvert(idTypeDescriptor, targetType);

}).orElseThrow(
() -> new IllegalStateException(String.format("Couldn't find RepositoryInformation for %s!", domainType)));
Expand Down
Loading