Skip to content

Commit

Permalink
chore(core): create SwaggerSchemaUtil as component
Browse files Browse the repository at this point in the history
  • Loading branch information
timonback committed Feb 2, 2024
1 parent f214a47 commit a4d3efa
Show file tree
Hide file tree
Showing 24 changed files with 195 additions and 124 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.github.stavshamir.springwolf.asyncapi.v3.model.components.ComponentSchema;
import io.github.stavshamir.springwolf.asyncapi.v3.model.schema.Schema;
import io.github.stavshamir.springwolf.asyncapi.v3.model.schema.SchemaObject;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -44,16 +43,16 @@ private ObjectNode mapToJsonSchema(

if (schema.getAnyOf() != null) {
ArrayNode arrayNode = objectMapper.createArrayNode();
for (Schema ofSchema : schema.getAnyOf()) {
for (ComponentSchema ofSchema : schema.getAnyOf()) {
SchemaObject schemaObject = getSchemaObject(ofSchema, definitions);
arrayNode.add(fromSchemaInternal(schemaObject, definitions, visited));
}
node.set("anyOf", arrayNode);
}
if (schema.getAllOf() != null) {
ArrayNode arrayNode = objectMapper.createArrayNode();
for (Schema ofSchema : schema.getAllOf()) {
SchemaObject schemaObject = getSchemaObject(ofSchema, definitions);
for (ComponentSchema allSchema : schema.getAllOf()) {
SchemaObject schemaObject = getSchemaObject(allSchema, definitions);
arrayNode.add(fromSchemaInternal(schemaObject, definitions, visited));
}
node.set("allOf", arrayNode);
Expand Down Expand Up @@ -111,7 +110,7 @@ private ObjectNode mapToJsonSchema(
}
if (schema.getOneOf() != null) {
ArrayNode arrayNode = objectMapper.createArrayNode();
for (Schema ofSchema : schema.getOneOf()) {
for (ComponentSchema ofSchema : schema.getOneOf()) {
SchemaObject schemaObject = getSchemaObject(ofSchema, definitions);
arrayNode.add(fromSchemaInternal(schemaObject, definitions, visited));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@

class JsonSchemaGeneratorTest {
private final ObjectMapper mapper = Json.mapper();
private final SwaggerSchemaUtil swaggerSchemaUtil = new SwaggerSchemaUtil();
private final JsonSchemaGenerator jsonSchemaGenerator = new JsonSchemaGenerator(mapper);

@ParameterizedTest
@MethodSource
public void validateJsonSchemaTest(String expectedJsonSchema, Supplier<Schema<?>> asyncApiSchema)
throws IOException {
// given
SchemaObject actualSchema = SwaggerSchemaUtil.mapSchema(asyncApiSchema.get());
SchemaObject actualSchema = swaggerSchemaUtil.mapSchema(asyncApiSchema.get());

// when
verifyValidJsonSchema(expectedJsonSchema);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import io.github.stavshamir.springwolf.asyncapi.v3.model.ExtendableObject;
import io.github.stavshamir.springwolf.asyncapi.v3.model.ExternalDocumentation;
import io.github.stavshamir.springwolf.asyncapi.v3.model.components.ComponentSchema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
Expand Down Expand Up @@ -105,28 +106,28 @@ public class SchemaObject extends ExtendableObject implements Schema {
private List<Object> examples;

@JsonProperty(value = "additionalProperties")
private Schema additionalProperties;
private ComponentSchema additionalProperties;

@JsonProperty(value = "required")
private List<String> required;

@JsonProperty(value = "allOf")
private List<Schema> allOf;
private List<ComponentSchema> allOf;

@JsonProperty(value = "oneOf")
private List<Schema> oneOf;
private List<ComponentSchema> oneOf;

@JsonProperty(value = "anyOf")
private List<Schema> anyOf;
private List<ComponentSchema> anyOf;

@JsonProperty(value = "const")
private Object constValue;

@JsonProperty(value = "not")
private Schema not;
private ComponentSchema not;

@JsonProperty(value = "items")
private Schema items;
private ComponentSchema items;

@JsonProperty(value = "uniqueItems")
private Boolean uniqueItems;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

import com.fasterxml.jackson.core.JsonProcessingException;
import io.github.stavshamir.springwolf.asyncapi.v3.jackson.DefaultAsyncApiSerializer;
import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageReference;
import io.github.stavshamir.springwolf.asyncapi.v3.model.components.ComponentSchema;
import org.junit.jupiter.api.Test;

import java.math.BigDecimal;
Expand Down Expand Up @@ -73,7 +75,8 @@ void shouldSerializeSimpleModel() throws JsonProcessingException {
void shouldSerializeStringToStringMapping() throws JsonProcessingException {
var schema = SchemaObject.builder()
.type("object")
.additionalProperties(SchemaObject.builder().type("string").build())
.additionalProperties(
ComponentSchema.of(SchemaObject.builder().type("string").build()))
.build();

var example =
Expand All @@ -92,7 +95,7 @@ void shouldSerializeStringToStringMapping() throws JsonProcessingException {
void shouldSerializeModelMapping() throws JsonProcessingException {
var schema = SchemaObject.builder()
.type("object")
.additionalProperties(SchemaReference.fromSchema("ComplexModel"))
.additionalProperties(ComponentSchema.of(MessageReference.toSchema("ComplexModel")))
.build();

var example =
Expand Down Expand Up @@ -199,16 +202,16 @@ void shouldSerializeModelsWithComposition() throws JsonProcessingException {
"ExtendedErrorModel",
SchemaObject.builder()
.allOf(List.of(
SchemaReference.fromSchema("ErrorModel"),
SchemaObject.builder()
ComponentSchema.of(MessageReference.toSchema("ErrorModel")),
ComponentSchema.of(SchemaObject.builder()
.type("object")
.required(List.of("rootCause"))
.properties(Map.of(
"rootCause",
SchemaObject.builder()
.type("string")
.build()))
.build()))
.build())))
.build()));

var example =
Expand Down Expand Up @@ -277,8 +280,8 @@ void shouldSerializeModelsWithPolimorphismSupport() throws JsonProcessingExcepti
.description(
"A representation of a cat. Note that `Cat` will be used as the discriminator value.")
.allOf(List.of(
SchemaReference.fromSchema("Pet"),
SchemaObject.builder()
ComponentSchema.of(MessageReference.toSchema("Pet")),
ComponentSchema.of(SchemaObject.builder()
.type("object")
.properties(Map.of(
"huntingSkill",
Expand All @@ -293,15 +296,15 @@ void shouldSerializeModelsWithPolimorphismSupport() throws JsonProcessingExcepti
"aggressive"))
.build()))
.required(List.of("huntingSkill"))
.build()))
.build())))
.build(),
"Dog",
SchemaObject.builder()
.description(
"A representation of a dog. Note that `Dog` will be used as the discriminator value.")
.allOf(List.of(
SchemaReference.fromSchema("Pet"),
SchemaObject.builder()
ComponentSchema.of(MessageReference.toSchema("Pet")),
ComponentSchema.of(SchemaObject.builder()
.type("object")
.properties(Map.of(
"packSize",
Expand All @@ -312,15 +315,15 @@ void shouldSerializeModelsWithPolimorphismSupport() throws JsonProcessingExcepti
.minimum(BigDecimal.ZERO)
.build()))
.required(List.of("packSize"))
.build()))
.build())))
.build(),
"StickInsect",
SchemaObject.builder()
.description(
"A representation of an Australian walking stick. Note that `StickBug` will be used as the discriminator value.")
.allOf(List.of(
SchemaReference.fromSchema("Pet"),
SchemaObject.builder()
ComponentSchema.of(MessageReference.toSchema("Pet")),
ComponentSchema.of(SchemaObject.builder()
.type("object")
.properties(Map.of(
"petType",
Expand All @@ -332,7 +335,7 @@ void shouldSerializeModelsWithPolimorphismSupport() throws JsonProcessingExcepti
.type("string")
.build()))
.required(List.of("color"))
.build()))
.build())))
.build()));
var example =
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import io.github.stavshamir.springwolf.configuration.properties.SpringwolfConfigProperties;
import io.github.stavshamir.springwolf.schemas.ComponentsService;
import io.github.stavshamir.springwolf.schemas.DefaultComponentsService;
import io.github.stavshamir.springwolf.schemas.SwaggerSchemaUtil;
import io.github.stavshamir.springwolf.schemas.example.ExampleGenerator;
import io.github.stavshamir.springwolf.schemas.example.ExampleJsonGenerator;
import io.github.stavshamir.springwolf.schemas.postprocessor.AvroSchemaPostProcessor;
Expand Down Expand Up @@ -80,13 +81,21 @@ public OperationsService operationsService(List<? extends OperationsScanner> ope
return new DefaultOperationsService(operationsScanners);
}

@Bean
@ConditionalOnMissingBean
public SwaggerSchemaUtil swaggerSchemaUtil() {
return new SwaggerSchemaUtil();
}

@Bean
@ConditionalOnMissingBean
public ComponentsService schemasService(
List<ModelConverter> modelConverters,
List<SchemasPostProcessor> schemaPostProcessors,
SwaggerSchemaUtil swaggerSchemaUtil,
SpringwolfConfigProperties springwolfConfigProperties) {
return new DefaultComponentsService(modelConverters, schemaPostProcessors, springwolfConfigProperties);
return new DefaultComponentsService(
modelConverters, schemaPostProcessors, swaggerSchemaUtil, springwolfConfigProperties);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class DefaultComponentsService implements ComponentsService {

private final ModelConverters converter = ModelConverters.getInstance();
private final List<SchemasPostProcessor> schemaPostProcessors;
private final SwaggerSchemaUtil swaggerSchemaUtil;
private final SpringwolfConfigProperties properties;

private final Map<String, Schema> schemas = new HashMap<>();
Expand All @@ -41,17 +42,19 @@ public class DefaultComponentsService implements ComponentsService {
public DefaultComponentsService(
List<ModelConverter> externalModelConverters,
List<SchemasPostProcessor> schemaPostProcessors,
SwaggerSchemaUtil swaggerSchemaUtil,
SpringwolfConfigProperties properties) {

externalModelConverters.forEach(converter::addConverter);
this.schemaPostProcessors = schemaPostProcessors;
this.swaggerSchemaUtil = swaggerSchemaUtil;
this.properties = properties;
}

@Override
public Map<String, SchemaObject> getSchemas() {
return schemas.entrySet().stream()
.map(entry -> Map.entry(entry.getKey(), SwaggerSchemaUtil.mapSchema(entry.getValue())))
.map(entry -> Map.entry(entry.getKey(), swaggerSchemaUtil.mapSchema(entry.getValue())))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,23 @@
import io.github.stavshamir.springwolf.asyncapi.v3.model.components.ComponentSchema;
import io.github.stavshamir.springwolf.asyncapi.v3.model.schema.SchemaObject;
import io.swagger.v3.oas.models.media.Schema;
import lombok.RequiredArgsConstructor;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RequiredArgsConstructor
public class SwaggerSchemaUtil {
private SwaggerSchemaUtil() {}

public static ComponentSchema mapSchemaOrRef(Schema schema) {
public ComponentSchema mapSchemaOrRef(Schema schema) {
if (schema.get$ref() != null) {
return ComponentSchema.of(new MessageReference(schema.get$ref()));
}
return ComponentSchema.of(mapSchema(schema));
}

public static SchemaObject mapSchema(Schema value) {
public SchemaObject mapSchema(Schema value) {
SchemaObject.SchemaObjectBuilder builder = SchemaObject.builder();

// TODO: .discriminator(value.getDiscriminator())
Expand Down Expand Up @@ -91,7 +92,7 @@ public static SchemaObject mapSchema(Schema value) {

Object additionalProperties = value.getAdditionalProperties();
if (additionalProperties instanceof Schema) {
builder.additionalProperties(mapSchema((Schema<?>) additionalProperties));
builder.additionalProperties(mapSchemaOrRef((Schema<?>) additionalProperties));
}

builder.required(value.getRequired());
Expand All @@ -100,36 +101,36 @@ public static SchemaObject mapSchema(Schema value) {
if (allOf != null) {
builder.allOf(allOf.stream()
.filter((el) -> el instanceof Schema<?>)
.map((Object schema) -> mapSchema((Schema<?>) schema))
.map((Object schema) -> mapSchemaOrRef((Schema<?>) schema))
.collect(Collectors.toList()));
}

List<Object> oneOf = value.getOneOf();
if (oneOf != null) {
builder.oneOf(oneOf.stream()
.filter((el) -> el instanceof Schema<?>)
.map((Object schema) -> mapSchema((Schema<?>) schema))
.map((Object schema) -> mapSchemaOrRef((Schema<?>) schema))
.collect(Collectors.toList()));
}

List<Object> anyOf = value.getAnyOf();
if (anyOf != null) {
builder.anyOf(anyOf.stream()
.filter((el) -> el instanceof Schema<?>)
.map((Object schema) -> mapSchema((Schema<?>) schema))
.map((Object schema) -> mapSchemaOrRef((Schema<?>) schema))
.collect(Collectors.toList()));
}

builder.constValue(value.getConst());

Schema not = value.getNot();
if (not != null) {
builder.not(mapSchema(not));
builder.not(mapSchemaOrRef(not));
}

Schema items = value.getItems();
if (items != null && items.getType() != null) {
builder.items(mapSchema(items));
if (items != null && "array".equals(value.getType())) {
builder.items(mapSchemaOrRef(items));
}
builder.uniqueItems(value.getUniqueItems());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import io.github.stavshamir.springwolf.configuration.properties.SpringwolfConfigProperties;
import io.github.stavshamir.springwolf.schemas.ComponentsService;
import io.github.stavshamir.springwolf.schemas.DefaultComponentsService;
import io.github.stavshamir.springwolf.schemas.SwaggerSchemaUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
Expand Down Expand Up @@ -75,10 +76,12 @@ public OperationAction getOperationType() {
return OperationAction.SEND;
}
};
private final SwaggerSchemaUtil swaggerSchemaUtil = new SwaggerSchemaUtil();
private final SpringwolfConfigProperties properties = new SpringwolfConfigProperties();
private final ClassScanner classScanner = mock(ClassScanner.class);
private final ComponentsService componentsService =
new DefaultComponentsService(emptyList(), emptyList(), properties);
new DefaultComponentsService(emptyList(), emptyList(), swaggerSchemaUtil, properties);

private final AsyncApiDocketService asyncApiDocketService = mock(AsyncApiDocketService.class);
private final PayloadClassExtractor payloadClassExtractor = new PayloadClassExtractor(properties);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import io.github.stavshamir.springwolf.configuration.properties.SpringwolfConfigProperties;
import io.github.stavshamir.springwolf.schemas.ComponentsService;
import io.github.stavshamir.springwolf.schemas.DefaultComponentsService;
import io.github.stavshamir.springwolf.schemas.SwaggerSchemaUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
Expand Down Expand Up @@ -74,10 +75,11 @@ public OperationAction getOperationType() {
return OperationAction.SEND;
}
};
private final SwaggerSchemaUtil swaggerSchemaUtil = new SwaggerSchemaUtil();
private final SpringwolfConfigProperties properties = new SpringwolfConfigProperties();
private final ClassScanner classScanner = mock(ClassScanner.class);
private final ComponentsService componentsService =
new DefaultComponentsService(emptyList(), emptyList(), properties);
new DefaultComponentsService(emptyList(), emptyList(), swaggerSchemaUtil, properties);
private final AsyncApiDocketService asyncApiDocketService = mock(AsyncApiDocketService.class);
private final PayloadClassExtractor payloadClassExtractor = new PayloadClassExtractor(properties);

Expand Down
Loading

0 comments on commit a4d3efa

Please sign in to comment.