-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #69 from SentryMan/valid
Optional Support/AOP Method Return Types
- Loading branch information
Showing
45 changed files
with
404 additions
and
314 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
blackbox-test/src/main/java/example/avaje/optional/CurseBearer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package example.avaje.optional; | ||
|
||
import java.util.Optional; | ||
import java.util.OptionalDouble; | ||
import java.util.OptionalInt; | ||
import java.util.OptionalLong; | ||
|
||
import io.avaje.validation.constraints.NotBlank; | ||
import io.avaje.validation.constraints.Positive; | ||
import io.avaje.validation.constraints.Valid; | ||
|
||
@Valid | ||
public record CurseBearer( | ||
@NotBlank(message = "it'll happen to you too") Optional<String> name, | ||
@Positive OptionalInt estus, | ||
@Positive(message = "You Died") OptionalLong souls, | ||
@Positive(message = "you didn't pass the vigor check") OptionalDouble vigor) {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
blackbox-test/src/test/java/example/avaje/optional/OptionalTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package example.avaje.optional; | ||
|
||
import static java.util.stream.Collectors.toSet; | ||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.fail; | ||
|
||
import java.util.Optional; | ||
import java.util.OptionalDouble; | ||
import java.util.OptionalInt; | ||
import java.util.OptionalLong; | ||
import java.util.Set; | ||
import java.util.stream.Stream; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
import example.avaje.composable.Sans; | ||
import io.avaje.validation.ConstraintViolation; | ||
import io.avaje.validation.ConstraintViolationException; | ||
import io.avaje.validation.Validator; | ||
|
||
class OptionalTest { | ||
|
||
final Validator validator = Validator.builder().build(); | ||
|
||
@Test | ||
void valid() { | ||
final var monarch = | ||
new CurseBearer( | ||
Optional.of("Belmont"), | ||
OptionalInt.of(5), | ||
OptionalLong.of(10000), | ||
OptionalDouble.of(42.0)); | ||
validator.validate(monarch); | ||
} | ||
|
||
@Test | ||
void validEmpty() { | ||
final var hollow = | ||
new CurseBearer( | ||
Optional.empty(), OptionalInt.empty(), OptionalLong.empty(), OptionalDouble.empty()); | ||
validator.validate(hollow); | ||
} | ||
|
||
@Test | ||
void validNull() { | ||
final var hollow = new CurseBearer(null, null, null, null); | ||
validator.validate(hollow); | ||
} | ||
|
||
@Test | ||
void invalid() { | ||
final var violations = | ||
violations( | ||
new CurseBearer( | ||
Optional.of(""), OptionalInt.of(0), OptionalLong.of(0), OptionalDouble.of(0))); | ||
assertThat(violations) | ||
.contains( | ||
"it'll happen to you too", | ||
"must be greater than 0", | ||
"You Died", | ||
"you didn't pass the vigor check"); | ||
} | ||
|
||
Set<String> violations(Object any) { | ||
try { | ||
validator.validate(any); | ||
fail("not expected"); | ||
return null; | ||
} catch (final ConstraintViolationException e) { | ||
return e.violations().stream().map(ConstraintViolation::message).collect(toSet()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 104 additions & 0 deletions
104
validator-generator/src/main/java/io/avaje/validation/generator/AdapterHelper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package io.avaje.validation.generator; | ||
|
||
import java.util.Map; | ||
import static io.avaje.validation.generator.ProcessingContext.isAssignable2Interface; | ||
|
||
public class AdapterHelper { | ||
|
||
static void writeAdapterWithValues( | ||
Append writer, ElementAnnotationContainer elementAnnotations, String indent, String type) { | ||
boolean first = true; | ||
final var annotations = elementAnnotations.annotations(); | ||
final var genericType = elementAnnotations.genericType(); | ||
final var typeUse1 = elementAnnotations.typeUse1(); | ||
final var typeUse2 = elementAnnotations.typeUse2(); | ||
final var hasValid = elementAnnotations.hasValid(); | ||
for (final var a : annotations.entrySet()) { | ||
if (first) { | ||
writer.append( | ||
"%sctx.<%s>adapter(%s.class, %s)", indent, type, a.getKey().shortName(), a.getValue()); | ||
first = false; | ||
continue; | ||
} | ||
writer | ||
.eol() | ||
.append( | ||
"%s .andThen(ctx.adapter(%s.class,%s))", | ||
indent, a.getKey().shortName(), a.getValue()); | ||
} | ||
|
||
if (annotations.isEmpty()) { | ||
writer.append("%sctx.<%s>noop()", indent, type); | ||
} | ||
|
||
if (!typeUse1.isEmpty() | ||
&& (isAssignable2Interface(genericType.topType(), "java.lang.Iterable"))) { | ||
writer.eol().append("%s .list()", indent); | ||
final var t = genericType.firstParamType(); | ||
writeTypeUse(writer, indent, t, typeUse1, genericType); | ||
|
||
} else if ((!typeUse1.isEmpty() || !typeUse2.isEmpty()) | ||
&& "java.util.Map".equals(genericType.topType())) { | ||
|
||
writer.eol().append("%s .mapKeys()", indent); | ||
writeTypeUse(writer, indent, genericType.firstParamType(), typeUse1, genericType); | ||
|
||
writer.eol().append("%s .mapValues()", indent); | ||
writeTypeUse(writer, indent, genericType.secondParamType(), typeUse2, false, genericType); | ||
|
||
} else if (genericType.topType().contains("[]") && hasValid) { | ||
|
||
writer.eol().append("%s .array()", indent); | ||
writeTypeUse(writer, indent, genericType.firstParamType(), typeUse1, genericType); | ||
} else if (hasValid) { | ||
writer | ||
.eol() | ||
.append( | ||
"%s .andThen(ctx.adapter(%s.class))", | ||
indent, Util.shortName(genericType.topType())); | ||
} else if (genericType.topType().contains("java.util.Optional")) { | ||
writer.eol().append("%s .optional()", indent); | ||
} | ||
} | ||
|
||
private static void writeTypeUse( | ||
Append writer, | ||
String indent, | ||
String firstParamType, | ||
Map<GenericType, String> typeUse12, | ||
GenericType genericType) { | ||
writeTypeUse(writer, indent, firstParamType, typeUse12, true, genericType); | ||
} | ||
|
||
private static void writeTypeUse( | ||
Append writer, | ||
String indent, | ||
String paramType, | ||
Map<GenericType, String> typeUseMap, | ||
boolean keys, | ||
GenericType genericType) { | ||
|
||
for (final var a : typeUseMap.entrySet()) { | ||
|
||
if (Constants.VALID_ANNOTATIONS.contains(a.getKey().topType())) { | ||
continue; | ||
} | ||
final var k = a.getKey().shortName(); | ||
final var v = a.getValue(); | ||
writer.eol().append("%s .andThenMulti(ctx.adapter(%s.class,%s))", indent, k, v); | ||
} | ||
|
||
if (!Util.isBasicType(paramType) | ||
&& typeUseMap.keySet().stream() | ||
.map(GenericType::topType) | ||
.anyMatch(Constants.VALID_ANNOTATIONS::contains)) { | ||
|
||
writer | ||
.eol() | ||
.append( | ||
"%s .andThenMulti(ctx.adapter(%s.class))", | ||
indent, | ||
Util.shortName(keys ? genericType.firstParamType() : genericType.secondParamType())); | ||
} | ||
} | ||
} |
Oops, something went wrong.