|
30 | 30 | import java.util.ArrayList;
|
31 | 31 | import java.util.Arrays;
|
32 | 32 | import java.util.List;
|
| 33 | +import java.util.Map; |
33 | 34 | import java.util.Optional;
|
34 | 35 | import java.util.function.Predicate;
|
35 | 36 | import java.util.stream.Collectors;
|
|
38 | 39 | import org.springframework.data.mapping.PersistentEntity;
|
39 | 40 | import org.springframework.data.mapping.PersistentProperty;
|
40 | 41 | import org.springframework.data.mapping.SimplePropertyHandler;
|
| 42 | +import org.springframework.data.util.KotlinReflectionUtils; |
41 | 43 | import org.springframework.util.Assert;
|
| 44 | +import org.springframework.util.ConcurrentReferenceHashMap; |
42 | 45 |
|
43 | 46 | /**
|
44 | 47 | * Value object to represent a Kotlin {@code copy} method. The lookup requires a {@code copy} method that matches the
|
45 | 48 | * primary constructor of the class regardless of whether the primary constructor is the persistence constructor.
|
46 | 49 | *
|
47 | 50 | * @author Mark Paluch
|
| 51 | + * @author Christoph Strobl |
48 | 52 | * @since 2.1
|
49 | 53 | */
|
50 | 54 | class KotlinCopyMethod {
|
51 | 55 |
|
| 56 | + private static final Map<Class<?>, Optional<KotlinCopyMethod>> COPY_METHOD_CACHE = new ConcurrentReferenceHashMap<>(); |
| 57 | + |
52 | 58 | private final Method publicCopyMethod;
|
53 | 59 | private final Method syntheticCopyMethod;
|
54 | 60 | private final int parameterCount;
|
@@ -78,15 +84,17 @@ public static Optional<KotlinCopyMethod> findCopyMethod(Class<?> type) {
|
78 | 84 |
|
79 | 85 | Assert.notNull(type, "Type must not be null");
|
80 | 86 |
|
81 |
| - Optional<Method> syntheticCopyMethod = findSyntheticCopyMethod(type); |
| 87 | + return COPY_METHOD_CACHE.computeIfAbsent(type, it -> { |
82 | 88 |
|
83 |
| - if (!syntheticCopyMethod.isPresent()) { |
84 |
| - return Optional.empty(); |
85 |
| - } |
| 89 | + Optional<Method> syntheticCopyMethod = findSyntheticCopyMethod(type); |
86 | 90 |
|
87 |
| - Optional<Method> publicCopyMethod = syntheticCopyMethod.flatMap(KotlinCopyMethod::findPublicCopyMethod); |
| 91 | + if (!syntheticCopyMethod.isPresent()) { |
| 92 | + return Optional.empty(); |
| 93 | + } |
88 | 94 |
|
89 |
| - return publicCopyMethod.map(method -> new KotlinCopyMethod(method, syntheticCopyMethod.get())); |
| 95 | + Optional<Method> publicCopyMethod = syntheticCopyMethod.flatMap(KotlinCopyMethod::findPublicCopyMethod); |
| 96 | + return publicCopyMethod.map(method -> new KotlinCopyMethod(method, syntheticCopyMethod.get())); |
| 97 | + }); |
90 | 98 | }
|
91 | 99 |
|
92 | 100 | public Method getPublicCopyMethod() {
|
@@ -171,7 +179,7 @@ private static Optional<Method> findPublicCopyMethod(Method defaultKotlinMethod)
|
171 | 179 | return Optional.empty();
|
172 | 180 | }
|
173 | 181 |
|
174 |
| - boolean usesValueClasses = KotlinValueUtils.hasValueClassProperty(type); |
| 182 | + boolean usesValueClasses = KotlinReflectionUtils.hasValueClassProperty(type); |
175 | 183 | List<KParameter> constructorArguments = getComponentArguments(primaryConstructor);
|
176 | 184 | Predicate<String> isCopyMethod;
|
177 | 185 |
|
@@ -242,7 +250,7 @@ private static Optional<Method> findSyntheticCopyMethod(Class<?> type) {
|
242 | 250 | return Optional.empty();
|
243 | 251 | }
|
244 | 252 |
|
245 |
| - boolean usesValueClasses = KotlinValueUtils.hasValueClassProperty(type); |
| 253 | + boolean usesValueClasses = KotlinReflectionUtils.hasValueClassProperty(type); |
246 | 254 |
|
247 | 255 | Predicate<String> isCopyMethod = usesValueClasses ? (it -> it.startsWith("copy-") && it.endsWith("$default"))
|
248 | 256 | : (it -> it.equals("copy$default"));
|
@@ -277,7 +285,7 @@ private static boolean matchesPrimaryConstructor(Class<?>[] parameterTypes, KFun
|
277 | 285 |
|
278 | 286 | KParameter kParameter = constructorArguments.get(i);
|
279 | 287 |
|
280 |
| - if (KotlinValueUtils.isValueClass(kParameter.getType())) { |
| 288 | + if (KotlinReflectionUtils.isValueClass(kParameter.getType())) { |
281 | 289 | // sigh. This can require deep unwrapping because the public vs. the synthetic copy methods use different
|
282 | 290 | // parameter types.
|
283 | 291 | continue;
|
|
0 commit comments