Skip to content

Commit

Permalink
[Backport main] Add support for codegen overrides (#1185)
Browse files Browse the repository at this point in the history
* Add support for codegen overrides

* Implement ability to override property type mappings

Signed-off-by: Thomas Farr <[email protected]>

* Ensure generated code is up-to-date

Signed-off-by: Thomas Farr <[email protected]>

* Fix license header

Signed-off-by: Thomas Farr <[email protected]>

* Fix tests

Signed-off-by: Thomas Farr <[email protected]>

---------

Signed-off-by: Thomas Farr <[email protected]>
(cherry picked from commit 9c5d9c1)

* spotlessApply

Signed-off-by: Thomas Farr <[email protected]>

---------

Signed-off-by: Thomas Farr <[email protected]>
  • Loading branch information
Xtansia authored Sep 5, 2024
1 parent 020e0b0 commit 43c1299
Show file tree
Hide file tree
Showing 19 changed files with 394 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.opensearch.client.codegen.model.OperationGroupMatcher;
import org.opensearch.client.codegen.model.ShapeRenderingContext;
import org.opensearch.client.codegen.model.SpecTransformer;
import org.opensearch.client.codegen.model.overrides.Overrides;
import org.opensearch.client.codegen.openapi.OpenApiSpecification;

public class CodeGenerator {
Expand Down Expand Up @@ -121,7 +122,7 @@ public static void main(String[] args) {

private static Namespace parseSpec(URI location) throws ApiSpecificationParseException {
var spec = OpenApiSpecification.retrieve(location);
var transformer = new SpecTransformer(OPERATION_MATCHER);
var transformer = new SpecTransformer(OPERATION_MATCHER, Overrides.OVERRIDES);
transformer.visit(spec);
return transformer.getRoot();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,12 @@ public static final class Builder extends ObjectBuilderBase<ShapeRenderingContex
private JavaCodeFormatter javaCodeFormatter;
private boolean ownedJavaCodeFormatter;

private Builder() {
super(ShapeRenderingContext::new);
}
private Builder() {}

@Nonnull
@Override
protected @Nonnull Builder self() {
return this;
protected ShapeRenderingContext construct() {
return new ShapeRenderingContext(this);
}

@Nonnull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import org.apache.commons.lang3.NotImplementedException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.opensearch.client.codegen.model.overrides.Overrides;
import org.opensearch.client.codegen.model.overrides.PropertyOverride;
import org.opensearch.client.codegen.openapi.HttpStatusCode;
import org.opensearch.client.codegen.openapi.In;
import org.opensearch.client.codegen.openapi.JsonPointer;
Expand All @@ -48,14 +50,17 @@ public class SpecTransformer {
@Nonnull
private final OperationGroupMatcher matcher;
@Nonnull
private final Overrides overrides;
@Nonnull
private final Namespace root = new Namespace();
@Nonnull
private final Set<OpenApiSchema> visitedSchemas = new HashSet<>();
@Nonnull
private final Map<OpenApiSchema, Type> schemaToType = new ConcurrentHashMap<>();

public SpecTransformer(@Nonnull OperationGroupMatcher matcher) {
public SpecTransformer(@Nonnull OperationGroupMatcher matcher, @Nonnull Overrides overrides) {
this.matcher = Objects.requireNonNull(matcher, "matcher must not be null");
this.overrides = Objects.requireNonNull(overrides, "overrides must not be null");
}

@Nonnull
Expand Down Expand Up @@ -285,9 +290,12 @@ private void visitInto(OpenApiSchema schema, ObjectShape shape) {
final var additionalProperties = new ArrayList<OpenApiSchema>();
final var required = collectObjectProperties(schema, properties, additionalProperties);

properties.forEach(
(k, v) -> shape.addBodyField(new Field(k, mapType(v), required.contains(k), v.getDescription().orElse(null), null))
);
final var overrides = this.overrides.getSchema(schema.getPointer());

properties.forEach((k, v) -> {
var type = overrides.flatMap(so -> so.getProperty(k)).flatMap(PropertyOverride::getMappedType).orElseGet(() -> mapType(v));
shape.addBodyField(new Field(k, type, required.contains(k), v.getDescription().orElse(null), null));
});

if (!additionalProperties.isEmpty()) {
var valueSchema = additionalProperties.size() == 1 ? additionalProperties.get(0) : OpenApiSchema.ANONYMOUS_UNTYPED;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public class Type {
"float",
"Float",
"double",
"Double"
"Double",
"Number"
);

public static Builder builder() {
Expand Down Expand Up @@ -148,6 +149,10 @@ public boolean isPrimitive() {
return PRIMITIVES.contains(name);
}

public boolean isNumber() {
return "Number".equals(name);
}

public boolean isEnum() {
return isEnum;
}
Expand Down Expand Up @@ -218,13 +223,12 @@ public static final class Builder extends ObjectBuilderBase<Type, Builder> {
private Type[] typeParams;
private boolean isEnum;

private Builder() {
super(Type::new);
}
private Builder() {}

@Nonnull
@Override
protected @Nonnull Builder self() {
return this;
protected Type construct() {
return new Type(this);
}

@Nonnull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,12 @@ public static final class Builder extends ObjectBuilderBase<TypeParameterDefinit
private String name;
private Type extendsType;

private Builder() {
super(TypeParameterDefinition::new);
}
private Builder() {}

@Nonnull
@Override
protected @Nonnull Builder self() {
return this;
protected TypeParameterDefinition construct() {
return new TypeParameterDefinition(this);
}

@Nonnull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,12 @@ public static Builder builder() {
public static class Builder extends ObjectBuilderBase<TypeParameterDiamond, Builder> {
private Either<Type[], TypeParameterDefinition[]> params;

private Builder() {
super(TypeParameterDiamond::new);
}
private Builder() {}

@Nonnull
@Override
protected @Nonnull Builder self() {
return this;
protected TypeParameterDiamond construct() {
return new TypeParameterDiamond(this);
}

@Nonnull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public static final class Lang {
public static final Type Float = Type.builder().withPackage(PACKAGE).withName("Float").build();
public static final Type Double = Type.builder().withPackage(PACKAGE).withName("Double").build();
public static final Type Object = Type.builder().withPackage(PACKAGE).withName("Object").build();
public static final Type Number = Type.builder().withPackage(PACKAGE).withName("Number").build();
}

public static final class Util {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

package org.opensearch.client.codegen.model.overrides;

import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opensearch.client.codegen.openapi.JsonPointer;
import org.opensearch.client.codegen.utils.ObjectBuilder;
import org.opensearch.client.codegen.utils.ObjectBuilderBase;

public class Overrides {
public static final Overrides OVERRIDES = builder().build();

@Nonnull
private final Map<JsonPointer, SchemaOverride> schemas;

private Overrides(Builder builder) {
this.schemas = builder.schemas != null ? Collections.unmodifiableMap(builder.schemas) : Collections.emptyMap();
}

@Nonnull
public Optional<SchemaOverride> getSchema(@Nonnull JsonPointer pointer) {
return Optional.ofNullable(schemas.get(pointer));
}

@Nonnull
public static Builder builder() {
return new Builder();
}

public static final class Builder extends ObjectBuilderBase<Overrides, Builder> {
@Nullable
private Map<JsonPointer, SchemaOverride> schemas;

private Builder() {}

@Nonnull
@Override
protected Overrides construct() {
return new Overrides(this);
}

@Nonnull
public Builder withSchemas(@Nonnull Function<SchemaOverride.MapBuilder, ObjectBuilder<Map<JsonPointer, SchemaOverride>>> fn) {
this.schemas = Objects.requireNonNull(fn, "fn must not be null").apply(SchemaOverride.mapBuilder()).build();
return this;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

package org.opensearch.client.codegen.model.overrides;

import java.util.Optional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opensearch.client.codegen.model.Type;
import org.opensearch.client.codegen.utils.MapBuilderBase;
import org.opensearch.client.codegen.utils.ObjectBuilderBase;

public final class PropertyOverride {
@Nullable
private final Type mappedType;

private PropertyOverride(Builder builder) {
this.mappedType = builder.mappedType;
}

@Nonnull
public Optional<Type> getMappedType() {
return Optional.ofNullable(mappedType);
}

@Nonnull
public static Builder builder() {
return new Builder();
}

@Nonnull
public static MapBuilder mapBuilder() {
return new MapBuilder();
}

public static final class Builder extends ObjectBuilderBase<PropertyOverride, Builder> {
@Nullable
private Type mappedType;

private Builder() {}

@Nonnull
@Override
protected PropertyOverride construct() {
return new PropertyOverride(this);
}

@Nonnull
public Builder withMappedType(@Nullable Type mappedType) {
this.mappedType = mappedType;
return this;
}
}

public static final class MapBuilder extends MapBuilderBase<String, PropertyOverride, Builder, MapBuilder> {
private MapBuilder() {}

@Nonnull
@Override
protected Builder valueBuilder() {
return builder();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

package org.opensearch.client.codegen.model.overrides;

import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opensearch.client.codegen.openapi.JsonPointer;
import org.opensearch.client.codegen.utils.MapBuilderBase;
import org.opensearch.client.codegen.utils.ObjectBuilder;
import org.opensearch.client.codegen.utils.ObjectBuilderBase;

public final class SchemaOverride {
@Nonnull
private final Map<String, PropertyOverride> properties;

private SchemaOverride(Builder builder) {
this.properties = builder.properties != null ? Collections.unmodifiableMap(builder.properties) : Collections.emptyMap();
}

@Nonnull
public Optional<PropertyOverride> getProperty(@Nonnull String key) {
return Optional.ofNullable(properties.get(key));
}

@Nonnull
public static Builder builder() {
return new Builder();
}

@Nonnull
public static MapBuilder mapBuilder() {
return new MapBuilder();
}

public static final class Builder extends ObjectBuilderBase<SchemaOverride, Builder> {
@Nullable
private Map<String, PropertyOverride> properties;

private Builder() {}

@Nonnull
@Override
protected SchemaOverride construct() {
return new SchemaOverride(this);
}

@Nonnull
public Builder withProperties(@Nonnull Function<PropertyOverride.MapBuilder, ObjectBuilder<Map<String, PropertyOverride>>> fn) {
this.properties = Objects.requireNonNull(fn, "fn must not be null").apply(PropertyOverride.mapBuilder()).build();
return this;
}
}

public static final class MapBuilder extends MapBuilderBase<JsonPointer, SchemaOverride, Builder, MapBuilder> {
private MapBuilder() {}

@Nonnull
@Override
protected Builder valueBuilder() {
return builder();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -354,13 +354,12 @@ public static class Builder extends ObjectBuilderBase<OpenApiSchema, Builder> {
@Nullable
private Semver versionRemoved;

private Builder() {
super(OpenApiSchema::new);
}
private Builder() {}

@Nonnull
@Override
protected @Nonnull Builder self() {
return this;
protected OpenApiSchema construct() {
return new OpenApiSchema(this);
}

@Nonnull
Expand Down
Loading

0 comments on commit 43c1299

Please sign in to comment.