diff --git a/java-client/src/main/java/org/opensearch/client/opensearch/OpenSearchHttpClient.java b/java-client/src/main/java/org/opensearch/client/opensearch/OpenSearchHttpClient.java index 5b45ae4425..4bad839de1 100644 --- a/java-client/src/main/java/org/opensearch/client/opensearch/OpenSearchHttpClient.java +++ b/java-client/src/main/java/org/opensearch/client/opensearch/OpenSearchHttpClient.java @@ -19,7 +19,6 @@ import org.opensearch.client.opensearch._types.OpenSearchException; import org.opensearch.client.opensearch.request.GetHttpRequest; import org.opensearch.client.transport.Endpoint; -import org.opensearch.client.transport.JsonEndpoint; import org.opensearch.client.transport.OpenSearchTransport; import org.opensearch.client.transport.TransportOptions; import org.opensearch.client.util.ObjectBuilder; diff --git a/java-client/src/main/java/org/opensearch/client/opensearch/request/PutHttpRequest.java b/java-client/src/main/java/org/opensearch/client/opensearch/request/PutHttpRequest.java new file mode 100644 index 0000000000..d49abc9a97 --- /dev/null +++ b/java-client/src/main/java/org/opensearch/client/opensearch/request/PutHttpRequest.java @@ -0,0 +1,145 @@ +/* + * 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.opensearch.request; + +import java.util.Map; +import java.util.function.Function; + +import javax.annotation.Nullable; + +import org.opensearch.client.Response; +import org.opensearch.client.json.JsonpMapper; +import org.opensearch.client.json.JsonpSerializable; +import org.opensearch.client.json.JsonpSerializer; +import org.opensearch.client.json.JsonpUtils; +import org.opensearch.client.opensearch._types.ErrorResponse; +import org.opensearch.client.opensearch._types.RequestBase; +import org.opensearch.client.transport.Endpoint; +import org.opensearch.client.transport.endpoints.SimpleEndpoint; +import org.opensearch.client.util.ApiTypeHelper; +import org.opensearch.client.util.ObjectBuilder; +import org.opensearch.client.util.ObjectBuilderBase; + +import jakarta.json.stream.JsonGenerator; + +public class PutHttpRequest extends RequestBase implements JsonpSerializable { + + private final String path; + private final Map queryParams; + private final Map headers; + + private final TDocument document; + + @Nullable + private final JsonpSerializer tDocumentSerializer; + + private PutHttpRequest(Builder builder) { + this.path = ApiTypeHelper.requireNonNull(builder.path, this, "path"); + this.queryParams = ApiTypeHelper.unmodifiable(builder.queryParams); + this.headers = ApiTypeHelper.unmodifiable(builder.headers); + this.document = ApiTypeHelper.requireNonNull(builder.document, this, "document"); + this.tDocumentSerializer = builder.tDocumentSerializer; + } + + public static PutHttpRequest of( + Function, ObjectBuilder>> fn) { + return fn.apply(new Builder<>()).build(); + } + + public final String path() { + return this.path; + } + + public final Map queryParams() { + return this.queryParams; + } + + public final Map headers() { + return this.headers; + } + + public final TDocument document() { + return this.document; + } + + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + JsonpUtils.serialize(this.document, generator, tDocumentSerializer, mapper); + + } + + public static class Builder extends ObjectBuilderBase + implements ObjectBuilder> { + private String path; + private Map queryParams; + private Map headers; + + private TDocument document; + + @Nullable + private JsonpSerializer tDocumentSerializer; + + public final Builder path(String path) { + this.path = path; + return this; + } + + public final Builder queryParams(String key, String value) { + this.queryParams = _mapPut(this.queryParams, key, value); + return this; + } + + public final Builder headers(String key, String value) { + this.headers = _mapPut(this.headers, key, value); + return this; + } + + public final Builder queryParams(Map queryParams) { + this.queryParams = _mapPutAll(this.queryParams, queryParams); + return this; + } + + public final Builder headers(Map headers) { + this.headers = _mapPutAll(this.headers, headers); + return this; + } + + public final Builder document(TDocument value) { + this.document = value; + return this; + } + + public final Builder tDocumentSerializer(@Nullable JsonpSerializer value) { + this.tDocumentSerializer = value; + return this; + } + + public PutHttpRequest build() { + _checkSingleUse(); + + return new PutHttpRequest(this); + } + } + + public static final Endpoint, Response, ErrorResponse> _ENDPOINT = new SimpleEndpoint<>( + + // Request method + request -> { + return "PUT"; + + }, request -> { + return request.path; + + }, request -> { + return request.queryParams; + + }, request -> { + return request.headers; + + }, true, null); +} diff --git a/java-client/src/main/java/org/opensearch/client/transport/endpoints/GenericEndpoint.java b/java-client/src/main/java/org/opensearch/client/transport/endpoints/GenericEndpoint.java new file mode 100644 index 0000000000..651c50e8a4 --- /dev/null +++ b/java-client/src/main/java/org/opensearch/client/transport/endpoints/GenericEndpoint.java @@ -0,0 +1,112 @@ +/* + * 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. + */ + +/* + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.client.transport.endpoints; + +import java.util.Collections; +import java.util.Map; +import java.util.function.Function; + +import org.apache.hc.core5.net.URLEncodedUtils; +import org.opensearch.client.json.JsonpDeserializer; +import org.opensearch.client.opensearch._types.ErrorResponse; + +public class GenericEndpoint { + + private static final Function> EMPTY_MAP = x -> Collections.emptyMap(); + + /** + * Returns a function that always returns an empty String to String map. Useful + * to avoid creating lots of + * duplicate lambdas in endpoints that don't have headers or parameters. + */ + @SuppressWarnings("unchecked") + public static Function> emptyMap() { + return (Function>) EMPTY_MAP; + } + + private final Function method; + private final Function requestUrl; + private final Function> queryParameters; + private final Function> headers; + private final Function hasRequestBody; + private final JsonpDeserializer responseParser; + + public GenericEndpoint( + Function method, + Function requestUrl, + Function> queryParameters, + Function> headers, + Function hasRequestBody, + JsonpDeserializer responseParser) { + this.method = method; + this.requestUrl = requestUrl; + this.queryParameters = queryParameters; + this.headers = headers; + this.hasRequestBody = hasRequestBody; + this.responseParser = responseParser; + } + + public String method(RequestT request) { + return this.method.apply(request); + } + + public String requestUrl(RequestT request) { + return this.requestUrl.apply(request); + } + + public Map queryParameters(RequestT request) { + return this.queryParameters.apply(request); + } + + public Map headers(RequestT request) { + return this.headers.apply(request); + } + + public boolean hasRequestBody(RequestT request) { + return this.hasRequestBody.apply(request); + } + + public JsonpDeserializer responseDeserializer() { + return this.responseParser; + } + + public boolean isError(int statusCode) { + return statusCode >= 400; + } + + public JsonpDeserializer errorDeserializer(int statusCode) { + return ErrorResponse._DESERIALIZER; + } + + public GenericEndpoint withResponseDeserializer( + JsonpDeserializer newResponseParser) { + return new GenericEndpoint<>( + method, + requestUrl, + queryParameters, + headers, + hasRequestBody, + newResponseParser); + } + + public static RuntimeException noPathTemplateFound(String what) { + return new RuntimeException("Could not find a request " + what + " with this set of properties. " + + "Please check the API documentation, or raise an issue if this should be a valid request."); + } + + public static void pathEncode(String src, StringBuilder dest) { + // TODO: avoid dependency on HttpClient here (and use something more efficient) + dest.append(URLEncodedUtils.formatSegments(src).substring(1)); + } +}