From 2b95da9302a1a62244d8c968e16b330ecf81598e Mon Sep 17 00:00:00 2001 From: Aleksandr Dubinsky Date: Wed, 2 Feb 2022 14:02:52 +0200 Subject: [PATCH] Port to Java 11 --- pom.xml | 4 +- .../jsonSchema/DefinitionsHandler.java | 11 ++- .../JsonSchemaGeneratorVisitor.java | 23 ++--- .../kjetland/jackson/jsonSchema/Utils.java | 8 +- .../jsonSchema/JsonSchemaGeneratorTest.java | 19 ++-- .../jackson/jsonSchema/TestUtils.java | 3 +- .../testData/ClassUsingValidation.java | 51 +++++------ .../ClassUsingValidationWithGroups.java | 24 ++--- .../testData/DefaultAndExamples.java | 23 ++--- .../testData/UsingJsonSchemaInjectTop.java | 88 +++++++++---------- 10 files changed, 135 insertions(+), 119 deletions(-) diff --git a/pom.xml b/pom.xml index 61e74e4..b99e68b 100644 --- a/pom.xml +++ b/pom.xml @@ -121,8 +121,8 @@ maven-compiler-plugin 3.8.1 - 17 - 17 + 11 + 11 diff --git a/src/main/java/com/kjetland/jackson/jsonSchema/DefinitionsHandler.java b/src/main/java/com/kjetland/jackson/jsonSchema/DefinitionsHandler.java index 7ae98ae..f5a1dfc 100644 --- a/src/main/java/com/kjetland/jackson/jsonSchema/DefinitionsHandler.java +++ b/src/main/java/com/kjetland/jackson/jsonSchema/DefinitionsHandler.java @@ -12,14 +12,21 @@ import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.IntStream; +import lombok.AccessLevel; +import lombok.Data; import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; +import lombok.experimental.FieldDefaults; // Class that manages creating new definitions or getting $refs to existing definitions @RequiredArgsConstructor class DefinitionsHandler { - record DefinitionInfo(String ref, JsonObjectFormatVisitor jsonObjectFormatVisitor) {} - record WorkInProgress(JavaType typeInProgress, ObjectNode nodeInProgress) {} + // can be records + @Data @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) @Accessors(fluent = true) + static class DefinitionInfo { String ref; JsonObjectFormatVisitor jsonObjectFormatVisitor; } + @Data @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) @Accessors(fluent = true) + static class WorkInProgress { JavaType typeInProgress; ObjectNode nodeInProgress; } final JsonSchemaConfig config; diff --git a/src/main/java/com/kjetland/jackson/jsonSchema/JsonSchemaGeneratorVisitor.java b/src/main/java/com/kjetland/jackson/jsonSchema/JsonSchemaGeneratorVisitor.java index acace76..58fb4f8 100644 --- a/src/main/java/com/kjetland/jackson/jsonSchema/JsonSchemaGeneratorVisitor.java +++ b/src/main/java/com/kjetland/jackson/jsonSchema/JsonSchemaGeneratorVisitor.java @@ -23,7 +23,11 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import javax.validation.constraints.*; +import lombok.AccessLevel; +import lombok.Data; import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; +import lombok.experimental.FieldDefaults; import lombok.extern.slf4j.Slf4j; @Slf4j @@ -357,7 +361,8 @@ class MapVisitor extends AbstractJsonFormatVisitorWithSerializerProvider impleme return new MapVisitor(); } - record PolymorphismInfo(String typePropertyName, String subTypeName) {} + @Data @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) @Accessors(fluent = true) + static class PolymorphismInfo { String typePropertyName; String subTypeName; } private PolymorphismInfo extractPolymorphismInfo(JavaType type) throws JsonMappingException { @@ -422,18 +427,14 @@ private List> extractSubTypes(Class type) { var subTypes = subTypeAnn.value(); return Stream.of(subTypes) .map(subType -> subType.value()) - // Who the hell thought of multiMap? God I hate Streams - // Also, another javac bug, lol (#9072340) -// .mapMulti((subType, consumer) -> { - .>mapMulti((subType, consumer) -> { + .flatMap(subType -> { var subSubTypes = extractSubTypes(subType); if (!subSubTypes.isEmpty()) - for (var subSubType : subSubTypes) - consumer.accept(subSubType); + return subSubTypes.stream(); else - consumer.accept(subType); + return Stream.of(subType); }) - .toList(); + .collect(Collectors.toList()); } else return ctx.config.subclassesResolver.getSubclasses(type); @@ -642,7 +643,9 @@ void handleProperty(String propertyName, JavaType propertyType, BeanProperty pro } // Need to check for Optional/Optional-special-case before we know what node to use here. - record PropertyNode(ObjectNode main, ObjectNode meta) {} +// record PropertyNode(ObjectNode main, ObjectNode meta) {} + @Data @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) @Accessors(fluent = true) + class PropertyNode { final ObjectNode main; final ObjectNode meta; } // Check if we should set this property as required. Primitive types MUST have a value, as does anything // with a @JsonProperty that has "required" set to true. Lastly, various javax.validation annotations also diff --git a/src/main/java/com/kjetland/jackson/jsonSchema/Utils.java b/src/main/java/com/kjetland/jackson/jsonSchema/Utils.java index 386b588..97990c3 100644 --- a/src/main/java/com/kjetland/jackson/jsonSchema/Utils.java +++ b/src/main/java/com/kjetland/jackson/jsonSchema/Utils.java @@ -61,10 +61,10 @@ public static void merge(JsonNode mainNode, JsonNode updateNode) { merge(jsonNode, updateNode.get(fieldName)); } else { - if (mainNode instanceof ObjectNode node) { + if (mainNode instanceof ObjectNode) { // Overwrite field var value = updateNode.get(fieldName); - node.set(fieldName, value); + ((ObjectNode)mainNode).set(fieldName, value); } } } @@ -165,8 +165,8 @@ public static List> extractGroupsFromAnnotation(Annotation annotation) return List.of(); } } - else if (annotation instanceof JsonSchemaInject _annotation) - return List.of(_annotation.javaxValidationGroups()); + else if (annotation instanceof JsonSchemaInject) + return List.of(((JsonSchemaInject)annotation).javaxValidationGroups()); else return List.of(); } diff --git a/src/test/java/com/kjetland/jackson/jsonSchema/JsonSchemaGeneratorTest.java b/src/test/java/com/kjetland/jackson/jsonSchema/JsonSchemaGeneratorTest.java index a239fd5..fda63fe 100644 --- a/src/test/java/com/kjetland/jackson/jsonSchema/JsonSchemaGeneratorTest.java +++ b/src/test/java/com/kjetland/jackson/jsonSchema/JsonSchemaGeneratorTest.java @@ -43,6 +43,7 @@ import java.util.Map; import java.util.Set; import java.util.TimeZone; +import java.util.stream.Collectors; import java.util.stream.Stream; import javax.validation.groups.Default; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -100,7 +101,7 @@ public class JsonSchemaGeneratorTest { @Test void generateSchemaForPojo() { - var enumList = List.of(MyEnum.values()).stream().map(Object::toString).toList(); + var enumList = List.of(MyEnum.values()).stream().map(Object::toString).collect(Collectors.toList()); { var jsonNode = assertToFromJson(jsonSchemaGenerator, testData.classNotExtendingAnything); @@ -464,7 +465,7 @@ void assertNullableChild2(JsonNode node, String path, String defName, boolean ht assertEquals (schema.at("/properties/myEnum/type").asText(), "string"); assertEquals (getArrayNodeAsListOfStrings(schema.at("/properties/myEnum/enum")), - Stream.of(MyEnum.values()).map(Enum::name).toList()); + Stream.of(MyEnum.values()).map(Enum::name).collect(Collectors.toList())); assertEquals (schema.at("/properties/myEnum/JsonSchemaInjectOnEnum").asText(), "true"); } @@ -493,7 +494,7 @@ void assertNullableChild2(JsonNode node, String path, String defName, boolean ht assertNullableType(schema, "/properties/myEnum", "string"); assertEquals (getArrayNodeAsListOfStrings(schema.at("/properties/myEnum/oneOf/1/enum")), - Stream.of(MyEnum.values()).map(Enum::name).toList()); + Stream.of(MyEnum.values()).map(Enum::name).collect(Collectors.toList())); } @Test void optional() { @@ -1119,7 +1120,7 @@ void checkInjected(JsonNode schema, String propertyName, boolean included) { @Test void polymorphismOneOfOrdering() { var schema = generateAndValidateSchema(jsonSchemaGeneratorHTML5, PolymorphismOrdering.class, null); - List oneOfList = toList(schema.at("/oneOf").iterator()).stream().map(e -> e.at("/$ref").asText()).toList(); + List oneOfList = toList(schema.at("/oneOf").iterator()).stream().map(e -> e.at("/$ref").asText()).collect(Collectors.toList()); assertEquals (List.of("#/definitions/PolymorphismOrderingChild3", "#/definitions/PolymorphismOrderingChild1", "#/definitions/PolymorphismOrderingChild4", "#/definitions/PolymorphismOrderingChild2"), oneOfList); } @@ -1180,12 +1181,12 @@ void checkInjected(JsonNode schema, String propertyName, boolean included) { out.println("--------------------------------------------"); out.println(schemaJson); - var fasit = """ - { - "everything" : "should be replaced" - }""".stripIndent(); + var fasit = + "{\n" + + " \"everything\" : \"should be replaced\"\n" + + "}"; - assertTrue ( schemaJson .equals (fasit) ); + assertEquals(fasit, schemaJson); } @Test void preventingPolymorphismWithClassTypeRemapping_classWithProperty() { diff --git a/src/test/java/com/kjetland/jackson/jsonSchema/TestUtils.java b/src/test/java/com/kjetland/jackson/jsonSchema/TestUtils.java index 7662d86..b17f189 100644 --- a/src/test/java/com/kjetland/jackson/jsonSchema/TestUtils.java +++ b/src/test/java/com/kjetland/jackson/jsonSchema/TestUtils.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.stream.Collectors; import java.util.stream.StreamSupport; import javax.annotation.Nullable; import lombok.SneakyThrows; @@ -161,7 +162,7 @@ List getArrayNodeAsListOfStrings(JsonNode node) { if (node instanceof MissingNode) return List.of(); else - return StreamSupport.stream(node.spliterator(), false).map(JsonNode::asText).toList(); + return StreamSupport.stream(node.spliterator(), false).map(JsonNode::asText).collect(Collectors.toList()); } List getRequiredList(JsonNode node) { diff --git a/src/test/java/com/kjetland/jackson/jsonSchema/testData/ClassUsingValidation.java b/src/test/java/com/kjetland/jackson/jsonSchema/testData/ClassUsingValidation.java index f263933..42cbb48 100644 --- a/src/test/java/com/kjetland/jackson/jsonSchema/testData/ClassUsingValidation.java +++ b/src/test/java/com/kjetland/jackson/jsonSchema/testData/ClassUsingValidation.java @@ -1,66 +1,67 @@ package com.kjetland.jackson.jsonSchema.testData; -import com.kjetland.jackson.jsonSchema.annotations.JsonSchemaInject; import java.util.List; import java.util.Map; import javax.validation.constraints.*; -import javax.validation.groups.Default; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.experimental.FieldDefaults; +import lombok.extern.jackson.Jacksonized; -public record ClassUsingValidation -( +@FieldDefaults(level = AccessLevel.PUBLIC, makeFinal = true) @Jacksonized @Builder @EqualsAndHashCode // Can be Java 17 record +public class ClassUsingValidation +{ @NotNull - String stringUsingNotNull, + String stringUsingNotNull; @NotBlank - String stringUsingNotBlank, + String stringUsingNotBlank; @NotNull @NotBlank - String stringUsingNotBlankAndNotNull, + String stringUsingNotBlankAndNotNull; @NotEmpty - String stringUsingNotEmpty, + String stringUsingNotEmpty; @NotEmpty - List notEmptyStringArray, // Per PojoArraysWithScala, we use always use Lists in Scala, and never raw arrays. + List notEmptyStringArray; // Per PojoArraysWithScala, we use always use Lists in Scala, and never raw arrays. @NotEmpty - Map notEmptyMap, + Map notEmptyMap; @Size(min=1, max=20) - String stringUsingSize, + String stringUsingSize; @Size(min=1) - String stringUsingSizeOnlyMin, + String stringUsingSizeOnlyMin; @Size(max=30) - String stringUsingSizeOnlyMax, + String stringUsingSizeOnlyMax; @Pattern(regexp = "_stringUsingPatternA|_stringUsingPatternB") - String stringUsingPattern, + String stringUsingPattern; @Pattern.List({ @Pattern(regexp = "^_stringUsing.*"), @Pattern(regexp = ".*PatternList$") }) - String stringUsingPatternList, + String stringUsingPatternList; @Min(1) - int intMin, + int intMin; @Max(10) - int intMax, + int intMax; @Min(1) - double doubleMin, + double doubleMin; @Max(10) - double doubleMax, + double doubleMax; @DecimalMin("1.5") - double decimalMin, + double decimalMin; @DecimalMax("2.5") - double decimalMax, + double decimalMax; @Email - String email -) -{ - + String email; } \ No newline at end of file diff --git a/src/test/java/com/kjetland/jackson/jsonSchema/testData/ClassUsingValidationWithGroups.java b/src/test/java/com/kjetland/jackson/jsonSchema/testData/ClassUsingValidationWithGroups.java index 018de80..8ae7cef 100644 --- a/src/test/java/com/kjetland/jackson/jsonSchema/testData/ClassUsingValidationWithGroups.java +++ b/src/test/java/com/kjetland/jackson/jsonSchema/testData/ClassUsingValidationWithGroups.java @@ -4,32 +4,36 @@ import com.kjetland.jackson.jsonSchema.testData.ClassUsingValidationWithGroups.ValidationGroup1; import javax.validation.constraints.NotNull; import javax.validation.groups.Default; - +import lombok.AccessLevel; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.experimental.FieldDefaults; +import lombok.extern.jackson.Jacksonized; @JsonSchemaInject(json = "{\"injected\":true}", javaxValidationGroups = { ValidationGroup1.class }) -public record ClassUsingValidationWithGroups -( +@EqualsAndHashCode @FieldDefaults(level = AccessLevel.PUBLIC, makeFinal = true) @Jacksonized @Builder // Can be Java 17 record +public class ClassUsingValidationWithGroups +{ @NotNull @JsonSchemaInject(json = "{\"injected\":true}") - String noGroup, + String noGroup; @NotNull(groups = { Default.class }) @JsonSchemaInject(json = "{\"injected\":true}", javaxValidationGroups = { Default.class }) - String defaultGroup, + String defaultGroup; @NotNull(groups = { ValidationGroup1.class }) @JsonSchemaInject(json = "{\"injected\":true}", javaxValidationGroups = { ValidationGroup1.class }) - String group1, + String group1; @NotNull(groups = { ValidationGroup2.class }) @JsonSchemaInject(json = "{\"injected\":true}", javaxValidationGroups = { ValidationGroup2.class }) - String group2, + String group2; @NotNull(groups = { ValidationGroup1.class, ValidationGroup2.class }) @JsonSchemaInject(json = "{\"injected\":true}", javaxValidationGroups = { ValidationGroup1.class, ValidationGroup2.class }) - String group12 -) -{ + String group12; + public interface ValidationGroup1 {} public interface ValidationGroup2 {} public interface ValidationGroup3_notInUse {} diff --git a/src/test/java/com/kjetland/jackson/jsonSchema/testData/DefaultAndExamples.java b/src/test/java/com/kjetland/jackson/jsonSchema/testData/DefaultAndExamples.java index 9dd606b..09577bf 100644 --- a/src/test/java/com/kjetland/jackson/jsonSchema/testData/DefaultAndExamples.java +++ b/src/test/java/com/kjetland/jackson/jsonSchema/testData/DefaultAndExamples.java @@ -3,25 +3,28 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.kjetland.jackson.jsonSchema.annotations.JsonSchemaDefault; import com.kjetland.jackson.jsonSchema.annotations.JsonSchemaExamples; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.experimental.FieldDefaults; +import lombok.extern.jackson.Jacksonized; - -public record DefaultAndExamples -( +@FieldDefaults(level = AccessLevel.PUBLIC, makeFinal = true) @Jacksonized @Builder @EqualsAndHashCode // Can be Java 17 record +public class DefaultAndExamples +{ @JsonSchemaExamples({"user@example.com"}) - String emailValue, + String emailValue; @JsonSchemaDefault("12") @JsonSchemaExamples({"10", "14", "18"}) - int fontSize, + int fontSize; @JsonProperty(defaultValue = "ds") - String defaultStringViaJsonValue, + String defaultStringViaJsonValue; @JsonProperty(defaultValue = "1") - int defaultIntViaJsonValue, + int defaultIntViaJsonValue; @JsonProperty(defaultValue = "true") - boolean defaultBoolViaJsonValue -) -{ + boolean defaultBoolViaJsonValue; } \ No newline at end of file diff --git a/src/test/java/com/kjetland/jackson/jsonSchema/testData/UsingJsonSchemaInjectTop.java b/src/test/java/com/kjetland/jackson/jsonSchema/testData/UsingJsonSchemaInjectTop.java index e033009..927322f 100644 --- a/src/test/java/com/kjetland/jackson/jsonSchema/testData/UsingJsonSchemaInjectTop.java +++ b/src/test/java/com/kjetland/jackson/jsonSchema/testData/UsingJsonSchemaInjectTop.java @@ -10,7 +10,13 @@ import java.util.function.Supplier; import javax.validation.constraints.Min; import javax.validation.constraints.Pattern; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Data; import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; +import lombok.experimental.FieldDefaults; +import lombok.extern.jackson.Jacksonized; /** * @@ -18,61 +24,52 @@ */ public class UsingJsonSchemaInjectTop { @JsonSchemaInject( - json= - """ - { - "patternProperties": { - "^s[a-zA-Z0-9]+": { - "type": "string" - } - }, - "properties": { - "injectedInProperties": "true" - } - } - """, + json="{\n" + + " \"patternProperties\": {\n" + + " \"^s[a-zA-Z0-9]+\": {\n" + + " \"type\": \"string\"\n" + + " }\n" + + " },\n" + + " \"properties\": {\n" + + " \"injectedInProperties\": \"true\"\n" + + " }\n" + + "}", strings = {@JsonSchemaString(path = "patternProperties/^i[a-zA-Z0-9]+/type", value = "integer")} ) - public record UsingJsonSchemaInject - ( + @FieldDefaults(level = AccessLevel.PUBLIC, makeFinal = true) @Jacksonized @Builder // Can be Java 17 record + public static class UsingJsonSchemaInject + { @JsonSchemaInject( - json= - """ - { - "options": { - "hidden": true - } - } - """) - String sa, + json="{\n" + + " \"options\": {\n" + + " \"hidden\": true\n" + + " }\n" + + "}") + String sa; @JsonSchemaInject( - json= - """ - { - "type": "integer", - "default": 12 - } - """, + json="{\n" + + " \"type\": \"integer\",\n" + + " \"default\": 12\n" + + "}", overrideAll = true ) @Pattern(regexp = "xxx") // Should not end up in schema since we're replacing with injected - String saMergeFalse, + String saMergeFalse; @JsonSchemaInject( bools = {@JsonSchemaBool(path = "exclusiveMinimum", value = true)}, ints = {@JsonSchemaInt(path = "multipleOf", value = 7)} ) @Min(5) - int ib, + int ib; @JsonSchemaInject(jsonSupplier = UserNamesLoader.class) - Set uns, + Set uns; @JsonSchemaInject(jsonSupplierViaLookup = "myCustomUserNamesLoader") - Set uns2 - ) - {} + Set uns2; + } public static class UserNamesLoader implements Supplier { ObjectMapper _objectMapper = new ObjectMapper(); @@ -103,15 +100,14 @@ public static class CustomUserNamesLoader implements Supplier { } @JsonSchemaInject( - json = """ - { - "everything": "should be replaced" - }""", + json = "{\n" + + " \"everything\": \"should be replaced\"\n" + + "}", overrideAll = true ) - public record UsingJsonSchemaInjectWithTopLevelMergeFalse - ( - String shouldBeIgnored - ) - {} + @FieldDefaults(level = AccessLevel.PUBLIC, makeFinal = true) @Jacksonized @Builder // Can be Java 17 record + public static class UsingJsonSchemaInjectWithTopLevelMergeFalse + { + String shouldBeIgnored; + } }