From d045d86f684d2a93708075456b978b8e9a207278 Mon Sep 17 00:00:00 2001 From: Thomas Farr Date: Fri, 4 Oct 2024 01:53:42 +1300 Subject: [PATCH] Improve code generation (#1219) - Render descriptions using markdown - Support generating "DictionaryResponse" types - Support discriminated unions Signed-off-by: Thomas Farr --- .../BulkByScrollTaskStatusOrException.java | 57 ++--- ...ByScrollTaskStatusOrExceptionBuilders.java | 61 +++++ .../client/opensearch/_types/ErrorCause.java | 4 +- .../DeleteDanglingIndexResponse.java | 3 +- .../ImportDanglingIndexResponse.java | 3 +- .../opensearch/ml/DeleteAgentResponse.java | 3 +- .../ml/DeleteConnectorResponse.java | 3 +- .../ml/DeleteModelGroupResponse.java | 3 +- .../opensearch/ml/DeleteModelResponse.java | 3 +- .../opensearch/ml/DeleteTaskResponse.java | 3 +- .../opensearch/ml/UndeployModelResponse.java | 103 +-------- .../snapshot/CloneSnapshotResponse.java | 3 +- .../opensearch/tasks/CancelResponse.java | 3 +- .../opensearch/tasks/GetTasksRequest.java | 4 +- .../client/opensearch/tasks/ListRequest.java | 24 +- .../client/opensearch/tasks/ListResponse.java | 3 +- .../opensearch/tasks/TaskExecutingNode.java | 12 +- .../client/opensearch/tasks/TaskGroup.java | 12 +- .../client/opensearch/tasks/TaskInfos.java | 21 ++ .../tasks/TaskListResponseBase.java | 8 +- .../endpoints/DictionaryResponse.java | 16 ++ java-codegen/build.gradle.kts | 3 + .../model/DictionaryResponseShape.java | 41 ++++ .../client/codegen/model/EnumShape.java | 41 +++- .../client/codegen/model/Field.java | 12 +- .../client/codegen/model/Namespace.java | 7 +- .../client/codegen/model/ObjectShape.java | 69 +++++- .../client/codegen/model/RequestShape.java | 6 +- .../client/codegen/model/Shape.java | 24 +- .../codegen/model/ShapeRenderingContext.java | 2 +- .../client/codegen/model/SpecTransformer.java | 135 ++++++++--- .../codegen/model/TaggedUnionShape.java | 143 +++++++++++- .../opensearch/client/codegen/model/Type.java | 32 ++- .../model/TypeParameterDefinition.java | 2 +- .../codegen/model/TypeParameterDiamond.java | 2 +- .../client/codegen/model/Types.java | 18 +- .../codegen/model/overrides/Overrides.java | 24 +- .../model/overrides/PropertyOverride.java | 33 ++- .../model/overrides/SchemaOverride.java | 74 ++++++- .../codegen/openapi/OpenApiDiscriminator.java | 29 +++ .../client/codegen/openapi/OpenApiSchema.java | 23 +- .../codegen/renderer/JavaCodeFormatter.java | 2 +- .../renderer/TemplateGlobalContext.java | 4 +- .../codegen/renderer/TemplateLoader.java | 2 +- .../codegen/renderer/TemplateRenderer.java | 7 +- .../renderer/TemplateValueFormatter.java | 2 +- .../client/codegen/utils/JavaClassKind.java | 3 +- .../client/codegen/utils/MapBuilderBase.java | 45 ---- .../client/codegen/utils/Markdown.java | 23 ++ .../codegen/{ => utils}/NameSanitizer.java | 24 +- .../codegen/utils/ObjectBuilderBase.java | 104 --------- .../client/codegen/utils/Strings.java | 12 + .../codegen/utils/builder/ListBuilder.java | 13 ++ .../utils/builder/ListBuilderBase.java | 36 +++ .../codegen/utils/builder/MapBuilder.java | 13 ++ .../codegen/utils/builder/MapBuilderBase.java | 35 +++ .../utils/{ => builder}/ObjectBuilder.java | 2 +- .../utils/builder/ObjectBuilderBase.java | 209 ++++++++++++++++++ .../utils/builder/ObjectListBuilderBase.java | 26 +++ .../utils/builder/ObjectMapBuilderBase.java | 27 +++ .../utils/builder/ObjectSetBuilderBase.java | 24 ++ .../codegen/utils/builder/SetBuilder.java | 13 ++ .../codegen/utils/builder/SetBuilderBase.java | 36 +++ .../DictionaryResponseShape.mustache | 32 +++ .../codegen/templates/EnumShape.mustache | 16 +- .../codegen/templates/ObjectShape.mustache | 11 +- .../templates/ObjectShape/Builder.mustache | 6 +- .../ObjectShape/Deserialize.mustache | 8 +- .../templates/ObjectShape/Equals.mustache | 43 ++-- .../templates/ObjectShape/Serialize.mustache | 3 + .../templates/TaggedUnionShape.mustache | 70 ++++-- .../TaggedUnionShape/Builders.mustache | 12 + .../VariantInterface.mustache | 7 + .../templates/Type/directSerializer.mustache | 11 +- 74 files changed, 1498 insertions(+), 455 deletions(-) create mode 100644 java-client/src/generated/java/org/opensearch/client/opensearch/_types/BulkByScrollTaskStatusOrExceptionBuilders.java create mode 100644 java-codegen/src/main/java/org/opensearch/client/codegen/model/DictionaryResponseShape.java create mode 100644 java-codegen/src/main/java/org/opensearch/client/codegen/openapi/OpenApiDiscriminator.java delete mode 100644 java-codegen/src/main/java/org/opensearch/client/codegen/utils/MapBuilderBase.java create mode 100644 java-codegen/src/main/java/org/opensearch/client/codegen/utils/Markdown.java rename java-codegen/src/main/java/org/opensearch/client/codegen/{ => utils}/NameSanitizer.java (63%) delete mode 100644 java-codegen/src/main/java/org/opensearch/client/codegen/utils/ObjectBuilderBase.java create mode 100644 java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ListBuilder.java create mode 100644 java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ListBuilderBase.java create mode 100644 java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/MapBuilder.java create mode 100644 java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/MapBuilderBase.java rename java-codegen/src/main/java/org/opensearch/client/codegen/utils/{ => builder}/ObjectBuilder.java (85%) create mode 100644 java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectBuilderBase.java create mode 100644 java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectListBuilderBase.java create mode 100644 java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectMapBuilderBase.java create mode 100644 java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectSetBuilderBase.java create mode 100644 java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/SetBuilder.java create mode 100644 java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/SetBuilderBase.java create mode 100644 java-codegen/src/main/resources/org/opensearch/client/codegen/templates/DictionaryResponseShape.mustache create mode 100644 java-codegen/src/main/resources/org/opensearch/client/codegen/templates/TaggedUnionShape/Builders.mustache create mode 100644 java-codegen/src/main/resources/org/opensearch/client/codegen/templates/TaggedUnionShape/VariantInterface.mustache diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/_types/BulkByScrollTaskStatusOrException.java b/java-client/src/generated/java/org/opensearch/client/opensearch/_types/BulkByScrollTaskStatusOrException.java index 6b5f183514..89b1f274bf 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/_types/BulkByScrollTaskStatusOrException.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/_types/BulkByScrollTaskStatusOrException.java @@ -60,9 +60,12 @@ public class BulkByScrollTaskStatusOrException implements TaggedUnion, PlainJsonSerializable { + /** + * {@link BulkByScrollTaskStatusOrException} variant kinds. + */ public enum Kind { - Status, - Exception + Exception, + Status } private final Kind _kind; @@ -95,35 +98,35 @@ public static BulkByScrollTaskStatusOrException of( } /** - * Is this variant instance of kind {@code status}? + * Is this variant instance of kind {@code exception}? */ - public boolean isStatus() { - return _kind == Kind.Status; + public boolean isException() { + return _kind == Kind.Exception; } /** - * Get the {@code status} variant value. + * Get the {@code exception} variant value. * - * @throws IllegalStateException if the current variant is not the {@code status} kind. + * @throws IllegalStateException if the current variant is not the {@code exception} kind. */ - public BulkByScrollTaskStatus status() { - return TaggedUnionUtils.get(this, Kind.Status); + public ErrorCause exception() { + return TaggedUnionUtils.get(this, Kind.Exception); } /** - * Is this variant instance of kind {@code exception}? + * Is this variant instance of kind {@code status}? */ - public boolean isException() { - return _kind == Kind.Exception; + public boolean isStatus() { + return _kind == Kind.Status; } /** - * Get the {@code exception} variant value. + * Get the {@code status} variant value. * - * @throws IllegalStateException if the current variant is not the {@code exception} kind. + * @throws IllegalStateException if the current variant is not the {@code status} kind. */ - public ErrorCause exception() { - return TaggedUnionUtils.get(this, Kind.Exception); + public BulkByScrollTaskStatus status() { + return TaggedUnionUtils.get(this, Kind.Status); } @Override @@ -137,26 +140,26 @@ public static class Builder extends ObjectBuilderBase implements ObjectBuilder status(BulkByScrollTaskStatus v) { - this._kind = Kind.Status; + public ObjectBuilder exception(ErrorCause v) { + this._kind = Kind.Exception; this._value = v; return this; } - public ObjectBuilder status( - Function> fn - ) { - return this.status(fn.apply(new BulkByScrollTaskStatus.Builder()).build()); + public ObjectBuilder exception(Function> fn) { + return this.exception(fn.apply(new ErrorCause.Builder()).build()); } - public ObjectBuilder exception(ErrorCause v) { - this._kind = Kind.Exception; + public ObjectBuilder status(BulkByScrollTaskStatus v) { + this._kind = Kind.Status; this._value = v; return this; } - public ObjectBuilder exception(Function> fn) { - return this.exception(fn.apply(new ErrorCause.Builder()).build()); + public ObjectBuilder status( + Function> fn + ) { + return this.status(fn.apply(new BulkByScrollTaskStatus.Builder()).build()); } @Override @@ -168,8 +171,8 @@ public BulkByScrollTaskStatusOrException build() { private static JsonpDeserializer buildBulkByScrollTaskStatusOrExceptionDeserializer() { return new UnionDeserializer.Builder(BulkByScrollTaskStatusOrException::new, false) - .addMember(Kind.Status, BulkByScrollTaskStatus._DESERIALIZER) .addMember(Kind.Exception, ErrorCause._DESERIALIZER) + .addMember(Kind.Status, BulkByScrollTaskStatus._DESERIALIZER) .build(); } diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/_types/BulkByScrollTaskStatusOrExceptionBuilders.java b/java-client/src/generated/java/org/opensearch/client/opensearch/_types/BulkByScrollTaskStatusOrExceptionBuilders.java new file mode 100644 index 0000000000..c69513caa4 --- /dev/null +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/_types/BulkByScrollTaskStatusOrExceptionBuilders.java @@ -0,0 +1,61 @@ +/* + * 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. + */ + +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +//---------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------- + +package org.opensearch.client.opensearch._types; + +import javax.annotation.Generated; + +/** + * Builders for {@link BulkByScrollTaskStatusOrException} variants. + */ +@Generated("org.opensearch.client.codegen.CodeGenerator") +public class BulkByScrollTaskStatusOrExceptionBuilders { + private BulkByScrollTaskStatusOrExceptionBuilders() {} + + /** + * Creates a builder for the {@link ErrorCause exception} {@code BulkByScrollTaskStatusOrException} variant. + */ + public static ErrorCause.Builder exception() { + return new ErrorCause.Builder(); + } + + /** + * Creates a builder for the {@link BulkByScrollTaskStatus status} {@code BulkByScrollTaskStatusOrException} variant. + */ + public static BulkByScrollTaskStatus.Builder status() { + return new BulkByScrollTaskStatus.Builder(); + } +} diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/_types/ErrorCause.java b/java-client/src/generated/java/org/opensearch/client/opensearch/_types/ErrorCause.java index 36a0c74b71..5ea3393694 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/_types/ErrorCause.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/_types/ErrorCause.java @@ -127,7 +127,7 @@ public final List rootCause() { } /** - * The server stack trace. Present only if the `error_trace=true` parameter was sent with the request. + * The server stack trace. Present only if the error_trace=true parameter was sent with the request. *

* API name: {@code stack_trace} *

@@ -298,7 +298,7 @@ public final Builder rootCause(Functionerror_trace=true parameter was sent with the request. *

* API name: {@code stack_trace} *

diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/dangling_indices/DeleteDanglingIndexResponse.java b/java-client/src/generated/java/org/opensearch/client/opensearch/dangling_indices/DeleteDanglingIndexResponse.java index abc22417e3..ba577d0d13 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/dangling_indices/DeleteDanglingIndexResponse.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/dangling_indices/DeleteDanglingIndexResponse.java @@ -71,6 +71,7 @@ public static DeleteDanglingIndexResponse of( public static class Builder extends AcknowledgedResponseBase.AbstractBuilder implements ObjectBuilder { + @Override protected Builder self() { return this; @@ -99,7 +100,7 @@ public DeleteDanglingIndexResponse build() { ); protected static void setupDeleteDanglingIndexResponseDeserializer(ObjectDeserializer op) { - AcknowledgedResponseBase.setupAcknowledgedResponseBaseDeserializer(op); + setupAcknowledgedResponseBaseDeserializer(op); } public int hashCode() { diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/dangling_indices/ImportDanglingIndexResponse.java b/java-client/src/generated/java/org/opensearch/client/opensearch/dangling_indices/ImportDanglingIndexResponse.java index f3da2fec28..bff172b8b6 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/dangling_indices/ImportDanglingIndexResponse.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/dangling_indices/ImportDanglingIndexResponse.java @@ -71,6 +71,7 @@ public static ImportDanglingIndexResponse of( public static class Builder extends AcknowledgedResponseBase.AbstractBuilder implements ObjectBuilder { + @Override protected Builder self() { return this; @@ -99,7 +100,7 @@ public ImportDanglingIndexResponse build() { ); protected static void setupImportDanglingIndexResponseDeserializer(ObjectDeserializer op) { - AcknowledgedResponseBase.setupAcknowledgedResponseBaseDeserializer(op); + setupAcknowledgedResponseBaseDeserializer(op); } public int hashCode() { diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteAgentResponse.java b/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteAgentResponse.java index ed8723369c..7b0c19eda5 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteAgentResponse.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteAgentResponse.java @@ -43,6 +43,7 @@ public static DeleteAgentResponse of(Function implements ObjectBuilder { + @Override protected Builder self() { return this; @@ -71,7 +72,7 @@ public DeleteAgentResponse build() { ); protected static void setupDeleteAgentResponseDeserializer(ObjectDeserializer op) { - WriteResponseBase.setupWriteResponseBaseDeserializer(op); + setupWriteResponseBaseDeserializer(op); } public int hashCode() { diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteConnectorResponse.java b/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteConnectorResponse.java index 8191f76081..dfc3f5a666 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteConnectorResponse.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteConnectorResponse.java @@ -43,6 +43,7 @@ public static DeleteConnectorResponse of(Function implements ObjectBuilder { + @Override protected Builder self() { return this; @@ -71,7 +72,7 @@ public DeleteConnectorResponse build() { ); protected static void setupDeleteConnectorResponseDeserializer(ObjectDeserializer op) { - WriteResponseBase.setupWriteResponseBaseDeserializer(op); + setupWriteResponseBaseDeserializer(op); } public int hashCode() { diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteModelGroupResponse.java b/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteModelGroupResponse.java index 77595ef8a3..2b2f0365ff 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteModelGroupResponse.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteModelGroupResponse.java @@ -43,6 +43,7 @@ public static DeleteModelGroupResponse of(Function implements ObjectBuilder { + @Override protected Builder self() { return this; @@ -71,7 +72,7 @@ public DeleteModelGroupResponse build() { ); protected static void setupDeleteModelGroupResponseDeserializer(ObjectDeserializer op) { - WriteResponseBase.setupWriteResponseBaseDeserializer(op); + setupWriteResponseBaseDeserializer(op); } public int hashCode() { diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteModelResponse.java b/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteModelResponse.java index 45e9cf97ef..a3082f0ea6 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteModelResponse.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteModelResponse.java @@ -43,6 +43,7 @@ public static DeleteModelResponse of(Function implements ObjectBuilder { + @Override protected Builder self() { return this; @@ -71,7 +72,7 @@ public DeleteModelResponse build() { ); protected static void setupDeleteModelResponseDeserializer(ObjectDeserializer op) { - WriteResponseBase.setupWriteResponseBaseDeserializer(op); + setupWriteResponseBaseDeserializer(op); } public int hashCode() { diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteTaskResponse.java b/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteTaskResponse.java index 21d872184a..c901124710 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteTaskResponse.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/ml/DeleteTaskResponse.java @@ -43,6 +43,7 @@ public static DeleteTaskResponse of(Function implements ObjectBuilder { + @Override protected Builder self() { return this; @@ -71,7 +72,7 @@ public DeleteTaskResponse build() { ); protected static void setupDeleteTaskResponseDeserializer(ObjectDeserializer op) { - WriteResponseBase.setupWriteResponseBaseDeserializer(op); + setupWriteResponseBaseDeserializer(op); } public int hashCode() { diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/ml/UndeployModelResponse.java b/java-client/src/generated/java/org/opensearch/client/opensearch/ml/UndeployModelResponse.java index f16439314e..a8d51b146e 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/ml/UndeployModelResponse.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/ml/UndeployModelResponse.java @@ -12,108 +12,43 @@ package org.opensearch.client.opensearch.ml; -import jakarta.json.stream.JsonGenerator; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; import java.util.function.Function; import javax.annotation.Generated; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import org.opensearch.client.json.JsonpDeserializable; import org.opensearch.client.json.JsonpDeserializer; -import org.opensearch.client.json.JsonpMapper; import org.opensearch.client.json.ObjectBuilderDeserializer; import org.opensearch.client.json.ObjectDeserializer; -import org.opensearch.client.json.PlainJsonSerializable; -import org.opensearch.client.util.ApiTypeHelper; +import org.opensearch.client.transport.endpoints.DictionaryResponse; import org.opensearch.client.util.ObjectBuilder; -import org.opensearch.client.util.ObjectBuilderBase; // typedef: ml.undeploy_model.Response @JsonpDeserializable @Generated("org.opensearch.client.codegen.CodeGenerator") -public class UndeployModelResponse implements PlainJsonSerializable { - - @Nonnull - private final Map nodes; - +public class UndeployModelResponse extends DictionaryResponse { // --------------------------------------------------------------------------------------------- private UndeployModelResponse(Builder builder) { - this.nodes = ApiTypeHelper.unmodifiable(builder.nodes); + super(builder); } public static UndeployModelResponse of(Function> fn) { return fn.apply(new Builder()).build(); } - /** - */ - @Nonnull - public final Map nodes() { - return this.nodes; - } - - /** - * Serialize this object to JSON. - */ - @Override - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - for (Map.Entry item0 : this.nodes.entrySet()) { - generator.writeKey(item0.getKey()); - item0.getValue().serialize(generator, mapper); - } - } - // --------------------------------------------------------------------------------------------- /** * Builder for {@link UndeployModelResponse}. */ - public static class Builder extends ObjectBuilderBase implements ObjectBuilder { - @Nullable - private Map nodes; - - /** - * - *

- * Adds all elements of map to nodes. - *

- */ - public final Builder nodes(Map map) { - this.nodes = _mapPutAll(this.nodes, map); + public static class Builder extends DictionaryResponse.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { return this; } - /** - * - *

- * Adds an entry to nodes. - *

- */ - public final Builder nodes(String key, UndeployModelNode value) { - this.nodes = _mapPut(this.nodes, key, value); - return this; - } - - /** - * - *

- * Adds a value to nodes using a builder lambda. - *

- */ - public final Builder nodes(String key, Function> fn) { - return nodes(key, fn.apply(new UndeployModelNode.Builder()).build()); - } - /** * Builds a {@link UndeployModelResponse}. * @@ -121,6 +56,8 @@ public final Builder nodes(String key, Function op) { - op.setUnknownFieldHandler((builder, name, parser, mapper) -> { - if (builder.nodes == null) { - builder.nodes = new HashMap<>(); - } - builder.nodes.put(name, UndeployModelNode._DESERIALIZER.deserialize(parser, mapper)); - }); - } - - public int hashCode() { - int result = 17; - result = 31 * result + Objects.hashCode(this.nodes); - return result; - } - - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || this.getClass() != o.getClass()) return false; - UndeployModelResponse other = (UndeployModelResponse) o; - return Objects.equals(this.nodes, other.nodes); + setupDictionaryResponseDeserializer(op, JsonpDeserializer.stringDeserializer(), UndeployModelNode._DESERIALIZER); } } diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/snapshot/CloneSnapshotResponse.java b/java-client/src/generated/java/org/opensearch/client/opensearch/snapshot/CloneSnapshotResponse.java index f538f4e142..d66f0d22bc 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/snapshot/CloneSnapshotResponse.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/snapshot/CloneSnapshotResponse.java @@ -67,6 +67,7 @@ public static CloneSnapshotResponse of(Function implements ObjectBuilder { + @Override protected Builder self() { return this; @@ -95,7 +96,7 @@ public CloneSnapshotResponse build() { ); protected static void setupCloneSnapshotResponseDeserializer(ObjectDeserializer op) { - AcknowledgedResponseBase.setupAcknowledgedResponseBaseDeserializer(op); + setupAcknowledgedResponseBaseDeserializer(op); } public int hashCode() { diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/CancelResponse.java b/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/CancelResponse.java index 2db28d13b1..402e678c20 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/CancelResponse.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/CancelResponse.java @@ -66,6 +66,7 @@ public static CancelResponse of(Function implements ObjectBuilder { + @Override protected Builder self() { return this; @@ -94,7 +95,7 @@ public CancelResponse build() { ); protected static void setupCancelResponseDeserializer(ObjectDeserializer op) { - TaskListResponseBase.setupTaskListResponseBaseDeserializer(op); + setupTaskListResponseBaseDeserializer(op); } public int hashCode() { diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/GetTasksRequest.java b/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/GetTasksRequest.java index 0111f19a39..92abd2bf54 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/GetTasksRequest.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/GetTasksRequest.java @@ -104,7 +104,7 @@ public final Time timeout() { } /** - * If `true`, the request blocks until the task has completed. + * If true, the request blocks until the task has completed. *

* API name: {@code wait_for_completion} *

@@ -159,7 +159,7 @@ public final Builder timeout(Function> fn) { } /** - * If `true`, the request blocks until the task has completed. + * If true, the request blocks until the task has completed. *

* API name: {@code wait_for_completion} *

diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/ListRequest.java b/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/ListRequest.java index e53367c802..9688566d8c 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/ListRequest.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/ListRequest.java @@ -110,7 +110,7 @@ public final List actions() { } /** - * If `true`, the response includes detailed information about shard recoveries. + * If true, the response includes detailed information about shard recoveries. *

* API name: {@code detailed} *

@@ -132,8 +132,8 @@ public final GroupBy groupBy() { } /** - * Comma-separated list of node IDs or names to limit the returned information; use `_local` to return information from the node you're - * connecting to, leave empty to get information from all nodes. + * Comma-separated list of node IDs or names to limit the returned information; use _local to return information from the + * node you're connecting to, leave empty to get information from all nodes. *

* API name: {@code nodes} *

@@ -144,7 +144,7 @@ public final List nodes() { } /** - * Parent task ID used to limit returned information. To return all tasks, omit this parameter or use a value of `-1`. + * Parent task ID used to limit returned information. To return all tasks, omit this parameter or use a value of -1. *

* API name: {@code parent_task_id} *

@@ -166,7 +166,7 @@ public final Time timeout() { } /** - * If `true`, the request blocks until the operation is complete. + * If true, the request blocks until the operation is complete. *

* API name: {@code wait_for_completion} *

@@ -228,7 +228,7 @@ public final Builder actions(String value, String... values) { } /** - * If `true`, the response includes detailed information about shard recoveries. + * If true, the response includes detailed information about shard recoveries. *

* API name: {@code detailed} *

@@ -250,8 +250,8 @@ public final Builder groupBy(@Nullable GroupBy value) { } /** - * Comma-separated list of node IDs or names to limit the returned information; use `_local` to return information from the node - * you're connecting to, leave empty to get information from all nodes. + * Comma-separated list of node IDs or names to limit the returned information; use _local to return information from + * the node you're connecting to, leave empty to get information from all nodes. *

* API name: {@code nodes} *

@@ -266,8 +266,8 @@ public final Builder nodes(List list) { } /** - * Comma-separated list of node IDs or names to limit the returned information; use `_local` to return information from the node - * you're connecting to, leave empty to get information from all nodes. + * Comma-separated list of node IDs or names to limit the returned information; use _local to return information from + * the node you're connecting to, leave empty to get information from all nodes. *

* API name: {@code nodes} *

@@ -282,7 +282,7 @@ public final Builder nodes(String value, String... values) { } /** - * Parent task ID used to limit returned information. To return all tasks, omit this parameter or use a value of `-1`. + * Parent task ID used to limit returned information. To return all tasks, omit this parameter or use a value of -1. *

* API name: {@code parent_task_id} *

@@ -314,7 +314,7 @@ public final Builder timeout(Function> fn) { } /** - * If `true`, the request blocks until the operation is complete. + * If true, the request blocks until the operation is complete. *

* API name: {@code wait_for_completion} *

diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/ListResponse.java b/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/ListResponse.java index 6e557c534d..aa7f84d722 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/ListResponse.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/ListResponse.java @@ -66,6 +66,7 @@ public static ListResponse of(Function implements ObjectBuilder { + @Override protected Builder self() { return this; @@ -94,7 +95,7 @@ public ListResponse build() { ); protected static void setupListResponseDeserializer(ObjectDeserializer op) { - TaskListResponseBase.setupTaskListResponseBaseDeserializer(op); + setupTaskListResponseBaseDeserializer(op); } public int hashCode() { diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/TaskExecutingNode.java b/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/TaskExecutingNode.java index 6bcaf68dae..563a74ea7a 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/TaskExecutingNode.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/TaskExecutingNode.java @@ -95,11 +95,6 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { * Builder for {@link TaskExecutingNode}. */ public static class Builder extends BaseNode.AbstractBuilder implements ObjectBuilder { - @Override - protected Builder self() { - return this; - } - private Map tasks; /** @@ -137,6 +132,11 @@ public final Builder tasks(String key, Function op) { - BaseNode.setupBaseNodeDeserializer(op); + setupBaseNodeDeserializer(op); op.add(Builder::tasks, JsonpDeserializer.stringMapDeserializer(TaskInfo._DESERIALIZER), "tasks"); } diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/TaskGroup.java b/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/TaskGroup.java index a38fab6c66..41978b24b8 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/TaskGroup.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/TaskGroup.java @@ -97,11 +97,6 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { * Builder for {@link TaskGroup}. */ public static class Builder extends TaskInfo.AbstractBuilder implements ObjectBuilder { - @Override - protected Builder self() { - return this; - } - @Nullable private List children; @@ -140,6 +135,11 @@ public final Builder children(Function op) { - TaskInfo.setupTaskInfoDeserializer(op); + setupTaskInfoDeserializer(op); op.add(Builder::children, JsonpDeserializer.arrayDeserializer(TaskGroup._DESERIALIZER), "children"); } diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/TaskInfos.java b/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/TaskInfos.java index e786f17581..4bf5585791 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/TaskInfos.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/TaskInfos.java @@ -59,6 +59,9 @@ @JsonpDeserializable @Generated("org.opensearch.client.codegen.CodeGenerator") public class TaskInfos implements TaggedUnion, PlainJsonSerializable { + /** + * {@link TaskInfos} variant kinds. + */ public enum Kind { GroupedByNone, GroupedByParents @@ -127,6 +130,24 @@ public Map groupedByParents() { public void serialize(JsonGenerator generator, JsonpMapper mapper) { if (_value instanceof JsonpSerializable) { ((JsonpSerializable) _value).serialize(generator, mapper); + } else { + switch (_kind) { + case GroupedByNone: + generator.writeStartArray(); + for (TaskInfo item0 : ((List) this._value)) { + item0.serialize(generator, mapper); + } + generator.writeEnd(); + break; + case GroupedByParents: + generator.writeStartObject(); + for (Map.Entry item0 : ((Map) this._value).entrySet()) { + generator.writeKey(item0.getKey()); + item0.getValue().serialize(generator, mapper); + } + generator.writeEnd(); + break; + } } } diff --git a/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/TaskListResponseBase.java b/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/TaskListResponseBase.java index 713bd8f4d3..fee4a80485 100644 --- a/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/TaskListResponseBase.java +++ b/java-client/src/generated/java/org/opensearch/client/opensearch/tasks/TaskListResponseBase.java @@ -89,7 +89,7 @@ public final List nodeFailures() { } /** - * Task information grouped by node, if `group_by` was set to `node` (the default). + * Task information grouped by node, if group_by was set to node (the default). *

* API name: {@code nodes} *

@@ -208,7 +208,7 @@ public final BuilderT nodeFailures(Functiongroup_by was set to node (the default). *

* API name: {@code nodes} *

@@ -223,7 +223,7 @@ public final BuilderT nodes(Map map) { } /** - * Task information grouped by node, if `group_by` was set to `node` (the default). + * Task information grouped by node, if group_by was set to node (the default). *

* API name: {@code nodes} *

@@ -238,7 +238,7 @@ public final BuilderT nodes(String key, TaskExecutingNode value) { } /** - * Task information grouped by node, if `group_by` was set to `node` (the default). + * Task information grouped by node, if group_by was set to node (the default). *

* API name: {@code nodes} *

diff --git a/java-client/src/main/java/org/opensearch/client/transport/endpoints/DictionaryResponse.java b/java-client/src/main/java/org/opensearch/client/transport/endpoints/DictionaryResponse.java index 2238ef2854..ae83e29ef8 100644 --- a/java-client/src/main/java/org/opensearch/client/transport/endpoints/DictionaryResponse.java +++ b/java-client/src/main/java/org/opensearch/client/transport/endpoints/DictionaryResponse.java @@ -36,6 +36,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import javax.annotation.Nullable; import org.opensearch.client.json.JsonpDeserializer; import org.opensearch.client.json.JsonpMapper; @@ -162,4 +163,19 @@ protected static { builder.putResult(name, tValueParser.deserialize(parser, params)); } ); } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + Objects.hashCode(result); + return result; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DictionaryResponse other = (DictionaryResponse) o; + return Objects.equals(this.result, other.result); + } } diff --git a/java-codegen/build.gradle.kts b/java-codegen/build.gradle.kts index 7049c7df98..25380dbf88 100644 --- a/java-codegen/build.gradle.kts +++ b/java-codegen/build.gradle.kts @@ -171,6 +171,9 @@ dependencies { // MIT implementation("org.semver4j", "semver4j", "5.3.0") + // BSD-2-Clause + implementation("org.commonmark", "commonmark", "0.23.0") + // EPL-2.0 testImplementation(platform("org.junit:junit-bom:5.11.1")) testImplementation("org.junit.jupiter", "junit-jupiter") diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/DictionaryResponseShape.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/DictionaryResponseShape.java new file mode 100644 index 0000000000..7d3691de9b --- /dev/null +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/DictionaryResponseShape.java @@ -0,0 +1,41 @@ +/* + * 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; + +import java.util.Collection; +import java.util.List; + +public class DictionaryResponseShape extends Shape { + private final Type keyType; + private final Type valueType; + + public DictionaryResponseShape( + Namespace parent, + String className, + String typedefName, + String description, + Type keyType, + Type valueType + ) { + super(parent, className, typedefName, description); + this.keyType = keyType; + this.valueType = valueType; + setExtendsType(Types.Client.Transport.Endpoints.DictionaryResponse(keyType, valueType)); + } + + @Override + public Collection getAnnotations() { + return List.of(Types.Client.Json.JsonpDeserializable); + } + + @Override + public boolean extendsOtherShape() { + return true; + } +} diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/EnumShape.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/EnumShape.java index 0968bd9886..90a2fae57c 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/model/EnumShape.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/EnumShape.java @@ -9,17 +9,18 @@ package org.opensearch.client.codegen.model; import java.util.Collection; -import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.TreeMap; import org.opensearch.client.codegen.utils.JavaClassKind; import org.opensearch.client.codegen.utils.Strings; public class EnumShape extends Shape { - private final List variants; + private final TreeMap variants = new TreeMap<>(); - public EnumShape(Namespace parent, String className, List variants, String typedefName, String description) { + public EnumShape(Namespace parent, String className, String typedefName, String description) { super(parent, className, typedefName, description); - this.variants = variants; } @Override @@ -37,13 +38,29 @@ public Collection getImplementsTypes() { return List.of(Types.Client.Json.JsonEnum); } + public void addVariant(String value, boolean deprecated) { + var variant = variants.get(value.toLowerCase()); + if (variant == null) { + variant = new Variant(value, deprecated); + variants.put(value.toLowerCase(), variant); + } else { + variant.addAlias(value); + variant.setDeprecated(variant.isDeprecated() || deprecated); + } + } + public Collection getVariants() { - return Collections.unmodifiableCollection(variants); + return variants.values(); + } + + public boolean anyHasAliases() { + return variants.values().stream().anyMatch(v -> !v.getAliases().isEmpty()); } public static class Variant { private final String wireName; - private final boolean deprecated; + private final Set aliases = new HashSet<>(); + private boolean deprecated; public Variant(String wireName, boolean deprecated) { this.wireName = wireName; @@ -54,6 +71,14 @@ public String getWireName() { return wireName; } + public Set getAliases() { + return aliases; + } + + public void addAlias(String alias) { + aliases.add(alias); + } + public String getName() { return Strings.toPascalCase(wireName); } @@ -61,5 +86,9 @@ public String getName() { public boolean isDeprecated() { return deprecated; } + + public void setDeprecated(boolean deprecated) { + this.deprecated = deprecated; + } } } diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/Field.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/Field.java index e4d1734572..62eabd6273 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/model/Field.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/Field.java @@ -8,10 +8,13 @@ package org.opensearch.client.codegen.model; +import java.util.HashSet; import java.util.Objects; +import java.util.Set; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import org.opensearch.client.codegen.NameSanitizer; +import org.opensearch.client.codegen.utils.Markdown; +import org.opensearch.client.codegen.utils.NameSanitizer; import org.opensearch.client.codegen.utils.Strings; public class Field { @@ -25,6 +28,7 @@ public class Field { @Nullable private final Deprecation deprecation; private final boolean isAdditionalProperties; + private final Set aliases = new HashSet<>(); public Field( @Nonnull String wireName, @@ -47,7 +51,7 @@ public Field( this.wireName = Strings.requireNonBlank(wireName, "wireName must not be null"); this.type = Objects.requireNonNull(type, "type must not be null"); this.required = required; - this.description = description; + this.description = description != null ? Markdown.toJavaDocHtml(description) : null; this.deprecation = deprecation; this.isAdditionalProperties = isAdditionalProperties; } @@ -84,4 +88,8 @@ public String getDescription() { public Deprecation getDeprecation() { return deprecation; } + + public void addAlias(String alias) { + aliases.add(alias); + } } diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/Namespace.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/Namespace.java index 7c2f4ebd88..35087e5f92 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/model/Namespace.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/Namespace.java @@ -23,7 +23,7 @@ import org.opensearch.client.codegen.utils.Strings; public class Namespace { - private static final Set PARTIAL_NAMESPACES = Set.of("", "snapshot"); + private static final Set PARTIAL_NAMESPACES = Set.of("", "snapshot", "indices"); private final Namespace parent; private final String name; @@ -104,6 +104,11 @@ private Type getClientType(boolean async) { return Type.builder().withPackage(getPackageName()).withName(getClientClassName(async, false)).build(); } + @Override + public String toString() { + return getPackageName(); + } + private static class Client extends Shape { private final boolean async; private final boolean base; diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/ObjectShape.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/ObjectShape.java index 32ba374de0..3ecac3830d 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/model/ObjectShape.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/ObjectShape.java @@ -10,9 +10,13 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.TreeMap; +import java.util.stream.Collectors; +import org.apache.commons.lang3.tuple.Pair; public class ObjectShape extends Shape { protected final Map bodyFields = new TreeMap<>(); @@ -28,7 +32,14 @@ public void addBodyField(Field field) { } public Collection getBodyFields() { - return bodyFields.values(); + var discriminatingFields = getReferencingDiscriminatedUnions().stream() + .map(ReferencingDiscriminatedUnion::getDiscriminatingField) + .collect(Collectors.toSet()); + if (!discriminatingFields.isEmpty()) { + return bodyFields.values().stream().filter(f -> !discriminatingFields.contains(f.getWireName())).collect(Collectors.toList()); + } else { + return bodyFields.values(); + } } public Collection getFields() { @@ -55,19 +66,67 @@ public boolean hasFieldsToSerialize() { return !bodyFields.isEmpty() || additionalPropertiesField != null; } - public boolean hasFields() { - return !bodyFields.isEmpty() || additionalPropertiesField != null; + public Collection getReferencingDiscriminatedUnions() { + return getIncomingReference(ReferenceKind.UnionVariant).stream() + .map(s -> (TaggedUnionShape) s) + .filter(TaggedUnionShape::isDiscriminated) + .sorted(Comparator.comparing(Shape::getClassName)) + .map(u -> { + var discriminatorValue = u.getVariants() + .stream() + .filter(v -> v.getType().equals(getType())) + .findFirst() + .orElseThrow() + .getName(); + + return new ReferencingDiscriminatedUnion(u, discriminatorValue); + }) + .collect(Collectors.toList()); + } + + public Set> getDistinctDiscriminatorFieldValues() { + return getReferencingDiscriminatedUnions().stream() + .map(u -> Pair.of(u.getDiscriminatingField(), u.getDiscriminatorValue())) + .collect(Collectors.toSet()); } public Collection getImplementsTypes() { - return hasFieldsToSerialize() && !extendsOtherShape() ? List.of(Types.Client.Json.PlainJsonSerializable) : null; + var types = new ArrayList(2); + + for (var union : getReferencingDiscriminatedUnions()) { + types.add(union.getUnion().getVariantBaseType()); + } + + if (hasFieldsToSerialize() && !extendsOtherShape()) { + types.add(Types.Client.Json.PlainJsonSerializable); + } + + return types; } public Collection getAnnotations() { return (hasFieldsToSerialize() || extendsOtherShape()) && !isAbstract() ? List.of(Types.Client.Json.JsonpDeserializable) : null; } - public static class BuilderModel { + public static class ReferencingDiscriminatedUnion { + private final TaggedUnionShape union; + private final String discriminatorValue; + + public ReferencingDiscriminatedUnion(TaggedUnionShape union, String discriminatorValue) { + this.union = union; + this.discriminatorValue = discriminatorValue; + } + + public TaggedUnionShape getUnion() { + return union; + } + + public String getDiscriminatingField() { + return union.getDiscriminatingField(); + } + public String getDiscriminatorValue() { + return discriminatorValue; + } } } diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/RequestShape.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/RequestShape.java index 136f8ead7b..f8d270e772 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/model/RequestShape.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/RequestShape.java @@ -151,10 +151,6 @@ public boolean hasAnyRequiredFields() { return fields.values().stream().anyMatch(Field::isRequired); } - public boolean hasFields() { - return !fields.isEmpty(); - } - public Type getJsonEndpointType() { return Types.Client.Transport.JsonEndpoint(getType(), getResponseType(), Types.Client.OpenSearch._Types.ErrorResponse); } @@ -173,6 +169,8 @@ private static String responseClassName(@Nonnull OperationGroup operationGroup) private static String classBaseName(@Nonnull OperationGroup operationGroup) { Objects.requireNonNull(operationGroup, "operationGroup must not be null"); switch (operationGroup.toString()) { + case "indices.get": + return "GetIndex"; case "snapshot.clone": return "CloneSnapshot"; case "tasks.get": diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/Shape.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/Shape.java index c44c8d72d9..7f3e6ab5cc 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/model/Shape.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/Shape.java @@ -19,10 +19,12 @@ import java.util.TreeSet; import java.util.stream.Collectors; import javax.annotation.Nonnull; +import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.opensearch.client.codegen.exceptions.RenderException; import org.opensearch.client.codegen.utils.JavaClassKind; +import org.opensearch.client.codegen.utils.Markdown; public abstract class Shape { private static final Logger LOGGER = LogManager.getLogger(); @@ -39,7 +41,7 @@ public Shape(Namespace parent, String className, String typedefName, String desc this.parent = parent; this.className = className; this.typedefName = typedefName; - this.description = description; + this.description = description != null ? Markdown.toJavaDocHtml(description) : null; } public String getPackageName() { @@ -110,6 +112,11 @@ private void addReference(ReferenceKind kind, Shape to) { to.incomingReferences.computeIfAbsent(kind, k -> new ArrayList<>()).add(this); } + protected Collection getIncomingReference(ReferenceKind kind) { + var refs = incomingReferences.get(kind); + return refs != null ? Collections.unmodifiableList(refs) : Collections.emptyList(); + } + public @Nonnull Type getType() { return Type.builder().withPackage(getPackageName()).withName(className).withTargetShape(this).build(); } @@ -128,6 +135,10 @@ public void render(ShapeRenderingContext ctx) throws RenderException { renderer.renderJava(this, outFile); } + public String getTemplateName() { + return getClass().getSimpleName(); + } + public Set getImports() { var imports = new TreeSet(); for (var type : referencedTypes) { @@ -137,6 +148,17 @@ public Set getImports() { } public boolean needsLegacyLicense() { + if ("analysis".equals(parent.getName()) && (className.startsWith("Cjk") || className.startsWith("Smartcn"))) { + return false; + } return !"ml".equals(parent.getName()); } + + @Override + public String toString() { + return new ToStringBuilder(this).append("className", className) + .append("parent", parent) + .append("extendsType", extendsType) + .toString(); + } } diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/ShapeRenderingContext.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/ShapeRenderingContext.java index 72a163ea3b..1f6ab5ce15 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/model/ShapeRenderingContext.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/ShapeRenderingContext.java @@ -16,8 +16,8 @@ import org.opensearch.client.codegen.renderer.TemplateLoader; import org.opensearch.client.codegen.renderer.TemplateRenderer; import org.opensearch.client.codegen.renderer.TemplateValueFormatter; -import org.opensearch.client.codegen.utils.ObjectBuilderBase; import org.opensearch.client.codegen.utils.Strings; +import org.opensearch.client.codegen.utils.builder.ObjectBuilderBase; public final class ShapeRenderingContext implements AutoCloseable { @Nonnull diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/SpecTransformer.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/SpecTransformer.java index 575a955811..b9452504f1 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/model/SpecTransformer.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/SpecTransformer.java @@ -11,7 +11,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -28,10 +27,12 @@ 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.model.overrides.SchemaOverride; import org.opensearch.client.codegen.openapi.HttpStatusCode; import org.opensearch.client.codegen.openapi.In; import org.opensearch.client.codegen.openapi.JsonPointer; import org.opensearch.client.codegen.openapi.MimeType; +import org.opensearch.client.codegen.openapi.OpenApiDiscriminator; import org.opensearch.client.codegen.openapi.OpenApiMediaType; import org.opensearch.client.codegen.openapi.OpenApiOperation; import org.opensearch.client.codegen.openapi.OpenApiParameter; @@ -43,6 +44,7 @@ import org.opensearch.client.codegen.openapi.OpenApiSchemaFormat; import org.opensearch.client.codegen.openapi.OpenApiSchemaType; import org.opensearch.client.codegen.openapi.OpenApiSpecification; +import org.opensearch.client.codegen.utils.Maps; import org.opensearch.client.codegen.utils.Versions; public class SpecTransformer { @@ -235,7 +237,8 @@ private Field visit(OpenApiParameter parameter) { private Shape visit(OpenApiSchema schema) { var namespace = schema.getNamespace().orElseThrow(); var name = schema.getName().orElseThrow(); - return visit(root.child(namespace), name, namespace + "." + name, schema); + var className = overrides.getSchema(schema.getPointer()).flatMap(SchemaOverride::getClassName).orElse(name); + return visit(root.child(namespace), className, namespace + "." + name, schema); } private Shape visit(Namespace parent, String className, String typedefName, OpenApiSchema schema) { @@ -250,42 +253,72 @@ private Shape visit(Namespace parent, String className, String typedefName, Open var description = schema.getDescription().orElse(null); var oneOf = schema.getOneOf(); + var isTaggedUnion = oneOf.isPresent() + && (schema.getDiscriminator().isPresent() || oneOf.orElseThrow().stream().allMatch(OpenApiSchema::hasTitle)); if (schema.isArray()) { shape = new ArrayShape(parent, className, mapType(schema), typedefName, description); visitedSchemas.putIfAbsent(schema, shape); } else if (schema.isStringEnum() || (oneOf.isPresent() && oneOf.get().stream().allMatch(OpenApiSchema::isStringEnum))) { - var variants = new ArrayList(); + var enumShape = new EnumShape(parent, className, typedefName, description); + shape = enumShape; + visitedSchemas.putIfAbsent(schema, shape); if (oneOf.isPresent()) { oneOf.get().forEach(s -> { var isDeprecated = s.getVersionDeprecated().isPresent(); - s.getEnums().orElseThrow().forEach(v -> variants.add(new EnumShape.Variant(v, isDeprecated))); + s.getEnums().orElseThrow().forEach(v -> enumShape.addVariant(v, isDeprecated)); }); } else { - schema.getEnums().orElseThrow().forEach(v -> variants.add(new EnumShape.Variant(v, false))); + schema.getEnums().orElseThrow().forEach(v -> enumShape.addVariant(v, false)); } - - variants.sort(Comparator.comparing(EnumShape.Variant::getName)); - - shape = new EnumShape(parent, className, variants, typedefName, description); - visitedSchemas.putIfAbsent(schema, shape); - } else if (oneOf.isPresent()) { - var taggedUnion = new TaggedUnionShape(parent, className, typedefName, description); + } else if (isTaggedUnion) { + var discriminatingField = schema.getDiscriminator().flatMap(OpenApiDiscriminator::getPropertyName).orElse(null); + var taggedUnion = new TaggedUnionShape(parent, className, typedefName, description, discriminatingField); shape = taggedUnion; visitedSchemas.putIfAbsent(schema, shape); oneOf.get().forEach(s -> { - var title = s.getTitle() - .orElseThrow(() -> new IllegalStateException("oneOf variant [" + s.getPointer() + "] is missing a `title` tag")); - taggedUnion.addVariant(title, mapType(s)); + String name; + if (discriminatingField != null) { + var props = new HashMap(); + collectObjectProperties(s, props, new ArrayList<>()); + name = Maps.tryGet(props, discriminatingField) + .flatMap(OpenApiSchema::getEnums) + .flatMap(enums -> enums.stream().findFirst()) + .orElseThrow( + () -> new IllegalStateException( + "oneOf variant [" + + s.getPointer() + + "] is missing the `" + + discriminatingField + + "` property as a single value enum" + ) + ); + } else { + name = s.getTitle() + .orElseThrow(() -> new IllegalStateException("oneOf variant [" + s.getPointer() + "] is missing a `title` tag")); + } + taggedUnion.addVariant(name, mapType(s)); }); } else if (schema.determineSingleType().orElse(null) == OpenApiSchemaType.Object) { - var objShape = new ObjectShape(parent, className, typedefName, description); - shape = objShape; - visitedSchemas.putIfAbsent(schema, shape); + if (schema.getProperties().isEmpty() && schema.getAdditionalProperties().isPresent()) { + shape = new DictionaryResponseShape( + parent, + className, + typedefName, + description, + Types.Java.Lang.String, + mapType(schema.getAdditionalProperties().orElseThrow()) + ); + visitedSchemas.putIfAbsent(schema, shape); + } else { + var objShape = new ObjectShape(parent, className, typedefName, description); + shape = objShape; + visitedSchemas.putIfAbsent(schema, shape); - visitInto(schema, objShape); + visitInto(schema, objShape); + } } else { throw new NotImplementedException("Unsupported schema: " + schema); } @@ -310,8 +343,15 @@ private void visitInto(OpenApiSchema schema, ObjectShape shape) { 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)); + var propOverrides = overrides.map(so -> so.getProperty(k)); + + var type = propOverrides.flatMap(PropertyOverride::getMappedType).orElseGet(() -> mapType(v)); + + var field = new Field(k, type, required.contains(k), v.getDescription().orElse(null), null); + + propOverrides.flatMap(PropertyOverride::getAliases).ifPresent(aliases -> aliases.forEach(field::addAlias)); + + shape.addBodyField(field); }); if (!additionalProperties.isEmpty()) { @@ -402,6 +442,13 @@ private Type mapType(OpenApiSchema schema, boolean boxed) { } private Type mapTypeInner(OpenApiSchema schema) { + if (schema.getPointer().isDirectChildOf(JsonPointer.of("components", "schemas"))) { + var type = mapTypeComponentsSchemas(schema); + if (type != null) { + return type; + } + } + if (schema.has$ref()) { schema = schema.resolve(); @@ -436,7 +483,6 @@ private Type mapTypeInner(OpenApiSchema schema) { case Array: return mapArray(schema); case String: - 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; @@ -449,6 +495,22 @@ private Type mapTypeInner(OpenApiSchema schema) { throw new UnsupportedOperationException("Can not get type name for: " + types); } + private Type mapTypeComponentsSchemas(OpenApiSchema schema) { + var key = schema.getPointer().getLastKey().orElseThrow(); + switch (key) { + case "_common:Duration": + return Types.Client.OpenSearch._Types.Time; + case "_common:Stringifiedinteger": + return Types.Primitive.Int; + case "_common:Stringifiedboolean": + return Types.Primitive.Boolean; + case "_common:StringifiedEpochTimeUnitMillis": + return Types.Primitive.Long; + default: + return null; + } + } + private Type mapOneOf(List oneOf) { if (isOneOfSingleAndArray(oneOf)) { return mapType(oneOf.get(1)); @@ -464,7 +526,7 @@ private Type mapOneOf(List oneOf) { return Types.Java.Lang.String; } - throw new UnsupportedOperationException("Can not get type name for oneOf: " + oneOf); + return Types.Client.Json.JsonData; } private Type mapAllOf(List allOf) { @@ -500,7 +562,10 @@ private Type mapInteger(OpenApiSchema schema) { } private Type mapNumber(OpenApiSchema schema) { - var format = schema.getFormat().orElse(OpenApiSchemaFormat.Float); + var format = schema.getFormat().orElse(null); + if (format == null) { + return Types.Java.Lang.Number; + } switch (format) { case Float: return Types.Primitive.Float; @@ -514,7 +579,7 @@ private Type mapNumber(OpenApiSchema schema) { } private boolean shouldKeepRef(OpenApiSchema schema) { - if (schema.isInteger() || schema.isNumber() || schema.isArray()) { + if (schema.isArray() || schema.isBoolean() || schema.isInteger() || schema.isNumber()) { return false; } if (schema.isString()) { @@ -526,8 +591,24 @@ private boolean shouldKeepRef(OpenApiSchema schema) { return false; } if (schema.getOneOf().isPresent()) { - var oneOf = schema.getOneOf().orElseThrow(); - return oneOf.stream().allMatch(s -> s.getTitle().isPresent()) || oneOf.stream().allMatch(OpenApiSchema::isStringEnum); + if (schema.getDiscriminator().isPresent()) { + return true; + } + var allObject = true; + var allHaveTitle = true; + var allStringEnum = true; + for (var s : schema.getOneOf().orElseThrow()) { + if (s.determineSingleType().orElse(null) != OpenApiSchemaType.Object) { + allObject = false; + } + if (s.getTitle().isEmpty()) { + allHaveTitle = false; + } + if (!s.isStringEnum()) { + allStringEnum = false; + } + } + return allObject || allHaveTitle || allStringEnum; } if (schema.getAllOf().isPresent()) { return schema.determineSingleType().orElse(null) == OpenApiSchemaType.Object; diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/TaggedUnionShape.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/TaggedUnionShape.java index cc3d28ff7c..8e317e2ef8 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/model/TaggedUnionShape.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/TaggedUnionShape.java @@ -8,29 +8,44 @@ package org.opensearch.client.codegen.model; -import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.opensearch.client.codegen.exceptions.RenderException; +import org.opensearch.client.codegen.utils.JavaClassKind; import org.opensearch.client.codegen.utils.Lists; +import org.opensearch.client.codegen.utils.Strings; -public class TaggedUnionShape extends ObjectShape { - private final List variants = new ArrayList<>(); +public class TaggedUnionShape extends Shape { + private final Map variants = new TreeMap<>(); + private final String discriminatingField; - public TaggedUnionShape(Namespace parent, String className, String typedefName, String description) { + public TaggedUnionShape(Namespace parent, String className, String typedefName, String description, String discriminatingField) { super(parent, className, typedefName, description); + this.discriminatingField = discriminatingField; } public void addVariant(String name, Type type) { - variants.add(new Variant(name, type.getBoxed())); + variants.put(name, new Variant(name, type.getBoxed())); tryAddReference(ReferenceKind.UnionVariant, type); } public Collection getVariants() { - return variants; + return variants.values(); } - public Collection getPrimitiveVariants() { - return Lists.filter(variants, v -> v.getType().isPrimitive()); + public Collection getShapeVariants() { + return Lists.filter(getVariants(), v -> v.getType().isInsidePackage("org.opensearch") && !v.getType().isEnum()); + } + + public Collection getNonShapeVariants() { + return Lists.filter(getVariants(), v -> !v.getType().isInsidePackage("org.opensearch")); + } + + public Variant getDefaultVariant() { + return variants.get("custom"); } @Override @@ -41,11 +56,40 @@ public Collection getAnnotations() { @Override public Collection getImplementsTypes() { return List.of( - Types.Client.Util.TaggedUnion(getType().getNestedType("Kind"), Types.Java.Lang.Object), + Types.Client.Util.TaggedUnion(getType().getNestedType("Kind"), getVariantBaseType()), Types.Client.Json.PlainJsonSerializable ); } + public boolean isDiscriminated() { + return discriminatingField != null; + } + + public String getDiscriminatingField() { + return discriminatingField; + } + + public Type getVariantBaseType() { + return isDiscriminated() + ? Type.builder().withPackage(getPackageName()).withName(getClassName() + "Variant").build() + : Types.Java.Lang.Object; + } + + public boolean canStringify() { + return !isDiscriminated() && getVariants().stream().allMatch(v -> v.getType().isString() || v.getType().isEnum()); + } + + @Override + public void render(ShapeRenderingContext ctx) throws RenderException { + super.render(ctx); + if (!getShapeVariants().isEmpty()) { + new Builders(this).render(ctx); + } + if (isDiscriminated()) { + new VariantInterface(this).render(ctx); + } + } + public static class Variant { private final String name; private final Type type; @@ -62,5 +106,86 @@ public String getName() { public Type getType() { return type; } + + @Override + public String toString() { + return new ToStringBuilder(this).append("name", name).append("type", type).toString(); + } + } + + public static class Builders extends Shape { + private static String buildDescription(TaggedUnionShape union) { + var desc = "Builders for {@link " + union.getClassName() + "} variants."; + var nonShapeVariants = union.getNonShapeVariants(); + if (!nonShapeVariants.isEmpty()) { + desc += "\n\nVariants "; + desc += Strings.join(nonShapeVariants, ", ", v -> "`" + v.getName() + "`"); + desc += " are not available here as they don't have a dedicated class. Use {@link " + + union.getClassName() + + "}'s builder for these."; + } + return desc; + } + + private final String unionClassName; + private final Collection variants; + + private Builders(TaggedUnionShape union) { + super(union.getParent(), union.getClassName() + "Builders", null, buildDescription(union)); + variants = union.getShapeVariants(); + unionClassName = union.getClassName(); + } + + public String getUnionClassName() { + return unionClassName; + } + + public Collection getVariants() { + return variants; + } + + @Override + public String getTemplateName() { + return "TaggedUnionShape/Builders"; + } + + @Override + public String toString() { + return new ToStringBuilder(this).append("unionClassName", unionClassName).append("variants", variants).toString(); + } + } + + public static class VariantInterface extends Shape { + private final String unionClassName; + + private VariantInterface(TaggedUnionShape union) { + super( + union.getParent(), + union.getClassName() + "Variant", + null, + "Base interface for {@link " + union.getClassName() + "} variants." + ); + unionClassName = union.getClassName(); + setExtendsType(Types.Client.Json.JsonpSerializable); + } + + @Override + public JavaClassKind getClassKind() { + return JavaClassKind.Interface; + } + + public String getUnionClassName() { + return unionClassName; + } + + @Override + public String getTemplateName() { + return "TaggedUnionShape/VariantInterface"; + } + + @Override + public String toString() { + return new ToStringBuilder(this).append("unionClassName", unionClassName).toString(); + } } } diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/Type.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/Type.java index f46c3f0306..92101c96a9 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/model/Type.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/Type.java @@ -16,11 +16,13 @@ import java.util.Set; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; import org.opensearch.client.codegen.renderer.lambdas.TypeIsDefinedLambda; import org.opensearch.client.codegen.renderer.lambdas.TypeQueryParamifyLambda; import org.opensearch.client.codegen.renderer.lambdas.TypeSerializerLambda; -import org.opensearch.client.codegen.utils.ObjectBuilderBase; import org.opensearch.client.codegen.utils.Strings; +import org.opensearch.client.codegen.utils.builder.ObjectBuilderBase; public class Type { private static final Set PRIMITIVES = Set.of("boolean", "char", "byte", "short", "int", "long", "float", "double"); @@ -70,11 +72,39 @@ public String toString() { return out.toString(); } + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || getClass() != o.getClass()) return false; + + Type type = (Type) o; + + return new EqualsBuilder().append(packageName, type.packageName) + .append(name, type.name) + .append(typeParams, type.typeParams) + .append(targetShape, type.targetShape) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37).append(packageName).append(name).append(typeParams).append(targetShape).toHashCode(); + } + @Nonnull public String getName() { return name; } + public Type[] getTypeParams() { + return typeParams; + } + + public boolean isInsidePackage(String pkg) { + return packageName != null && packageName.startsWith(pkg); + } + @Nonnull public Type getBoxed() { switch (name) { diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/TypeParameterDefinition.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/TypeParameterDefinition.java index 76935c0273..f4316f37b2 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/model/TypeParameterDefinition.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/TypeParameterDefinition.java @@ -10,8 +10,8 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import org.opensearch.client.codegen.utils.ObjectBuilderBase; import org.opensearch.client.codegen.utils.Strings; +import org.opensearch.client.codegen.utils.builder.ObjectBuilderBase; public final class TypeParameterDefinition { @Nonnull diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/TypeParameterDiamond.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/TypeParameterDiamond.java index 074452d78a..50725ff100 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/model/TypeParameterDiamond.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/TypeParameterDiamond.java @@ -12,7 +12,7 @@ import java.util.function.Function; import javax.annotation.Nonnull; import org.opensearch.client.codegen.utils.Either; -import org.opensearch.client.codegen.utils.ObjectBuilderBase; +import org.opensearch.client.codegen.utils.builder.ObjectBuilderBase; public final class TypeParameterDiamond { @Nonnull diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/Types.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/Types.java index aff4712672..7545444777 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/model/Types.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/Types.java @@ -76,10 +76,7 @@ public static final class Util { public static final Type HashMap = Type.builder().withPackage(PACKAGE).withName("HashMap").build(); public static Type Map(Type keyType, Type valueType) { - return Map.toBuilder() - .withTypeParameters(keyType, valueType) - .withTargetShape(valueType.getTargetShape().orElse(null)) - .build(); + return Map.toBuilder().withTypeParameters(keyType, valueType).build(); } public static final Type Map = Type.builder().withPackage(PACKAGE).withName("Map").build(); @@ -89,12 +86,7 @@ public static Type MapEntry(Type keyType, Type valueType) { } public static Type List(Type valueType) { - return Type.builder() - .withPackage(PACKAGE) - .withName("List") - .withTypeParameters(valueType) - .withTargetShape(valueType.getTargetShape().orElse(null)) - .build(); + return Type.builder().withPackage(PACKAGE).withName("List").withTypeParameters(valueType).build(); } public static final class Concurrent { @@ -180,6 +172,12 @@ public static Type JsonEndpoint(Type requestType, Type responseType, Type errorT public static final class Endpoints { public static final String PACKAGE = Transport.PACKAGE + ".endpoints"; + + public static Type DictionaryResponse(Type keyType, Type valueType) { + return DictionaryResponse.withTypeParameters(keyType, valueType); + } + + public static final Type DictionaryResponse = Type.builder().withPackage(PACKAGE).withName("DictionaryResponse").build(); public static final Type SimpleEndpoint = Type.builder().withPackage(PACKAGE).withName("SimpleEndpoint").build(); } } diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/overrides/Overrides.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/overrides/Overrides.java index e4c9759ca2..7a8ef32339 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/model/overrides/Overrides.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/overrides/Overrides.java @@ -12,15 +12,33 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Set; 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; +import org.opensearch.client.codegen.utils.builder.ObjectBuilder; +import org.opensearch.client.codegen.utils.builder.ObjectBuilderBase; public class Overrides { - public static final Overrides OVERRIDES = builder().build(); + private static final JsonPointer SCHEMAS = JsonPointer.of("components", "schemas"); + + public static final Overrides OVERRIDES = builder().withSchemas( + s -> s.with(SCHEMAS.append("_common.query_dsl:QueryContainer"), so -> so.withClassName("Query")) + .with(SCHEMAS.append("indices._common:IndexSettings"), so -> so.withAliasProvider((k) -> { + switch (k) { + case "index": + case "indexing": + case "mapping": + case "search": + case "settings": + case "top_metrics_max_size": + return null; + default: + return Set.of("index." + k); + } + })) + ).build(); @Nonnull private final Map schemas; diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/overrides/PropertyOverride.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/overrides/PropertyOverride.java index c7e01d10a8..efdb28770f 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/model/overrides/PropertyOverride.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/overrides/PropertyOverride.java @@ -8,19 +8,27 @@ package org.opensearch.client.codegen.model.overrides; +import java.util.Objects; import java.util.Optional; +import java.util.Set; +import java.util.function.Function; 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; +import org.opensearch.client.codegen.utils.builder.ObjectBuilder; +import org.opensearch.client.codegen.utils.builder.ObjectBuilderBase; +import org.opensearch.client.codegen.utils.builder.ObjectMapBuilderBase; +import org.opensearch.client.codegen.utils.builder.SetBuilder; public final class PropertyOverride { @Nullable private final Type mappedType; + @Nullable + private final Set aliases; private PropertyOverride(Builder builder) { this.mappedType = builder.mappedType; + this.aliases = builder.aliases; } @Nonnull @@ -28,6 +36,11 @@ public Optional getMappedType() { return Optional.ofNullable(mappedType); } + @Nonnull + public Optional> getAliases() { + return Optional.ofNullable(aliases); + } + @Nonnull public static Builder builder() { return new Builder(); @@ -41,6 +54,8 @@ public static MapBuilder mapBuilder() { public static final class Builder extends ObjectBuilderBase { @Nullable private Type mappedType; + @Nullable + private Set aliases; private Builder() {} @@ -55,9 +70,21 @@ public Builder withMappedType(@Nullable Type mappedType) { this.mappedType = mappedType; return this; } + + @Nonnull + public Builder withAliases(@Nullable Set aliases) { + this.aliases = aliases; + return this; + } + + @Nonnull + public Builder withAliases(@Nonnull Function, ObjectBuilder>> fn) { + this.aliases = Objects.requireNonNull(fn, "fn must not be null").apply(new SetBuilder<>()).build(); + return this; + } } - public static final class MapBuilder extends MapBuilderBase { + public static final class MapBuilder extends ObjectMapBuilderBase { private MapBuilder() {} @Nonnull diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/model/overrides/SchemaOverride.java b/java-codegen/src/main/java/org/opensearch/client/codegen/model/overrides/SchemaOverride.java index d8359b11ff..a72db9173e 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/model/overrides/SchemaOverride.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/model/overrides/SchemaOverride.java @@ -9,28 +9,67 @@ package org.opensearch.client.codegen.model.overrides; import java.util.Collections; +import java.util.HashSet; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.function.Function; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import org.opensearch.client.codegen.model.Type; 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; +import org.opensearch.client.codegen.utils.builder.ObjectBuilder; +import org.opensearch.client.codegen.utils.builder.ObjectBuilderBase; +import org.opensearch.client.codegen.utils.builder.ObjectMapBuilderBase; public final class SchemaOverride { + private final boolean skipGeneration; @Nonnull private final Map properties; + @Nullable + private final Function> aliasProvider; + @Nullable + private final String className; private SchemaOverride(Builder builder) { + this.skipGeneration = builder.skipGeneration; this.properties = builder.properties != null ? Collections.unmodifiableMap(builder.properties) : Collections.emptyMap(); + this.aliasProvider = builder.aliasProvider; + this.className = builder.className; } @Nonnull - public Optional getProperty(@Nonnull String key) { - return Optional.ofNullable(properties.get(key)); + public PropertyOverride getProperty(@Nonnull String key) { + var orig = properties.get(key); + Type mappedType = null; + Set aliases = null; + if (orig != null) { + mappedType = orig.getMappedType().orElse(null); + aliases = orig.getAliases().map(HashSet::new).orElse(null); + } + + if (aliasProvider != null) { + var providerAliases = aliasProvider.apply(key); + if (providerAliases != null) { + if (aliases == null) { + aliases = new HashSet<>(providerAliases); + } else { + aliases.addAll(providerAliases); + } + } + } + + return PropertyOverride.builder().withMappedType(mappedType).withAliases(aliases).build(); + } + + public boolean shouldSkipGeneration() { + return skipGeneration; + } + + @Nonnull + public Optional getClassName() { + return Optional.ofNullable(className); } @Nonnull @@ -44,8 +83,13 @@ public static MapBuilder mapBuilder() { } public static final class Builder extends ObjectBuilderBase { + private boolean skipGeneration; @Nullable private Map properties; + @Nullable + private Function> aliasProvider; + @Nullable + private String className; private Builder() {} @@ -55,14 +99,32 @@ protected SchemaOverride construct() { return new SchemaOverride(this); } + @Nonnull + public Builder withSkipGeneration(boolean skipGeneration) { + this.skipGeneration = skipGeneration; + return this; + } + @Nonnull public Builder withProperties(@Nonnull Function>> fn) { this.properties = Objects.requireNonNull(fn, "fn must not be null").apply(PropertyOverride.mapBuilder()).build(); return this; } + + @Nonnull + public Builder withAliasProvider(@Nullable Function> aliasProvider) { + this.aliasProvider = aliasProvider; + return this; + } + + @Nonnull + public Builder withClassName(@Nullable String className) { + this.className = className; + return this; + } } - public static final class MapBuilder extends MapBuilderBase { + public static final class MapBuilder extends ObjectMapBuilderBase { private MapBuilder() {} @Nonnull diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/openapi/OpenApiDiscriminator.java b/java-codegen/src/main/java/org/opensearch/client/codegen/openapi/OpenApiDiscriminator.java new file mode 100644 index 0000000000..2cf855dbb4 --- /dev/null +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/openapi/OpenApiDiscriminator.java @@ -0,0 +1,29 @@ +/* + * 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.openapi; + +import io.swagger.v3.oas.models.media.Discriminator; +import java.util.Optional; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class OpenApiDiscriminator extends OpenApiElement { + @Nullable + private final String propertyName; + + protected OpenApiDiscriminator(@Nullable OpenApiElement parent, @Nonnull JsonPointer pointer, @Nonnull Discriminator discriminator) { + super(parent, pointer); + this.propertyName = discriminator.getPropertyName(); + } + + @Nonnull + public Optional getPropertyName() { + return Optional.ofNullable(propertyName); + } +} diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/openapi/OpenApiSchema.java b/java-codegen/src/main/java/org/opensearch/client/codegen/openapi/OpenApiSchema.java index 8a1a3d1d03..304b3e4055 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/openapi/OpenApiSchema.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/openapi/OpenApiSchema.java @@ -22,9 +22,9 @@ import javax.annotation.Nullable; import org.opensearch.client.codegen.utils.Lists; import org.opensearch.client.codegen.utils.Maps; -import org.opensearch.client.codegen.utils.ObjectBuilderBase; import org.opensearch.client.codegen.utils.Sets; import org.opensearch.client.codegen.utils.Versions; +import org.opensearch.client.codegen.utils.builder.ObjectBuilderBase; import org.semver4j.Semver; public class OpenApiSchema extends OpenApiRefElement { @@ -66,6 +66,8 @@ public class OpenApiSchema extends OpenApiRefElement { @Nullable private final String pattern; @Nullable + private final OpenApiDiscriminator discriminator; + @Nullable private final Semver versionRemoved; @Nullable private final Semver versionDeprecated; @@ -87,6 +89,7 @@ private OpenApiSchema(@Nonnull Builder builder) { required = builder.required; title = builder.title; pattern = builder.pattern; + discriminator = builder.discriminator; versionRemoved = builder.versionRemoved; versionDeprecated = builder.versionDeprecated; } @@ -98,7 +101,10 @@ protected OpenApiSchema(@Nullable OpenApiElement parent, @Nonnull JsonPointer var key = pointer.getLastKey().orElseThrow(); var colonIdx = key.indexOf(':'); if (colonIdx >= 0) { - namespace = key.substring(0, colonIdx).replaceAll("\\._common", "").replaceAll("^_common", "_types"); + namespace = key.substring(0, colonIdx) + .replaceAll("\\._common", "") + .replaceAll("^_common", "_types") + .replaceAll("^_core", "core"); name = key.substring(colonIdx + 1); } else { namespace = null; @@ -136,6 +142,8 @@ protected OpenApiSchema(@Nullable OpenApiElement parent, @Nonnull JsonPointer pattern = schema.getPattern(); + discriminator = child("discriminator", schema.getDiscriminator(), OpenApiDiscriminator::new); + var extensions = schema.getExtensions(); versionRemoved = Maps.tryGet(extensions, "x-version-removed").map(v -> Versions.coerce((String) v)).orElse(null); @@ -256,6 +264,10 @@ public Optional> getRequired() { return Sets.unmodifiableOpt(required); } + public boolean hasTitle() { + return title != null; + } + @Nonnull public Optional getTitle() { return Optional.ofNullable(title); @@ -266,6 +278,11 @@ public Optional getPattern() { return Optional.ofNullable(pattern); } + @Nonnull + public Optional getDiscriminator() { + return Optional.ofNullable(discriminator); + } + @Nonnull public Optional getVersionRemoved() { return Optional.ofNullable(versionRemoved); @@ -355,6 +372,8 @@ public static class Builder extends ObjectBuilderBase { @Nullable private String pattern; @Nullable + private OpenApiDiscriminator discriminator; + @Nullable private Semver versionRemoved; @Nullable private Semver versionDeprecated; diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/JavaCodeFormatter.java b/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/JavaCodeFormatter.java index 8f2717a120..08273b2947 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/JavaCodeFormatter.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/JavaCodeFormatter.java @@ -25,7 +25,7 @@ import javax.annotation.Nonnull; import org.opensearch.client.codegen.exceptions.JavaFormatterException; import org.opensearch.client.codegen.utils.MavenArtifactResolver; -import org.opensearch.client.codegen.utils.ObjectBuilderBase; +import org.opensearch.client.codegen.utils.builder.ObjectBuilderBase; public class JavaCodeFormatter implements AutoCloseable { private final Formatter formatter; diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/TemplateGlobalContext.java b/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/TemplateGlobalContext.java index 2208392b1c..236a6d1623 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/TemplateGlobalContext.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/TemplateGlobalContext.java @@ -17,8 +17,9 @@ import org.apache.commons.text.StringEscapeUtils; import org.opensearch.client.codegen.model.Types; import org.opensearch.client.codegen.renderer.lambdas.TemplateStringLambda; -import org.opensearch.client.codegen.utils.ObjectBuilderBase; +import org.opensearch.client.codegen.utils.NameSanitizer; import org.opensearch.client.codegen.utils.Strings; +import org.opensearch.client.codegen.utils.builder.ObjectBuilderBase; public final class TemplateGlobalContext implements Mustache.CustomContext { @Nonnull @@ -47,6 +48,7 @@ public static Builder builder() { return new Builder().withLambda("quoted", s -> '\"' + StringEscapeUtils.escapeJava(s) + '\"') .withLambda("camelCase", Strings::toCamelCase) .withLambda("pascalCase", Strings::toPascalCase) + .withLambda("asFieldName", NameSanitizer::wireNameToField) .withLambda("toLower", s -> s.toLowerCase()) .withLambda("ERROR", s -> { throw new RuntimeException(s); diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/TemplateLoader.java b/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/TemplateLoader.java index 6a6583125b..8fb20e5dec 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/TemplateLoader.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/TemplateLoader.java @@ -17,8 +17,8 @@ import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nonnull; import org.apache.commons.io.IOUtils; -import org.opensearch.client.codegen.utils.ObjectBuilderBase; import org.opensearch.client.codegen.utils.Strings; +import org.opensearch.client.codegen.utils.builder.ObjectBuilderBase; public final class TemplateLoader implements Mustache.TemplateLoader { private static final ConcurrentHashMap CACHE = new ConcurrentHashMap<>(); diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/TemplateRenderer.java b/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/TemplateRenderer.java index 32daa020c2..e5b5b5d1c8 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/TemplateRenderer.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/TemplateRenderer.java @@ -23,7 +23,7 @@ import org.opensearch.client.codegen.exceptions.JavaFormatterException; import org.opensearch.client.codegen.exceptions.RenderException; import org.opensearch.client.codegen.model.Shape; -import org.opensearch.client.codegen.utils.ObjectBuilderBase; +import org.opensearch.client.codegen.utils.builder.ObjectBuilderBase; public final class TemplateRenderer { @Nonnull @@ -47,7 +47,8 @@ private TemplateRenderer(@Nonnull Builder builder) { public void render(String templateName, Object context, Writer out) throws RenderException { try { - templateCache.computeIfAbsent(templateName, compiler::loadTemplate).execute(context, this.context, out); + var template = templateCache.computeIfAbsent(templateName, compiler::loadTemplate); + template.execute(context, this.context, out); } catch (MustacheException e) { throw new RenderException("Failed to render: " + context, e); } @@ -60,7 +61,7 @@ public String render(String templateName, Object context) throws RenderException } public void renderJava(Shape shape, File outputFile) throws RenderException { - var classBody = render(shape.getClass().getSimpleName(), shape); + var classBody = render(shape.getTemplateName(), shape); var classHeader = render("Partials/ClassHeader", shape); try (Writer fileWriter = new FileWriter(outputFile)) { diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/TemplateValueFormatter.java b/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/TemplateValueFormatter.java index fa71560173..714620ec4a 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/TemplateValueFormatter.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/renderer/TemplateValueFormatter.java @@ -13,7 +13,7 @@ import java.util.Map; import java.util.Objects; import javax.annotation.Nonnull; -import org.opensearch.client.codegen.utils.ObjectBuilderBase; +import org.opensearch.client.codegen.utils.builder.ObjectBuilderBase; public final class TemplateValueFormatter implements Mustache.Formatter { @Nonnull diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/JavaClassKind.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/JavaClassKind.java index 2e587790c2..76bdc1d5a4 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/JavaClassKind.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/JavaClassKind.java @@ -13,7 +13,8 @@ public enum JavaClassKind { Class, - Enum; + Enum, + Interface; private static final Map VALUES = Maps.createLookupOf(values(), JavaClassKind::toString); diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/MapBuilderBase.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/MapBuilderBase.java deleted file mode 100644 index 221d434d16..0000000000 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/MapBuilderBase.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.utils; - -import java.util.Collections; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public abstract class MapBuilderBase, Self extends MapBuilderBase> extends - ObjectBuilderBase, Self> { - @Nullable - private Map map; - - protected MapBuilderBase() {} - - protected abstract @Nonnull VBuilder valueBuilder(); - - @Override - protected @Nonnull Map construct() { - return map != null ? Collections.unmodifiableMap(map) : Collections.emptyMap(); - } - - public @Nonnull Self with(@Nonnull Map map) { - this.map = _mapPutAll(this.map, map); - return self(); - } - - public @Nonnull Self with(@Nonnull K key, @Nonnull V value) { - this.map = _mapPut(this.map, key, value); - return self(); - } - - public @Nonnull Self with(@Nonnull K key, @Nonnull Function> fn) { - return with(key, Objects.requireNonNull(fn, "fn must not be null").apply(valueBuilder()).build()); - } -} diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/Markdown.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/Markdown.java new file mode 100644 index 0000000000..4f005f2a87 --- /dev/null +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/Markdown.java @@ -0,0 +1,23 @@ +/* + * 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.utils; + +import org.commonmark.parser.Parser; +import org.commonmark.renderer.html.HtmlRenderer; + +public final class Markdown { + private Markdown() {} + + private static final Parser PARSER = Parser.builder().build(); + private static final HtmlRenderer RENDERER = HtmlRenderer.builder().omitSingleParagraphP(true).build(); + + public static String toJavaDocHtml(String markdown) { + return RENDERER.render(PARSER.parse(markdown)).strip(); + } +} diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/NameSanitizer.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/NameSanitizer.java similarity index 63% rename from java-codegen/src/main/java/org/opensearch/client/codegen/NameSanitizer.java rename to java-codegen/src/main/java/org/opensearch/client/codegen/utils/NameSanitizer.java index 8370a06c14..badf2dd36e 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/NameSanitizer.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/NameSanitizer.java @@ -6,21 +6,25 @@ * compatible open source license. */ -package org.opensearch.client.codegen; +package org.opensearch.client.codegen.utils; -import java.util.HashSet; import java.util.Set; import javax.annotation.Nonnull; -import org.opensearch.client.codegen.utils.Strings; public class NameSanitizer { - private static final Set reservedWords = new HashSet<>() { - { - add("default"); - add("native"); - add("transient"); - } - }; + private static final Set reservedWords = Set.of( + "default", + "native", + "transient", + "boolean", + "char", + "byte", + "short", + "int", + "long", + "float", + "double" + ); @Nonnull public static String wireNameToField(@Nonnull String wireName) { diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/ObjectBuilderBase.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/ObjectBuilderBase.java deleted file mode 100644 index 8e71c9da70..0000000000 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/ObjectBuilderBase.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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. - */ - -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/* - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -package org.opensearch.client.codegen.utils; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import javax.annotation.Nonnull; - -public abstract class ObjectBuilderBase> implements ObjectBuilder { - private boolean _used = false; - - protected ObjectBuilderBase() {} - - protected @Nonnull Self self() { - // noinspection unchecked - return (Self) this; - } - - protected abstract @Nonnull T construct(); - - protected final void _ensureSingleUse() { - if (this._used) { - throw new IllegalStateException("Object builders can only be used once"); - } - this._used = true; - } - - @Override - public final @Nonnull T build() { - var self = self(); - self._ensureSingleUse(); - return self.construct(); - } - - // ----- Map utilities - - private static final class OwnedMap extends HashMap { - OwnedMap() {} - - OwnedMap(Map m) { - super(m); - } - } - - private static Map _mutableMap(Map map) { - if (map == null) { - return new OwnedMap<>(); - } else if (map instanceof ObjectBuilderBase.OwnedMap) { - return map; - } else { - // Adding to a map we don't own: make a defensive copy, also ensuring it is mutable. - return new OwnedMap<>(map); - } - } - - protected static Map _mapPut(Map map, K key, V value) { - map = _mutableMap(map); - map.put(key, value); - return map; - } - - protected static Map _mapPutAll(Map map, Map entries) { - if (map == null) { - // Keep the original map to avoid an unnecessary copy. - // It will be copied if we add more entries. - return Objects.requireNonNull(entries); - } else { - map = _mutableMap(map); - map.putAll(entries); - return map; - } - } -} diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/Strings.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/Strings.java index d6a751a84f..4f74c68671 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/Strings.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/Strings.java @@ -8,10 +8,13 @@ package org.opensearch.client.codegen.utils; +import java.util.Collection; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.apache.commons.text.CaseUtils; @@ -73,4 +76,13 @@ public static String toCamelCase(@Nonnull String str) { public static String toPascalCase(@Nonnull String str) { return toCamelCase(str, true); } + + @Nonnull + public static String join(@Nonnull Collection items, @Nonnull String delimiter, @Nonnull Function mapper) { + Objects.requireNonNull(items, "items must not be null"); + Objects.requireNonNull(delimiter, "delimiter must not be null"); + Objects.requireNonNull(mapper, "mapper must not be null"); + + return items.stream().map(mapper).collect(Collectors.joining(delimiter)); + } } diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ListBuilder.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ListBuilder.java new file mode 100644 index 0000000000..d4f8ce3098 --- /dev/null +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ListBuilder.java @@ -0,0 +1,13 @@ +/* + * 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.utils.builder; + +public final class ListBuilder extends ListBuilderBase> { + public ListBuilder() {} +} diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ListBuilderBase.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ListBuilderBase.java new file mode 100644 index 0000000000..eee8b04880 --- /dev/null +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ListBuilderBase.java @@ -0,0 +1,36 @@ +/* + * 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.utils.builder; + +import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class ListBuilderBase> extends ObjectBuilderBase, Builder> { + @Nullable + private List list; + + protected ListBuilderBase() {} + + @Override + protected final @Nonnull List construct() { + return _mutableList(list); + } + + public final @Nonnull Builder with(@Nonnull List list) { + this.list = _listAddAll(this.list, list); + return self(); + } + + @SafeVarargs + public final @Nonnull Builder with(@Nonnull V value, @Nonnull V... values) { + this.list = _listAdd(this.list, value, values); + return self(); + } +} diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/MapBuilder.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/MapBuilder.java new file mode 100644 index 0000000000..4889f780a8 --- /dev/null +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/MapBuilder.java @@ -0,0 +1,13 @@ +/* + * 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.utils.builder; + +public final class MapBuilder extends MapBuilderBase> { + public MapBuilder() {} +} diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/MapBuilderBase.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/MapBuilderBase.java new file mode 100644 index 0000000000..8208b9a4f4 --- /dev/null +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/MapBuilderBase.java @@ -0,0 +1,35 @@ +/* + * 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.utils.builder; + +import java.util.Map; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class MapBuilderBase> extends ObjectBuilderBase, Builder> { + @Nullable + private Map map; + + protected MapBuilderBase() {} + + @Override + protected final @Nonnull Map construct() { + return _mutableMap(map); + } + + public final @Nonnull Builder with(@Nonnull Map map) { + this.map = _mapPutAll(this.map, map); + return self(); + } + + public final @Nonnull Builder with(@Nonnull K key, @Nonnull V value) { + this.map = _mapPut(this.map, key, value); + return self(); + } +} diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/ObjectBuilder.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectBuilder.java similarity index 85% rename from java-codegen/src/main/java/org/opensearch/client/codegen/utils/ObjectBuilder.java rename to java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectBuilder.java index 3414747040..ece3e9a90c 100644 --- a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/ObjectBuilder.java +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectBuilder.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.client.codegen.utils; +package org.opensearch.client.codegen.utils.builder; import javax.annotation.Nonnull; diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectBuilderBase.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectBuilderBase.java new file mode 100644 index 0000000000..efcf93779f --- /dev/null +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectBuilderBase.java @@ -0,0 +1,209 @@ +/* + * 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. + */ + +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.client.codegen.utils.builder; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Function; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class ObjectBuilderBase> implements ObjectBuilder { + private boolean _used = false; + + protected ObjectBuilderBase() {} + + protected @Nonnull Builder self() { + // noinspection unchecked + return (Builder) this; + } + + protected abstract @Nonnull T construct(); + + protected final void _ensureSingleUse() { + if (this._used) { + throw new IllegalStateException("Object builders can only be used once"); + } + this._used = true; + } + + @Override + public final @Nonnull T build() { + var self = self(); + self._ensureSingleUse(); + return self.construct(); + } + + // ----- Conditional utilities + + public final @Nonnull Builder when(boolean condition, @Nonnull Function fn) { + return condition ? Objects.requireNonNull(fn, "fn must not be null").apply(self()) : self(); + } + + public final @Nonnull Builder whenNonNull(@Nullable V value, @Nonnull BiFunction fn) { + return value != null ? Objects.requireNonNull(fn, "fn must not be null").apply(self(), value) : self(); + } + + // ----- Set utilities + + private static final class OwnedSet extends HashSet { + OwnedSet() {} + + OwnedSet(Collection c) { + super(c); + } + }; + + protected static Set _mutableSet(Set set) { + if (set == null) { + return new OwnedSet<>(); + } else if (set instanceof OwnedSet) { + return set; + } else { + // Adding to a set we don't own: make a defensive copy, also ensuring it is mutable. + return new OwnedSet<>(set); + } + } + + @SafeVarargs + protected static Set _setAdd(Set set, T value, T... values) { + set = _mutableSet(set); + set.add(value); + if (values.length > 0) { + set.addAll(Arrays.asList(values)); + } + return set; + } + + protected static Set _setAddAll(Set set, Set values) { + if (set == null) { + // Keep the original set to avoid an unnecessary copy. + // It will be copied if we add more values. + return Objects.requireNonNull(values); + } else { + set = _mutableSet(set); + set.addAll(values); + return set; + } + } + + // ----- List utilities + + private static final class OwnedList extends ArrayList { + OwnedList() {} + + OwnedList(Collection c) { + super(c); + } + }; + + protected static List _mutableList(List list) { + if (list == null) { + return new OwnedList<>(); + } else if (list instanceof OwnedList) { + return list; + } else { + // Adding to a list we don't own: make a defensive copy, also ensuring it is mutable. + return new OwnedList<>(list); + } + } + + @SafeVarargs + protected static List _listAdd(List list, T value, T... values) { + list = _mutableList(list); + list.add(value); + if (values.length > 0) { + list.addAll(Arrays.asList(values)); + } + return list; + } + + protected static List _listAddAll(List list, List values) { + if (list == null) { + // Keep the original list to avoid an unnecessary copy. + // It will be copied if we add more values. + return Objects.requireNonNull(values); + } else { + list = _mutableList(list); + list.addAll(values); + return list; + } + } + + // ----- Map utilities + + private static final class OwnedMap extends HashMap { + OwnedMap() {} + + OwnedMap(Map m) { + super(m); + } + } + + protected static Map _mutableMap(Map map) { + if (map == null) { + return new OwnedMap<>(); + } else if (map instanceof OwnedMap) { + return map; + } else { + // Adding to a map we don't own: make a defensive copy, also ensuring it is mutable. + return new OwnedMap<>(map); + } + } + + protected static Map _mapPut(Map map, K key, V value) { + map = _mutableMap(map); + map.put(key, value); + return map; + } + + protected static Map _mapPutAll(Map map, Map entries) { + if (map == null) { + // Keep the original map to avoid an unnecessary copy. + // It will be copied if we add more entries. + return Objects.requireNonNull(entries); + } else { + map = _mutableMap(map); + map.putAll(entries); + return map; + } + } +} diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectListBuilderBase.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectListBuilderBase.java new file mode 100644 index 0000000000..482295c411 --- /dev/null +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectListBuilderBase.java @@ -0,0 +1,26 @@ +/* + * 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.utils.builder; + +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nonnull; + +public abstract class ObjectListBuilderBase< + V, + VBuilder extends ObjectBuilder, + Builder extends ObjectListBuilderBase> extends ListBuilderBase { + protected ObjectListBuilderBase() {} + + protected abstract @Nonnull VBuilder valueBuilder(); + + public final @Nonnull Builder with(@Nonnull Function> fn) { + return with(Objects.requireNonNull(fn, "fn must not be null").apply(valueBuilder()).build()); + } +} diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectMapBuilderBase.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectMapBuilderBase.java new file mode 100644 index 0000000000..7ea407f75e --- /dev/null +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectMapBuilderBase.java @@ -0,0 +1,27 @@ +/* + * 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.utils.builder; + +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nonnull; + +public abstract class ObjectMapBuilderBase< + K, + V, + VBuilder extends ObjectBuilder, + Builder extends ObjectMapBuilderBase> extends MapBuilderBase { + protected ObjectMapBuilderBase() {} + + protected abstract @Nonnull VBuilder valueBuilder(); + + public final @Nonnull Builder with(@Nonnull K key, @Nonnull Function> fn) { + return with(key, Objects.requireNonNull(fn, "fn must not be null").apply(valueBuilder()).build()); + } +} diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectSetBuilderBase.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectSetBuilderBase.java new file mode 100644 index 0000000000..5cb8623a1e --- /dev/null +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/ObjectSetBuilderBase.java @@ -0,0 +1,24 @@ +/* + * 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.utils.builder; + +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nonnull; + +public abstract class ObjectSetBuilderBase, Builder extends ObjectSetBuilderBase> + extends SetBuilderBase { + protected ObjectSetBuilderBase() {} + + protected abstract @Nonnull VBuilder valueBuilder(); + + public final @Nonnull Builder with(@Nonnull Function> fn) { + return with(Objects.requireNonNull(fn, "fn must not be null").apply(valueBuilder()).build()); + } +} diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/SetBuilder.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/SetBuilder.java new file mode 100644 index 0000000000..3841dfcfdd --- /dev/null +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/SetBuilder.java @@ -0,0 +1,13 @@ +/* + * 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.utils.builder; + +public final class SetBuilder extends SetBuilderBase> { + public SetBuilder() {} +} diff --git a/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/SetBuilderBase.java b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/SetBuilderBase.java new file mode 100644 index 0000000000..4696d96ae9 --- /dev/null +++ b/java-codegen/src/main/java/org/opensearch/client/codegen/utils/builder/SetBuilderBase.java @@ -0,0 +1,36 @@ +/* + * 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.utils.builder; + +import java.util.Set; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class SetBuilderBase> extends ObjectBuilderBase, Builder> { + @Nullable + private Set set; + + protected SetBuilderBase() {} + + @Override + protected final @Nonnull Set construct() { + return _mutableSet(set); + } + + public final @Nonnull Builder with(@Nonnull Set set) { + this.set = _setAddAll(this.set, set); + return self(); + } + + @SafeVarargs + public final @Nonnull Builder with(@Nonnull V value, @Nonnull V... values) { + this.set = _setAdd(this.set, value, values); + return self(); + } +} diff --git a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/DictionaryResponseShape.mustache b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/DictionaryResponseShape.mustache new file mode 100644 index 0000000000..b04a2eb119 --- /dev/null +++ b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/DictionaryResponseShape.mustache @@ -0,0 +1,32 @@ +{{>Partials/ClassDeclaration}} { + // --------------------------------------------------------------------------------------------- + + {{>ObjectShape/Constructor}} + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link {{className}}}. + */ + public static class Builder extends {{extendsType.name}}.AbstractBuilder<{{keyType}}, {{valueType}}, Builder> + implements {{TYPES.Client.Util.ObjectBuilder}}<{{className}}> { + {{>ObjectShape/Builder/SelfImpl}} + + /** + * Builds a {@link {{className}}}. + * + * @throws NullPointerException if some of the required fields are null. + */ + public {{className}} build() { + _checkSingleUse(); + super.tKeySerializer(null); + super.tValueSerializer(null); + + return new {{className}}(this); + } + } + + // --------------------------------------------------------------------------------------------- + + {{>ObjectShape/Deserialize}} +} \ No newline at end of file diff --git a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/EnumShape.mustache b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/EnumShape.mustache index a9a14284f0..719c40ba20 100644 --- a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/EnumShape.mustache +++ b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/EnumShape.mustache @@ -6,16 +6,28 @@ {{#deprecated}} @Deprecated {{/deprecated}} - {{name}}({{#quoted}}{{wireName}}{{/quoted}}){{#-last}};{{/-last}}{{^-last}},{{/-last}} + {{name}}({{#quoted}}{{wireName}}{{/quoted}}{{#aliases}}, {{#quoted}}{{.}}{{/quoted}}{{/aliases}}){{#-last}};{{/-last}}{{^-last}},{{/-last}} {{/variants}} private final String jsonValue; +{{#anyHasAliases}} + private final String[] aliases; +{{/anyHasAliases}} - {{className}}(String jsonValue) { + {{className}}(String jsonValue{{#anyHasAliases}}, String... aliases{{/anyHasAliases}}) { this.jsonValue = jsonValue; +{{#anyHasAliases}} + this.aliases = aliases; +{{/anyHasAliases}} } public String jsonValue() { return this.jsonValue; } +{{#anyHasAliases}} + + public String[] aliases() { + return this.aliases; + } +{{/anyHasAliases}} public static final JsonEnum.Deserializer<{{className}}> _DESERIALIZER = new JsonEnum.Deserializer<>({{className}}.values()); } \ No newline at end of file diff --git a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape.mustache b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape.mustache index 0cd936e3b4..25bf01d350 100644 --- a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape.mustache +++ b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape.mustache @@ -4,7 +4,16 @@ // --------------------------------------------------------------------------------------------- {{>ObjectShape/Constructor}} - +{{#referencingDiscriminatedUnions}} + + /** + * {@link {{union.className}}} variant kind. + */ + @Override + public {{union.type}}.Kind _{{#camelCase}}{{union.className}}{{/camelCase}}Kind() { + return {{union.type}}.Kind.{{#pascalCase}}{{discriminatorValue}}{{/pascalCase}}; + } +{{/referencingDiscriminatedUnions}} {{>ObjectShape/Getters}} {{#hasFieldsToSerialize}} diff --git a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape/Builder.mustache b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape/Builder.mustache index b3ab0f1355..f9a8abeeaa 100644 --- a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape/Builder.mustache +++ b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape/Builder.mustache @@ -5,10 +5,10 @@ {{#extendsOtherShape}} public static class Builder extends {{extendsType}}.AbstractBuilder implements {{TYPES.Client.Util.ObjectBuilder}}<{{className}}> { - {{>ObjectShape/Builder/SelfImpl}} - {{>ObjectShape/Builder/Fields}} + {{>ObjectShape/Builder/SelfImpl}} + {{>ObjectShape/Builder/BuildImpl}} } {{/extendsOtherShape}} @@ -35,7 +35,9 @@ protected abstract static class AbstractBuilder> extends {{#extendsOtherShape}}{{extendsType}}.AbstractBuilder{{/extendsOtherShape}}{{^extendsOtherShape}}{{TYPES.Client.Util.ObjectBuilderBase}}{{/extendsOtherShape}} { {{>ObjectShape/Builder/Fields}} + {{^extendsOtherShape}} protected abstract BuilderT self(); + {{/extendsOtherShape}} } {{/extendedByOtherShape}} \ No newline at end of file diff --git a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape/Deserialize.mustache b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape/Deserialize.mustache index 4496a97a93..ddb9adaddc 100644 --- a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape/Deserialize.mustache +++ b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape/Deserialize.mustache @@ -12,10 +12,10 @@ protected static > void setup{{className}}Deserializer({{TYPES.Client.Json.ObjectDeserializer}} op) { {{/extendedByOtherShape}} {{#extendsOtherShape}} - {{extendsType}}.setup{{extendsType.name}}Deserializer(op); + setup{{extendsType.name}}Deserializer(op{{#extendsType.typeParams}}, {{>Type/deserializer}}{{/extendsType.typeParams}}); {{/extendsOtherShape}} {{#bodyFields}} - op.add({{#extendedByOtherShape}}Abstract{{/extendedByOtherShape}}Builder::{{name}}, {{#type}}{{>Type/deserializer}}{{/type}}, {{#quoted}}{{wireName}}{{/quoted}}); + op.add({{#extendedByOtherShape}}Abstract{{/extendedByOtherShape}}Builder::{{name}}, {{#type}}{{>Type/deserializer}}{{/type}}, {{#quoted}}{{wireName}}{{/quoted}}{{#aliases}}, {{#quoted}}{{.}}{{/quoted}}{{/aliases}}); {{/bodyFields}} {{#additionalPropertiesField}} op.setUnknownFieldHandler((builder, name, parser, mapper) -> { @@ -25,4 +25,8 @@ builder.{{name}}.put(name, {{#type.mapValueType}}{{>Type/deserializer}}{{/type.mapValueType}}.deserialize(parser, mapper)); }); {{/additionalPropertiesField}} + {{#distinctDiscriminatorFieldValues}} + + op.ignore({{#quoted}}{{key}}{{/quoted}}); + {{/distinctDiscriminatorFieldValues}} } \ No newline at end of file diff --git a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape/Equals.mustache b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape/Equals.mustache index 1670834380..b5bd3c03af 100644 --- a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape/Equals.mustache +++ b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape/Equals.mustache @@ -6,27 +6,28 @@ {{/extendsOtherShape}} if(this == o) return true; if(o == null || this.getClass() != o.getClass()) return false; - {{^hasFields}} - return true; - {{/hasFields}} - {{#hasFields}} + {{#fields}} + {{#-first}} {{className}} other = ({{className}})o; return - {{#fields}} - {{#required}} - {{#type.isPrimitive}} - this.{{name}} == other.{{name}} - {{/type.isPrimitive}} - {{^type.isPrimitive}} - this.{{name}}.equals(other.{{name}}) - {{/type.isPrimitive}} - {{/required}} - {{^required}} - {{TYPES.Java.Util.Objects}}.equals(this.{{name}}, other.{{name}}) - {{/required}} - {{^-last}} - && - {{/-last}} - {{/fields}}; - {{/hasFields}} + {{/-first}} + {{^-first}} + && + {{/-first}} + {{#required}} + {{#type.isPrimitive}} + this.{{name}} == other.{{name}} + {{/type.isPrimitive}} + {{^type.isPrimitive}} + this.{{name}}.equals(other.{{name}}) + {{/type.isPrimitive}} + {{/required}} + {{^required}} + {{TYPES.Java.Util.Objects}}.equals(this.{{name}}, other.{{name}}) + {{/required}} + {{/fields}} + {{^fields}} + return true + {{/fields}} + ; } diff --git a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape/Serialize.mustache b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape/Serialize.mustache index e40f75049e..130c94bcec 100644 --- a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape/Serialize.mustache +++ b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/ObjectShape/Serialize.mustache @@ -11,6 +11,9 @@ {{/extendsOtherShape}} protected void serializeInternal({{TYPES.Jakarta.Json.Stream.JsonGenerator}} generator, {{TYPES.Client.Json.JsonpMapper}} mapper) { +{{#distinctDiscriminatorFieldValues}} + generator.write({{#quoted}}{{key}}{{/quoted}}, {{#quoted}}{{value}}{{/quoted}}); +{{/distinctDiscriminatorFieldValues}} {{#extendsOtherShape}} super.serializeInternal(generator, mapper); {{/extendsOtherShape}} diff --git a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/TaggedUnionShape.mustache b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/TaggedUnionShape.mustache index 8a584d6812..fd51d4d80a 100644 --- a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/TaggedUnionShape.mustache +++ b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/TaggedUnionShape.mustache @@ -1,10 +1,26 @@ {{>Partials/ClassDeclaration}} { - public enum Kind { - {{#variants}}{{#pascalCase}}{{name}}{{/pascalCase}}{{^-last}},{{/-last}}{{/variants}} + /** + * {@link {{className}}} variant kinds. + */ + public enum Kind{{#discriminated}} implements {{TYPES.Client.Json.JsonEnum}}{{/discriminated}} { + {{#variants}}{{#pascalCase}}{{name}}{{/pascalCase}}{{#discriminated}}({{#quoted}}{{name}}{{/quoted}}){{/discriminated}}{{^-last}},{{/-last}}{{/variants}} + {{#discriminated}}; + + private final String jsonValue; + + Kind(String jsonValue) { + this.jsonValue = jsonValue; + } + + @Override + public String jsonValue() { + return jsonValue; + } + {{/discriminated}} } private final Kind _kind; - private final Object _value; + private final {{variantBaseType}} _value; @Override public final Kind _kind() { @@ -12,14 +28,22 @@ } @Override - public final Object _get() { + public final {{variantBaseType}} _get() { return _value; } +{{#discriminated}} + public {{className}}({{variantBaseType}} value) { + this._kind = {{TYPES.Client.Util.ApiTypeHelper}}.requireNonNull(value._{{#camelCase}}{{className}}{{/camelCase}}Kind(), this, ""); + this._value = {{TYPES.Client.Util.ApiTypeHelper}}.requireNonNull(value, this, ""); + } +{{/discriminated}} +{{^discriminated}} private {{className}}(Kind kind, Object value) { this._kind = kind; this._value = value; } +{{/discriminated}} private {{className}}(Builder builder) { this._kind = {{TYPES.Client.Util.ApiTypeHelper}}.requireNonNull(builder._kind, builder, ""); @@ -30,7 +54,7 @@ return fn.apply(new Builder()).build(); } -{{#false}} +{{#canStringify}} public String _toJsonString() { switch (_kind) { {{#variants}} @@ -42,7 +66,7 @@ } } -{{/false}} +{{/canStringify}} {{#variants}} /** * Is this variant instance of kind {@code {{name}}}? @@ -56,7 +80,7 @@ * * @throws IllegalStateException if the current variant is not the {@code {{name}}} kind. */ - public {{type}} {{#camelCase}}{{name}}{{/camelCase}}() { + public {{type}} {{#asFieldName}}{{name}}{{/asFieldName}}() { return {{TYPES.Client.Util.TaggedUnionUtils}}.get(this, Kind.{{#pascalCase}}{{name}}{{/pascalCase}}); } @@ -64,9 +88,13 @@ @Override public void serialize({{TYPES.Jakarta.Json.Stream.JsonGenerator}} generator, {{TYPES.Client.Json.JsonpMapper}} mapper) { + {{#discriminated}} + mapper.serialize(_value, generator); + {{/discriminated}} + {{^discriminated}} if (_value instanceof {{TYPES.Client.Json.JsonpSerializable}}) { (({{TYPES.Client.Json.JsonpSerializable}}) _value).serialize(generator, mapper); - }{{#primitiveVariants}}{{#-first}} else { + }{{#nonShapeVariants}}{{#-first}} else { switch (_kind) { {{/-first}} case {{#pascalCase}}{{name}}{{/pascalCase}}: @@ -76,23 +104,24 @@ } } {{/-last}} - {{/primitiveVariants}} + {{/nonShapeVariants}} + {{/discriminated}} } public static class Builder extends {{TYPES.Client.Util.ObjectBuilderBase}} implements {{TYPES.Client.Util.ObjectBuilder}}<{{className}}> { private Kind _kind; - private Object _value; + private {{variantBaseType}} _value; {{#variants}} - public {{TYPES.Client.Util.ObjectBuilder}}<{{className}}> {{#camelCase}}{{name}}{{/camelCase}}({{type}} v) { + public {{TYPES.Client.Util.ObjectBuilder}}<{{className}}> {{#asFieldName}}{{name}}{{/asFieldName}}({{type}} v) { this._kind = Kind.{{#pascalCase}}{{name}}{{/pascalCase}}; this._value = v; return this; } {{#type.hasBuilder}} - public {{TYPES.Client.Util.ObjectBuilder}}<{{className}}> {{#camelCase}}{{name}}{{/camelCase}}({{type.builderFnType}} fn) { - return this.{{#camelCase}}{{name}}{{/camelCase}}(fn.apply(new {{type.builderType}}()).build()); + public {{TYPES.Client.Util.ObjectBuilder}}<{{className}}> {{#asFieldName}}{{name}}{{/asFieldName}}({{type.builderFnType}} fn) { + return this.{{#asFieldName}}{{name}}{{/asFieldName}}(fn.apply(new {{type.builderType}}()).build()); } {{/type.hasBuilder}} @@ -104,13 +133,26 @@ } } +{{#discriminated}} + protected static void setup{{className}}Deserializer({{TYPES.Client.Json.ObjectDeserializer}} op) { + {{#variants}} + op.add(Builder::{{#asFieldName}}{{name}}{{/asFieldName}}, {{type}}._DESERIALIZER, {{#quoted}}{{name}}{{/quoted}}); + {{/variants}} + + op.setTypeProperty({{#quoted}}{{discriminatingField}}{{/quoted}}, {{#defaultVariant}}Kind.{{#pascalCase}}{{name}}{{/pascalCase}}.jsonValue(){{/defaultVariant}}{{^defaultVariant}}null{{/defaultVariant}}); + } + + public static final {{TYPES.Client.Json.JsonpDeserializer}}<{{className}}> _DESERIALIZER = {{TYPES.Client.Json.ObjectBuilderDeserializer}}.lazy(Builder::new, {{className}}::setup{{className}}Deserializer, Builder::build); +{{/discriminated}} +{{^discriminated}} private static {{TYPES.Client.Json.JsonpDeserializer}}<{{className}}> build{{className}}Deserializer() { - return new {{TYPES.Client.Json.UnionDeserializer.builderType}}<{{className}}, Kind, Object>({{className}}::new, false) + return new {{TYPES.Client.Json.UnionDeserializer.builderType}}<{{className}}, Kind, Object>({{className}}::new, {{canStringify}}) {{#variants}}.addMember(Kind.{{#pascalCase}}{{name}}{{/pascalCase}}, {{#type}}{{>Type/deserializer}}{{/type}}){{/variants}} .build(); } public static final {{TYPES.Client.Json.JsonpDeserializer}}<{{className}}> _DESERIALIZER = {{TYPES.Client.Json.JsonpDeserializer}}.lazy({{className}}::build{{className}}Deserializer); +{{/discriminated}} {{>TaggedUnionShape/HashCode}} diff --git a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/TaggedUnionShape/Builders.mustache b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/TaggedUnionShape/Builders.mustache new file mode 100644 index 0000000000..2e0fda8676 --- /dev/null +++ b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/TaggedUnionShape/Builders.mustache @@ -0,0 +1,12 @@ +{{>Partials/ClassDeclaration}} { + private {{className}}() {} + +{{#variants}} + /** + * Creates a builder for the {@link {{type.name}} {{name}}} {@code {{unionClassName}}} variant. + */ + public static {{type.builderType}} {{#asFieldName}}{{name}}{{/asFieldName}}() { + return new {{type.builderType}}(); + } +{{/variants}} +} diff --git a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/TaggedUnionShape/VariantInterface.mustache b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/TaggedUnionShape/VariantInterface.mustache new file mode 100644 index 0000000000..bc0bdcbd6d --- /dev/null +++ b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/TaggedUnionShape/VariantInterface.mustache @@ -0,0 +1,7 @@ +{{>Partials/ClassDeclaration}} { + {{unionClassName}}.Kind _{{#camelCase}}{{unionClassName}}{{/camelCase}}Kind(); + + default {{unionClassName}} _to{{unionClassName}}() { + return new {{unionClassName}}(this); + } +} diff --git a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/Type/directSerializer.mustache b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/Type/directSerializer.mustache index 34f4345fca..f0768a1e03 100644 --- a/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/Type/directSerializer.mustache +++ b/java-codegen/src/main/resources/org/opensearch/client/codegen/templates/Type/directSerializer.mustache @@ -1,7 +1,16 @@ {{#type.isMap}} for ({{type.mapEntryType}} item{{depth}} : {{value}}.entrySet()) { generator.writeKey(item{{depth}}.getKey()); - {{#type.mapValueType.serializer}}item{{depth}}.getValue(){{/type.mapValueType.serializer}} + {{#type.mapValueType.isList}} + generator.writeStartArray(); + if (item{{depth}}.getValue() != null) { + {{#type.mapValueType.directSerializer}}item{{depth}}.getValue(){{/type.mapValueType.directSerializer}} + } + generator.writeEnd(); + {{/type.mapValueType.isList}} + {{^type.mapValueType.isList}} + {{#type.mapValueType.serializer}}item{{depth}}.getValue(){{/type.mapValueType.serializer}} + {{/type.mapValueType.isList}} } {{/type.isMap}} {{#type.isList}}