Skip to content

Commit

Permalink
Add a JsonSchemaMapperV2 interface rather than breaking original.
Browse files Browse the repository at this point in the history
  • Loading branch information
Xtansia committed Mar 14, 2023
1 parent 344625d commit 7c92736
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

package software.amazon.smithy.jsonschema;

import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.shapes.Shape;

/**
Expand All @@ -29,7 +28,7 @@ public byte getOrder() {
}

@Override
public Schema.Builder updateSchema(Shape shape, Schema.Builder schema, JsonSchemaConfig config, Model model) {
public Schema.Builder updateSchema(Shape shape, Schema.Builder schema, JsonSchemaConfig config) {
for (String feature : config.getDisableFeatures()) {
schema.disableProperty(feature);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

package software.amazon.smithy.jsonschema;

import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.shapes.Shape;

/**
Expand All @@ -42,8 +41,7 @@ default byte getOrder() {
* @param shape Shape used for the conversion.
* @param schemaBuilder Schema builder to update.
* @param config JSON Schema config.
* @param model Model the converted shape belongs to.
* @return Returns an updated schema builder.
*/
Schema.Builder updateSchema(Shape shape, Schema.Builder schemaBuilder, JsonSchemaConfig config, Model model);
Schema.Builder updateSchema(Shape shape, Schema.Builder schemaBuilder, JsonSchemaConfig config);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/


package software.amazon.smithy.jsonschema;

import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.shapes.Shape;

/**
* Context for a JSON schema mapping.
*
* @param <T> Type of Smithy {@link Shape} being mapped.
*/
public class JsonSchemaMapperContext<T extends Shape> {
private final Model model;
private final T shape;
private final JsonSchemaConfig config;

JsonSchemaMapperContext(
Model model,
T shape,
JsonSchemaConfig config
) {
this.model = model;
this.shape = shape;
this.config = config;
}

/**
* Gets the Smithy model being converted.
*
* @return Returns the Smithy model.
*/
public Model getModel() {
return model;
}

/**
* Gets the Smithy shape being mapped.
*
* @return Returns the Smithy shape.
*/
public T getShape() {
return shape;
}

/**
* Gets the JSON schema configuration object.
*
* @return Returns the JSON schema config object.
*/
public JsonSchemaConfig getConfig() {
return config;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.jsonschema;

import software.amazon.smithy.model.shapes.Shape;

public interface JsonSchemaMapperV2 extends JsonSchemaMapper {
default Schema.Builder updateSchema(Shape shape, Schema.Builder schemaBuilder, JsonSchemaConfig config) {
return schemaBuilder;
}

/**
* Updates a schema builder.
*
* @param context Context of this schema mapping.
* @param schemaBuilder Schema builder to update.
* @return Returns an updated schema builder.
*/
Schema.Builder updateSchema(JsonSchemaMapperContext<? extends Shape> context, Schema.Builder schemaBuilder);
}
Original file line number Diff line number Diff line change
Expand Up @@ -334,9 +334,16 @@ private Schema.Builder updateBuilder(Shape shape, Schema.Builder builder) {
* @param builder Schema being built.
* @return Returns the built schema.
*/
private Schema buildSchema(Shape shape, Schema.Builder builder) {
private <T extends Shape> Schema buildSchema(T shape, Schema.Builder builder) {
JsonSchemaConfig config = converter.getConfig();
JsonSchemaMapperContext<T> context = new JsonSchemaMapperContext<>(model, shape, config);

for (JsonSchemaMapper mapper : mappers) {
mapper.updateSchema(shape, builder, converter.getConfig(), model);
builder = mapper.updateSchema(shape, builder, config);

if (mapper instanceof JsonSchemaMapperV2) {
builder = ((JsonSchemaMapperV2) mapper).updateSchema(context, builder);
}
}

return builder.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

package software.amazon.smithy.jsonschema;

import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.traits.TimestampFormatTrait;

Expand All @@ -31,7 +30,7 @@ public byte getOrder() {
}

@Override
public Schema.Builder updateSchema(Shape shape, Schema.Builder builder, JsonSchemaConfig config, Model model) {
public Schema.Builder updateSchema(Shape shape, Schema.Builder builder, JsonSchemaConfig config) {
String format = config.detectJsonTimestampFormat(shape).orElse(null);

if (format == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,17 @@
import static org.junit.jupiter.api.Assertions.assertFalse;

import org.junit.jupiter.api.Test;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.shapes.StringShape;
import software.amazon.smithy.utils.SetUtils;

public class DisableMapperTest {
@Test
public void removesDisabledKeywords() {
StringShape shape = StringShape.builder().id("smithy.example#String").build();
Model model = Model.builder().addShape(shape).build();
Schema.Builder builder = Schema.builder().type("string").format("foo");
JsonSchemaConfig config = new JsonSchemaConfig();
config.setDisableFeatures(SetUtils.of("format"));
Schema schema = new DisableMapper().updateSchema(shape, builder, config, model).build();
Schema schema = new DisableMapper().updateSchema(shape, builder, config).build();

assertThat(schema.getType().get(), equalTo("string"));
assertFalse(schema.getFormat().isPresent());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ public void canUseCustomPropertyNamingStrategy() {
public void canAddCustomSchemaMapper() {
Shape struct = StructureShape.builder().id("smithy.example#Foo").build();
Model model = Model.builder().addShape(struct).build();
JsonSchemaMapper mapper = (shape, builder, conf, _model) -> builder.putExtension("Hi", Node.from("There"));
JsonSchemaMapper mapper = (shape, builder, conf) -> builder.putExtension("Hi", Node.from("There"));
SchemaDocument doc = JsonSchemaConverter.builder().addMapper(mapper).model(model).build().convert();

assertTrue(doc.getDefinition("#/definitions/Foo").isPresent());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import static org.junit.jupiter.api.Assertions.assertFalse;

import org.junit.jupiter.api.Test;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.shapes.TimestampShape;
import software.amazon.smithy.model.traits.TimestampFormatTrait;

Expand All @@ -31,8 +30,7 @@ public void convertsDateTimeToStringAndDateTimeFormat() {
.id("smithy.example#Timestamp")
.addTrait(new TimestampFormatTrait(TimestampFormatTrait.DATE_TIME))
.build();
Model model = Model.builder().addShape(shape).build();
Schema schema = new TimestampMapper().updateSchema(shape, Schema.builder(), new JsonSchemaConfig(), model).build();
Schema schema = new TimestampMapper().updateSchema(shape, Schema.builder(), new JsonSchemaConfig()).build();

assertThat(schema.getType().get(), equalTo("string"));
assertThat(schema.getFormat().get(), equalTo("date-time"));
Expand All @@ -44,8 +42,7 @@ public void convertsHttpDateToString() {
.id("smithy.example#Timestamp")
.addTrait(new TimestampFormatTrait(TimestampFormatTrait.HTTP_DATE))
.build();
Model model = Model.builder().addShape(shape).build();
Schema schema = new TimestampMapper().updateSchema(shape, Schema.builder(), new JsonSchemaConfig(), model).build();
Schema schema = new TimestampMapper().updateSchema(shape, Schema.builder(), new JsonSchemaConfig()).build();

assertThat(schema.getType().get(), equalTo("string"));
assertFalse(schema.getFormat().isPresent());
Expand All @@ -57,8 +54,7 @@ public void convertsEpochSecondsToNumber() {
.id("smithy.example#Timestamp")
.addTrait(new TimestampFormatTrait(TimestampFormatTrait.EPOCH_SECONDS))
.build();
Model model = Model.builder().addShape(shape).build();
Schema schema = new TimestampMapper().updateSchema(shape, Schema.builder(), new JsonSchemaConfig(), model).build();
Schema schema = new TimestampMapper().updateSchema(shape, Schema.builder(), new JsonSchemaConfig()).build();

assertThat(schema.getType().get(), equalTo("number"));
assertFalse(schema.getFormat().isPresent());
Expand All @@ -70,8 +66,7 @@ public void convertsEpochUnknownToNumber() {
.id("smithy.example#Timestamp")
.addTrait(new TimestampFormatTrait("epoch-millis"))
.build();
Model model = Model.builder().addShape(shape).build();
Schema schema = new TimestampMapper().updateSchema(shape, Schema.builder(), new JsonSchemaConfig(), model).build();
Schema schema = new TimestampMapper().updateSchema(shape, Schema.builder(), new JsonSchemaConfig()).build();

assertThat(schema.getType().get(), equalTo("number"));
assertFalse(schema.getFormat().isPresent());
Expand All @@ -80,10 +75,9 @@ public void convertsEpochUnknownToNumber() {
@Test
public void supportsDefaultTimestampFormat() {
TimestampShape shape = TimestampShape.builder().id("smithy.example#Timestamp").build();
Model model = Model.builder().addShape(shape).build();
JsonSchemaConfig config = new JsonSchemaConfig();
config.setDefaultTimestampFormat(TimestampFormatTrait.Format.DATE_TIME);
Schema schema = new TimestampMapper().updateSchema(shape, Schema.builder(), config, model).build();
Schema schema = new TimestampMapper().updateSchema(shape, Schema.builder(), config).build();

assertThat(schema.getType().get(), equalTo("string"));
assertThat(schema.getFormat().get(), equalTo("date-time"));
Expand All @@ -94,8 +88,7 @@ public void assumesDateTimeStringWhenNoFormatOrDefaultPresent() {
TimestampShape shape = TimestampShape.builder()
.id("smithy.example#Timestamp")
.build();
Model model = Model.builder().addShape(shape).build();
Schema schema = new TimestampMapper().updateSchema(shape, Schema.builder(), new JsonSchemaConfig(), model).build();
Schema schema = new TimestampMapper().updateSchema(shape, Schema.builder(), new JsonSchemaConfig()).build();

assertThat(schema.getType().get(), equalTo("string"));
assertThat(schema.getFormat().get(), equalTo("date-time"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
import java.util.Optional;
import java.util.Set;
import software.amazon.smithy.jsonschema.JsonSchemaConfig;
import software.amazon.smithy.jsonschema.JsonSchemaMapper;
import software.amazon.smithy.jsonschema.JsonSchemaMapperContext;
import software.amazon.smithy.jsonschema.JsonSchemaMapperV2;
import software.amazon.smithy.jsonschema.Schema;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.node.Node;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.traits.DeprecatedTrait;
Expand All @@ -46,15 +46,15 @@
* <p>Note: the properties and features added by this mapper can be removed using
* {@link OpenApiConfig#setDisableFeatures}.
*/
public final class OpenApiJsonSchemaMapper implements JsonSchemaMapper {
public final class OpenApiJsonSchemaMapper implements JsonSchemaMapperV2 {

/** See https://swagger.io/docs/specification/data-models/keywords/. */
private static final Set<String> UNSUPPORTED_KEYWORD_DIRECTIVES = SetUtils.of(
"propertyNames",
"contentMediaType");

@Override
public Schema.Builder updateSchema(Shape shape, Schema.Builder builder, JsonSchemaConfig config, Model model) {
public Schema.Builder updateSchema(Shape shape, Schema.Builder builder, JsonSchemaConfig config) {
getResolvedExternalDocs(shape, config)
.map(ExternalDocumentation::toNode)
.ifPresent(docs -> builder.putExtension("externalDocs", docs));
Expand Down Expand Up @@ -93,14 +93,20 @@ public Schema.Builder updateSchema(Shape shape, Schema.Builder builder, JsonSche
}
}

SpecificationExtensionsMapper.findSpecificationExtensions(model, shape, builder::putExtension);

// Remove unsupported JSON Schema keywords.
UNSUPPORTED_KEYWORD_DIRECTIVES.forEach(builder::disableProperty);

return builder;
}

@Override
public Schema.Builder updateSchema(JsonSchemaMapperContext<? extends Shape> context, Schema.Builder builder) {
SpecificationExtensionsMapper.findSpecificationExtensions(
context.getModel(), context.getShape(), builder::putExtension);

return builder;
}

private void handleFormatKeyword(Schema.Builder builder, OpenApiConfig config) {
String blobFormat = config.getDefaultBlobFormat();
if (config.getVersion().supportsContentEncodingKeyword()) {
Expand Down

0 comments on commit 7c92736

Please sign in to comment.