1 /*
2  * Copyright 2011-2020 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.springframework.data.repository.core.support;
17
18 import lombok.Getter;
19
20 import java.util.List;
21 import java.util.function.Supplier;
22
23 import org.springframework.data.repository.Repository;
24 import org.springframework.data.repository.core.RepositoryMetadata;
25 import org.springframework.data.util.ClassTypeInformation;
26 import org.springframework.data.util.TypeInformation;
27 import org.springframework.util.Assert;
28
29 /**
30  * Default implementation of {@link RepositoryMetadata}. Will inspect generic types of {@link Repository} to find out
31  * about domain and id class.
32  *
33  * @author Oliver Gierke
34  * @author Thomas Darimont
35  */

36 @Getter
37 public class DefaultRepositoryMetadata extends AbstractRepositoryMetadata {
38
39     private static final String MUST_BE_A_REPOSITORY = String.format("Given type must be assignable to %s!",
40             Repository.class);
41
42     private final Class<?> idType;
43     private final Class<?> domainType;
44
45     /**
46      * Creates a new {@link DefaultRepositoryMetadata} for the given repository interface.
47      *
48      * @param repositoryInterface must not be {@literal null}.
49      */

50     public DefaultRepositoryMetadata(Class<?> repositoryInterface) {
51
52         super(repositoryInterface);
53         Assert.isTrue(Repository.class.isAssignableFrom(repositoryInterface), MUST_BE_A_REPOSITORY);
54
55         List<TypeInformation<?>> arguments = ClassTypeInformation.from(repositoryInterface) //
56                 .getRequiredSuperTypeInformation(Repository.class)//
57                 .getTypeArguments();
58
59         this.domainType = resolveTypeParameter(arguments, 0,
60                 () -> String.format("Could not resolve domain type of %s!", repositoryInterface));
61         this.idType = resolveTypeParameter(arguments, 1,
62                 () -> String.format("Could not resolve id type of %s!", repositoryInterface));
63     }
64
65     private static Class<?> resolveTypeParameter(List<TypeInformation<?>> arguments, int index,
66             Supplier<String> exceptionMessage) {
67
68         if (arguments.size() <= index || arguments.get(index) == null) {
69             throw new IllegalArgumentException(exceptionMessage.get());
70         }
71
72         return arguments.get(index).getType();
73     }
74 }
75