-
Notifications
You must be signed in to change notification settings - Fork 64
feat: java validation support on supplier method #282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,7 @@ | |
import java.lang.reflect.AnnotatedParameterizedType; | ||
import java.lang.reflect.AnnotatedType; | ||
import java.lang.reflect.Field; | ||
import java.util.function.Supplier; | ||
import java.util.stream.Stream; | ||
|
||
/** | ||
|
@@ -112,6 +113,14 @@ public MethodScope findGetter() { | |
* @return public getter from within the field's declaring class | ||
*/ | ||
private MethodScope doFindGetter() { | ||
if (this.getMember().getType().isInstanceOf(Supplier.class)) { | ||
ResolvedMethod[] methods = getContext().resolveWithMembers(this.getMember().getType()).getMemberMethods(); | ||
return Stream.of(methods) | ||
.filter(method -> method.getName().equals("get")) | ||
Comment on lines
+117
to
+119
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. question: Collecting all methods only to then filter by name seems excessive. Isn't there an easy way to just look-up the one method we're interested in? |
||
.findFirst() | ||
.map(method -> this.getContext().createMethodScope(method, this.getDeclaringTypeMembers())) | ||
.orElse(null); | ||
} | ||
String capitalisedFieldName = this.getDeclaredName().substring(0, 1).toUpperCase() + this.getDeclaredName().substring(1); | ||
String getterName1 = "get" + capitalisedFieldName; | ||
String getterName2 = "is" + capitalisedFieldName; | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,5 +1,5 @@ | ||||||
/* | ||||||
* Copyright 2019 VicTools. | ||||||
* Copyright 2020 VicTools & Sascha Kohlmann | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why change the copyright?
Suggested change
|
||||||
* | ||||||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
* you may not use this file except in compliance with the License. | ||||||
|
@@ -25,6 +25,7 @@ | |||||
import java.lang.annotation.Annotation; | ||||||
import java.lang.reflect.Member; | ||||||
import java.util.Optional; | ||||||
import java.util.function.Supplier; | ||||||
|
||||||
/** | ||||||
* Representation of a single introspected field or method. | ||||||
|
@@ -321,14 +322,21 @@ public <A extends Annotation> A getContainerItemAnnotationConsideringFieldAndGet | |||||
if (this.isFakeContainerItemScope()) { | ||||||
return this.getContainerItemAnnotationConsideringFieldAndGetter(annotationClass); | ||||||
} | ||||||
if (this.getOverriddenType() != null | ||||||
&& this.getDeclaredType().getErasedType() == Optional.class | ||||||
&& this.getOverriddenType().getErasedType() == this.getDeclaredType().getTypeParameters().get(0).getErasedType()) { | ||||||
if (this.getOverriddenType() != null && (isSupplier() || isOptional())) { | ||||||
return this.getContainerItemAnnotationConsideringFieldAndGetter(annotationClass); | ||||||
} | ||||||
return null; | ||||||
} | ||||||
|
||||||
private boolean isSupplier() { | ||||||
return this.member.getType().isInstanceOf(Supplier.class); | ||||||
} | ||||||
|
||||||
private boolean isOptional() { | ||||||
return this.getDeclaredType().getErasedType() == Optional.class | ||||||
&& this.getOverriddenType().getErasedType() == this.getDeclaredType().getTypeParameters().get(0).getErasedType(); | ||||||
} | ||||||
Comment on lines
+331
to
+338
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: While I agree with adding the support for the Additionally, I'd also include the check of the supplied type against the member's overridden one – same as for |
||||||
|
||||||
/** | ||||||
* Returns the name to be used to reference this member in its parent's "properties". | ||||||
* | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,13 +33,15 @@ | |
import jakarta.validation.constraints.NotNull; | ||
import jakarta.validation.constraints.Null; | ||
import jakarta.validation.constraints.Pattern; | ||
import jakarta.validation.constraints.PositiveOrZero; | ||
import jakarta.validation.constraints.Size; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.List; | ||
import java.util.Optional; | ||
import java.util.Scanner; | ||
import java.util.function.Supplier; | ||
import org.junit.jupiter.api.Test; | ||
import org.skyscreamer.jsonassert.JSONAssert; | ||
import org.skyscreamer.jsonassert.JSONCompareMode; | ||
|
@@ -63,6 +65,7 @@ public void testIntegration() throws Exception { | |
JakartaValidationOption.INCLUDE_PATTERN_EXPRESSIONS); | ||
SchemaGeneratorConfig config = new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_2019_09, OptionPreset.PLAIN_JSON) | ||
.with(Option.NULLABLE_ARRAY_ITEMS_ALLOWED) | ||
.with(Option.FLATTENED_SUPPLIERS) | ||
.with(module) | ||
.build(); | ||
SchemaGenerator generator = new SchemaGenerator(config); | ||
|
@@ -77,7 +80,7 @@ private static String loadResource(String resourcePath) throws IOException { | |
StringBuilder stringBuilder = new StringBuilder(); | ||
try (InputStream inputStream = IntegrationTest.class | ||
.getResourceAsStream(resourcePath); | ||
Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8.name())) { | ||
Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8.name())) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (non-blocking): Let's avoid unnecessary whitespace changes in pull requests for features. |
||
while (scanner.hasNext()) { | ||
stringBuilder.append(scanner.nextLine()).append('\n'); | ||
} | ||
|
@@ -128,5 +131,27 @@ static class TestClass { | |
@DecimalMin(value = "0", inclusive = false) | ||
@DecimalMax(value = "1", inclusive = false) | ||
public double exclusiveRangeDouble; | ||
|
||
@PositiveOrZero | ||
public IntegrationTest.TestSupplier supplierPositiveOrZero; | ||
|
||
public TestSupplierWithAnnotation supplierWithAnnotationPositiveOrZero; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: The tests should also consider a field with type @PositiveOrZero
public Supplier<Integer> getSupplierPositiveOrZeroWithGetter() {
return this.supplierPositiveOrzeroWithGetter;
} |
||
|
||
static class TestSupplier implements Supplier<Integer> { | ||
|
||
@Override | ||
public Integer get() { | ||
return 0; | ||
} | ||
} | ||
|
||
static class TestSupplierWithAnnotation implements Supplier<Integer> { | ||
|
||
@Override | ||
@PositiveOrZero | ||
public Integer get() { | ||
return 0; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: While this achieves the specific use-case you're after, it constitutes a breaking change to this library. I suggest making this dependent on the
Option.FLATTENED_SUPPLIERS
at the least.Plus: the supplier's functional interface implementation is not technically a field's getter. The actual getter could have annotations that may be relevant to consider too, which would get lost here now, wouldn't they?
I'm not sure this is the right place for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If possible, this should be handled within the
FlattenedWrapperModule
. May need to indicate somehow which method is deemed relevant for this.