Skip to content

Commit

Permalink
Tweak codegen logic for formatting, documentation and handling of any…
Browse files Browse the repository at this point in the history
…Of (opensearch-project#1152)

* Re-generate code

Signed-off-by: Thomas Farr <tsfarr@amazon.com>

* Improve builder doc comments

Signed-off-by: Thomas Farr <tsfarr@amazon.com>

* Fix list/map isDefined serialize logic

Signed-off-by: Thomas Farr <tsfarr@amazon.com>

* Add support for deprecated enums

Signed-off-by: Thomas Farr <tsfarr@amazon.com>

* Improve isDefined logic

Signed-off-by: Thomas Farr <tsfarr@amazon.com>

* Allow overriding request/response naming

Signed-off-by: Thomas Farr <tsfarr@amazon.com>

* Support anyOf

Signed-off-by: Thomas Farr <tsfarr@amazon.com>

* Update spec

Signed-off-by: Thomas Farr <tsfarr@amazon.com>

* spotlessApply

Signed-off-by: Thomas Farr <tsfarr@amazon.com>

---------

Signed-off-by: Thomas Farr <tsfarr@amazon.com>
(cherry picked from commit 7b954af)
  • Loading branch information
Xtansia committed Aug 30, 2024
1 parent f37f1c2 commit cd49cec
Show file tree
Hide file tree
Showing 22 changed files with 3,086 additions and 906 deletions.
3,661 changes: 2,819 additions & 842 deletions java-codegen/opensearch-openapi.yaml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,11 @@ public Collection<Variant> getVariants() {

public static class Variant {
private final String wireName;
private final boolean deprecated;

public Variant(String wireName) {
public Variant(String wireName, boolean deprecated) {
this.wireName = wireName;
this.deprecated = deprecated;
}

public String getWireName() {
Expand All @@ -55,5 +57,9 @@ public String getWireName() {
public String getName() {
return Strings.toPascalCase(wireName);
}

public boolean isDeprecated() {
return deprecated;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,22 @@ public Type getJsonEndpointType() {

@Nonnull
private static String requestClassName(@Nonnull OperationGroup operationGroup) {
Objects.requireNonNull(operationGroup, "operationGroup must not be null");
return Strings.toPascalCase(operationGroup.getName()) + "Request";
return classBaseName(operationGroup) + "Request";
}

@Nonnull
private static String responseClassName(@Nonnull OperationGroup operationGroup) {
return classBaseName(operationGroup) + "Response";
}

@Nonnull
private static String classBaseName(@Nonnull OperationGroup operationGroup) {
Objects.requireNonNull(operationGroup, "operationGroup must not be null");
return Strings.toPascalCase(operationGroup.getName()) + "Response";
switch (operationGroup.toString()) {
case "tasks.get":
return "GetTasks";
default:
return Strings.toPascalCase(operationGroup.getName());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public JavaClassKind getClassKind() {
}

public boolean isAbstract() {
return this.className.endsWith("Base");
return this.className.endsWith("Base") || this.className.startsWith("Base");
}

public String getTypedefName() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.NotImplementedException;
Expand Down Expand Up @@ -110,7 +109,7 @@ private void visit(@Nonnull OperationGroup group, @Nonnull List<OpenApiOperation
if (s.get$ref()
.map(OpenApiRefElement.RelativeRef::getPointer)
.flatMap(JsonPointer::getLastKey)
.map("_common:AcknowledgedResponseBase"::equals)
.map(k -> k.endsWith("Base"))
.orElse(false)) {
return OpenApiSchema.builder().withPointer(s.getPointer()).withAllOf(s, OpenApiSchema.ANONYMOUS_OBJECT).build();
}
Expand Down Expand Up @@ -246,15 +245,16 @@ private void visit(Namespace parent, String className, String typedefName, OpenA

if (schema.isArray()) {
shape = new ArrayShape(parent, className, mapType(schema), typedefName, description);
} else if (schema.isObject() || schema.hasAllOf() || schema.equals(OpenApiSchema.ANONYMOUS_OBJECT)) {
} else if (schema.determineSingleType().orElse(null) == OpenApiSchemaType.Object) {
var objShape = new ObjectShape(parent, className, typedefName, description);
visitInto(schema, objShape);
shape = objShape;
} else if (schema.isString() && schema.hasEnums()) {
var deprecatedEnums = schema.getDeprecatedEnums().orElseGet(Collections::emptySet);
shape = new EnumShape(
parent,
className,
Lists.map(schema.getEnums().orElseThrow(), EnumShape.Variant::new),
Lists.map(schema.getEnums().orElseThrow(), v -> new EnumShape.Variant(v, deprecatedEnums.contains(v))),
typedefName,
description
);
Expand All @@ -280,30 +280,77 @@ private void visitInto(OpenApiSchema schema, ObjectShape shape) {
schema = allOf.get().get(1);
}

final var required = schema.getRequired().orElse(Collections.emptySet());
schema.getProperties()
.ifPresent(
props -> props.forEach(
(k, v) -> shape.addBodyField(new Field(k, mapType(v), required.contains(k), v.getDescription().orElse(null), null))
)
);
final var properties = new HashMap<String, OpenApiSchema>();
final var additionalProperties = new ArrayList<OpenApiSchema>();
final var required = collectObjectProperties(schema, properties, additionalProperties);

var additionalProperties = schema.getAdditionalProperties().orElse(null);
if (additionalProperties != null) {
var valueType = mapType(additionalProperties);
properties.forEach(
(k, v) -> { shape.addBodyField(new Field(k, mapType(v), required.contains(k), v.getDescription().orElse(null), null)); }
);

if (!additionalProperties.isEmpty()) {
var valueSchema = additionalProperties.size() == 1 ? additionalProperties.get(0) : OpenApiSchema.ANONYMOUS_UNTYPED;
shape.setAdditionalPropertiesField(
new Field(
additionalProperties.getTitle().orElseThrow(),
Types.Java.Util.Map(Types.Java.Lang.String, valueType),
valueSchema.getTitle().orElseThrow(),
Types.Java.Util.Map(Types.Java.Lang.String, mapType(valueSchema)),
false,
additionalProperties.getDescription().orElse(null),
valueSchema.getDescription().orElse(null),
null,
true
)
);
}
}

private Set<String> collectObjectProperties(
OpenApiSchema schema,
Map<String, OpenApiSchema> properties,
List<OpenApiSchema> additionalProperties
) {
if (schema.has$ref()) {
return collectObjectProperties(schema.resolve(), properties, additionalProperties);
}

if (schema.hasAllOf()) {
var required = new HashSet<String>();
for (var component : schema.getAllOf().orElseThrow()) {
required.addAll(collectObjectProperties(component, properties, additionalProperties));
}
return required;
}

if (schema.hasAnyOf() || schema.hasOneOf()) {
Set<String> required = null;
for (var component : schema.getAnyOf().or(schema::getOneOf).orElseThrow()) {
var componentRequired = collectObjectProperties(component, properties, additionalProperties);
if (required == null) {
required = new HashSet<>(componentRequired);
} else {
required.retainAll(componentRequired);
}
}
return required;
}

schema.getProperties().ifPresent(props -> props.forEach((k, v) -> {
var existing = properties.get(k);
if (existing != null) {
var existingType = existing.determineSingleType().orElse(null);
var newType = v.determineSingleType().orElse(null);
if (existingType != null
&& (existingType == OpenApiSchemaType.Object || existingType == OpenApiSchemaType.Array || existingType != newType)) {
v = OpenApiSchema.ANONYMOUS_UNTYPED;
}
}
properties.put(k, v);
}));

schema.getAdditionalProperties().ifPresent(additionalProperties::add);

return schema.getRequired().orElseGet(Collections::emptySet);
}

private Type mapType(OpenApiSchema schema) {
return mapType(schema, false);
}
Expand Down Expand Up @@ -356,8 +403,7 @@ private Type mapTypeInner(OpenApiSchema schema) {
case Array:
return mapArray(schema);
case String:
if (schema.getPattern().map("^([0-9]+)(?:d|h|m|s|ms|micros|nanos)$"::equals).orElse(false))
return Types.Client.OpenSearch._Types.Time;
if ("_common:Duration".equals(schema.getPointer().getLastKey().orElse(null))) return Types.Client.OpenSearch._Types.Time;
return Types.Java.Lang.String;
case Boolean:
return Types.Primitive.Boolean;
Expand All @@ -374,7 +420,7 @@ private Type mapOneOf(List<OpenApiSchema> oneOf) {
return mapType(oneOf.get(1));
}

var types = oneOf.stream().map(OpenApiSchema::determineTypes).flatMap(Set::stream).collect(Collectors.toSet());
var types = OpenApiSchema.determineTypes(oneOf);

if (types.size() == 2
&& types.contains(OpenApiSchemaType.String)
Expand Down Expand Up @@ -420,7 +466,7 @@ private Type mapNumber(OpenApiSchema schema) {
}

private boolean shouldKeepRef(OpenApiSchema schema) {
if (schema.isNumber()) {
if (schema.isNumber() || schema.isArray()) {
return false;
}
if (schema.isString() && schema.getEnums().isEmpty()) {
Expand All @@ -430,8 +476,7 @@ private boolean shouldKeepRef(OpenApiSchema schema) {
return schema.getOneOf().orElseThrow().stream().allMatch(s -> s.getTitle().isPresent());
}
if (schema.getAllOf().isPresent()) {
var types = schema.determineTypes();
return types.size() == 1 && types.iterator().next().equals(OpenApiSchemaType.Object);
return schema.determineSingleType().orElse(null) == OpenApiSchemaType.Object;
}
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import org.opensearch.client.codegen.renderer.lambdas.TypeIsDefinedLambda;
import org.opensearch.client.codegen.renderer.lambdas.TypeQueryParamifyLambda;
import org.opensearch.client.codegen.renderer.lambdas.TypeSerializerLambda;

Expand Down Expand Up @@ -201,6 +202,10 @@ public Mustache.Lambda queryParamify() {
return new TypeQueryParamifyLambda(this);
}

public Mustache.Lambda isDefined() {
return new TypeIsDefinedLambda(this);
}

public static final class Builder {
private String pkg;
private String name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
public enum HttpStatusCode {
Ok("200"),
Created("201"),
NoContent("204"),
BadRequest("400"),
Forbidden("403"),
NotFound("404"),
Expand Down
Loading

0 comments on commit cd49cec

Please sign in to comment.