diff --git a/CHANGELOG.md b/CHANGELOG.md index 457303f5..f44767e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- Introduce convenience function `MemberScope.getAnnotationConsideringFieldAndGetter(Class)` ## [3.3.0] - 2019-10-25 ### Fixed diff --git a/pom.xml b/pom.xml index e2adc483..518647b8 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.github.victools jsonschema-generator - 3.3.1-SNAPSHOT + 3.4.0-SNAPSHOT jar diff --git a/src/main/java/com/github/victools/jsonschema/generator/FieldScope.java b/src/main/java/com/github/victools/jsonschema/generator/FieldScope.java index 6632c902..3b6af981 100644 --- a/src/main/java/com/github/victools/jsonschema/generator/FieldScope.java +++ b/src/main/java/com/github/victools/jsonschema/generator/FieldScope.java @@ -20,6 +20,7 @@ import com.fasterxml.classmate.ResolvedTypeWithMembers; import com.fasterxml.classmate.members.ResolvedField; import com.fasterxml.classmate.members.ResolvedMethod; +import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.stream.Stream; @@ -112,4 +113,14 @@ public MethodScope findGetter() { public boolean hasGetter() { return this.findGetter() != null; } + + @Override + public A getAnnotationConsideringFieldAndGetter(Class annotationClass) { + A annotation = this.getAnnotation(annotationClass); + if (annotation == null) { + MemberScope associatedGetter = this.findGetter(); + annotation = associatedGetter == null ? null : associatedGetter.getAnnotation(annotationClass); + } + return annotation; + } } diff --git a/src/main/java/com/github/victools/jsonschema/generator/MemberScope.java b/src/main/java/com/github/victools/jsonschema/generator/MemberScope.java index d6656a62..eb396f45 100644 --- a/src/main/java/com/github/victools/jsonschema/generator/MemberScope.java +++ b/src/main/java/com/github/victools/jsonschema/generator/MemberScope.java @@ -245,6 +245,15 @@ public A getAnnotation(Class annotationClass) { return this.member.get(annotationClass); } + /** + * Return the annotation of the given type on the member, if such an annotation is present on either the field or its getter. + * + * @param type of annotation + * @param annotationClass type of annotation + * @return annotation instance (or {@code null} if no annotation of the given type is present) + */ + public abstract A getAnnotationConsideringFieldAndGetter(Class annotationClass); + /* ============================================== * * Convenience methods for member in this context * * ============================================== */ diff --git a/src/main/java/com/github/victools/jsonschema/generator/MethodScope.java b/src/main/java/com/github/victools/jsonschema/generator/MethodScope.java index 1a955ead..019721ac 100644 --- a/src/main/java/com/github/victools/jsonschema/generator/MethodScope.java +++ b/src/main/java/com/github/victools/jsonschema/generator/MethodScope.java @@ -19,6 +19,7 @@ import com.fasterxml.classmate.ResolvedType; import com.fasterxml.classmate.ResolvedTypeWithMembers; import com.fasterxml.classmate.members.ResolvedMethod; +import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.List; import java.util.stream.Collectors; @@ -138,6 +139,16 @@ public boolean isGetter() { return this.findGetterField() != null; } + @Override + public A getAnnotationConsideringFieldAndGetter(Class annotationClass) { + A annotation = this.getAnnotation(annotationClass); + if (annotation == null) { + MemberScope associatedField = this.findGetterField(); + annotation = associatedField == null ? null : associatedField.getAnnotation(annotationClass); + } + return annotation; + } + /** * Returns the name to be used to reference this method in its parent's "properties". * diff --git a/src/test/java/com/github/victools/jsonschema/generator/FieldScopeTest.java b/src/test/java/com/github/victools/jsonschema/generator/FieldScopeTest.java index e5bac352..74631248 100644 --- a/src/test/java/com/github/victools/jsonschema/generator/FieldScopeTest.java +++ b/src/test/java/com/github/victools/jsonschema/generator/FieldScopeTest.java @@ -16,6 +16,10 @@ package com.github.victools.jsonschema.generator; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import junitparams.JUnitParamsRunner; import junitparams.Parameters; import org.junit.Assert; @@ -68,9 +72,28 @@ public void testHasGetter(String fieldName, boolean expectedResult) throws Excep Assert.assertEquals(expectedResult, result); } + @Test + @Parameters({ + "fieldWithoutGetter, false", + "fieldWithPrivateGetter, true", + "fieldWithPublicGetter, false", + "fieldWithPublicBooleanGetter, true" + }) + public void testGetAnnotationConsideringFieldAndGetter(String fieldName, boolean annotationExpectedToBeFound) { + FieldScope field = this.getTestClassField(fieldName); + TestAnnotation annotation = field.getAnnotationConsideringFieldAndGetter(TestAnnotation.class); + + if (annotationExpectedToBeFound) { + Assert.assertNotNull(annotation); + } else { + Assert.assertNull(annotation); + } + } + private static class TestClass { private String fieldWithoutGetter; + @TestAnnotation private int fieldWithPrivateGetter; private long fieldWithPublicGetter; private boolean fieldWithPublicBooleanGetter; @@ -83,8 +106,14 @@ public long getFieldWithPublicGetter() { return this.fieldWithPublicGetter; } + @TestAnnotation public boolean isFieldWithPublicBooleanGetter() { return this.fieldWithPublicBooleanGetter; } } + + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD, ElementType.METHOD}) + private static @interface TestAnnotation { + } } diff --git a/src/test/java/com/github/victools/jsonschema/generator/MethodScopeTest.java b/src/test/java/com/github/victools/jsonschema/generator/MethodScopeTest.java index 6bc2923e..75169b7d 100644 --- a/src/test/java/com/github/victools/jsonschema/generator/MethodScopeTest.java +++ b/src/test/java/com/github/victools/jsonschema/generator/MethodScopeTest.java @@ -16,6 +16,10 @@ package com.github.victools.jsonschema.generator; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import junitparams.JUnitParamsRunner; import junitparams.Parameters; import org.junit.Assert; @@ -76,12 +80,32 @@ public void testIsGetter(String methodName, boolean expectedResult) throws Excep Assert.assertEquals(expectedResult, result); } + @Test + @Parameters({ + "calculateSomething, false", + "getFieldWithPrivateGetter, true", + "getFieldWithPublicGetter, false", + "isFieldWithPublicBooleanGetter, true" + }) + public void testGetAnnotationConsideringFieldAndGetter(String methodName, boolean annotationExpectedToBeFound) { + MethodScope method = this.getTestClassMethod(methodName); + TestAnnotation annotation = method.getAnnotationConsideringFieldAndGetter(TestAnnotation.class); + + if (annotationExpectedToBeFound) { + Assert.assertNotNull(annotation); + } else { + Assert.assertNull(annotation); + } + } + private static class TestClass { private int fieldWithPrivateGetter; private long fieldWithPublicGetter; + @TestAnnotation private boolean fieldWithPublicBooleanGetter; + @TestAnnotation private int getFieldWithPrivateGetter() { return this.fieldWithPrivateGetter; } @@ -114,4 +138,9 @@ public int calculateSomething() { return 42; } } + + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD, ElementType.METHOD}) + private static @interface TestAnnotation { + } } diff --git a/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorTest.java b/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorTest.java index 4a429738..b1981c6f 100644 --- a/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorTest.java +++ b/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorTest.java @@ -17,6 +17,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; @@ -99,8 +100,15 @@ private static void populateConfigPart(SchemaGeneratorConfigPart configPart, } Object parametersForTestGenerateSchema() { - Module neutralModule = configBuilder -> { - }; + Module neutralModule = configBuilder -> configBuilder.with((javaType, context) -> { + if (Integer.class == javaType.getErasedType()) { + ObjectNode customNode = configBuilder.getObjectMapper() + .createObjectNode() + .put("$comment", "custom definition for Integer.class"); + return new CustomDefinition(customNode, false); + } + return null; + }); Module methodModule = configBuilder -> populateConfigPart(configBuilder.forMethods(), "looked-up from method: "); Module fieldModule = configBuilder -> populateConfigPart(configBuilder.forFields(), "looked-up from field: "); return new Object[][]{ diff --git a/src/test/resources/com/github/victools/jsonschema/generator/testclass1-FULL_DOCUMENTATION.json b/src/test/resources/com/github/victools/jsonschema/generator/testclass1-FULL_DOCUMENTATION.json index 4f8eda18..d44e278d 100644 --- a/src/test/resources/com/github/victools/jsonschema/generator/testclass1-FULL_DOCUMENTATION.json +++ b/src/test/resources/com/github/victools/jsonschema/generator/testclass1-FULL_DOCUMENTATION.json @@ -1,4 +1,9 @@ { + "definitions": { + "Integer (nullable)": { + "$comment": "custom definition for Integer.class" + } + }, "type": "object", "properties": { "CONSTANT": { @@ -15,7 +20,7 @@ "type": ["string", "null"] }, "ignoredInternalValue": { - "type": ["integer", "null"] + "$ref": "#/definitions/Integer (nullable)" }, "primitiveValue": { "type": "integer" diff --git a/src/test/resources/com/github/victools/jsonschema/generator/testclass3-FULL_DOCUMENTATION.json b/src/test/resources/com/github/victools/jsonschema/generator/testclass3-FULL_DOCUMENTATION.json index 9dd26035..7028ee57 100644 --- a/src/test/resources/com/github/victools/jsonschema/generator/testclass3-FULL_DOCUMENTATION.json +++ b/src/test/resources/com/github/victools/jsonschema/generator/testclass3-FULL_DOCUMENTATION.json @@ -1,5 +1,8 @@ { "definitions": { + "Integer (nullable)": { + "$comment": "custom definition for Integer.class" + }, "Optional (nullable)": { "type": ["object", "null"], "properties": { @@ -71,7 +74,7 @@ "type": ["string", "null"] }, "ignoredInternalValue": { - "type": ["integer", "null"] + "$ref": "#/definitions/Integer (nullable)" }, "primitiveValue": { "type": "integer"