1
16 package org.springframework.data.repository.core.support;
17
18 import java.lang.reflect.Method;
19 import java.util.Arrays;
20 import java.util.Collections;
21 import java.util.List;
22 import java.util.Set;
23
24 import org.springframework.core.KotlinDetector;
25 import org.springframework.data.domain.Pageable;
26 import org.springframework.data.repository.Repository;
27 import org.springframework.data.repository.core.CrudMethods;
28 import org.springframework.data.repository.core.RepositoryMetadata;
29 import org.springframework.data.repository.util.QueryExecutionConverters;
30 import org.springframework.data.repository.util.ReactiveWrappers;
31 import org.springframework.data.util.ClassTypeInformation;
32 import org.springframework.data.util.KotlinReflectionUtils;
33 import org.springframework.data.util.Lazy;
34 import org.springframework.data.util.TypeInformation;
35 import org.springframework.util.Assert;
36
37
45 public abstract class AbstractRepositoryMetadata implements RepositoryMetadata {
46
47 private final TypeInformation<?> typeInformation;
48 private final Class<?> repositoryInterface;
49 private final Lazy<CrudMethods> crudMethods;
50
51
56 public AbstractRepositoryMetadata(Class<?> repositoryInterface) {
57
58 Assert.notNull(repositoryInterface, "Given type must not be null!");
59 Assert.isTrue(repositoryInterface.isInterface(), "Given type must be an interface!");
60
61 this.repositoryInterface = repositoryInterface;
62 this.typeInformation = ClassTypeInformation.from(repositoryInterface);
63 this.crudMethods = Lazy.of(() -> new DefaultCrudMethods(this));
64 }
65
66
73 public static RepositoryMetadata getMetadata(Class<?> repositoryInterface) {
74
75 Assert.notNull(repositoryInterface, "Repository interface must not be null!");
76
77 return Repository.class.isAssignableFrom(repositoryInterface) ? new DefaultRepositoryMetadata(repositoryInterface)
78 : new AnnotationRepositoryMetadata(repositoryInterface);
79 }
80
81
85 @Override
86 public TypeInformation<?> getReturnType(Method method) {
87
88 TypeInformation<?> returnType = null;
89 if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinReflectionUtils.isSuspend(method)) {
90
91
92 List<TypeInformation<?>> types = typeInformation.getParameterTypes(method);
93 returnType = types.get(types.size() - 1).getComponentType();
94 }
95
96 if (returnType == null) {
97 returnType = typeInformation.getReturnType(method);
98 }
99
100 return returnType;
101 }
102
103
107 public Class<?> getReturnedDomainClass(Method method) {
108 return QueryExecutionConverters.unwrapWrapperTypes(getReturnType(method)).getType();
109 }
110
111
115 public Class<?> getRepositoryInterface() {
116 return this.repositoryInterface;
117 }
118
119
123 @Override
124 public CrudMethods getCrudMethods() {
125 return this.crudMethods.get();
126 }
127
128
132 @Override
133 public boolean isPagingRepository() {
134
135 return getCrudMethods().getFindAllMethod()
136 .map(it -> Arrays.asList(it.getParameterTypes()).contains(Pageable.class))
137 .orElse(false);
138 }
139
140
144 @Override
145 public Set<Class<?>> getAlternativeDomainTypes() {
146 return Collections.emptySet();
147 }
148
149
153 @Override
154 public boolean isReactiveRepository() {
155 return ReactiveWrappers.usesReactiveType(repositoryInterface);
156 }
157 }
158