Skip to content

Commit 812716d

Browse files
specialize generics hacking
1 parent 983c07d commit 812716d

File tree

3 files changed

+52
-40
lines changed

3 files changed

+52
-40
lines changed

src/main/java/org/springframework/data/util/NewTypeDiscoverer.java

+49-39
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@
6161
import java.util.Set;
6262
import java.util.concurrent.ConcurrentHashMap;
6363
import java.util.stream.Collectors;
64-
import java.util.stream.IntStream;
65-
import java.util.stream.Stream;
6664

6765
import org.springframework.beans.BeanUtils;
6866
import org.springframework.core.MethodParameter;
@@ -94,15 +92,15 @@ public class NewTypeDiscoverer<S> implements TypeInformation<S> {
9492
MAP_TYPES = mapTypes.toArray(new Class[0]);
9593
}
9694

97-
private ResolvableType type;
95+
ResolvableType resolvableType;
9896
private Map<String, Optional<TypeInformation<?>>> fields = new ConcurrentHashMap<>();
9997

10098
private final Lazy<TypeInformation<?>> componentType;
10199
private final Lazy<TypeInformation<?>> valueType;
102100

103101
public NewTypeDiscoverer(ResolvableType type) {
104102

105-
this.type = type;
103+
this.resolvableType = type;
106104
this.componentType = Lazy.of(this::doGetComponentType);
107105
this.valueType = Lazy.of(this::doGetMapValueType);
108106
}
@@ -139,15 +137,15 @@ public TypeInformation<?> getProperty(String name) {
139137

140138
private Optional<TypeInformation<?>> getPropertyInformation(String fieldname) {
141139

142-
Class<?> rawType = type.toClass();
140+
Class<?> rawType = resolvableType.toClass();
143141
var field = ReflectionUtils.findField(rawType, fieldname);
144142

145143
if (field != null) {
146-
return Optional.of(new NewTypeDiscoverer(ResolvableType.forField(field, type)));
144+
return Optional.of(new NewTypeDiscoverer(ResolvableType.forField(field, resolvableType)));
147145
}
148146

149147
return findPropertyDescriptor(rawType, fieldname).map(it -> {
150-
return new NewTypeDiscoverer(ResolvableType.forType(it.getPropertyType(), type));
148+
return new NewTypeDiscoverer(ResolvableType.forType(it.getPropertyType(), resolvableType));
151149
});
152150
}
153151

@@ -191,23 +189,23 @@ protected TypeInformation<?> doGetComponentType() {
191189
var rawType = getType();
192190

193191
if (rawType.isArray()) {
194-
return new NewTypeDiscoverer<>(type.getComponentType());
192+
return new NewTypeDiscoverer<>(resolvableType.getComponentType());
195193
}
196194

197195
if (isMap()) {
198196
if(ClassUtils.isAssignable(Map.class, rawType)) {
199-
ResolvableType mapValueType = type.asMap().getGeneric(0);
197+
ResolvableType mapValueType = resolvableType.asMap().getGeneric(0);
200198
if (ResolvableType.NONE.equals(mapValueType)) {
201199
return null;
202200
}
203201

204202
return mapValueType != null ? new NewTypeDiscoverer(mapValueType) : new ClassTypeInformation<>(Object.class);
205203
}
206-
if (type.hasGenerics()) {
207-
ResolvableType mapValueType = type.getGeneric(0);
204+
if (resolvableType.hasGenerics()) {
205+
ResolvableType mapValueType = resolvableType.getGeneric(0);
208206
return mapValueType != null ? new NewTypeDiscoverer(mapValueType) : new ClassTypeInformation<>(Object.class);
209207
}
210-
return Arrays.stream(type.getInterfaces()).filter(ResolvableType::hasGenerics)
208+
return Arrays.stream(resolvableType.getInterfaces()).filter(ResolvableType::hasGenerics)
211209
.findFirst()
212210
.map(it -> it.getGeneric(0))
213211
.map(NewTypeDiscoverer::new)
@@ -216,16 +214,16 @@ protected TypeInformation<?> doGetComponentType() {
216214

217215
if (Iterable.class.isAssignableFrom(rawType)) {
218216

219-
ResolvableType mapValueType = type.as(Iterable.class).getGeneric(0);
217+
ResolvableType mapValueType = resolvableType.as(Iterable.class).getGeneric(0);
220218
if(ResolvableType.NONE.equals(mapValueType) ) {
221219
return null;
222220
}
223-
if (type.hasGenerics()) {
224-
mapValueType = type.getGeneric(0);
221+
if (resolvableType.hasGenerics()) {
222+
mapValueType = resolvableType.getGeneric(0);
225223
return mapValueType != null ? new NewTypeDiscoverer(mapValueType) : new ClassTypeInformation<>(Object.class);
226224
}
227225

228-
return Arrays.stream(type.getInterfaces()).filter(ResolvableType::hasGenerics)
226+
return Arrays.stream(resolvableType.getInterfaces()).filter(ResolvableType::hasGenerics)
229227
.findFirst()
230228
.map(it -> it.getGeneric(0))
231229
.filter(it -> !ResolvableType.NONE.equals(it))
@@ -241,15 +239,15 @@ protected TypeInformation<?> doGetComponentType() {
241239
}
242240

243241
if (isNullableWrapper()) {
244-
ResolvableType mapValueType = type.getGeneric(0);
242+
ResolvableType mapValueType = resolvableType.getGeneric(0);
245243
if(ResolvableType.NONE.equals(mapValueType) ) {
246244
return null;
247245
}
248246
return mapValueType != null ? new NewTypeDiscoverer(mapValueType) : new ClassTypeInformation<>(Object.class);
249247
}
250248

251-
if (type.hasGenerics()) {
252-
ResolvableType mapValueType = type.getGeneric(0);
249+
if (resolvableType.hasGenerics()) {
250+
ResolvableType mapValueType = resolvableType.getGeneric(0);
253251
return mapValueType != null ? new NewTypeDiscoverer(mapValueType) : new ClassTypeInformation<>(Object.class);
254252
}
255253

@@ -285,28 +283,28 @@ protected TypeInformation<?> doGetMapValueType() {
285283

286284
if(isMap()) {
287285
if(ClassUtils.isAssignable(Map.class, getType())) {
288-
ResolvableType mapValueType = type.asMap().getGeneric(1);
286+
ResolvableType mapValueType = resolvableType.asMap().getGeneric(1);
289287
if (ResolvableType.NONE.equals(mapValueType)) {
290288
return null;
291289
}
292290

293291
return mapValueType != null ? new NewTypeDiscoverer(mapValueType) : new ClassTypeInformation<>(Object.class);
294292
}
295-
if (type.hasGenerics()) {
296-
ResolvableType mapValueType = type.getGeneric(1);
293+
if (resolvableType.hasGenerics()) {
294+
ResolvableType mapValueType = resolvableType.getGeneric(1);
297295
return mapValueType != null ? new NewTypeDiscoverer(mapValueType) : new ClassTypeInformation<>(Object.class);
298296
}
299-
return Arrays.stream(type.getInterfaces()).filter(ResolvableType::hasGenerics)
297+
return Arrays.stream(resolvableType.getInterfaces()).filter(ResolvableType::hasGenerics)
300298
.findFirst()
301299
.map(it -> it.getGeneric(1))
302300
.map(NewTypeDiscoverer::new)
303301
.orElse(null);
304302
}
305303

306-
if(!type.hasGenerics()) {
304+
if(!resolvableType.hasGenerics()) {
307305
return null;
308306
}
309-
ResolvableType x = Arrays.stream(type.getGenerics()).skip(1).findFirst().orElse(null);
307+
ResolvableType x = Arrays.stream(resolvableType.getGenerics()).skip(1).findFirst().orElse(null);
310308
if(x == null || ResolvableType.NONE.equals(x)) {
311309
return null;
312310
}
@@ -316,12 +314,12 @@ protected TypeInformation<?> doGetMapValueType() {
316314

317315
@Override
318316
public Class<S> getType() {
319-
return (Class<S>) type.toClass();
317+
return (Class<S>) resolvableType.toClass();
320318
}
321319

322320
@Override
323321
public ClassTypeInformation<?> getRawTypeInformation() {
324-
return new ClassTypeInformation<>(this.type.getRawClass());
322+
return new ClassTypeInformation<>(this.resolvableType.getRawClass());
325323
}
326324

327325
@Nullable
@@ -353,7 +351,7 @@ public TypeInformation<?> getReturnType(Method method) {
353351
public List<TypeInformation<?>> getParameterTypes(Method method) {
354352

355353
return Streamable.of(method.getParameters()).stream().map(MethodParameter::forParameter)
356-
.map(it -> ResolvableType.forMethodParameter(it, type)).map(NewTypeDiscoverer::new)
354+
.map(it -> ResolvableType.forMethodParameter(it, resolvableType)).map(NewTypeDiscoverer::new)
357355
.collect(Collectors.toList());
358356

359357
}
@@ -374,28 +372,28 @@ public TypeInformation<?> getSuperTypeInformation(Class<?> superType) {
374372

375373
List<ResolvableType> candidates = new ArrayList<>();
376374

377-
ResolvableType genericSuperclass = type.getSuperType();
375+
ResolvableType genericSuperclass = resolvableType.getSuperType();
378376
if (genericSuperclass != null) {
379377
candidates.add(genericSuperclass);
380378
}
381379

382-
candidates.addAll(Arrays.asList(type.getInterfaces()));
380+
candidates.addAll(Arrays.asList(resolvableType.getInterfaces()));
383381

384382
for (var candidate : candidates) {
385383
if (ObjectUtils.nullSafeEquals(superType, candidate.toClass())) {
386384
return new NewTypeDiscoverer(candidate);
387385
} else {
388386
var sup = candidate.getSuperType();
389387
if (sup != null && !ResolvableType.NONE.equals(sup)) {
390-
if(sup.equals(type)) {
388+
if(sup.equals(resolvableType)) {
391389
return this;
392390
}
393391
return new NewTypeDiscoverer(sup);
394392
}
395393
}
396394
}
397395

398-
return new NewTypeDiscoverer(type.as(superType));
396+
return new NewTypeDiscoverer(resolvableType.as(superType));
399397
}
400398

401399
@Override
@@ -410,7 +408,7 @@ public boolean isAssignableFrom(TypeInformation<?> target) {
410408
return true;
411409
}
412410

413-
if(type.isAssignableFrom(target.getType())) {
411+
if(resolvableType.isAssignableFrom(target.getType())) {
414412
return true;
415413
}
416414

@@ -420,14 +418,26 @@ public boolean isAssignableFrom(TypeInformation<?> target) {
420418
@Override
421419
public List<TypeInformation<?>> getTypeArguments() {
422420

423-
if (!type.hasGenerics()) {
421+
if (!resolvableType.hasGenerics()) {
424422
return Collections.emptyList();
425423
}
426-
return Arrays.stream(type.getGenerics()).map(NewTypeDiscoverer::new).collect(Collectors.toList());
424+
return Arrays.stream(resolvableType.getGenerics()).map(NewTypeDiscoverer::new).collect(Collectors.toList());
427425
}
428426

429427
@Override
430428
public TypeInformation<? extends S> specialize(ClassTypeInformation<?> type) {
429+
// if(isAssignableFrom(type)) {
430+
// return new ClassTypeInformation(type.getType());
431+
// }
432+
// return new NewTypeDiscoverer(type.resolvableType.as(getType()));
433+
// if(type.resolvableType.isAssignableFrom(type.resolvableType)) {
434+
// return (TypeInformation<? extends S>) type;
435+
// }
436+
437+
if(this.resolvableType.getGenerics().length == type.resolvableType.getGenerics().length) {
438+
return new NewTypeDiscoverer<>(ResolvableType.forClassWithGenerics(type.getType(), this.resolvableType.getGenerics()));
439+
}
440+
431441
return new ClassTypeInformation(type.getType());
432442
}
433443

@@ -438,12 +448,12 @@ public boolean equals(Object o) {
438448

439449
NewTypeDiscoverer<?> that = (NewTypeDiscoverer<?>) o;
440450

441-
if(!ObjectUtils.nullSafeEquals(type.getType(), that.type.getType())) {
451+
if(!ObjectUtils.nullSafeEquals(resolvableType.getType(), that.resolvableType.getType())) {
442452
return false;
443453
}
444454

445-
List<? extends Class<?>> collect1 = Arrays.stream(type.getGenerics()).map(ResolvableType::toClass).collect(Collectors.toList());
446-
List<? extends Class<?>> collect2 = Arrays.stream(that.type.getGenerics()).map(ResolvableType::toClass).collect(Collectors.toList());
455+
List<? extends Class<?>> collect1 = Arrays.stream(resolvableType.getGenerics()).map(ResolvableType::toClass).collect(Collectors.toList());
456+
List<? extends Class<?>> collect2 = Arrays.stream(that.resolvableType.getGenerics()).map(ResolvableType::toClass).collect(Collectors.toList());
447457

448458
if(!ObjectUtils.nullSafeEquals(collect1, collect2)) {
449459
return false;
@@ -453,7 +463,7 @@ public boolean equals(Object o) {
453463

454464
@Override
455465
public int hashCode() {
456-
return ObjectUtils.nullSafeHashCode(type.toClass());
466+
return ObjectUtils.nullSafeHashCode(resolvableType.toClass());
457467
}
458468

459469
@Override

src/test/java/org/springframework/data/util/NewClassTypeInformationUnitTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ public void detectsSpecialMapAsMapValueType() {
330330
@Test // DATACMNS-446
331331
public void createsToStringRepresentation() {
332332
assertThat(ClassTypeInformation.from(SpecialPerson.class).toString())
333-
.isEqualTo("org.springframework.data.util.ClassTypeInformationUnitTests$SpecialPerson");
333+
.isEqualTo("org.springframework.data.util.NewClassTypeInformationUnitTests$SpecialPerson");
334334
}
335335

336336
@Test // DATACMNS-590

src/test/java/org/springframework/data/util/ParameterizedTypeInformationUnitTests.java

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.Locale;
2929

3030
import org.junit.jupiter.api.BeforeEach;
31+
import org.junit.jupiter.api.Disabled;
3132
import org.junit.jupiter.api.Test;
3233
import org.junit.jupiter.api.extension.ExtendWith;
3334
import org.mockito.Mock;
@@ -44,6 +45,7 @@
4445
*/
4546
@ExtendWith(MockitoExtension.class)
4647
@MockitoSettings(strictness = Strictness.LENIENT)
48+
@Disabled("no longer valid")
4749
class ParameterizedTypeInformationUnitTests {
4850

4951
@Mock ParameterizedType one;

0 commit comments

Comments
 (0)