Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ docker-spring-boot = "10.0.0"
gradle-nexus-publish-plugin = "2.0.0"
io-awspring-cloud = "4.0.0"
io-confluent = "8.2.0"
io-swagger-core-v3 = "2.2.40"
io-swagger-core-v3 = "2.2.41"
jackson-core = "2.21.1"
kotlin = "2.3.10"
node-plugin = "7.1.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,24 @@
public class SchemaTitleModelConverter implements ModelConverter {
@Override
public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator<ModelConverter> chain) {
if (!chain.hasNext()) return null;

Schema<?> schema = chain.next().resolve(type, context, chain);
if (schema == null) return null;

JavaType javaType = Json.mapper().constructType(type.getType());
if (chain.hasNext()) {
Schema<?> schema = chain.next().resolve(type, context, chain);
boolean isPrimitiveType = PrimitiveType.createProperty(type.getType()) != null;
if (schema != null && !isPrimitiveType) {
if (schema.get$ref() != null) {
Schema<?> definedModel = context.resolve(type);
if (definedModel != null && definedModel.getTitle() == null) {
definedModel.setTitle(javaType.getRawClass().getSimpleName());
}
}
boolean isPrimitiveType = PrimitiveType.createProperty(type.getType()) != null;
if (isPrimitiveType) return schema;

if (schema.get$ref() != null) {
Schema<?> definedModel = context.resolve(type);
if (definedModel != null && definedModel.getTitle() == null) {
definedModel.setTitle(javaType.getRawClass().getSimpleName());
}
return schema;
} else if (schema.getTitle() == null) {
schema.setTitle(javaType.getRawClass().getSimpleName());
}
return null;

return schema;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ void getArraySchemas() {
"array",
ComponentSchema.of(SchemaObject.builder()
.type(Set.of(SchemaType.ARRAY.getValue()))
.title("List")
.items(ComponentSchema.of(SchemaObject.builder()
.type(Set.of(SchemaType.STRING.getValue()))
.description("items description")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
// SPDX-License-Identifier: Apache-2.0
package io.github.springwolf.core.asyncapi.schemas.converters;

import io.swagger.v3.core.converter.AnnotatedType;
import io.swagger.v3.core.converter.ModelConverter;
import io.swagger.v3.core.converter.ModelConverterContext;
import io.swagger.v3.oas.models.media.Schema;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.Collections;
import java.util.Iterator;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class SchemaTitleModelConverterTest {

private final SchemaTitleModelConverter converter = new SchemaTitleModelConverter();

private ModelConverterContext context;

@BeforeEach
void setUp() {
context = mock(ModelConverterContext.class);
}

@Test
void returnsNullWhenChainIsEmpty() {
// given
AnnotatedType type = new AnnotatedType(SimpleClass.class);
Iterator<ModelConverter> emptyChain = Collections.emptyIterator();

// when
Schema<?> result = converter.resolve(type, context, emptyChain);

// then
assertThat(result).isNull();
}

@Test
void returnsNullWhenChainReturnsNull() {
// given
AnnotatedType type = new AnnotatedType(SimpleClass.class);
ModelConverter nextConverter = mock(ModelConverter.class);
when(nextConverter.resolve(any(), any(), any())).thenReturn(null);
Iterator<ModelConverter> chain =
Collections.singletonList(nextConverter).iterator();

// when
Schema<?> result = converter.resolve(type, context, chain);

// then
assertThat(result).isNull();
}

@Test
void returnsSchemaWithoutModificationForPrimitiveType() {
// given - int is a primitive type recognized by PrimitiveType.createProperty
AnnotatedType type = new AnnotatedType(Integer.class);
Schema<?> primitiveSchema = new Schema<>();
ModelConverter nextConverter = mock(ModelConverter.class);
when(nextConverter.resolve(any(), any(), any())).thenReturn(primitiveSchema);
Iterator<ModelConverter> chain =
Collections.singletonList(nextConverter).iterator();

// when
Schema<?> result = converter.resolve(type, context, chain);

// then
assertThat(result).isSameAs(primitiveSchema);
assertThat(result.getTitle()).isNull();
}

@Test
void setsTitleOnSchemaWithoutRefForComplexType() {
// given
AnnotatedType type = new AnnotatedType(SimpleClass.class);
Schema<?> schema = new Schema<>();
// no $ref, no title set
ModelConverter nextConverter = mock(ModelConverter.class);
when(nextConverter.resolve(any(), any(), any())).thenReturn(schema);
Iterator<ModelConverter> chain =
Collections.singletonList(nextConverter).iterator();

// when
Schema<?> result = converter.resolve(type, context, chain);

// then
assertThat(result).isSameAs(schema);
assertThat(result.getTitle()).isEqualTo("SimpleClass");
}

@Test
void doesNotOverwriteExistingTitleOnSchema() {
// given
AnnotatedType type = new AnnotatedType(SimpleClass.class);
Schema<?> schema = new Schema<>();
schema.setTitle("ExistingTitle");
ModelConverter nextConverter = mock(ModelConverter.class);
when(nextConverter.resolve(any(), any(), any())).thenReturn(schema);
Iterator<ModelConverter> chain =
Collections.singletonList(nextConverter).iterator();

// when
Schema<?> result = converter.resolve(type, context, chain);

// then
assertThat(result).isSameAs(schema);
assertThat(result.getTitle()).isEqualTo("ExistingTitle");
}

@Test
void setsTitleOnDefinedModelWhenSchemaHasRef() {
// given
AnnotatedType type = new AnnotatedType(SimpleClass.class);
Schema<?> schemaWithRef = new Schema<>();
schemaWithRef.set$ref("#/components/schemas/SimpleClass");
Schema<?> definedModel = new Schema<>();
// definedModel has no title yet

ModelConverter nextConverter = mock(ModelConverter.class);
when(nextConverter.resolve(any(), any(), any())).thenReturn(schemaWithRef);
when(context.resolve(type)).thenReturn(definedModel);
Iterator<ModelConverter> chain =
Collections.singletonList(nextConverter).iterator();

// when
Schema<?> result = converter.resolve(type, context, chain);

// then
assertThat(result).isSameAs(schemaWithRef);
assertThat(definedModel.getTitle()).isEqualTo("SimpleClass");
}

@Test
void doesNotOverwriteExistingTitleOnDefinedModelWhenSchemaHasRef() {
// given
AnnotatedType type = new AnnotatedType(SimpleClass.class);
Schema<?> schemaWithRef = new Schema<>();
schemaWithRef.set$ref("#/components/schemas/SimpleClass");
Schema<?> definedModel = new Schema<>();
definedModel.setTitle("ExistingTitle");

ModelConverter nextConverter = mock(ModelConverter.class);
when(nextConverter.resolve(any(), any(), any())).thenReturn(schemaWithRef);
when(context.resolve(type)).thenReturn(definedModel);
Iterator<ModelConverter> chain =
Collections.singletonList(nextConverter).iterator();

// when
Schema<?> result = converter.resolve(type, context, chain);

// then
assertThat(result).isSameAs(schemaWithRef);
assertThat(definedModel.getTitle()).isEqualTo("ExistingTitle");
}

@Test
void doesNotSetTitleWhenDefinedModelIsNullForRefSchema() {
// given
AnnotatedType type = new AnnotatedType(SimpleClass.class);
Schema<?> schemaWithRef = new Schema<>();
schemaWithRef.set$ref("#/components/schemas/SimpleClass");

ModelConverter nextConverter = mock(ModelConverter.class);
when(nextConverter.resolve(any(), any(), any())).thenReturn(schemaWithRef);
when(context.resolve(type)).thenReturn(null);
Iterator<ModelConverter> chain =
Collections.singletonList(nextConverter).iterator();

// when
Schema<?> result = converter.resolve(type, context, chain);

// then
assertThat(result).isSameAs(schemaWithRef);
}

static class SimpleClass {
public String name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
]
},
"io.github.springwolf.core.integrationtests.application.polymorphic.PolymorphicPayloadApplication.Cat": {
"title": "Cat",
"type": "object",
"examples": [
{
Expand All @@ -51,6 +52,7 @@
]
},
"io.github.springwolf.core.integrationtests.application.polymorphic.PolymorphicPayloadApplication.Dog": {
"title": "Dog",
"type": "object",
"examples": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
} ]
},
"io.github.springwolf.core.asyncapi.components.DefaultJsonComponentsServiceIntegrationTest.SchemaWithOneOf.ImplementationOne" : {
"title" : "ImplementationOne",
"type" : "object",
"properties" : {
"firstOne" : {
Expand All @@ -43,6 +44,7 @@
} ]
},
"io.github.springwolf.core.asyncapi.components.DefaultJsonComponentsServiceIntegrationTest.SchemaWithOneOf.ImplementationTwo" : {
"title" : "ImplementationTwo",
"type" : "object",
"properties" : {
"firstTwo" : {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"type" : "object",
"properties" : {
"flist" : {
"title" : "List",
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/io.github.springwolf.core.asyncapi.components.DefaultJsonComponentsServiceIntegrationTest.SimpleFoo"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,15 @@
"$ref" : "#/components/schemas/io.github.springwolf.core.asyncapi.components.DefaultJsonComponentsServiceIntegrationTest.ComplexFoo.Nested.Cyclic"
},
"nli" : {
"title" : "List",
"type" : "array",
"items" : {
"type" : "integer",
"format" : "int32"
}
},
"nmfm" : {
"title" : "Map",
"type" : "object",
"additionalProperties" : {
"$ref" : "#/components/schemas/io.github.springwolf.core.asyncapi.components.DefaultJsonComponentsServiceIntegrationTest.ComplexFoo.Nested.MyClass"
Expand All @@ -83,6 +85,7 @@
"type" : "string"
},
"nsm" : {
"title" : "Set",
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/io.github.springwolf.core.asyncapi.components.DefaultJsonComponentsServiceIntegrationTest.ComplexFoo.Nested.MyClass"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"type" : "object",
"properties" : {
"b" : {
"title" : "Bar",
"type" : "string",
"enum" : [ "BAR1", "BAR2" ]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"examples" : [ "2024-04-24T00:00:00.000+00:00" ]
},
"ls_plain" : {
"title" : "List",
"type" : "array",
"description" : "List without example",
"items" : {
Expand All @@ -28,6 +29,7 @@
}
},
"mss" : {
"title" : "Map",
"type" : "object",
"description" : "Map with example",
"examples" : [ {
Expand All @@ -40,6 +42,7 @@
}
},
"mss_plain" : {
"title" : "Map",
"type" : "object",
"description" : "Map without example",
"additionalProperties" : {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"io.github.springwolf.core.asyncapi.components.DefaultJsonComponentsServiceIntegrationTest.ListWrapper" : {
"title" : "ListWrapper",
"type" : "array",
"properties" : {
"empty" : {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"io.github.springwolf.core.asyncapi.components.DefaultJsonComponentsServiceIntegrationTest.JsonTypeTest.JsonTypeInfoExampleOne" : {
"title" : "JsonTypeInfoExampleOne",
"type" : "object",
"description" : "Json Type Info Example One model",
"examples" : [ {
Expand All @@ -20,6 +21,7 @@
} ]
},
"io.github.springwolf.core.asyncapi.components.DefaultJsonComponentsServiceIntegrationTest.JsonTypeTest.JsonTypeInfoExampleTwo" : {
"title" : "JsonTypeInfoExampleTwo",
"type" : "object",
"description" : "Json Type Info Example Two model",
"examples" : [ {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
} ]
},
"io.github.springwolf.core.asyncapi.components.DefaultXmlComponentsServiceIntegrationTest.SchemaWithOneOf.ImplementationOne" : {
"title" : "ImplementationOne",
"type" : "string",
"properties" : {
"firstOne" : {
Expand All @@ -32,6 +33,7 @@
"examples" : [ "<ImplementationOne><firstOne>string</firstOne><secondOne>string</secondOne></ImplementationOne>" ]
},
"io.github.springwolf.core.asyncapi.components.DefaultXmlComponentsServiceIntegrationTest.SchemaWithOneOf.ImplementationTwo" : {
"title" : "ImplementationTwo",
"type" : "string",
"properties" : {
"firstTwo" : {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"type" : "string",
"properties" : {
"flist" : {
"title" : "List",
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/io.github.springwolf.core.asyncapi.components.DefaultXmlComponentsServiceIntegrationTest.SimpleFoo"
Expand Down
Loading
Loading