Skip to content

Commit

Permalink
preserve descriptions next to the $ref
Browse files Browse the repository at this point in the history
some code cleanup
  • Loading branch information
bartoszm committed Dec 28, 2022
1 parent ab2ab2c commit d630691
Show file tree
Hide file tree
Showing 17 changed files with 96 additions and 366 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<groupId>com.amartus.sonata</groupId>
<artifactId>blender</artifactId>
<description>SonataBlendingTool</description>
<version>1.9.5-SNAPSHOT</version>
<version>1.9.5</version>
<properties>
<openapi.generator.version>6.2.0</openapi.generator.version>
<jackson.version>2.14.0</jackson.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,58 +18,28 @@

package com.amartus.sonata.blender.impl;

import io.swagger.models.ArrayModel;
import io.swagger.models.ComposedModel;
import io.swagger.models.ExternalDocs;
import io.swagger.models.Model;
import io.swagger.models.ModelImpl;
import io.swagger.models.Path;
import io.swagger.models.RefModel;
import io.swagger.models.RefPath;
import io.swagger.models.RefResponse;
import io.swagger.models.Response;
import io.swagger.models.Scheme;
import io.swagger.models.SecurityRequirement;
import io.swagger.models.Swagger;
import io.swagger.models.*;
import io.swagger.models.auth.ApiKeyAuthDefinition;
import io.swagger.models.auth.OAuth2Definition;
import io.swagger.models.auth.SecuritySchemeDefinition;
import io.swagger.models.parameters.AbstractSerializableParameter;
import io.swagger.models.parameters.BodyParameter;
import io.swagger.models.parameters.RefParameter;
import io.swagger.models.parameters.SerializableParameter;
import io.swagger.models.properties.AbstractNumericProperty;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.ComposedProperty;
import io.swagger.models.properties.FileProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.ObjectProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.RefProperty;
import io.swagger.models.properties.StringProperty;
import io.swagger.models.properties.*;
import io.swagger.parser.SwaggerParser;
import io.swagger.parser.SwaggerResolver;
import io.swagger.parser.util.SwaggerDeserializationResult;
import io.swagger.v3.core.util.Json;
import io.swagger.v3.core.util.PrimitiveType;
import io.swagger.v3.core.util.Yaml;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.oas.models.*;
import io.swagger.v3.oas.models.headers.Header;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.ComposedSchema;
import io.swagger.v3.oas.models.media.Content;
import io.swagger.v3.oas.models.media.Discriminator;
import io.swagger.v3.oas.models.media.FileSchema;
import io.swagger.v3.oas.models.media.MediaType;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.media.*;
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.parameters.RequestBody;
import io.swagger.v3.oas.models.responses.ApiResponse;
Expand All @@ -90,23 +60,18 @@
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.*;
import java.util.stream.Collectors;

/**
* Clone of io.swagger.v3.parser.converter.SwaggerConverter (with reduced visability
* with override of some private access modifiers to protected
*/
class SwaggerConverterClone implements SwaggerParserExtension {
private List<String> globalConsumes = new ArrayList<>();
private List<String> globalProduces = new ArrayList<>();
private Components components = new Components();
private Map<String, io.swagger.models.parameters.Parameter> globalV2Parameters = new HashMap<>();
private final List<String> globalConsumes = new ArrayList<>();
private final List<String> globalProduces = new ArrayList<>();
private final Components components = new Components();
private final Map<String, io.swagger.models.parameters.Parameter> globalV2Parameters = new HashMap<>();

@Override
public SwaggerParseResult readLocation(String url, List<AuthorizationValue> auths, ParseOptions options) {
Expand All @@ -122,8 +87,7 @@ public SwaggerParseResult readLocation(String url, List<AuthorizationValue> auth

@Override
public SwaggerParseResult readContents(String swaggerAsString, List<AuthorizationValue> auth, ParseOptions options) {
SwaggerDeserializationResult result = new SwaggerParser().readWithInfo(swaggerAsString, options == null ?
true : options.isResolve());
SwaggerDeserializationResult result = new SwaggerParser().readWithInfo(swaggerAsString, options == null || options.isResolve());

if (options != null) {
if (options.isResolve()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.amartus.sonata.blender.impl.postprocess.RenameTypesPostprocessor.*;
import static com.amartus.sonata.blender.impl.postprocess.RenameTypesPostprocessor.NameConverter;

public class ComposedPostprocessor implements Consumer<OpenAPI> {
private static final Logger log = LoggerFactory.getLogger(ComposedPostprocessor.class);

private List<Consumer<OpenAPI>> postprocessors = List.of(
private final List<Consumer<OpenAPI>> postprocessors = List.of(
new RemoveSuperflousTypeDeclarations(),
new RenameTypesPostprocessor(converter()),
new PropertyEnumExternalize(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ public class ConvertOneOfToAllOffInheritance implements Consumer<OpenAPI> {

private static final Logger log = LoggerFactory.getLogger(ConvertOneOfToAllOffInheritance.class);
private OasWrapper openAPI;
private Predicate<Schema> isReference = s -> s.get$ref() != null;
private Predicate<Schema> isOneOf = s -> {
private final Predicate<Schema> isReference = s -> s.get$ref() != null;
private final Predicate<Schema> isOneOf = s -> {
if (s instanceof ComposedSchema) {
ComposedSchema c = (ComposedSchema) s;
return c.getOneOf() != null && !c.getOneOf().isEmpty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,26 @@ public void accept(OpenAPI openAPI) {
substitutions.forEach((a,b) -> log.debug("Renaming {} to {}", a, b));
}

var newNames = new HashSet(substitutions.values());
var newNames = new HashSet<>(substitutions.values());
if(newNames.size() < substitutions.size()) {
log.warn("Conflicting substitution names. Skipping.");
return;
}
if(schemas.keySet().stream().anyMatch(newNames::contains)) {
if (schemas.keySet().stream().anyMatch(newNames::contains)) {
log.warn("Name substitution already defined in the model. Skipping.");
return;
}
schemas.values().forEach(s -> Optional.ofNullable(s.getExtensions()).ifPresent(e -> e.remove(extensionName)));
renameSchemas(openAPI);
renameReferences(openAPI);
cleanupExtensions(openAPI);
}

private void cleanupExtensions(OpenAPI openAPI) {
var schemas = new OasWrapper(openAPI).schemas().values();
schemas.forEach(s -> {
Optional.ofNullable(s.getExtensions()).ifPresent(e -> e.remove(extensionName));
});
}

private void renameSchemas(OpenAPI oas) {
Expand Down Expand Up @@ -89,7 +97,6 @@ protected String convert(String ref) {
private void renameReferences(OpenAPI openAPI) {
new RenameReferences().accept(openAPI);
new RenamePathReferences().accept(openAPI);
//FIXME rename refrences in response ref and body ref
}

protected Optional<String> toName(Schema schema) {
Expand All @@ -115,16 +122,11 @@ public void accept(OpenAPI openAPI) {
});

schemas.forEach(RenameTypesPostprocessor.this::tryConverting);

openAPI.getPaths().entrySet().stream().map(Map.Entry::getValue)
.flatMap(pi -> pi.readOperations().stream());

}

private Stream<Operation> toOperations(OpenAPI oas) {
return Optional.ofNullable(oas.getPaths())
.map(p -> p.entrySet().stream()
.map(Map.Entry::getValue).flatMap(pi -> pi.readOperations().stream())
return Optional.ofNullable(oas.getPaths())
.map(p -> p.values().stream().flatMap(pi -> pi.readOperations().stream())
).orElse(Stream.empty());
}

Expand All @@ -140,7 +142,7 @@ private Stream<Schema> schemas(ApiResponse r) {
}

private Stream<Schema> schemas(Content c) {
if(c == null) Stream.empty();
if (c == null) return Stream.empty();
return c.values().stream().map(MediaType::getSchema);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public interface NameConverter extends Function<String, ProductSpecificationNami
private static String toName(String type) {
return split(type, '-').map(WordUtils::capitalize)
.collect(Collectors.joining(""));
};
}

NameConverter urn = id -> {
var uri = URI.create(id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
public class IdSchemaResolver {

private static final Logger log = LoggerFactory.getLogger(IdSchemaResolver.class);
private UrnPredicate urnPredicate;
private final UrnPredicate urnPredicate;

public IdSchemaResolver(String functionName) {
this.urnPredicate = new UrnPredicate(functionName);
Expand Down Expand Up @@ -72,7 +72,12 @@ private UrnPredicate(String functionName) {

@Override
public boolean test(Path path) {
var toInclude = namingStrategy.provideNameAndDiscriminator(null, read(path))
var content = read(path);
if (content == null) {
log.debug("Not in json or yaml format: {}", path.toAbsolutePath().normalize());
return false;
}
var toInclude = namingStrategy.provideNameAndDiscriminator(null, content)
.map(n -> {
String disc = n.getDiscriminatorValue();
return (disc.endsWith("all") || disc.endsWith(functionName));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import io.swagger.v3.core.util.Json31;
import io.swagger.v3.oas.models.OpenAPI;
import org.openapitools.codegen.serializer.OpenAPISerializer;

Expand All @@ -34,7 +35,7 @@ public static ObjectMapper yamlMapper() {
}

public static ObjectMapper jsonMapper() {
return enhance(new ObjectMapper());
return enhance(Json31.mapper());
}

private static ObjectMapper enhance(ObjectMapper mapper) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
package com.amartus.sonata.blender.impl.yaml;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
Expand All @@ -31,7 +30,7 @@

public class SchemaSerializer extends JsonSerializer<Schema> implements ResolvableSerializer {

private JsonSerializer<Object> defaultSerializer;
private final JsonSerializer<Object> defaultSerializer;

public SchemaSerializer(JsonSerializer<Object> serializer) {
defaultSerializer = serializer;
Expand All @@ -47,7 +46,7 @@ public void resolve(SerializerProvider serializerProvider) throws JsonMappingExc
@Override
public void serialize(
Schema value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
throws IOException {

// handle ref schema serialization skipping all other props
if (StringUtils.isBlank(value.get$ref())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.core.util.Yaml;
import io.swagger.v3.core.util.Yaml31;

public class YamlMapperFactory {
public ObjectMapper createYaml() {
var mapper = Yaml.mapper();
var mapper = Yaml31.mapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
return mapper;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ public class OpenAPIResolver {
private final ComponentsProcessor componentsProcessor;
private final PathsProcessor pathProcessor;
private final OperationProcessor operationsProcessor;
private io.swagger.v3.parser.OpenAPIResolver.Settings settings;
private Set<String> resolveValidationMessages = new HashSet<>();
private final io.swagger.v3.parser.OpenAPIResolver.Settings settings;
private final Set<String> resolveValidationMessages = new HashSet<>();

public ResolverCache getCache() {
return cache;
Expand All @@ -32,7 +32,7 @@ public OpenAPIResolver(OpenAPI openApi, ResolverCache cache, io.swagger.v3.parse
this.openApi = openApi;
this.settings = settings != null ? settings : new io.swagger.v3.parser.OpenAPIResolver.Settings();
this.cache = cache;
componentsProcessor = new ComponentsProcessor(openApi,this.cache);
componentsProcessor = new ComponentsProcessor(openApi, this.cache);
pathProcessor = new PathsProcessor(this.cache, openApi,this.settings);
operationsProcessor = new OperationProcessor(cache, openApi);
}
Expand Down
24 changes: 10 additions & 14 deletions src/main/java/com/amartus/sonata/blender/parser/ResolverCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.*;
import java.util.regex.Matcher;
Expand All @@ -47,16 +47,16 @@ public class ResolverCache extends io.swagger.v3.parser.ResolverCache {
private static final Pattern CALLBACKS_PATTERN = Pattern.compile("^" + RefType.COMPONENTS.getInternalPrefix() + "callbacks/(?<name>.+)");
private static final Pattern HEADERS_PATTERN = Pattern.compile("^" + RefType.COMPONENTS.getInternalPrefix() + "headers/(?<name>.+)");
private static final Pattern SECURITY_SCHEMES = Pattern.compile("^" + RefType.COMPONENTS.getInternalPrefix() + "securitySchemes/(?<name>.+)");
private static final Pattern PATHS_PATTERN = Pattern.compile("^" + RefType.PATH.getInternalPrefix() + "(?<name>.+)");
private static final Pattern PATHS_PATTERN = Pattern.compile("^" + RefType.PATH.getInternalPrefix() + "(?<name>.+)");

private final OpenAPI openApi;
private final List<AuthorizationValue> auths;
private final Path parentDirectory;
private final String rootPath;
private Map<String, Object> resolutionCache = new HashMap<>();
private Map<String, String> externalFileCache = new HashMap<>();
private List<String> referencedModelKeys = new ArrayList<>();
private Set<String> resolveValidationMessages;
private final Map<String, Object> resolutionCache = new HashMap<>();
private final Map<String, String> externalFileCache = new HashMap<>();
private final List<String> referencedModelKeys = new ArrayList<>();
private final Set<String> resolveValidationMessages;
private final ParseOptions parseOptions;
private final DeserializerProvider provider;
protected boolean openapi31;
Expand All @@ -65,7 +65,7 @@ public class ResolverCache extends io.swagger.v3.parser.ResolverCache {
* a map that stores original external references, and their associated renamed
* references
*/
private Map<String, String> renameCache = new HashMap<>();
private final Map<String, String> renameCache = new HashMap<>();

public ResolverCache(OpenAPI openApi, List<AuthorizationValue> auths, String parentFileLocation, DeserializerProvider provider) {
this(openApi, auths, parentFileLocation, new HashSet<>(), provider);
Expand Down Expand Up @@ -199,7 +199,7 @@ else if (rootPath != null) {
} else {
if (expectedType.equals(Schema.class)) {
OpenAPIDeserializer deserializer = provider.deserializer();
result = (T) deserializer.getSchema((ObjectNode) tree, definitionPath.replace("/", "."), new OpenAPIDeserializer.ParseResult().openapi31(openapi31));
result = (T) deserializer.getSchema(tree, definitionPath.replace("/", "."), new OpenAPIDeserializer.ParseResult().openapi31(openapi31));
} else {
result = DeserializationUtils.deserialize(tree, file, expectedType, openapi31);
}
Expand All @@ -219,7 +219,7 @@ private <T> T deserializeFragment(JsonNode node, Class<T> expectedType, String f
OpenAPIDeserializer.ParseResult parseResult = new OpenAPIDeserializer.ParseResult();
T result = null;
if (expectedType.equals(Schema.class)) {
result = (T) deserializer.getSchema((ObjectNode) node, definitionPath.replace("/", "."), parseResult);
result = (T) deserializer.getSchema(node, definitionPath.replace("/", "."), parseResult);
} else if (expectedType.equals(RequestBody.class)) {
result = (T) deserializer.getRequestBody((ObjectNode) node, definitionPath.replace("/", "."), parseResult);
} else if (expectedType.equals(ApiResponse.class)) {
Expand Down Expand Up @@ -348,11 +348,7 @@ else if(ref.startsWith("#/components/securitySchemes")) {

private String unescapePointer(String jsonPathElement) {
// URL decode the fragment
try {
jsonPathElement = URLDecoder.decode(jsonPathElement, "UTF-8");
} catch (UnsupportedEncodingException e) {
//
}
jsonPathElement = URLDecoder.decode(jsonPathElement, StandardCharsets.UTF_8);
// Unescape the JSON Pointer segment using the algorithm described in RFC 6901, section 4:
// https://tools.ietf.org/html/rfc6901#section-4
// First transform any occurrence of the sequence '~1' to '/'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
package com.amartus.sonata.blender.impl;

import com.amartus.Utils;
import io.swagger.v3.oas.models.media.ComposedSchema;
import io.swagger.v3.oas.models.media.ObjectSchema;
import io.swagger.v3.oas.models.media.Schema;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -81,7 +80,7 @@ public void testProtectDescriptions() {
var schemas = new ProductSpecReader("testToAugment", dirPath.resolve(name))
.readSchemas();
singleRootSchema(schemas);
var root = (ObjectSchema) ((ComposedSchema) schemas.get(name)).getAllOf().get(1);
var root = (ObjectSchema) schemas.get(name).getAllOf().get(1);
root.getProperties().forEach((k,v) -> {
assertNotNull(v.getDescription());
});
Expand Down
Loading

0 comments on commit d630691

Please sign in to comment.