Closed mikolajmitura closed 4 years ago
Hi! Thank you for the detailed explanation!
Your initial attempt was almost correct: generics-resolver job is to correctly substitute variables in types and let you use usual reflection api to investigate types as you want.
So in your example, resolver must be used to resolve field type List<AnotherBean<List<String>>>
and, after that, you can do everything without it.
There are several utility methods that may help you (not actually tied to context scope):
context.resolveTypeGenerics(type)
shields you from actual type implementations ("give me type's generics)context.resolveGenericOf(type)
simplifies types "projection" ("I want to know the class of this type").Complete example (it's groovy - minor simplifications are not mistakes):
GenericsContext context = GenericsResolver
// SomeBean
.resolve(SomeBean)
// List<AnotherBean<List<String>>>
.fieldType(SomeBean.getDeclaredField("listInSomeBean"))
// AnotherBean<List<String>>
Type type = context.genericType(0)
// List<String>
type = context.resolveTypeGenerics(type)[0]
// String
Class res = context.resolveGenericOf(type)
Now about
GenericsContext genericsContextOfListInSomeBean = genericsContextOfList.genericContext(0); // <- THIS ONE WILL BE HELPFUL, will return GenericsContext for 'AnotherBean<List<String>>'
This is already possible with inlying types: context.inlyingType(genericsContextOfList.genericType(0))
. But in your case, this is useless as generics context is ONLY required to properly track generic variables. When you already have exact type you can investigate it directly (as shown above).
If your type contains variables, you can use context to replace variables with known generic values:
context.resolveType(type)
after that you'll have pure type to work with (resolver will actually repackage type).
Ask me if something is not clear: api is not simple, I know (don't have good ideas on how to simplify it).
Great!, The 'inlyingType' is what I looked for, I don't know why I didn't check that method... Generally generics are not so simple, I'm wondering that I had problem with find framework like that. This framework is doing a lot of good job :-)
GenericsContext context = GenericsResolver.resolve(SomeBean.class);
Field listField = getField(SomeBean.class, "listInSomeBean", true);
GenericsContext genericsContextOfList = context.fieldType(listField);
GenericsContext genericsContext = genericsContextOfList.inlyingType(genericsContextOfList.genericType(0));
Field someObjectField = getField(genericsContextOfList.generic(0), "someObject", true);
GenericsContext someObjectFieldGenericContext = genericsContext.fieldType(someObjectField);
System.out.println(someObjectFieldGenericContext.generic(0));
As I mentioned earlier that validation for paths is my target here:
From Type I will have a problem to get generic context for field 'someObject' from AnotherBean.
btw I will try make pull request and you will let me know that is acceptable :-)
Summary: have to deny the request, but will add these use-cases in documentation as api usage examples.
@mikolajmitura thank you again for your efforts! It wasn't for nothing!
Hi,
for example please consider that paths:
Target is to validate that some certain paths are correct for certain class (here SomeBean class) But this validation will needs to be done without runtime data.
I tried with code like below:
My proposition is to add method GenericsContext .genericContext(int position)
I don't know that others faced with that kind of problem. Maybe you have a some solution for that? Maybe I don't see something.
Thanks in advance :-)