From d2b31105de153a9c849f8485222751e02d041ae6 Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Mon, 10 Mar 2025 15:34:29 +0100 Subject: [PATCH 01/38] new transport --- java-client/build.gradle.kts | 13 +- .../builders/ElasticsearchClientBuilder.java | 124 +++++++++++ .../transport/DefaultTransportOptions.java | 6 + .../clients/transport/TransportOptions.java | 2 + .../rest_client/MultiBufferEntity.java | 52 +++-- .../rest_client/RestClientHttpClient.java | 24 +- .../rest_client/RestClientOptions.java | 11 +- .../rest_client/SafeResponseConsumer.java | 132 ----------- .../documentation/DocTestsTransport.java | 5 + .../getting_started/ConnectingTest.java | 30 +-- .../getting_started/MigrateHlrcTest.java | 74 ------- .../ElasticsearchTestServer.java | 35 +-- .../_helpers/builders/ClientBuilderTest.java | 38 ++++ .../esql/EsqlAdapterEndToEndTest.java | 5 +- .../clients/transport/RequestOptionsTest.java | 17 +- .../clients/transport/TransportTest.java | 16 +- .../clients/transport/TransportUtilsTest.java | 26 +-- .../endpoints/BinaryEndpointTest.java | 4 +- .../OpenTelemetryForElasticsearchTest.java | 2 +- .../rest_client/MultiBufferEntityTest.java | 2 +- .../rest_client/RestClientOptionsTest.java | 12 +- .../rest_client/SafeResponseConsumerTest.java | 206 ------------------ 22 files changed, 307 insertions(+), 529 deletions(-) create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java delete mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest_client/SafeResponseConsumer.java delete mode 100644 java-client/src/test/java/co/elastic/clients/documentation/getting_started/MigrateHlrcTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuilderTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest_client/SafeResponseConsumerTest.java diff --git a/java-client/build.gradle.kts b/java-client/build.gradle.kts index e8634354c..c43cf7a95 100644 --- a/java-client/build.gradle.kts +++ b/java-client/build.gradle.kts @@ -38,8 +38,8 @@ checkstyle { } java { - targetCompatibility = JavaVersion.VERSION_1_8 - sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_17 withJavadocJar() withSourcesJar() @@ -200,13 +200,14 @@ signing { dependencies { // Compile and test with the last 7.x version to make sure transition scenarios where // the Java API client coexists with a 7.x HLRC work fine - val elasticsearchVersion = "8.10.0" val jacksonVersion = "2.17.0" val openTelemetryVersion = "1.29.0" - // Apache 2.0 - // https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-low.html - api("org.elasticsearch.client", "elasticsearch-rest-client", elasticsearchVersion) + // build the low level repo + implementation("co.elastic.lowclient", "low-level-java-client", "9.0.0") + // temporary, should eventually get these two from low level (something something gradle doesn't do transitive dep. from local) + api("commons-logging", "commons-logging", "1.3.3") + api("org.apache.httpcomponents.client5", "httpclient5", "5.4") // Apache 2.0 // https://search.maven.org/artifact/com.google.code.findbugs/jsr305 diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java new file mode 100644 index 000000000..3ed4b121b --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java @@ -0,0 +1,124 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch._helpers.builders; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.message.BasicHeader; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; + +import javax.net.ssl.SSLContext; +import java.net.URISyntaxException; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.Optional; + +// TODO do we want separate builder subclasses to make sure that only 1 auth method has been provided? +public class ElasticsearchClientBuilder { + + private HttpHost host; + private String username; + private String password; + private String token; + private String apiKey; + private SSLContext sslContext; + private JsonpMapper mapper; + + public ElasticsearchClientBuilder withHost(String url) throws URISyntaxException { + this.host = HttpHost.create(url); + return this; + } + + public ElasticsearchClientBuilder withUsernameAndPassword(String username, String password) { + this.username = username; + this.password = password; + return this; + } + + public ElasticsearchClientBuilder withToken(String token) { + this.token = token; + return this; + } + + public ElasticsearchClientBuilder withApiKey(String apiKey) { + this.apiKey = apiKey; + return this; + } + + public ElasticsearchClientBuilder withSslContext(SSLContext sslContext) { + this.sslContext = sslContext; + return this; + } + + public ElasticsearchClientBuilder withMapper(JsonpMapper mapper) { + this.mapper = mapper; + return this; + } + + public ElasticsearchClient build() { + + // defaulting to localhost + if (this.host == null) { + try { + this.host = HttpHost.create("http://localhost:9200"); + } catch (URISyntaxException e) { + // can't throw + } + } + + RestClientBuilder restClientBuilder = RestClient.builder(host); + + if (this.username != null && this.password != null) { + var cred = Base64.getEncoder().encodeToString((username + ":" + password).getBytes()); + restClientBuilder.setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Basic " + cred) + }); + } else if (this.apiKey != null) { + restClientBuilder.setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "ApiKey " + apiKey) + }); + } else if (this.token != null) { + restClientBuilder.setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Bearer " + token) + }); + } + + try { + restClientBuilder.setSslContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + + if (this.mapper == null) { + ObjectMapper mapper = JsonMapper.builder().build(); + this.mapper = new JacksonJsonpMapper(mapper); + } + + RestClientTransport transport = new RestClientTransport(restClientBuilder.build(), mapper); + return new ElasticsearchClient(transport); + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/DefaultTransportOptions.java b/java-client/src/main/java/co/elastic/clients/transport/DefaultTransportOptions.java index cdc35639e..9714b863c 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/DefaultTransportOptions.java +++ b/java-client/src/main/java/co/elastic/clients/transport/DefaultTransportOptions.java @@ -100,6 +100,12 @@ public Function, Boolean> onWarnings() { return onWarnings; } + @Override + public void updateToken(String token) { + this.headers.put("Authorization", "Bearer " + token); + } + + @Override public boolean keepResponseBodyOnException() { return keepResponseBodyOnException; diff --git a/java-client/src/main/java/co/elastic/clients/transport/TransportOptions.java b/java-client/src/main/java/co/elastic/clients/transport/TransportOptions.java index 9cbbdd40d..f5603b9b3 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/TransportOptions.java +++ b/java-client/src/main/java/co/elastic/clients/transport/TransportOptions.java @@ -38,6 +38,8 @@ public interface TransportOptions { Function, Boolean> onWarnings(); + void updateToken(String token); + /** * If {@code true}, the response body in {@code TransportException.response().body()} is guaranteed to be * replayable (i.e. buffered), even if the original response was streamed. This allows inspecting the diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java index f1a8e81db..836761a37 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java @@ -20,11 +20,14 @@ package co.elastic.clients.transport.rest_client; import co.elastic.clients.util.NoCopyByteArrayOutputStream; -import org.apache.http.entity.AbstractHttpEntity; -import org.apache.http.entity.ContentType; -import org.apache.http.nio.ContentEncoder; -import org.apache.http.nio.IOControl; -import org.apache.http.nio.entity.HttpAsyncContentProducer; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpException; +import org.apache.hc.core5.http.io.entity.AbstractHttpEntity; +import org.apache.hc.core5.http.nio.AsyncRequestProducer; +import org.apache.hc.core5.http.nio.DataStreamChannel; +import org.apache.hc.core5.http.nio.RequestChannel; +import org.apache.hc.core5.http.protocol.HttpContext; + import java.io.IOException; import java.io.InputStream; @@ -37,7 +40,7 @@ /** * An HTTP entity based on a sequence of byte buffers. */ -class MultiBufferEntity extends AbstractHttpEntity implements HttpAsyncContentProducer { +class MultiBufferEntity extends AbstractHttpEntity implements AsyncRequestProducer { private final Iterable buffers; @@ -45,11 +48,9 @@ class MultiBufferEntity extends AbstractHttpEntity implements HttpAsyncContentPr private volatile ByteBuffer currentBuffer; MultiBufferEntity(Iterable buffers, ContentType contentType) { + //TODO where to find contentEncoding? + super(contentType.toString(),null, true); this.buffers = buffers; - setChunked(true); - if (contentType != null) { - setContentType(contentType.toString()); - } init(); } @@ -68,11 +69,22 @@ private void init() { } } + @Override + public void sendRequest(RequestChannel channel, HttpContext context) throws HttpException, IOException { + //TODO looks the same as produce? check which one is actually called + System.out.println("s"); + } + @Override public boolean isRepeatable() { return true; } + @Override + public void failed(Exception cause) { + + } + @Override public long getContentLength() { // Use chunked encoding @@ -100,21 +112,33 @@ public void writeTo(OutputStream out) throws IOException { } @Override - public void produceContent(ContentEncoder encoder, IOControl ioControl) throws IOException { + public int available() { + return currentBuffer.remaining(); + } + + @Override + public void produce(DataStreamChannel channel) throws IOException { + //TODO really not sure + if (currentBuffer == null) { - encoder.complete(); + channel.endStream(); return; } - encoder.write(currentBuffer); + channel.write(currentBuffer); if (!currentBuffer.hasRemaining()) { if (iterator.hasNext()) { currentBuffer = iterator.next().duplicate(); } else { currentBuffer = null; - encoder.complete(); + channel.endStream(); } } } + + @Override + public void releaseResources() { + //TODO probably clear buffers + } } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java index 1bcc06b05..ba46f55cd 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java @@ -24,11 +24,12 @@ import co.elastic.clients.transport.http.TransportHttpClient; import co.elastic.clients.util.BinaryData; import co.elastic.clients.util.NoCopyByteArrayOutputStream; -import org.apache.http.Header; -import org.apache.http.HeaderElement; -import org.apache.http.HttpEntity; -import org.apache.http.entity.ContentType; -import org.apache.http.util.EntityUtils; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HeaderElement; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.message.BasicHeaderValueParser; import org.elasticsearch.client.Cancellable; import org.elasticsearch.client.ResponseListener; import org.elasticsearch.client.RestClient; @@ -173,8 +174,6 @@ private org.elasticsearch.client.Request createRestRequest(Request request, Rest clientReq.setEntity(new MultiBufferEntity(body, ct)); } - // Request parameter intercepted by LLRC - clientReq.addParameter("ignore", "400,401,403,404,405"); return clientReq; } @@ -192,7 +191,7 @@ public Node node() { @Override public int statusCode() { - return restResponse.getStatusLine().getStatusCode(); + return restResponse.getStatusCode(); } @Override @@ -206,8 +205,9 @@ public List headers(String name) { for (int i = 0; i < headers.length; i++) { Header header = headers[i]; if (header.getName().equalsIgnoreCase(name)) { - HeaderElement[] elements = header.getElements(); - return new AbstractList() { + BasicHeaderValueParser elementParser = new BasicHeaderValueParser(); + HeaderElement[] elements = elementParser.parseElements(header.getValue(), null); + return new AbstractList<>() { @Override public String get(int index) { return elements[index].getValue(); @@ -251,8 +251,8 @@ private static class HttpEntityBinaryData implements BinaryData { @Override public String contentType() { - Header h = entity.getContentType(); - return h == null ? "application/octet-stream" : h.getValue(); + String h = entity.getContentType(); + return h == null ? "application/octet-stream" : h; } @Override diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java index 842a45c62..3824a2655 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java @@ -24,8 +24,8 @@ import co.elastic.clients.transport.http.HeaderMap; import co.elastic.clients.util.LanguageRuntimeVersions; import co.elastic.clients.util.VisibleForTesting; -import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; -import org.apache.http.util.VersionInfo; +import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; +import org.apache.hc.core5.util.VersionInfo; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.WarningsHandler; @@ -102,6 +102,11 @@ public Function, Boolean> onWarnings() { return warnings -> options.getWarningsHandler().warningsShouldFailRequest(warnings); } + @Override + public void updateToken(String token) { + options.updateToken(token); + } + @Override public boolean keepResponseBodyOnException() { return this.keepResponseBodyOnException; @@ -204,7 +209,7 @@ public RestClientOptions build() { } static RestClientOptions initialOptions() { - return new RestClientOptions(SafeResponseConsumer.DEFAULT_REQUEST_OPTIONS, false); + return new RestClientOptions(RequestOptions.DEFAULT, false); } private static RequestOptions.Builder addBuiltinHeaders(RequestOptions.Builder builder) { diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/SafeResponseConsumer.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/SafeResponseConsumer.java deleted file mode 100644 index b0cab714c..000000000 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/SafeResponseConsumer.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport.rest_client; - -import org.apache.http.HttpException; -import org.apache.http.HttpResponse; -import org.apache.http.nio.ContentDecoder; -import org.apache.http.nio.IOControl; -import org.apache.http.nio.protocol.HttpAsyncResponseConsumer; -import org.apache.http.protocol.HttpContext; -import org.elasticsearch.client.HttpAsyncResponseConsumerFactory; -import org.elasticsearch.client.RequestOptions; - -import java.io.IOException; - -/** - * A response consumer that will propagate Errors as RuntimeExceptions to avoid crashing the IOReactor. - */ -public class SafeResponseConsumer implements HttpAsyncResponseConsumer { - - private final HttpAsyncResponseConsumer delegate; - - /** - * A consumer factory that safely wraps the one provided by {@code RequestOptions.DEFAULT}. - */ - public static final HttpAsyncResponseConsumerFactory DEFAULT_FACTORY = () -> new SafeResponseConsumer<>( - RequestOptions.DEFAULT.getHttpAsyncResponseConsumerFactory().createHttpAsyncResponseConsumer() - ); - - /** - * Same as {@code RequestOptions.DEFAULT} with a safe consumer factory - */ - public static final RequestOptions DEFAULT_REQUEST_OPTIONS = RequestOptions.DEFAULT - .toBuilder() - .setHttpAsyncResponseConsumerFactory(DEFAULT_FACTORY) - .build(); - - public SafeResponseConsumer(HttpAsyncResponseConsumer delegate) { - this.delegate = delegate; - } - - @SuppressWarnings("unchecked") - private static void throwUnchecked(Throwable thr) throws T { - throw (T) thr; - } - - @Override - public void responseReceived(HttpResponse response) throws IOException, HttpException { - try { - delegate.responseReceived(response); - } catch(Exception e) { - throwUnchecked(e); - } catch(Throwable e) { - throw new RuntimeException("Error receiving response", e); - } - } - - @Override - public void consumeContent(ContentDecoder decoder, IOControl ioControl) throws IOException { - try { - delegate.consumeContent(decoder, ioControl); - } catch(Exception e) { - throwUnchecked(e); - } catch(Throwable e) { - throw new RuntimeException("Error consuming content", e); - } - } - - @Override - public void responseCompleted(HttpContext context) { - try { - delegate.responseCompleted(context); - } catch(Exception e) { - throwUnchecked(e); - } catch(Throwable e) { - throw new RuntimeException("Error completing response", e); - } - } - - @Override - public void failed(Exception ex) { - try { - delegate.failed(ex); - } catch(Exception e) { - throwUnchecked(e); - } catch(Throwable e) { - throw new RuntimeException("Error handling failure", e); - } - } - - @Override - public Exception getException() { - return delegate.getException(); - } - - @Override - public T getResult() { - return delegate.getResult(); - } - - @Override - public boolean isDone() { - return delegate.isDone(); - } - - @Override - public void close() throws IOException { - delegate.close(); - } - - @Override - public boolean cancel() { - return delegate.cancel(); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java b/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java index 6d1c41eb5..b3a6befee 100644 --- a/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java +++ b/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java @@ -64,6 +64,11 @@ public Function, Boolean> onWarnings() { return null; } + @Override + public void updateToken(String token) { + + } + @Override public boolean keepResponseBodyOnException() { return false; diff --git a/java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java b/java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java index a97a2ac8e..255fc79ff 100644 --- a/java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java +++ b/java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java @@ -17,35 +17,12 @@ * under the License. */ +//TODO rewrite package co.elastic.clients.documentation.getting_started; -import co.elastic.clients.documentation.usage.Product; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.core.search.Hit; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.TransportUtils; -import co.elastic.clients.transport.instrumentation.OpenTelemetryForElasticsearch; -import co.elastic.clients.transport.rest_client.RestClientTransport; -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.sdk.OpenTelemetrySdk; -import org.apache.http.Header; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.message.BasicHeader; -import org.elasticsearch.client.RestClient; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import javax.net.ssl.SSLContext; -import java.io.File; - public class ConnectingTest { - @Disabled // we don't have a running ES + /*@Disabled // we don't have a running ES @Test public void createClient() throws Exception { //tag::create-client @@ -208,6 +185,7 @@ AuthScope.ANY, new UsernamePasswordCredentials(login, password) //end::create-secure-client-fingerprint } - private void processProduct(Product p) {} + private void processProduct(Product p) {}*/ } + diff --git a/java-client/src/test/java/co/elastic/clients/documentation/getting_started/MigrateHlrcTest.java b/java-client/src/test/java/co/elastic/clients/documentation/getting_started/MigrateHlrcTest.java deleted file mode 100644 index e857188b7..000000000 --- a/java-client/src/test/java/co/elastic/clients/documentation/getting_started/MigrateHlrcTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.documentation.getting_started; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.rest_client.RestClientTransport; -import org.apache.http.HttpHost; -import org.elasticsearch.client.RestClient; -import org.junit.jupiter.api.Test; - -public class MigrateHlrcTest { - - // Fake HLRC -- we don't want to import it for just one example - public static class RestHighLevelClient { - } - - public static class RestHighLevelClientBuilder { - - public RestHighLevelClientBuilder(RestClient restClient) { - } - - public RestHighLevelClientBuilder setApiCompatibilityMode(Boolean enabled) { - return this; - } - - public RestHighLevelClient build() { - return new RestHighLevelClient(); - } - } - - @Test - public void migrate() { - //tag::migrate - // Create the low-level client - RestClient httpClient = RestClient.builder( - new HttpHost("localhost", 9200) - ).build(); - - // Create the HLRC - RestHighLevelClient hlrc = new RestHighLevelClientBuilder(httpClient) - .setApiCompatibilityMode(true) // <1> - .build(); - - // Create the Java API Client with the same low level client - ElasticsearchTransport transport = new RestClientTransport( - httpClient, - new JacksonJsonpMapper() - ); - - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - // hlrc and esClient share the same httpClient - //end::migrate - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java index 9fca54c03..066584f60 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java @@ -30,10 +30,9 @@ import co.elastic.clients.transport.endpoints.DelegatingJsonEndpoint; import co.elastic.clients.transport.rest_client.RestClientTransport; import org.apache.commons.io.FileUtils; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.message.BasicHeader; import org.elasticsearch.client.RestClient; import org.testcontainers.elasticsearch.ElasticsearchContainer; import org.testcontainers.images.builder.ImageFromDockerfile; @@ -51,6 +50,7 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Base64; +import java.util.Optional; public class ElasticsearchTestServer implements AutoCloseable { @@ -62,6 +62,7 @@ public class ElasticsearchTestServer implements AutoCloseable { private ElasticsearchClient client; private static ElasticsearchTestServer global; + private static final String artifactsApiUrl = "https://artifacts-api.elastic.co/v1/versions/"; public static synchronized ElasticsearchTestServer global() { @@ -103,16 +104,22 @@ public ElasticsearchTestServer(String... plugins) { } protected void setup(String url, SSLContext sslContext) { - BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); - credsProv.setCredentials( - AuthScope.ANY, new UsernamePasswordCredentials("elastic", "changeme") - ); - restClient = RestClient.builder(HttpHost.create(url)) - .setHttpClientConfigCallback(hc -> hc - .setDefaultCredentialsProvider(credsProv) - .setSSLContext(sslContext) - ) - .build(); + try { + HttpHost host = HttpHost.create(url); + + var pwd = Base64.getEncoder().encodeToString("elastic:changeme".getBytes()); + + + restClient = RestClient.builder(HttpHost.create(url)) + .setSslContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())) + .setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Basic " + pwd) + }) + //.setCompressionEnabled(true) + .build(); + } catch (Exception e) { + throw new RuntimeException(e); + } transport = new RestClientTransport(restClient, mapper); client = new ElasticsearchClient(transport); } diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuilderTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuilderTest.java new file mode 100644 index 000000000..9ea131488 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuilderTest.java @@ -0,0 +1,38 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch._helpers.builders; + +public class ClientBuilderTest { + +// @Test +// public void build() throws IOException, URISyntaxException, NoSuchAlgorithmException { +// +// // create client with helper +// ElasticsearchClient client = new ElasticsearchClientBuilder() +// .withHost("url") +// .withUsernameAndPassword("elastic", "changeme") +// .withSslContext(SSLContext.getDefault()) +// .build(); +// +// // test call (won't work) +// InfoResponse res = client.info(); +// assert res != null; +// } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java index eaa413e2b..f54caa27d 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java @@ -26,12 +26,13 @@ import co.elastic.clients.elasticsearch._helpers.esql.objects.ObjectsEsqlAdapter; import co.elastic.clients.json.jackson.JacksonJsonpMapper; import co.elastic.clients.transport.rest_client.RestClientTransport; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.io.entity.ByteArrayEntity; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; import org.apache.commons.io.IOUtils; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.entity.ContentType; + import org.elasticsearch.client.Request; import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.Assertions; diff --git a/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java b/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java index c7927f980..46e725df9 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java @@ -23,9 +23,9 @@ import co.elastic.clients.json.jsonb.JsonbJsonpMapper; import co.elastic.clients.transport.rest_client.RestClientTransport; import com.sun.net.httpserver.HttpServer; -import org.apache.http.HttpHost; -import org.apache.http.NameValuePair; -import org.apache.http.client.utils.URLEncodedUtils; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.NameValuePair; +import org.apache.hc.core5.net.URLEncodedUtils; import org.elasticsearch.client.ResponseException; import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.AfterEach; @@ -59,9 +59,9 @@ public void classSetup() throws IOException { } // Call to info() - // Send back all request headers with a 418 that will cause an exception where we can access the LLRC response + // Send back all request headers with a 501 that will cause an exception where we can access the LLRC response ex.getResponseHeaders().putAll(ex.getRequestHeaders()); - ex.sendResponseHeaders(418, 0); + ex.sendResponseHeaders(501, 0); OutputStreamWriter out = new OutputStreamWriter(ex.getResponseBody(), StandardCharsets.UTF_8); for (Map.Entry> header: ex.getRequestHeaders().entrySet()) { out.write("header-"); @@ -81,9 +81,8 @@ public void classSetup() throws IOException { }); httpServer.start(); - InetSocketAddress address = httpServer.getAddress(); - restClient = RestClient.builder(new HttpHost(address.getHostString(), address.getPort(), "http")) - .build(); + restClient = RestClient.builder(new HttpHost("http",httpServer.getAddress().getHostString(), + httpServer.getAddress().getPort())).build(); } @AfterEach @@ -94,7 +93,7 @@ public void classTearDown() throws IOException { private Properties getProps(ElasticsearchClient client) throws IOException { ResponseException ex = assertThrows(ResponseException.class, client::info); - assertEquals(418, ex.getResponse().getStatusLine().getStatusCode()); + assertEquals(501, ex.getResponse().getStatusCode()); Properties result = new Properties(); result.load(ex.getResponse().getEntity().getContent()); return result; diff --git a/java-client/src/test/java/co/elastic/clients/transport/TransportTest.java b/java-client/src/test/java/co/elastic/clients/transport/TransportTest.java index d25466bbd..d01d93961 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/TransportTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/TransportTest.java @@ -22,11 +22,12 @@ import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.jackson.JacksonJsonpMapper; import co.elastic.clients.transport.http.RepeatableBodyResponse; +import co.elastic.clients.transport.http.TransportHttpClient; import co.elastic.clients.transport.rest_client.RestClientOptions; import co.elastic.clients.transport.rest_client.RestClientTransport; import co.elastic.clients.util.BinaryData; import com.sun.net.httpserver.HttpServer; -import org.apache.http.HttpHost; +import org.apache.hc.core5.http.HttpHost; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.Response; import org.elasticsearch.client.RestClient; @@ -63,7 +64,7 @@ public void testXMLResponse() throws Exception { InetSocketAddress address = httpServer.getAddress(); RestClient restClient = RestClient - .builder(new HttpHost(address.getHostString(), address.getPort(), "http")) + .builder(new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort())) .build(); ElasticsearchClient esClient = new ElasticsearchClient(new RestClientTransport(restClient, @@ -81,7 +82,7 @@ public void testXMLResponse() throws Exception { // Original response is transport-dependent Response restClientResponse = (Response) ex.response().originalResponse(); - assertEquals(401, restClientResponse.getStatusLine().getStatusCode()); + assertEquals(401, restClientResponse.getStatusCode()); } @@ -103,10 +104,9 @@ public void testOriginalJsonBodyRetrievalException() throws Exception { }); httpServer.start(); - InetSocketAddress address = httpServer.getAddress(); RestClient restClient = RestClient - .builder(new HttpHost(address.getHostString(), address.getPort(), "http")) + .builder(new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort())) .build(); // no transport options, response is not RepeatableBodyResponse, original body cannot be retrieved @@ -137,9 +137,11 @@ public void testOriginalJsonBodyRetrievalException() throws Exception { httpServer.stop(0); assertEquals(200, ex.statusCode()); - assertEquals(RepeatableBodyResponse.class, ex.response().getClass()); + //TODO apparently the new byteentity is always repeatable + // no need for the whole RepeatableBodyResponse if true? + //assertEquals(RepeatableBodyResponse.class, ex.response().getClass()); - try (RepeatableBodyResponse repeatableResponse = (RepeatableBodyResponse) ex.response()){ + try (TransportHttpClient.Response repeatableResponse = ex.response()){ BinaryData body = repeatableResponse.body(); StringBuilder sb = new StringBuilder(); BufferedReader br = new BufferedReader(new InputStreamReader(body.asInputStream())); diff --git a/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java b/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java index 9b0ee3081..06a475373 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java @@ -23,10 +23,9 @@ import co.elastic.clients.elasticsearch.ElasticsearchTestServer; import co.elastic.clients.json.SimpleJsonpMapper; import co.elastic.clients.transport.rest_client.RestClientTransport; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.message.BasicHeader; import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -39,6 +38,8 @@ import java.security.MessageDigest; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; +import java.util.Base64; +import java.util.Optional; public class TransportUtilsTest extends Assertions { @@ -88,17 +89,14 @@ public void testCaCertificate() throws Exception { private void checkConnection(SSLContext sslContext) throws Exception { ElasticsearchContainer container = ElasticsearchTestServer.global().container(); - BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); - credsProv.setCredentials( - AuthScope.ANY, new UsernamePasswordCredentials("elastic", "changeme") - ); + var creds = Base64.getEncoder().encodeToString("elastic:changeme".getBytes()); - RestClient restClient = RestClient.builder(new HttpHost("localhost", container.getMappedPort(9200), "https")) - .setHttpClientConfigCallback(c -> c - .setSSLContext(sslContext) - .setDefaultCredentialsProvider(credsProv) - ) - .build(); + RestClient restClient = RestClient.builder(new HttpHost("https", "localhost", + container.getMappedPort(9200))) + .setSslContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())) + .setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Basic " + creds) + }).build(); RestClientTransport transport = new RestClientTransport(restClient, SimpleJsonpMapper.INSTANCE); ElasticsearchClient esClient = new ElasticsearchClient(transport); diff --git a/java-client/src/test/java/co/elastic/clients/transport/endpoints/BinaryEndpointTest.java b/java-client/src/test/java/co/elastic/clients/transport/endpoints/BinaryEndpointTest.java index de4175b3c..2c4426509 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/endpoints/BinaryEndpointTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/endpoints/BinaryEndpointTest.java @@ -27,7 +27,7 @@ import co.elastic.clients.transport.rest_client.RestClientTransport; import com.sun.net.httpserver.HttpServer; import org.apache.commons.io.IOUtils; -import org.apache.http.HttpHost; +import org.apache.hc.core5.http.HttpHost; import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; @@ -72,7 +72,7 @@ public static void cleanup() { @Test public void testMvtSearch() throws IOException { RestClient llrc = RestClient.builder( - new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort(), "http") + new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) ).build(); RestClientTransport transport = new RestClientTransport(llrc, new SimpleJsonpMapper()); diff --git a/java-client/src/test/java/co/elastic/clients/transport/instrumentation/OpenTelemetryForElasticsearchTest.java b/java-client/src/test/java/co/elastic/clients/transport/instrumentation/OpenTelemetryForElasticsearchTest.java index f9435165d..5c33ff5ec 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/instrumentation/OpenTelemetryForElasticsearchTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/instrumentation/OpenTelemetryForElasticsearchTest.java @@ -39,7 +39,7 @@ import io.opentelemetry.sdk.trace.export.SpanExporter; import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; -import org.apache.http.HttpHost; +import org.apache.hc.core5.http.HttpHost; import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest_client/MultiBufferEntityTest.java b/java-client/src/test/java/co/elastic/clients/transport/rest_client/MultiBufferEntityTest.java index b241c1905..75dc4b8cc 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest_client/MultiBufferEntityTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest_client/MultiBufferEntityTest.java @@ -24,7 +24,7 @@ import co.elastic.clients.transport.endpoints.BinaryResponse; import com.sun.net.httpserver.HttpServer; import org.apache.commons.io.IOUtils; -import org.apache.http.HttpHost; +import org.apache.hc.core5.http.HttpHost; import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest_client/RestClientOptionsTest.java b/java-client/src/test/java/co/elastic/clients/transport/rest_client/RestClientOptionsTest.java index cf8995944..2f83b5bc8 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest_client/RestClientOptionsTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest_client/RestClientOptionsTest.java @@ -27,7 +27,7 @@ import co.elastic.clients.transport.endpoints.BooleanResponse; import com.sun.net.httpserver.Headers; import com.sun.net.httpserver.HttpServer; -import org.apache.http.HttpHost; +import org.apache.hc.core5.http.HttpHost; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.AfterAll; @@ -124,7 +124,7 @@ private void checkUserAgent(String testName, String value) { @Test void testNoRequestOptions() throws Exception { RestClient llrc = RestClient.builder( - new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort(), "http") + new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) ).build(); ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper()); @@ -137,7 +137,7 @@ void testNoRequestOptions() throws Exception { @Test void testTransportRequestOptions() throws Exception { RestClient llrc = RestClient.builder( - new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort(), "http") + new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) ).build(); ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper(), @@ -152,7 +152,7 @@ void testTransportRequestOptions() throws Exception { @Test void testClientRequestOptions() throws Exception { RestClient llrc = RestClient.builder( - new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort(), "http") + new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) ).build(); ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper()); @@ -167,7 +167,7 @@ void testClientRequestOptions() throws Exception { @Test void testLambdaOptionsBuilder() throws Exception { RestClient llrc = RestClient.builder( - new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort(), "http") + new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) ).build(); ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper()); @@ -189,7 +189,7 @@ void testRequestOptionsOverridingBuiltin() throws Exception { .build(); RestClient llrc = RestClient.builder( - new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort(), "http") + new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) ).build(); ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper(), new RestClientOptions(options,false)); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest_client/SafeResponseConsumerTest.java b/java-client/src/test/java/co/elastic/clients/transport/rest_client/SafeResponseConsumerTest.java deleted file mode 100644 index 2910ed5d5..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport/rest_client/SafeResponseConsumerTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport.rest_client; - -import com.sun.net.httpserver.HttpServer; -import org.apache.http.HttpEntity; -import org.apache.http.HttpException; -import org.apache.http.HttpHost; -import org.apache.http.HttpResponse; -import org.apache.http.entity.ContentType; -import org.apache.http.nio.ContentDecoder; -import org.apache.http.nio.IOControl; -import org.elasticsearch.client.HeapBufferedAsyncResponseConsumer; -import org.elasticsearch.client.HttpAsyncResponseConsumerFactory; -import org.elasticsearch.client.Request; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.RestClient; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; - -public class SafeResponseConsumerTest { - - static HttpServer Server; - static HttpHost ESHost; - - // A consumer factory that throws an Error, to simulate the effect of an OOME - static HttpAsyncResponseConsumerFactory FailingConsumerFactory = () -> new HeapBufferedAsyncResponseConsumer(100 * 1024 * 1024) { - @Override - protected void onResponseReceived(HttpResponse httpResponse) throws HttpException, IOException { - super.onResponseReceived(httpResponse); - } - - @Override - protected void onContentReceived(ContentDecoder decoder, IOControl ioctrl) throws IOException { - super.onContentReceived(decoder, ioctrl); - throw new Error("Error in onContentReceived"); - } - - @Override - protected void onEntityEnclosed(HttpEntity entity, ContentType contentType) throws IOException { - super.onEntityEnclosed(entity, contentType); - } - }; - - @BeforeAll - public static void setup() throws Exception { - Server = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); - Server.start(); - - Server.createContext("/", exchange -> { - String path = exchange.getRequestURI().getPath(); - exchange.getResponseHeaders().set("Content-Type", "application/json"); - exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); - - if (path.equals("/")) { - byte[] bytes = Info.getBytes(StandardCharsets.UTF_8); - exchange.sendResponseHeaders(200, bytes.length); - exchange.getResponseBody().write(bytes); - exchange.close(); - return; - } - - exchange.sendResponseHeaders(404, -1); - exchange.close(); - }); - - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - try { - Server.stop(1); - } catch (Exception e) { - // Ignore - } - })); - - ESHost = new HttpHost(Server.getAddress().getAddress(), Server.getAddress().getPort()); - } - - @AfterAll - public static void tearDown() { - Server.stop(0); - } - - @Test - public void testReactorDeath() throws Exception { - - // Request options that will simulate an OOME and cause the reactor to die - RequestOptions.Builder failingOptionsBuilder = RequestOptions.DEFAULT.toBuilder(); - failingOptionsBuilder.setHttpAsyncResponseConsumerFactory(FailingConsumerFactory); - RequestOptions failingOptions = failingOptionsBuilder.build(); - - RestClient restClient = RestClient.builder(ESHost).build(); - - // First request, to warm things up. - // An "indice exists" request, that has no response body - Request existsReq = new Request("HEAD", "/index-name"); - restClient.performRequest(existsReq); - - try { - Request infoReq = new Request("GET", "/"); - infoReq.setOptions(failingOptions); - - restClient.performRequest(infoReq); - Assertions.fail("First request should not succeed"); - } catch(Exception t) { -// System.err.println("Request 1 error"); -// t.printStackTrace(); - } - - Thread.sleep(1000); - - try { - // 2nd request with no specific options - Request infoReq = new Request("GET", "/"); - restClient.performRequest(infoReq); - Assertions.fail("Second request should not succeed"); - } catch(Exception t) { -// System.err.println("Request 2 error"); -// t.printStackTrace(); - } - - restClient.close(); - } - - @Test - public void testReactorSurvival() throws Exception { - - // Request options that will simulate an OOME and wrapped in the safe consumer that will - // avoid the reactor's death - RequestOptions.Builder protectedFailingOptionsBuilder = RequestOptions.DEFAULT.toBuilder(); - protectedFailingOptionsBuilder.setHttpAsyncResponseConsumerFactory(() -> - new SafeResponseConsumer<>(FailingConsumerFactory.createHttpAsyncResponseConsumer()) - ); - RequestOptions protectedFailingOptions = protectedFailingOptionsBuilder.build(); - - RestClient restClient = RestClient.builder(ESHost).build(); - - // First request, to warm things up. - // An "indice exists" request, that has no response body - Request existsReq = new Request("HEAD", "/index-name"); - restClient.performRequest(existsReq); - - try { - Request infoReq = new Request("GET", "/"); - infoReq.setOptions(protectedFailingOptions); - - restClient.performRequest(infoReq); - Assertions.fail("First request should not succeed"); - } catch(Exception t) { - // System.err.println("Request 1 error"); - // t.printStackTrace(); - } - - { - // 2nd request with no specific options - Request infoReq = new Request("GET", "/"); - - Response resp = restClient.performRequest(infoReq); - Assertions.assertEquals(200, resp.getStatusLine().getStatusCode()); - } - - restClient.close(); - } - - private static final String Info = "{\n" + - " \"cluster_name\": \"foo\",\n" + - " \"cluster_uuid\": \"bar\",\n" + - " \"version\": {\n" + - " \"build_date\": \"2022-01-28T08:36:04.875279988Z\",\n" + - " \"minimum_wire_compatibility_version\": \"6.8.0\",\n" + - " \"build_hash\": \"bee86328705acaa9a6daede7140defd4d9ec56bd\",\n" + - " \"number\": \"7.17.0\",\n" + - " \"lucene_version\": \"8.11.1\",\n" + - " \"minimum_index_compatibility_version\": \"6.0.0-beta1\",\n" + - " \"build_flavor\": \"default\",\n" + - " \"build_snapshot\": false,\n" + - " \"build_type\": \"docker\"\n" + - " },\n" + - " \"name\": \"instance-0000000000\",\n" + - " \"tagline\": \"You Know, for Search\"\n" + - "}"; -} From 42def674783639f45bec7e091eb96c1be7a39adb Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Tue, 11 Mar 2025 12:23:13 +0100 Subject: [PATCH 02/38] fix multibufferentity --- .../rest_client/MultiBufferEntity.java | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java index 836761a37..13e78665c 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java @@ -23,6 +23,7 @@ import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.io.entity.AbstractHttpEntity; +import org.apache.hc.core5.http.nio.AsyncDataProducer; import org.apache.hc.core5.http.nio.AsyncRequestProducer; import org.apache.hc.core5.http.nio.DataStreamChannel; import org.apache.hc.core5.http.nio.RequestChannel; @@ -40,7 +41,7 @@ /** * An HTTP entity based on a sequence of byte buffers. */ -class MultiBufferEntity extends AbstractHttpEntity implements AsyncRequestProducer { +class MultiBufferEntity extends AbstractHttpEntity implements AsyncDataProducer { private final Iterable buffers; @@ -48,8 +49,7 @@ class MultiBufferEntity extends AbstractHttpEntity implements AsyncRequestProduc private volatile ByteBuffer currentBuffer; MultiBufferEntity(Iterable buffers, ContentType contentType) { - //TODO where to find contentEncoding? - super(contentType.toString(),null, true); + super(contentType,null,true); this.buffers = buffers; init(); } @@ -69,22 +69,11 @@ private void init() { } } - @Override - public void sendRequest(RequestChannel channel, HttpContext context) throws HttpException, IOException { - //TODO looks the same as produce? check which one is actually called - System.out.println("s"); - } - @Override public boolean isRepeatable() { return true; } - @Override - public void failed(Exception cause) { - - } - @Override public long getContentLength() { // Use chunked encoding @@ -118,8 +107,6 @@ public int available() { @Override public void produce(DataStreamChannel channel) throws IOException { - //TODO really not sure - if (currentBuffer == null) { channel.endStream(); return; @@ -139,6 +126,6 @@ public void produce(DataStreamChannel channel) throws IOException { @Override public void releaseResources() { - //TODO probably clear buffers + init(); } } From 85382fe185eb1ee419c272df039d45a4881e3d53 Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Thu, 13 Mar 2025 16:38:09 +0100 Subject: [PATCH 03/38] client builder refactor --- .../builders/ElasticsearchClientBuilder.java | 22 ++++-- .../rest_client/MultiBufferEntity.java | 5 -- .../_helpers/builders/ClientBuilderTest.java | 38 ---------- .../_helpers/builders/ClientBuildersTest.java | 72 +++++++++++++++++++ 4 files changed, 87 insertions(+), 50 deletions(-) delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuilderTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuildersTest.java diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java index 3ed4b121b..b303bcfef 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java @@ -22,6 +22,8 @@ import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.JsonpMapper; import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.TransportOptions; +import co.elastic.clients.transport.rest_client.RestClientOptions; import co.elastic.clients.transport.rest_client.RestClientTransport; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.json.JsonMapper; @@ -47,38 +49,44 @@ public class ElasticsearchClientBuilder { private String apiKey; private SSLContext sslContext; private JsonpMapper mapper; + private RestClientOptions transportOptions; - public ElasticsearchClientBuilder withHost(String url) throws URISyntaxException { + public ElasticsearchClientBuilder host(String url) throws URISyntaxException { this.host = HttpHost.create(url); return this; } - public ElasticsearchClientBuilder withUsernameAndPassword(String username, String password) { + public ElasticsearchClientBuilder usernameAndPassword(String username, String password) { this.username = username; this.password = password; return this; } - public ElasticsearchClientBuilder withToken(String token) { + public ElasticsearchClientBuilder token(String token) { this.token = token; return this; } - public ElasticsearchClientBuilder withApiKey(String apiKey) { + public ElasticsearchClientBuilder apiKey(String apiKey) { this.apiKey = apiKey; return this; } - public ElasticsearchClientBuilder withSslContext(SSLContext sslContext) { + public ElasticsearchClientBuilder sslContext(SSLContext sslContext) { this.sslContext = sslContext; return this; } - public ElasticsearchClientBuilder withMapper(JsonpMapper mapper) { + public ElasticsearchClientBuilder jsonMapper(JsonpMapper mapper) { this.mapper = mapper; return this; } + public ElasticsearchClientBuilder transportOptions(RestClientOptions transportOptions) { + this.transportOptions = transportOptions; + return this; + } + public ElasticsearchClient build() { // defaulting to localhost @@ -118,7 +126,7 @@ public ElasticsearchClient build() { this.mapper = new JacksonJsonpMapper(mapper); } - RestClientTransport transport = new RestClientTransport(restClientBuilder.build(), mapper); + RestClientTransport transport = new RestClientTransport(restClientBuilder.build(), mapper, transportOptions); return new ElasticsearchClient(transport); } } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java index 13e78665c..044133de1 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java @@ -21,14 +21,9 @@ import co.elastic.clients.util.NoCopyByteArrayOutputStream; import org.apache.hc.core5.http.ContentType; -import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.io.entity.AbstractHttpEntity; import org.apache.hc.core5.http.nio.AsyncDataProducer; -import org.apache.hc.core5.http.nio.AsyncRequestProducer; import org.apache.hc.core5.http.nio.DataStreamChannel; -import org.apache.hc.core5.http.nio.RequestChannel; -import org.apache.hc.core5.http.protocol.HttpContext; - import java.io.IOException; import java.io.InputStream; diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuilderTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuilderTest.java deleted file mode 100644 index 9ea131488..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuilderTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch._helpers.builders; - -public class ClientBuilderTest { - -// @Test -// public void build() throws IOException, URISyntaxException, NoSuchAlgorithmException { -// -// // create client with helper -// ElasticsearchClient client = new ElasticsearchClientBuilder() -// .withHost("url") -// .withUsernameAndPassword("elastic", "changeme") -// .withSslContext(SSLContext.getDefault()) -// .build(); -// -// // test call (won't work) -// InfoResponse res = client.info(); -// assert res != null; -// } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuildersTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuildersTest.java new file mode 100644 index 000000000..3c0d3dcab --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuildersTest.java @@ -0,0 +1,72 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch._helpers.builders; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.transport.rest_client.RestClientOptions; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import org.elasticsearch.client.RequestOptions; +import org.junit.jupiter.api.Test; + +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.net.URISyntaxException; +import java.security.NoSuchAlgorithmException; + +import static org.junit.Assert.assertTrue; + +public class ClientBuildersTest { + + @Test + public void build() throws IOException, URISyntaxException, NoSuchAlgorithmException { + + // create client with helper + ElasticsearchClient client = new ElasticsearchClientBuilder() + .host("url") + .usernameAndPassword("elastic", "changeme") + .sslContext(SSLContext.getDefault()) + .build(); + + RestClientOptions options = new RestClientOptions(RequestOptions.DEFAULT, true); + + client = client.withTransportOptions(options); + + // checking options correctness + assertTrue(client._transport().getClass().equals(RestClientTransport.class)); + assertTrue(client._transportOptions().keepResponseBodyOnException()); + assertTrue(client._transportOptions().headers().size() == 3); + + //assertTrue(client._transport().options().keepResponseBodyOnException()); TODO ? + + // token update utility + + client._transportOptions().updateToken("token"); + assertTrue(client._transportOptions().headers().size() == 4); + assertTrue(client._transportOptions().headers().stream().anyMatch(h -> h.getKey().equals( + "Authorization"))); + } + + @Test + public void altSearchBuild() { + // Standard search + + } +} From 1adfa2bd00b7d4e5b3402c7cdb0fdbfa5731e5ea Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Tue, 25 Mar 2025 10:19:50 +0100 Subject: [PATCH 04/38] temp --- .../rest_client/RestTransportClientTest.java | 1 + .../clients/esql/article/EsqlArticle.java | 2 +- java-client/build.gradle.kts | 9 +- .../builders/ElasticsearchClientBuilder.java | 5 +- .../MultiBufferEntity.java | 2 +- .../RestClientHttpClient.java | 2 +- .../RestClientOptions.java | 2 +- .../RestClientTransport.java | 2 +- .../low_level_client/Cancellable.java | 108 ++ .../low_level_client/DeadHostState.java | 112 ++ .../HttpDeleteWithEntity.java | 41 + .../low_level_client/HttpGetWithEntity.java | 41 + .../LanguageRuntimeVersions.java | 137 +++ .../low_level_client/Request.java | 189 ++++ .../low_level_client/RequestLogger.java | 181 +++ .../low_level_client/RequestOptions.java | 340 ++++++ .../low_level_client/Response.java | 208 ++++ .../low_level_client/ResponseException.java | 79 ++ .../low_level_client/ResponseListener.java | 48 + .../low_level_client/RestClient.java | 1006 +++++++++++++++++ .../low_level_client/RestClientBuilder.java | 379 +++++++ .../WarningFailureException.java | 62 + .../low_level_client/WarningsHandler.java | 53 + .../consumer/BasicAsyncResponseConsumer.java | 60 + .../consumer/BufferedByteConsumer.java | 76 ++ .../HttpAsyncResponseConsumerFactory.java | 66 ++ .../low_level_client/node/Node.java | 278 +++++ .../selector/HasAttributeNodeSelector.java | 76 ++ .../node/selector/NodeSelector.java | 95 ++ .../PreferHasAttributeNodeSelector.java | 105 ++ .../producer/BasicAsyncEntityProducer.java | 128 +++ .../low_level_client/utils/Constants.java | 7 + .../ElasticsearchTestServer.java | 2 +- .../_helpers/builders/ClientBuildersTest.java | 5 +- .../esql/EsqlAdapterEndToEndTest.java | 2 +- .../RequestOptionsTest.java | 4 +- .../TransportTest.java | 6 +- .../TransportUtilsTest.java | 4 +- .../VersionInfoTest.java | 2 +- .../endpoints/BinaryEndpointTest.java | 4 +- .../endpoints/BooleanEndpointTest.java | 2 +- .../endpoints/EndpointBaseTest.java | 2 +- .../endpoints/SimpleEndpointTest.java | 2 +- .../http/HeaderMapTest.java | 2 +- .../OpenTelemetryForElasticsearchTest.java | 6 +- .../BasicAsyncResponseConsumerTests.java | 76 ++ .../ClientsGraalVMThreadsFilter.java | 33 + .../low_level_client/DeadHostStateTests.java | 136 +++ .../FailureTrackingResponseListenerTests.java | 112 ++ .../HasAttributeNodeSelectorTests.java | 78 ++ .../HostsTrackingFailureListener.java | 62 + .../low_level_client/NodeSelectorTests.java | 131 +++ .../low_level_client/NodeTests.java | 175 +++ .../PreferHasAttributeNodeSelectorTests.java | 89 ++ .../low_level_client/RequestLoggerTests.java | 204 ++++ .../low_level_client/RequestOptionsTests.java | 211 ++++ .../low_level_client/RequestTests.java | 249 ++++ .../ResponseExceptionTests.java | 93 ++ .../RestClientBuilderIntegTests.java | 227 ++++ .../RestClientBuilderTests.java | 268 +++++ .../RestClientDocumentation.java | 461 ++++++++ .../RestClientGzipCompressionTests.java | 257 +++++ .../RestClientMultipleHostsIntegTests.java | 402 +++++++ .../RestClientMultipleHostsTests.java | 341 ++++++ .../RestClientSingleHostIntegTests.java | 457 ++++++++ .../RestClientSingleHostTests.java | 694 ++++++++++++ .../low_level_client/RestClientTestCase.java | 119 ++ .../low_level_client/RestClientTestUtil.java | 119 ++ .../low_level_client/RestClientTests.java | 456 ++++++++ .../rest_client/MultiBufferEntityTest.java | 3 +- .../rest_client/RestClientOptionsTest.java | 4 +- 71 files changed, 9364 insertions(+), 36 deletions(-) rename java-client/src/main/java/co/elastic/clients/transport/{rest_client => rest5_client}/MultiBufferEntity.java (98%) rename java-client/src/main/java/co/elastic/clients/transport/{rest_client => rest5_client}/RestClientHttpClient.java (99%) rename java-client/src/main/java/co/elastic/clients/transport/{rest_client => rest5_client}/RestClientOptions.java (99%) rename java-client/src/main/java/co/elastic/clients/transport/{rest_client => rest5_client}/RestClientTransport.java (97%) create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Cancellable.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/DeadHostState.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/HttpDeleteWithEntity.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/HttpGetWithEntity.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/LanguageRuntimeVersions.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Request.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RequestLogger.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RequestOptions.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Response.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/ResponseException.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/ResponseListener.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RestClient.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RestClientBuilder.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/WarningFailureException.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/WarningsHandler.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/BasicAsyncResponseConsumer.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/BufferedByteConsumer.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/HttpAsyncResponseConsumerFactory.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/Node.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/HasAttributeNodeSelector.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/NodeSelector.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/PreferHasAttributeNodeSelector.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/producer/BasicAsyncEntityProducer.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/utils/Constants.java rename java-client/src/test/java/co/elastic/clients/{transport => transport5}/RequestOptionsTest.java (98%) rename java-client/src/test/java/co/elastic/clients/{transport => transport5}/TransportTest.java (97%) rename java-client/src/test/java/co/elastic/clients/{transport => transport5}/TransportUtilsTest.java (97%) rename java-client/src/test/java/co/elastic/clients/{transport => transport5}/VersionInfoTest.java (96%) rename java-client/src/test/java/co/elastic/clients/{transport => transport5}/endpoints/BinaryEndpointTest.java (97%) rename java-client/src/test/java/co/elastic/clients/{transport => transport5}/endpoints/BooleanEndpointTest.java (96%) rename java-client/src/test/java/co/elastic/clients/{transport => transport5}/endpoints/EndpointBaseTest.java (98%) rename java-client/src/test/java/co/elastic/clients/{transport => transport5}/endpoints/SimpleEndpointTest.java (98%) rename java-client/src/test/java/co/elastic/clients/{transport => transport5}/http/HeaderMapTest.java (98%) rename java-client/src/test/java/co/elastic/clients/{transport => transport5}/instrumentation/OpenTelemetryForElasticsearchTest.java (97%) create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/BasicAsyncResponseConsumerTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/ClientsGraalVMThreadsFilter.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/DeadHostStateTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/FailureTrackingResponseListenerTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/HasAttributeNodeSelectorTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/HostsTrackingFailureListener.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/NodeSelectorTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/NodeTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/PreferHasAttributeNodeSelectorTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestLoggerTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestOptionsTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/ResponseExceptionTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientBuilderIntegTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientBuilderTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientDocumentation.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientGzipCompressionTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientMultipleHostsIntegTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientMultipleHostsTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientSingleHostIntegTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientSingleHostTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTestCase.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTestUtil.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTests.java rename java-client/src/test/java/co/elastic/clients/{transport => transport5}/rest_client/MultiBufferEntityTest.java (96%) rename java-client/src/test/java/co/elastic/clients/{transport => transport5}/rest_client/RestClientOptionsTest.java (97%) diff --git a/example-transports/src/test/java/co/elastic/clients/transport/rest_client/RestTransportClientTest.java b/example-transports/src/test/java/co/elastic/clients/transport/rest_client/RestTransportClientTest.java index fe0866652..d0d29569e 100644 --- a/example-transports/src/test/java/co/elastic/clients/transport/rest_client/RestTransportClientTest.java +++ b/example-transports/src/test/java/co/elastic/clients/transport/rest_client/RestTransportClientTest.java @@ -20,6 +20,7 @@ package co.elastic.clients.transport.rest_client; import co.elastic.clients.transport.TransportHttpClientTest; +import co.elastic.clients.transport.rest5_client.RestClientHttpClient; import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; diff --git a/examples/esql-article/src/main/java/co/elastic/clients/esql/article/EsqlArticle.java b/examples/esql-article/src/main/java/co/elastic/clients/esql/article/EsqlArticle.java index e73af8fac..9544db0c2 100644 --- a/examples/esql-article/src/main/java/co/elastic/clients/esql/article/EsqlArticle.java +++ b/examples/esql-article/src/main/java/co/elastic/clients/esql/article/EsqlArticle.java @@ -25,7 +25,7 @@ import co.elastic.clients.elasticsearch.core.bulk.BulkOperation; import co.elastic.clients.json.jackson.JacksonJsonpMapper; import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.rest5_client.RestClientTransport; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.MappingIterator; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/java-client/build.gradle.kts b/java-client/build.gradle.kts index c43cf7a95..20438a86a 100644 --- a/java-client/build.gradle.kts +++ b/java-client/build.gradle.kts @@ -200,14 +200,13 @@ signing { dependencies { // Compile and test with the last 7.x version to make sure transition scenarios where // the Java API client coexists with a 7.x HLRC work fine + val elasticsearchVersion = "8.17.0" val jacksonVersion = "2.17.0" val openTelemetryVersion = "1.29.0" - // build the low level repo - implementation("co.elastic.lowclient", "low-level-java-client", "9.0.0") - // temporary, should eventually get these two from low level (something something gradle doesn't do transitive dep. from local) - api("commons-logging", "commons-logging", "1.3.3") - api("org.apache.httpcomponents.client5", "httpclient5", "5.4") + // Apache 2.0 + // https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-low.html + api("org.elasticsearch.client", "elasticsearch-rest-client", elasticsearchVersion) // Apache 2.0 // https://search.maven.org/artifact/com.google.code.findbugs/jsr305 diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java index b303bcfef..d36f085ba 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java @@ -22,9 +22,8 @@ import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.JsonpMapper; import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.TransportOptions; -import co.elastic.clients.transport.rest_client.RestClientOptions; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.rest5_client.RestClientOptions; +import co.elastic.clients.transport.rest5_client.RestClientTransport; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.json.JsonMapper; import org.apache.hc.core5.http.Header; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/MultiBufferEntity.java similarity index 98% rename from java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/MultiBufferEntity.java index 044133de1..674e85da8 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/MultiBufferEntity.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.rest_client; +package co.elastic.clients.transport.rest5_client; import co.elastic.clients.util.NoCopyByteArrayOutputStream; import org.apache.hc.core5.http.ContentType; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientHttpClient.java similarity index 99% rename from java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientHttpClient.java index ba46f55cd..53a5da2e5 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientHttpClient.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.rest_client; +package co.elastic.clients.transport.rest5_client; import co.elastic.clients.transport.TransportOptions; import co.elastic.clients.transport.http.HeaderMap; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientOptions.java similarity index 99% rename from java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientOptions.java index 3824a2655..5be7ee405 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientOptions.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.rest_client; +package co.elastic.clients.transport.rest5_client; import co.elastic.clients.transport.TransportOptions; import co.elastic.clients.transport.Version; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientTransport.java similarity index 97% rename from java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientTransport.java index dbadfbe1a..65e78249e 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientTransport.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.rest_client; +package co.elastic.clients.transport.rest5_client; import co.elastic.clients.json.JsonpMapper; import co.elastic.clients.transport.ElasticsearchTransportBase; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Cancellable.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Cancellable.java new file mode 100644 index 000000000..70bd0c2a4 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Cancellable.java @@ -0,0 +1,108 @@ +/* + * 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. + */ +package co.elastic.clients.transport.rest5_client.low_level_client; + +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.concurrent.CancellableDependency; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.ResponseListener; +import org.elasticsearch.client.RestClient; + +import java.util.concurrent.CancellationException; + +/** + * Represents an operation that can be cancelled. + * Returned when executing async requests through + * {@link RestClient#performRequestAsync(Request, ResponseListener)}, so that the request + * can be cancelled if needed. Cancelling a request will result in calling + * {@link HttpUriRequestBase#abort()} on the underlying + * request object, which will in turn cancel its corresponding {@link java.util.concurrent.Future}. + * Note that cancelling a request does not automatically translate to aborting its execution on the server + * side, which needs to be specifically implemented in each API. + */ +public abstract class Cancellable implements org.apache.hc.core5.concurrent.Cancellable { + + /** + * Executes some arbitrary code iff the on-going request has not been cancelled, otherwise throws + * {@link CancellationException}. + */ + abstract void runIfNotCancelled(Runnable runnable); + + static final Cancellable NO_OP = new Cancellable() { + @Override + public boolean cancel() { + throw new UnsupportedOperationException(); + } + + @Override + void runIfNotCancelled(Runnable runnable) { + throw new UnsupportedOperationException(); + } + }; + + static Cancellable fromRequest(HttpUriRequestBase httpRequest) { + return new RequestCancellable(httpRequest); + } + + private static class RequestCancellable extends Cancellable { + + private final CancellableDependency httpRequest; + + private RequestCancellable(HttpUriRequestBase httpRequest) { + this.httpRequest = httpRequest; + } + + public synchronized boolean cancel() { + return this.httpRequest.cancel(); + } + + /** + * Executes some arbitrary code iff the on-going request has not been cancelled, otherwise throws + * {@link CancellationException}. + * This is needed to guarantee that cancelling a request works correctly even in case + * {@link #cancel()} is called between different + * attempts of the same request. The low-level client reuses the same instance of the + * {@link HttpUriRequestBase} by + * calling + * {@link HttpUriRequestBase#reset()} between subsequent retries. The {@link #cancel()} + * method can be called at anytime, + * and we need to handle the case where it gets called while there is no request being executed as + * one attempt may have failed and + * the subsequent attempt has not been started yet. + * If the request has already been cancelled we don't go ahead with the next attempt, and + * artificially raise the + * {@link CancellationException}, otherwise we run the provided {@link Runnable} which will reset + * the request and send the next + * attempt. + * Note that this method must be synchronized as well as the {@link #cancel()} method, to prevent a + * request from being cancelled + * when there is no future to cancel, which would make cancelling the request a no-op. + */ + synchronized void runIfNotCancelled(Runnable runnable) { + if (this.httpRequest.isCancelled()) { + throw newCancellationException(); + } + runnable.run(); + } + } + + static CancellationException newCancellationException() { + return new CancellationException("request was cancelled"); + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/DeadHostState.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/DeadHostState.java new file mode 100644 index 000000000..eb109bb73 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/DeadHostState.java @@ -0,0 +1,112 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level_client; + +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +/** + * Holds the state of a dead connection to a host. Keeps track of how many failed attempts were performed and + * when the host should be retried (based on number of previous failed attempts). + * Class is immutable, a new copy of it should be created each time the state has to be changed. + */ +final class DeadHostState implements Comparable { + + private static final long MIN_CONNECTION_TIMEOUT_NANOS = TimeUnit.MINUTES.toNanos(1); + static final long MAX_CONNECTION_TIMEOUT_NANOS = TimeUnit.MINUTES.toNanos(30); + static final Supplier DEFAULT_TIME_SUPPLIER = System::nanoTime; + + private final int failedAttempts; + private final long deadUntilNanos; + private final Supplier timeSupplier; + + /** + * Build the initial dead state of a host. Useful when a working host stops functioning + * and needs to be marked dead after its first failure. In such case the host will be retried after a minute or so. + * + * @param timeSupplier a way to supply the current time and allow for unit testing + */ + DeadHostState(Supplier timeSupplier) { + this.failedAttempts = 1; + this.deadUntilNanos = timeSupplier.get() + MIN_CONNECTION_TIMEOUT_NANOS; + this.timeSupplier = timeSupplier; + } + + /** + * Build the dead state of a host given its previous dead state. Useful when a host has been failing before, hence + * it already failed for one or more consecutive times. The more failed attempts we register the longer we wait + * to retry that same host again. Minimum is 1 minute (for a node the only failed once created + * through {@link #DeadHostState(Supplier)}), maximum is 30 minutes (for a node that failed more than 10 consecutive times) + * + * @param previousDeadHostState the previous state of the host which allows us to increase the wait till the next retry attempt + */ + DeadHostState(DeadHostState previousDeadHostState) { + long timeoutNanos = (long) Math.min( + MIN_CONNECTION_TIMEOUT_NANOS * 2 * Math.pow(2, previousDeadHostState.failedAttempts * 0.5 - 1), + MAX_CONNECTION_TIMEOUT_NANOS + ); + this.deadUntilNanos = previousDeadHostState.timeSupplier.get() + timeoutNanos; + this.failedAttempts = previousDeadHostState.failedAttempts + 1; + this.timeSupplier = previousDeadHostState.timeSupplier; + } + + /** + * Indicates whether it's time to retry to failed host or not. + * + * @return true if the host should be retried, false otherwise + */ + boolean shallBeRetried() { + return timeSupplier.get() - deadUntilNanos > 0; + } + + /** + * Returns the timestamp (nanos) till the host is supposed to stay dead without being retried. + * After that the host should be retried. + */ + long getDeadUntilNanos() { + return deadUntilNanos; + } + + int getFailedAttempts() { + return failedAttempts; + } + + @Override + public int compareTo(DeadHostState other) { + if (timeSupplier != other.timeSupplier) { + throw new IllegalArgumentException( + "can't compare DeadHostStates holding different time suppliers as they may be based on different clocks" + ); + } + return Long.compare(deadUntilNanos, other.deadUntilNanos); + } + + @Override + public String toString() { + return "DeadHostState{" + + "failedAttempts=" + + failedAttempts + + ", deadUntilNanos=" + + deadUntilNanos + + ", timeSupplier=" + + timeSupplier + + '}'; + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/HttpDeleteWithEntity.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/HttpDeleteWithEntity.java new file mode 100644 index 000000000..7357da1bb --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/HttpDeleteWithEntity.java @@ -0,0 +1,41 @@ +/* + * 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. + */ +package co.elastic.clients.transport.rest5_client.low_level_client; + +import org.apache.hc.client5.http.classic.methods.HttpDelete; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; + +import java.net.URI; + +/** + * Allows to send DELETE requests providing a body (not supported out of the box) + */ +final class HttpDeleteWithEntity extends HttpUriRequestBase { + + static final String METHOD_NAME = HttpDelete.METHOD_NAME; + + public HttpDeleteWithEntity(URI requestUri) { + super(METHOD_NAME, requestUri); + } + + @Override + public String getMethod() { + return METHOD_NAME; + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/HttpGetWithEntity.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/HttpGetWithEntity.java new file mode 100644 index 000000000..c798da031 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/HttpGetWithEntity.java @@ -0,0 +1,41 @@ +/* + * 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. + */ +package co.elastic.clients.transport.rest5_client.low_level_client; + +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; + +import java.net.URI; + +/** + * Allows to send GET requests providing a body (not supported out of the box) + */ +final class HttpGetWithEntity extends HttpUriRequestBase { + + static final String METHOD_NAME = HttpGet.METHOD_NAME; + + public HttpGetWithEntity(URI requestUri) { + super(METHOD_NAME, requestUri); + } + + @Override + public String getMethod() { + return METHOD_NAME; + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/LanguageRuntimeVersions.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/LanguageRuntimeVersions.java new file mode 100644 index 000000000..c2c4b3a32 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/LanguageRuntimeVersions.java @@ -0,0 +1,137 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level_client; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +// Copied verbatim from https://github.com/elastic/jvm-languages-sniffer + +class LanguageRuntimeVersions { + + /** + * Returns runtime information by looking up classes identifying non-Java JVM + * languages and appending a key with their name and their major.minor version, if available + */ + public static String getRuntimeMetadata() { + StringBuilder s = new StringBuilder(); + String version; + + version = kotlinVersion(); + if (version != null) { + s.append(",kt=").append(version); + } + + version = scalaVersion(); + if (version != null) { + s.append(",sc=").append(version); + } + + version = clojureVersion(); + if (version != null) { + s.append(",clj=").append(version); + } + + version = groovyVersion(); + if (version != null) { + s.append(",gy=").append(version); + } + + version = jRubyVersion(); + if (version != null) { + s.append(",jrb=").append(version); + } + + return s.toString(); + } + + public static String kotlinVersion() { + // KotlinVersion.CURRENT.toString() + return keepMajorMinor(getStaticField("kotlin.KotlinVersion", "CURRENT")); + } + + public static String scalaVersion() { + // scala.util.Properties.versionNumberString() + return keepMajorMinor(callStaticMethod("scala.util.Properties", "versionNumberString")); + } + + public static String clojureVersion() { + // (clojure-version) which translates to + // clojure.core$clojure_version.invokeStatic() + return keepMajorMinor(callStaticMethod("clojure.core$clojure_version", "invokeStatic")); + } + + public static String groovyVersion() { + // groovy.lang.GroovySystem.getVersion() + // There's also getShortVersion(), but only since Groovy 3.0.1 + return keepMajorMinor(callStaticMethod("groovy.lang.GroovySystem", "getVersion")); + } + + public static String jRubyVersion() { + // org.jruby.runtime.Constants.VERSION + return keepMajorMinor(getStaticField("org.jruby.runtime.Constants", "VERSION")); + } + + private static String getStaticField(String className, String fieldName) { + Class clazz; + try { + clazz = Class.forName(className); + } catch (ClassNotFoundException e) { + return null; + } + + try { + Field field = clazz.getField(fieldName); + return field.get(null).toString(); + } catch (Exception e) { + return ""; // can't get version information + } + } + + private static String callStaticMethod(String className, String methodName) { + Class clazz; + try { + clazz = Class.forName(className); + } catch (ClassNotFoundException e) { + return null; + } + + try { + Method m = clazz.getMethod(methodName); + return m.invoke(null).toString(); + } catch (Exception e) { + return ""; // can't get version information + } + } + + static String keepMajorMinor(String version) { + if (version == null) { + return null; + } + + int firstDot = version.indexOf('.'); + int secondDot = version.indexOf('.', firstDot + 1); + if (secondDot < 0) { + return version; + } else { + return version.substring(0, secondDot); + } + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Request.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Request.java new file mode 100644 index 000000000..d35b0d985 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Request.java @@ -0,0 +1,189 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level_client; + + +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.elasticsearch.client.RequestOptions; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import static java.util.Collections.unmodifiableMap; + +/** + * HTTP Request to Elasticsearch. + */ +public final class Request { + private final String method; + private final String endpoint; + private final Map parameters = new HashMap<>(); + + private HttpEntity entity; + private org.elasticsearch.client.RequestOptions options = org.elasticsearch.client.RequestOptions.DEFAULT; + + /** + * Create the {@linkplain Request}. + * @param method the HTTP method + * @param endpoint the path of the request (without scheme, host, port, or prefix) + */ + public Request(String method, String endpoint) { + this.method = Objects.requireNonNull(method, "method cannot be null"); + this.endpoint = Objects.requireNonNull(endpoint, "endpoint cannot be null"); + } + + /** + * The HTTP method. + */ + public String getMethod() { + return method; + } + + /** + * The path of the request (without scheme, host, port, or prefix). + */ + public String getEndpoint() { + return endpoint; + } + + /** + * Add a query string parameter. + * @param name the name of the url parameter. Must not be null. + * @param value the value of the url parameter. If {@code null} then + * the parameter is sent as {@code name} rather than {@code name=value} + * @throws IllegalArgumentException if a parameter with that name has + * already been set + */ + public void addParameter(String name, String value) { + Objects.requireNonNull(name, "url parameter name cannot be null"); + if (parameters.containsKey(name)) { + throw new IllegalArgumentException("url parameter [" + name + "] has already been set to [" + parameters.get(name) + "]"); + } else { + parameters.put(name, value); + } + } + + public void addParameters(Map paramSource) { + paramSource.forEach(this::addParameter); + } + + /** + * Query string parameters. The returned map is an unmodifiable view of the + * map in the request so calls to {@link #addParameter(String, String)} + * will change it. + */ + public Map getParameters() { + return unmodifiableMap(parameters); + } + + /** + * Set the body of the request. If not set or set to {@code null} then no + * body is sent with the request. + */ + public void setEntity(HttpEntity entity) { + this.entity = entity; + } + + /** + * Set the body of the request to a string. If not set or set to + * {@code null} then no body is sent with the request. The + * {@code Content-Type} will be sent as {@code application/json}. + * If you need a different content type then use + * {@link #setEntity(HttpEntity)}. + */ + public void setJsonEntity(String body) { + setEntity(body == null ? null : new StringEntity(body, ContentType.APPLICATION_JSON)); + } + + /** + * The body of the request. If {@code null} then no body + * is sent with the request. + */ + public HttpEntity getEntity() { + return entity; + } + + /** + * Set the portion of an HTTP request to Elasticsearch that can be + * manipulated without changing Elasticsearch's behavior. + */ + public void setOptions(org.elasticsearch.client.RequestOptions options) { + Objects.requireNonNull(options, "options cannot be null"); + this.options = options; + } + + /** + * Set the portion of an HTTP request to Elasticsearch that can be + * manipulated without changing Elasticsearch's behavior. + */ + public void setOptions(org.elasticsearch.client.RequestOptions.Builder options) { + Objects.requireNonNull(options, "options cannot be null"); + this.options = options.build(); + } + + /** + * Get the portion of an HTTP request to Elasticsearch that can be + * manipulated without changing Elasticsearch's behavior. + */ + public RequestOptions getOptions() { + return options; + } + + @Override + public String toString() { + StringBuilder b = new StringBuilder(); + b.append("Request{"); + b.append("method='").append(method).append('\''); + b.append(", endpoint='").append(endpoint).append('\''); + if (false == parameters.isEmpty()) { + b.append(", params=").append(parameters); + } + if (entity != null) { + b.append(", entity=").append(entity); + } + b.append(", options=").append(options); + return b.append('}').toString(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null || (obj.getClass() != getClass())) { + return false; + } + if (obj == this) { + return true; + } + + Request other = (Request) obj; + return method.equals(other.method) + && endpoint.equals(other.endpoint) + && parameters.equals(other.parameters) + && Objects.equals(entity, other.entity) + && options.equals(other.options); + } + + @Override + public int hashCode() { + return Objects.hash(method, endpoint, parameters, entity, options); + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RequestLogger.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RequestLogger.java new file mode 100644 index 000000000..0d225d23e --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RequestLogger.java @@ -0,0 +1,181 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level_client; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hc.client5.http.classic.methods.HttpUriRequest; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.io.entity.BufferedHttpEntity; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.elasticsearch.client.node.Node; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +/** + * Helper class that exposes static methods to unify the way requests are logged. + * Includes trace logging to log complete requests and responses in curl format. + * Useful for debugging, manually sending logged requests via curl and checking their responses. + * Trace logging is a feature that all the language clients provide. + */ +final class RequestLogger { + + private static final Log tracer = LogFactory.getLog("tracer"); + + private RequestLogger() { + } + + /** + * Logs a request that yielded a response + */ + static void logResponse(Log logger, HttpUriRequest request, HttpHost host, + ClassicHttpResponse httpResponse) { + if (logger.isDebugEnabled()) { + logger.debug( + "request [" + + request.getMethod() + + " " + + host + + getUri(request.getRequestUri()) + + "] returned [" + + httpResponse.getCode() + + "]" + ); + } + if (logger.isWarnEnabled()) { + Header[] warnings = httpResponse.getHeaders("Warning"); + if (warnings != null && warnings.length > 0) { + logger.warn(buildWarningMessage(request, host, warnings)); + } + } + if (tracer.isTraceEnabled()) { + String requestLine; + try { + requestLine = buildTraceRequest(request, host); + } catch (IOException | ParseException e) { + requestLine = ""; + tracer.trace("error while reading request for trace purposes", e); + } + String responseLine; + try { + responseLine = buildTraceResponse(httpResponse); + } catch (IOException e) { + responseLine = ""; + tracer.trace("error while reading response for trace purposes", e); + } + tracer.trace(requestLine + '\n' + responseLine); + } + } + + /** + * Logs a request that failed + */ + static void logFailedRequest(Log logger, HttpUriRequest request, Node node, Exception e) { + if (logger.isDebugEnabled()) { + logger.debug("request [" + request.getMethod() + " " + node.getHost() + getUri(request.getRequestUri()) + "] failed", e); + } + if (tracer.isTraceEnabled()) { + String traceRequest; + try { + traceRequest = buildTraceRequest(request, node.getHost()); + } catch (IOException | ParseException e1) { + tracer.trace("error while reading request for trace purposes", e); + traceRequest = ""; + } + tracer.trace(traceRequest); + } + } + + static String buildWarningMessage(HttpUriRequest request, HttpHost host, Header[] warnings) { + StringBuilder message = new StringBuilder("request [").append(request.getMethod()) + .append(" ") + .append(host) + .append(getUri(request.getRequestUri())) + .append("] returned ") + .append(warnings.length) + .append(" warnings: "); + for (int i = 0; i < warnings.length; i++) { + if (i > 0) { + message.append(","); + } + message.append("[").append(warnings[i].getValue()).append("]"); + } + return message.toString(); + } + + /** + * Creates curl output for given request + */ + static String buildTraceRequest(HttpUriRequest request, HttpHost host) throws IOException, + ParseException { + String requestLine = "curl -iX " + request.getMethod() + " '" + host + getUri(request.getRequestUri()) + "'"; + + if (request.getEntity() != null) { + requestLine += " -d '"; + HttpEntity entity = request.getEntity(); + if (!entity.isRepeatable()) { + entity = new BufferedHttpEntity(request.getEntity()); + request.setEntity(entity); + } + requestLine += EntityUtils.toString(entity, StandardCharsets.UTF_8) + "'"; + } + return requestLine; + } + + /** + * Creates curl output for given response + */ + static String buildTraceResponse(ClassicHttpResponse httpResponse) throws IOException { + StringBuilder responseLine = new StringBuilder(); + responseLine.append("# ").append(httpResponse.getCode()); + for (Header header : httpResponse.getHeaders()) { + responseLine.append("\n# ").append(header.getName()).append(": ").append(header.getValue()); + } + responseLine.append("\n#"); + HttpEntity entity = httpResponse.getEntity(); + if (entity != null) { + if (!entity.isRepeatable()) { + entity = new BufferedHttpEntity(entity); + } + httpResponse.setEntity(entity); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()))) { + String line; + while ((line = reader.readLine()) != null) { + responseLine.append("\n# ").append(line); + } + } + } + return responseLine.toString(); + } + + private static String getUri(String requestLine) { + if (requestLine.charAt(0) != '/') { + return "/" + requestLine; + } + return requestLine; + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RequestOptions.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RequestOptions.java new file mode 100644 index 000000000..a729918a5 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RequestOptions.java @@ -0,0 +1,340 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level_client; + +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.message.BasicHeader; +import org.apache.hc.core5.http.nio.AsyncResponseConsumer; +import org.elasticsearch.client.RestClientBuilder; +import org.elasticsearch.client.WarningsHandler; +import org.elasticsearch.client.consumer.HttpAsyncResponseConsumerFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * The portion of an HTTP request to Elasticsearch that can be + * manipulated without changing Elasticsearch's behavior. + */ +public final class RequestOptions { + /** + * Default request options. + */ + public static final RequestOptions DEFAULT = new Builder( + Collections.emptyList(), + Collections.emptyMap(), + HttpAsyncResponseConsumerFactory.DEFAULT, + null, + null + ).build(); + + private final List
headers; + private final Map parameters; + private final HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory; + private final WarningsHandler warningsHandler; + private final RequestConfig requestConfig; + + private RequestOptions(Builder builder) { + this.headers = builder.headers; + this.parameters = Collections.unmodifiableMap(builder.parameters); + this.httpAsyncResponseConsumerFactory = builder.httpAsyncResponseConsumerFactory; + this.warningsHandler = builder.warningsHandler; + this.requestConfig = builder.requestConfig; + } + + /** + * Create a builder that contains these options but can be modified. + */ + public Builder toBuilder() { + return new Builder(headers, parameters, httpAsyncResponseConsumerFactory, warningsHandler, + requestConfig); + } + + /** + * Headers to attach to the request. + */ + public List
getHeaders() { + return List.copyOf(headers); + } + + /** + * Return true if the options contain the given header + */ + public boolean containsHeader(String name) { + return headers.stream().anyMatch(h -> name.equalsIgnoreCase(h.getName())); + } + + /** + * Replaces an existing bearer token header + */ + public void updateToken(String token) { + headers.stream() + .filter(h -> "Bearer ".equalsIgnoreCase(h.getName())) + .findAny().ifPresent(headers::remove); + headers.add(new ReqHeader("Authorization", "Bearer " +token)); + } + + public Map getParameters() { + return parameters; + } + + /** + * The {@link HttpAsyncResponseConsumerFactory} used to create one + * {@link AsyncResponseConsumer} callback per retry. Controls how the + * response body gets streamed from a non-blocking HTTP connection on the + * client side. + */ + public HttpAsyncResponseConsumerFactory getHttpAsyncResponseConsumerFactory() { + return httpAsyncResponseConsumerFactory; + } + + + /** + * How this request should handle warnings. If null (the default) then + * this request will default to the behavior dictacted by + * {@link org.elasticsearch.client.RestClientBuilder#setStrictDeprecationMode}. + *

+ * This can be set to {@link WarningsHandler#PERMISSIVE} if the client + * should ignore all warnings which is the same behavior as setting + * strictDeprecationMode to true. It can be set to + * {@link WarningsHandler#STRICT} if the client should fail if there are + * any warnings which is the same behavior as settings + * strictDeprecationMode to false. + *

+ * It can also be set to a custom implementation of + * {@linkplain WarningsHandler} to permit only certain warnings or to + * fail the request if the warnings returned don't + * exactly match some set. + */ + public WarningsHandler getWarningsHandler() { + return warningsHandler; + } + + /** + * get RequestConfig, which can set socketTimeout, connectTimeout + * and so on by request + * + * @return RequestConfig + */ + public RequestConfig getRequestConfig() { + return requestConfig; + } + + @Override + public String toString() { + StringBuilder b = new StringBuilder(); + b.append("RequestOptions{"); + boolean comma = false; + if (!headers.isEmpty()) { + b.append("headers="); + comma = true; + for (int h = 0; h < headers.size(); h++) { + if (h != 0) { + b.append(','); + } + b.append(headers.get(h).toString()); + } + } + if (httpAsyncResponseConsumerFactory != HttpAsyncResponseConsumerFactory.DEFAULT) { + if (comma) b.append(", "); + comma = true; + b.append("consumerFactory=").append(httpAsyncResponseConsumerFactory); + } + if (warningsHandler != null) { + if (comma) b.append(", "); + comma = true; + b.append("warningsHandler=").append(warningsHandler); + } + return b.append('}').toString(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null || (obj.getClass() != getClass())) { + return false; + } + if (obj == this) { + return true; + } + + RequestOptions other = (RequestOptions) obj; + return headers.equals(other.headers) + && httpAsyncResponseConsumerFactory.equals(other.httpAsyncResponseConsumerFactory) + && Objects.equals(warningsHandler, other.warningsHandler); + } + + @Override + public int hashCode() { + return Objects.hash(headers, warningsHandler, httpAsyncResponseConsumerFactory); + } + + /** + * Builds {@link RequestOptions}. Get one by calling + * {@link RequestOptions#toBuilder} on {@link RequestOptions#DEFAULT} or + * any other {@linkplain RequestOptions}. + */ + public static class Builder { + private final List

headers; + private final Map parameters; + private HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory; + private WarningsHandler warningsHandler; + private RequestConfig requestConfig; + + private Builder( + List
headers, + Map parameters, + HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory, + WarningsHandler warningsHandler, + RequestConfig requestConfig + ) { + this.headers = new ArrayList<>(headers); + this.parameters = new HashMap<>(parameters); + this.httpAsyncResponseConsumerFactory = httpAsyncResponseConsumerFactory; + this.warningsHandler = warningsHandler; + this.requestConfig = requestConfig; + } + + /** + * Build the {@linkplain RequestOptions}. + */ + public RequestOptions build() { + return new RequestOptions(this); + } + + /** + * Add the provided header to the request. + */ + public Builder addHeader(String name, String value) { + Objects.requireNonNull(name, "header name cannot be null"); + Objects.requireNonNull(value, "header value cannot be null"); + this.headers.add(new ReqHeader(name, value)); + return this; + } + + /** + * Remove all headers with the given name. + */ + public Builder removeHeader(String name) { + Objects.requireNonNull(name, "header name cannot be null"); + this.headers.removeIf(h -> name.equalsIgnoreCase(h.getName())); + return this; + } + + /** + * Return all headers for the request + */ + public List
getHeaders() { + return this.headers; + } + + /** + * Add the provided parameter to the request. + */ + public Builder addParameter(String key, String value) { + Objects.requireNonNull(key, "parameter key cannot be null"); + Objects.requireNonNull(value, "parameter value cannot be null"); + this.parameters.merge(key, value, (existingValue, newValue) -> String.join(",", existingValue, + newValue)); + return this; + } + + /** + * Set the {@link HttpAsyncResponseConsumerFactory} used to create one + * {@link AsyncResponseConsumer} callback per retry. Controls how the + * response body gets streamed from a non-blocking HTTP connection on the + * client side. + */ + public Builder setHttpAsyncResponseConsumerFactory(HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory) { + this.httpAsyncResponseConsumerFactory = Objects.requireNonNull( + httpAsyncResponseConsumerFactory, + "httpAsyncResponseConsumerFactory cannot be null" + ); + return this; + } + + /** + * How this request should handle warnings. If null (the default) then + * this request will default to the behavior dictacted by + * {@link RestClientBuilder#setStrictDeprecationMode}. + *

+ * This can be set to {@link WarningsHandler#PERMISSIVE} if the client + * should ignore all warnings which is the same behavior as setting + * strictDeprecationMode to true. It can be set to + * {@link WarningsHandler#STRICT} if the client should fail if there are + * any warnings which is the same behavior as settings + * strictDeprecationMode to false. + *

+ * It can also be set to a custom implementation of + * {@linkplain WarningsHandler} to permit only certain warnings or to + * fail the request if the warnings returned don't + * exactly match some set. + */ + public Builder setWarningsHandler(WarningsHandler warningsHandler) { + this.warningsHandler = warningsHandler; + return this; + } + + /** + * set RequestConfig, which can set socketTimeout, connectTimeout + * and so on by request + * + * @param requestConfig http client RequestConfig + * @return Builder + */ + public Builder setRequestConfig(RequestConfig requestConfig) { + this.requestConfig = requestConfig; + return this; + } + } + + /** + * Custom implementation of {@link BasicHeader} that overrides equals and + * hashCode so it is easier to test equality of {@link RequestOptions}. + */ + static final class ReqHeader extends BasicHeader { + + ReqHeader(String name, String value) { + super(name, value); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (other instanceof ReqHeader) { + Header otherHeader = (Header) other; + return Objects.equals(getName(), otherHeader.getName()) && Objects.equals(getValue(), + otherHeader.getValue()); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(getName(), getValue()); + } + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Response.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Response.java new file mode 100644 index 000000000..83c2a1537 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Response.java @@ -0,0 +1,208 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level_client; + + +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.message.BasicClassicHttpResponse; +import org.apache.hc.core5.http.message.RequestLine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Holds an elasticsearch response. It wraps the {@link BasicClassicHttpResponse} returned and associates + * it with its corresponding {@link RequestLine} and {@link HttpHost}. + */ +public class Response { + + private final RequestLine requestLine; + private final HttpHost host; + private final ClassicHttpResponse response; + + Response(RequestLine requestLine, HttpHost host, ClassicHttpResponse response) { + Objects.requireNonNull(requestLine, "requestLine cannot be null"); + Objects.requireNonNull(host, "host cannot be null"); + Objects.requireNonNull(response, "response cannot be null"); + this.requestLine = requestLine; + this.host = host; + this.response = response; + } + + /** + * Returns the request line that generated this response + */ + public RequestLine getRequestLine() { + return requestLine; + } + + /** + * Returns the node that returned this response + */ + public HttpHost getHost() { + return host; + } + + public int getStatusCode() { + return response.getCode(); + } + + /** + * Returns all the response headers + */ + public Header[] getHeaders() { + return response.getHeaders(); + } + + /** + * Returns the value of the first header with a specified name of this message. + * If there is more than one matching header in the message the first element is returned. + * If there is no matching header in the message null is returned. + */ + public String getHeader(String name) { + Header header = response.getFirstHeader(name); + if (header == null) { + return null; + } + return header.getValue(); + } + + /** + * Returns the response body available, null otherwise + * + * @see HttpEntity + */ + public HttpEntity getEntity() { + return response.getEntity(); + } + + /** + * Optimized regular expression to test if a string matches the RFC 1123 date + * format (with quotes and leading space). Start/end of line characters and + * atomic groups are used to prevent backtracking. + */ + private static final Pattern WARNING_HEADER_DATE_PATTERN = Pattern.compile("^ " + // start of line, + // leading space + // quoted RFC 1123 date format + "\"" + // opening quote + "(?>Mon|Tue|Wed|Thu|Fri|Sat|Sun), " + // day of week, atomic group to prevent backtracking + "\\d{2} " + // 2-digit day + "(?>Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) " + // month, atomic group to prevent + // backtracking + "\\d{4} " + // 4-digit year + "\\d{2}:\\d{2}:\\d{2} " + // (two-digit hour):(two-digit minute):(two-digit second) + "GMT" + // GMT + "\"$"); // closing quote (optional, since an older version can still send a warn-date), end of line + + /** + * Length of RFC 1123 format (with quotes and leading space), used in + * matchWarningHeaderPatternByPrefix(String). + */ + // tag::noformat + private static final int WARNING_HEADER_DATE_LENGTH = 0 + + 1 + + 1 + + 3 + 1 + 1 + + 2 + 1 + + 3 + 1 + + 4 + 1 + + 2 + 1 + 2 + 1 + 2 + 1 + + 3 + + 1; + // end::noformat + + /** + * Tests if a string matches the RFC 7234 specification for warning headers. + * This assumes that the warn code is always 299 or 300 and the warn agent is + * always Elasticsearch. + * + * @param s the value of a warning header formatted according to RFC 7234 + * @return {@code true} if the input string matches the specification + */ + private static boolean matchWarningHeaderPatternByPrefix(final String s) { + return s.startsWith("299 Elasticsearch-") || s.startsWith("300 Elasticsearch-"); + } + + /** + * Refer to org.elasticsearch.common.logging.DeprecationLogger + */ + private static String extractWarningValueFromWarningHeader(final String s) { + String warningHeader = s; + + /* + * The following block tests for the existence of a RFC 1123 date in the warning header. If the + * date exists, it is removed for + * extractWarningValueFromWarningHeader(String) to work properly (as it does not handle dates). + */ + if (s.length() > WARNING_HEADER_DATE_LENGTH) { + final String possibleDateString = s.substring(s.length() - WARNING_HEADER_DATE_LENGTH); + final Matcher matcher = WARNING_HEADER_DATE_PATTERN.matcher(possibleDateString); + + if (matcher.matches()) { + warningHeader = warningHeader.substring(0, s.length() - WARNING_HEADER_DATE_LENGTH); + } + } + + final int firstQuote = warningHeader.indexOf('\"'); + final int lastQuote = warningHeader.length() - 1; + final String warningValue = warningHeader.substring(firstQuote + 1, lastQuote); + return warningValue; + } + + /** + * Returns a list of all warning headers returned in the response. + */ + public List getWarnings() { + List warnings = new ArrayList<>(); + for (Header header : response.getHeaders("Warning")) { + String warning = header.getValue(); + if (matchWarningHeaderPatternByPrefix(warning)) { + warnings.add(extractWarningValueFromWarningHeader(warning)); + } else { + warnings.add(warning); + } + } + return warnings; + } + + /** + * Returns true if there is at least one warning header returned in the + * response. + */ + public boolean hasWarnings() { + Header[] warnings = response.getHeaders("Warning"); + return warnings != null && warnings.length > 0; + } + + ClassicHttpResponse getHttpResponse() { + return response; + } + + @Override + public String toString() { + return "Response{requestLine=" + requestLine + ", host=" + host + ", response=" + response.getCode() + '}'; + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/ResponseException.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/ResponseException.java new file mode 100644 index 000000000..bca172de8 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/ResponseException.java @@ -0,0 +1,79 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level_client; + +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.io.entity.BufferedHttpEntity; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.elasticsearch.client.Response; + +import java.io.IOException; +import java.util.Locale; + +/** + * Exception thrown when an elasticsearch node responds to a request with a status code that indicates an error. + * Holds the response that was returned. + */ +public final class ResponseException extends IOException { + + private final Response response; + + public ResponseException(Response response) throws IOException { + super(buildMessage(response)); + this.response = response; + } + + static String buildMessage(Response response) throws IOException { + String message = String.format( + Locale.ROOT, + "method [%s], host [%s], URI [%s], status line [%s]", + response.getRequestLine().getMethod(), + response.getHost(), + response.getRequestLine().getUri(), + response.getStatusCode() + ); + + if (response.hasWarnings()) { + message += "\nWarnings: " + response.getWarnings(); + } + + HttpEntity entity = response.getEntity(); + if (entity != null) { + if (!entity.isRepeatable()) { + entity = new BufferedHttpEntity(entity); + response.getHttpResponse().setEntity(entity); + } + try { + message += "\n" + EntityUtils.toString(entity); + } catch (ParseException e) { // TODO 99% sure this will never get thrown. can suppress? + throw new RuntimeException("Could not parse headers: " + e); + } + } + return message; + } + + /** + * Returns the {@link Response} that caused this exception to be thrown. + */ + public Response getResponse() { + return response; + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/ResponseListener.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/ResponseListener.java new file mode 100644 index 000000000..0bdcb311d --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/ResponseListener.java @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level_client; + +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseException; +import org.elasticsearch.client.RestClient; + +/** + * Listener to be provided when calling async performRequest methods provided by {@link RestClient}. + * Those methods that do accept a listener will return immediately, execute asynchronously, and notify + * the listener whenever the request yielded a response, or failed with an exception. + * + *

+ * Note that it is not safe to call {@link RestClient#close()} from either of these + * callbacks. + */ +public interface ResponseListener { + + /** + * Method invoked if the request yielded a successful response + */ + void onSuccess(Response response); + + /** + * Method invoked if the request failed. There are two main categories of failures: connection failures (usually + * {@link java.io.IOException}s, or responses that were treated as errors based on their error response code + * ({@link ResponseException}s). + */ + void onFailure(Exception exception); +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RestClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RestClient.java new file mode 100644 index 000000000..7c2a30df6 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RestClient.java @@ -0,0 +1,1006 @@ +/* + * 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. + */ +package co.elastic.clients.transport.rest5_client.low_level_client; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hc.client5.http.ClientProtocolException; +import org.apache.hc.client5.http.ConnectTimeoutException; +import org.apache.hc.client5.http.async.HttpAsyncClient; +import org.apache.hc.client5.http.classic.methods.HttpHead; +import org.apache.hc.client5.http.classic.methods.HttpOptions; +import org.apache.hc.client5.http.classic.methods.HttpPatch; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.classic.methods.HttpPut; +import org.apache.hc.client5.http.classic.methods.HttpTrace; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.entity.GzipCompressingEntity; +import org.apache.hc.client5.http.entity.GzipDecompressingEntity; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.core5.concurrent.FutureCallback; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.ConnectionClosedException; +import org.apache.hc.core5.http.ContentTooLongException; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpRequest; +import org.apache.hc.core5.http.ProtocolException; +import org.apache.hc.core5.http.message.RequestLine; +import org.apache.hc.core5.http.nio.AsyncRequestProducer; +import org.apache.hc.core5.http.nio.AsyncResponseConsumer; +import org.apache.hc.core5.http.nio.support.AsyncRequestBuilder; +import org.apache.hc.core5.net.URIBuilder; +import org.apache.hc.core5.reactor.IOReactorStatus; +import org.elasticsearch.client.Cancellable; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseException; +import org.elasticsearch.client.ResponseListener; +import org.elasticsearch.client.RestClientBuilder; +import org.elasticsearch.client.WarningFailureException; +import org.elasticsearch.client.WarningsHandler; +import org.elasticsearch.client.node.Node; +import org.elasticsearch.client.node.selector.NodeSelector; +import org.elasticsearch.client.producer.BasicAsyncEntityProducer; + +import javax.net.ssl.SSLHandshakeException; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.net.ConnectException; +import java.net.SocketTimeoutException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Collections.singletonList; +import static org.apache.hc.core5.http.HttpHeaders.CONTENT_ENCODING; +import static org.apache.hc.core5.http.HttpHeaders.CONTENT_LENGTH; + +/** + * Client that connects to an Elasticsearch cluster through HTTP. + *

+ * Must be created using {@link org.elasticsearch.client.RestClientBuilder}, which allows to set all the different options or just + * rely on defaults. + * The hosts that are part of the cluster need to be provided at creation time, but can also be replaced later + * by calling {@link #setNodes(Collection)}. + *

+ * The method {@link #performRequest(org.elasticsearch.client.Request)} allows to send a request to the cluster. When + * sending a request, a host gets selected out of the provided ones in a round-robin fashion. Failing hosts + * are marked dead and + * retried after a certain amount of time (minimum 1 minute, maximum 30 minutes), depending on how many + * times they previously + * failed (the more failures, the later they will be retried). In case of failures all of the alive nodes + * (or dead nodes that + * deserve a retry) are retried until one responds or none of them does, in which case an + * {@link IOException} will be thrown. + *

+ * Requests can be either synchronous or asynchronous. The asynchronous variants all end with {@code Async}. + *

+ * Requests can be traced by enabling trace logging for "tracer". The trace logger outputs requests and + * responses in curl format. + */ +public class RestClient implements Closeable { + + public static final String IGNORE_RESPONSE_CODES_PARAM = "ignore"; + + private static final Log logger = LogFactory.getLog(RestClient.class); + + private final CloseableHttpAsyncClient client; + // We don't rely on default headers supported by HttpAsyncClient as those cannot be replaced. + // These are package private for tests. + final List

defaultHeaders; + private final String pathPrefix; + private final AtomicInteger lastNodeIndex = new AtomicInteger(0); + private final ConcurrentMap blacklist = new ConcurrentHashMap<>(); + private final FailureListener failureListener; + private final NodeSelector nodeSelector; + private volatile List nodes; + private final org.elasticsearch.client.WarningsHandler warningsHandler; + private final boolean compressionEnabled; + private final boolean metaHeaderEnabled; + + RestClient( + CloseableHttpAsyncClient client, + Header[] defaultHeaders, + List nodes, + String pathPrefix, + FailureListener failureListener, + NodeSelector nodeSelector, + boolean strictDeprecationMode, + boolean compressionEnabled, + boolean metaHeaderEnabled + ) { + this.client = client; + this.defaultHeaders = Collections.unmodifiableList(Arrays.asList(defaultHeaders)); + this.failureListener = failureListener; + this.pathPrefix = pathPrefix; + this.nodeSelector = nodeSelector; + this.warningsHandler = strictDeprecationMode ? org.elasticsearch.client.WarningsHandler.STRICT : org.elasticsearch.client.WarningsHandler.PERMISSIVE; + this.compressionEnabled = compressionEnabled; + this.metaHeaderEnabled = metaHeaderEnabled; + setNodes(nodes); + } + + /** + * Returns a new {@link org.elasticsearch.client.RestClientBuilder} to help with {@link RestClient} creation. + * Creates a new builder instance and sets the nodes that the client will send requests to. + * + * @param cloudId a valid elastic cloud cloudId that will route to a cluster. The cloudId is located in + * the user console https://cloud.elastic.co and will resemble a string like the following + * optionalHumanReadableName:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRlbGFzdGljc2VhcmNoJGtpYmFuYQ== + */ + public static org.elasticsearch.client.RestClientBuilder builder(String cloudId) { + // there is an optional first portion of the cloudId that is a human readable string, but it is not + // used. + if (cloudId.contains(":")) { + if (cloudId.indexOf(':') == cloudId.length() - 1) { + throw new IllegalStateException("cloudId " + cloudId + " must begin with a human readable " + + "identifier followed by a colon"); + } + cloudId = cloudId.substring(cloudId.indexOf(':') + 1); + } + + String decoded = new String(Base64.getDecoder().decode(cloudId), UTF_8); + // once decoded the parts are separated by a $ character. + // they are respectively domain name and optional port, elasticsearch id, kibana id + String[] decodedParts = decoded.split("\\$"); + if (decodedParts.length != 3) { + throw new IllegalStateException("cloudId " + cloudId + " did not decode to a cluster identifier" + + " correctly"); + } + + // domain name and optional port + String[] domainAndMaybePort = decodedParts[0].split(":", 2); + String domain = domainAndMaybePort[0]; + int port; + + if (domainAndMaybePort.length == 2) { + try { + port = Integer.parseInt(domainAndMaybePort[1]); + } catch (NumberFormatException nfe) { + throw new IllegalStateException("cloudId " + cloudId + " does not contain a valid port " + + "number"); + } + } else { + port = 443; + } + + String url = decodedParts[1] + "." + domain; + return builder(new HttpHost("https", url, port)); + } + + /** + * Returns a new {@link org.elasticsearch.client.RestClientBuilder} to help with {@link RestClient} creation. + * Creates a new builder instance and sets the hosts that the client will send requests to. + *

+ * Prefer this to {@link #builder(HttpHost...)} if you have metadata up front about the nodes. + * If you don't either one is fine. + */ + public static org.elasticsearch.client.RestClientBuilder builder(Node... nodes) { + return new org.elasticsearch.client.RestClientBuilder(nodes == null ? null : Arrays.asList(nodes)); + } + + /** + * Returns a new {@link org.elasticsearch.client.RestClientBuilder} to help with {@link RestClient} creation. + * Creates a new builder instance and sets the nodes that the client will send requests to. + *

+ * You can use this if you do not have metadata up front about the nodes. If you do, prefer + * {@link #builder(Node...)}. + * + * @see Node#Node(HttpHost) + */ + public static org.elasticsearch.client.RestClientBuilder builder(HttpHost... hosts) { + if (hosts == null || hosts.length == 0) { + throw new IllegalArgumentException("hosts must not be null nor empty"); + } + List nodes = Arrays.stream(hosts).map(Node::new).collect(Collectors.toList()); + return new org.elasticsearch.client.RestClientBuilder(nodes); + } + + /** + * Get the underlying HTTP client. + */ + public HttpAsyncClient getHttpClient() { + return this.client; + } + + /** + * Replaces the nodes with which the client communicates. + */ + public synchronized void setNodes(Collection nodes) { // TODO why the whole method synchronized? + if (nodes == null || nodes.isEmpty()) { + throw new IllegalArgumentException("node list must not be null or empty"); + } + + Map nodesByHost = new LinkedHashMap<>(); + for (Node node : nodes) { + Objects.requireNonNull(node, "node cannot be null"); + nodesByHost.put(node.getHost(), node); // TODO same host twice will be overwritten. should + // throw exception? + } + this.nodes = new ArrayList<>(nodesByHost.values()); + this.blacklist.clear(); + } + + /** + * Get the list of nodes that the client knows about. The list is + * unmodifiable. + */ + public List getNodes() { + return nodes; + } + + /** + * check client running status + * + * @return client running status + */ + public boolean isRunning() { + return client.getStatus() == IOReactorStatus.ACTIVE; + } + + /** + * Sends a request to the Elasticsearch cluster that the client points to. + * Blocks until the request is completed and returns its response or fails + * by throwing an exception. Selects a host out of the provided ones in a + * round-robin fashion. Failing hosts are marked dead and retried after a + * certain amount of time (minimum 1 minute, maximum 30 minutes), depending + * on how many times they previously failed (the more failures, the later + * they will be retried). In case of failures all of the alive nodes (or + * dead nodes that deserve a retry) are retried until one responds or none + * of them does, in which case an {@link IOException} will be thrown. + *

+ * This method works by performing an asynchronous call and waiting + * for the result. If the asynchronous call throws an exception we wrap + * it and rethrow it so that the stack trace attached to the exception + * contains the call site. While we attempt to preserve the original + * exception this isn't always possible and likely haven't covered all of + * the cases. You can get the original exception from + * {@link Exception#getCause()}. + * + * @param request the request to perform + * @return the response returned by Elasticsearch + * @throws IOException in case of a problem or the connection was aborted + * @throws ClientProtocolException in case of an http protocol error + * @throws org.elasticsearch.client.ResponseException in case Elasticsearch responded with a status code that indicated an + * error + */ + public org.elasticsearch.client.Response performRequest(org.elasticsearch.client.Request request) throws IOException { + InternalRequest internalRequest = new InternalRequest(request); + return performRequest(nextNodes(), internalRequest, null); + } + + private org.elasticsearch.client.Response performRequest(final Iterator nodes, final InternalRequest request, + Exception previousException) + throws IOException { + RequestContext context = request.createContextForNextAttempt(nodes.next()); + ClassicHttpResponse httpResponse; + try { + httpResponse = client.execute(context.requestProducer, + context.asyncResponseConsumer, + context.context, null).get(); + } catch (Exception e) { + org.elasticsearch.client.RequestLogger.logFailedRequest(logger, request.httpRequest, context.node, e); + onFailure(context.node); + Exception cause = extractAndWrapCause(e); + addSuppressedException(previousException, cause); + if (isRetryableException(e) && nodes.hasNext()) { + return performRequest(nodes, request, cause); + } + if (cause instanceof IOException) { + throw (IOException) cause; + } + if (cause instanceof RuntimeException) { + throw (RuntimeException) cause; + } + throw new IllegalStateException("unexpected exception type: must be either RuntimeException or " + + "IOException", cause); + } + ResponseOrResponseException responseOrResponseException = convertResponse(request, context.node, + httpResponse); + if (responseOrResponseException.responseException == null) { + return responseOrResponseException.response; + } + addSuppressedException(previousException, responseOrResponseException.responseException); + if (nodes.hasNext()) { + return performRequest(nodes, request, responseOrResponseException.responseException); + } + throw responseOrResponseException.responseException; + } + + private ResponseOrResponseException convertResponse(InternalRequest request, Node node, + ClassicHttpResponse httpResponse) throws IOException { + org.elasticsearch.client.RequestLogger.logResponse(logger, request.httpRequest, node.getHost(), httpResponse); + int statusCode = httpResponse.getCode(); + + HttpEntity entity = httpResponse.getEntity(); + if (entity != null) { + Header encoding = null; + try { + encoding = httpResponse.getHeader(CONTENT_ENCODING); + } catch (ProtocolException e) { // TODO 99% sure this will never get thrown. can suppress? + throw new RuntimeException("Couldn't retrieve content encoding: " + e); + } + if (encoding != null && "gzip".equals(encoding.getValue())) { + // Decompress and cleanup response headers + httpResponse.setEntity(new GzipDecompressingEntity(entity)); + httpResponse.removeHeaders(CONTENT_ENCODING); + httpResponse.removeHeaders(CONTENT_LENGTH); + } + } + + org.elasticsearch.client.Response response = new org.elasticsearch.client.Response(new RequestLine(request.httpRequest), node.getHost(), httpResponse); + if (isCorrectServerResponse(statusCode)) { + onResponse(node); + if (request.warningsHandler.warningsShouldFailRequest(response.getWarnings())) { + throw new WarningFailureException(response); + } + return new ResponseOrResponseException(response); + } + org.elasticsearch.client.ResponseException responseException = new org.elasticsearch.client.ResponseException(response); + if (isRetryStatus(statusCode)) { + // mark host dead and retry against next one + onFailure(node); + return new ResponseOrResponseException(responseException); + } + // mark host alive and don't retry, as the error should be a request problem + onResponse(node); + throw responseException; + } + + /** + * Sends a request to the Elasticsearch cluster that the client points to. + * The request is executed asynchronously and the provided + * {@link org.elasticsearch.client.ResponseListener} gets notified upon request completion or + * failure. Selects a host out of the provided ones in a round-robin + * fashion. Failing hosts are marked dead and retried after a certain + * amount of time (minimum 1 minute, maximum 30 minutes), depending on how + * many times they previously failed (the more failures, the later they + * will be retried). In case of failures all of the alive nodes (or dead + * nodes that deserve a retry) are retried until one responds or none of + * them does, in which case an {@link IOException} will be thrown. + * + * @param request the request to perform + * @param responseListener the {@link org.elasticsearch.client.ResponseListener} to notify when the + * request is completed or fails + */ + public org.elasticsearch.client.Cancellable performRequestAsync(org.elasticsearch.client.Request request, org.elasticsearch.client.ResponseListener responseListener) { + try { + FailureTrackingResponseListener failureTrackingResponseListener = + new FailureTrackingResponseListener(responseListener); + InternalRequest internalRequest = new InternalRequest(request); + performRequestAsync(nextNodes(), internalRequest, failureTrackingResponseListener); + return internalRequest.cancellable; + } catch (Exception e) { + responseListener.onFailure(e); + return org.elasticsearch.client.Cancellable.NO_OP; + } + } + + private void performRequestAsync( + final Iterator nodes, + final InternalRequest request, + final FailureTrackingResponseListener listener + ) { + request.cancellable.runIfNotCancelled(() -> { + final RequestContext context; + context = request.createContextForNextAttempt(nodes.next()); + Future futureRef = client.execute(context.requestProducer, context.asyncResponseConsumer, context.context, + new FutureCallback() { + @Override + public void completed(ClassicHttpResponse httpResponse) { + try { + ResponseOrResponseException responseOrResponseException = convertResponse(request, + context.node, httpResponse); + if (responseOrResponseException.responseException == null) { + listener.onSuccess(responseOrResponseException.response); + } else { + if (nodes.hasNext()) { + listener.trackFailure(responseOrResponseException.responseException); + performRequestAsync(nodes, request, listener); + } else { + listener.onDefinitiveFailure(responseOrResponseException.responseException); + } + } + } catch (Exception e) { + listener.onDefinitiveFailure(e); + } + } + + @Override + public void failed(Exception failure) { + try { + org.elasticsearch.client.RequestLogger.logFailedRequest(logger, request.httpRequest, context.node, + failure); + onFailure(context.node); + if (isRetryableException(failure) && nodes.hasNext()) { + listener.trackFailure(failure); + performRequestAsync(nodes, request, listener); + } else { + listener.onDefinitiveFailure(failure); + } + } catch (Exception e) { + listener.onDefinitiveFailure(e); + } + } + + @Override + public void cancelled() { + listener.onDefinitiveFailure(org.elasticsearch.client.Cancellable.newCancellationException()); + } + }); + // needed to be able to cancel asnyc requests + if (futureRef instanceof org.apache.hc.core5.concurrent.Cancellable) { + request.httpRequest.setDependency((org.apache.hc.core5.concurrent.Cancellable) futureRef); + } + }); + } + + /** + * Returns a non-empty {@link Iterator} of nodes to be used for a request + * that match the {@link NodeSelector}. + *

+ * If there are no living nodes that match the {@link NodeSelector} + * this will return the dead node that matches the {@link NodeSelector} + * that is closest to being revived. + * + * @throws IOException if no nodes are available + */ + private Iterator nextNodes() throws IOException { + List nodes = this.nodes; + return selectNodes(nodes, blacklist, lastNodeIndex, nodeSelector).iterator(); + } + + /** + * Select nodes to try and sorts them so that the first one will be tried initially, then the following + * ones + * if the previous attempt failed and so on. Package private for testing. + */ + static Iterable selectNodes( + List nodes, + Map blacklist, + AtomicInteger lastNodeIndex, + NodeSelector nodeSelector + ) throws IOException { + /* + * Sort the nodes into living and dead lists. + */ + List livingNodes = new ArrayList<>(Math.max(0, nodes.size() - blacklist.size())); + List deadNodes = null; + if (!blacklist.isEmpty()) { + deadNodes = new ArrayList<>(blacklist.size()); + new ArrayList<>(blacklist.size()); + for (Node node : nodes) { + org.elasticsearch.client.DeadHostState deadness = blacklist.get(node.getHost()); + if (deadness == null || deadness.shallBeRetried()) { + livingNodes.add(node); + } else { + deadNodes.add(new DeadNode(node, deadness)); + } + } + } + // happy path when no failing nodes + else { + livingNodes.addAll(nodes); + } + + if (!livingNodes.isEmpty()) { + /* + * Normal state: there is at least one living node. If the + * selector is ok with any over the living nodes then use them + * for the request. + */ + List selectedLivingNodes = new ArrayList<>(livingNodes); + nodeSelector.select(selectedLivingNodes); + if (!selectedLivingNodes.isEmpty()) { + /* + * Rotate the list using a global counter as the distance so subsequent + * requests will try the nodes in a different order. + */ + Collections.rotate(selectedLivingNodes, lastNodeIndex.getAndIncrement()); + return selectedLivingNodes; + } + } + + /* + * Last resort: there are no good nodes to use, either because + * the selector rejected all the living nodes or because there aren't + * any living ones. Either way, we want to revive a single dead node + * that the NodeSelectors are OK with. We do this by passing the dead + * nodes through the NodeSelector so it can have its say in which nodes + * are ok. If the selector is ok with any of the nodes then we will take + * the one in the list that has the lowest revival time and try it. + */ + if (deadNodes != null && !deadNodes.isEmpty()) { + final List selectedDeadNodes = new ArrayList<>(deadNodes); + /* + * We'd like NodeSelectors to remove items directly from deadNodes + * so we can find the minimum after it is filtered without having + * to compare many things. This saves us a sort on the unfiltered + * list. + */ + nodeSelector.select(() -> new DeadNodeIteratorAdapter(selectedDeadNodes.iterator())); + if (!selectedDeadNodes.isEmpty()) { + return singletonList(Collections.min(selectedDeadNodes).node); + } + } + throw new IOException("NodeSelector [" + nodeSelector + "] rejected all nodes, living: " + livingNodes + " and dead: " + deadNodes); + } + + /** + * Called after each successful request call. + * Receives as an argument the host that was used for the successful request. + */ + private void onResponse(Node node) { + org.elasticsearch.client.DeadHostState removedHost = this.blacklist.remove(node.getHost()); + if (logger.isDebugEnabled() && removedHost != null) { + logger.debug("removed [" + node + "] from blacklist"); + } + } + + /** + * Called after each failed attempt. + * Receives as an argument the host that was used for the failed attempt. + */ + private void onFailure(Node node) { + org.elasticsearch.client.DeadHostState previousDeadHostState = blacklist.putIfAbsent( + node.getHost(), + new org.elasticsearch.client.DeadHostState(org.elasticsearch.client.DeadHostState.DEFAULT_TIME_SUPPLIER) + ); + if (previousDeadHostState == null) { + if (logger.isDebugEnabled()) { + logger.debug("added [" + node + "] to blacklist"); + } + } else { + blacklist.replace(node.getHost(), previousDeadHostState, + new org.elasticsearch.client.DeadHostState(previousDeadHostState)); + if (logger.isDebugEnabled()) { + logger.debug("updated [" + node + "] already in blacklist"); + } + } + failureListener.onFailure(node); + } + + @Override + public void close() throws IOException { + client.close(); + } + + /** + * 400 or lower responses are part of the server behavior, only considering >500 for dead nodes marking + * purposes + */ + private static boolean isCorrectServerResponse(int statusCode) { + return statusCode < 500; + } + + private static boolean isRetryStatus(int statusCode) { + switch (statusCode) { + case 502: + case 503: + case 504: + return true; + } + return false; + } + + /** + * Should an exception cause retrying the request? + */ + private static boolean isRetryableException(Throwable e) { + if (e instanceof ExecutionException) { + e = e.getCause(); + } + if (e instanceof ContentTooLongException) { + return false; + } + return true; + } + + private static void addSuppressedException(Exception suppressedException, Exception currentException) { + if (suppressedException != null && suppressedException != currentException) { + currentException.addSuppressed(suppressedException); + } + } + + private static HttpUriRequestBase createHttpRequest(String method, URI uri, HttpEntity entity, + boolean compressionEnabled) { + switch (method.toUpperCase(Locale.ROOT)) { + case org.elasticsearch.client.HttpDeleteWithEntity.METHOD_NAME: + return addRequestBody(new org.elasticsearch.client.HttpDeleteWithEntity(uri), entity, compressionEnabled); + case org.elasticsearch.client.HttpGetWithEntity.METHOD_NAME: + return addRequestBody(new org.elasticsearch.client.HttpGetWithEntity(uri), entity, compressionEnabled); + case HttpHead.METHOD_NAME: + return addRequestBody(new HttpHead(uri), entity, compressionEnabled); + case HttpOptions.METHOD_NAME: + return addRequestBody(new HttpOptions(uri), entity, compressionEnabled); + case HttpPatch.METHOD_NAME: + return addRequestBody(new HttpPatch(uri), entity, compressionEnabled); + case HttpPost.METHOD_NAME: + HttpPost httpPost = new HttpPost(uri); + addRequestBody(httpPost, entity, compressionEnabled); + return httpPost; + case HttpPut.METHOD_NAME: + return addRequestBody(new HttpPut(uri), entity, compressionEnabled); + case HttpTrace.METHOD_NAME: + return addRequestBody(new HttpTrace(uri), entity, compressionEnabled); + default: + throw new UnsupportedOperationException("http method not supported: " + method); + } + } + + private static HttpUriRequestBase addRequestBody(HttpUriRequestBase httpRequest, HttpEntity entity, + boolean compressionEnabled) { + if (entity != null) { + if (canHaveBody(httpRequest)) { + if (compressionEnabled) { + entity = new ContentCompressingEntity(entity); + } + httpRequest.setEntity(entity); + } else { + throw new UnsupportedOperationException(httpRequest.getMethod() + " with body is not " + + "supported"); + } + } + return httpRequest; + } + + private static boolean canHaveBody(HttpRequest httpRequest) { + return httpRequest.getMethod().contains("PUT") || httpRequest.getMethod().contains("POST") || + httpRequest.getMethod().contains("PATCH") || + httpRequest instanceof org.elasticsearch.client.HttpDeleteWithEntity || httpRequest instanceof org.elasticsearch.client.HttpGetWithEntity; + } + + static URI buildUri(String pathPrefix, String path, Map params) { + Objects.requireNonNull(path, "path must not be null"); + try { + String fullPath; + if (pathPrefix != null && pathPrefix.isEmpty() == false) { + if (pathPrefix.endsWith("/") && path.startsWith("/")) { + fullPath = pathPrefix.substring(0, pathPrefix.length() - 1) + path; + } else if (pathPrefix.endsWith("/") || path.startsWith("/")) { + fullPath = pathPrefix + path; + } else { + fullPath = pathPrefix + "/" + path; + } + } else { + fullPath = path; + } + + URIBuilder uriBuilder = new URIBuilder(fullPath); + for (Map.Entry param : params.entrySet()) { + uriBuilder.addParameter(param.getKey(), param.getValue()); + } + return uriBuilder.build(); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e.getMessage(), e); + } + } + + /** + * Listener used in any async call to wrap the provided user listener (or SyncResponseListener in sync + * calls). + * Allows to track potential failures coming from the different retry attempts and returning to the + * original listener + * only when we got a response (successful or not to be retried) or there are no hosts to retry against. + */ + static class FailureTrackingResponseListener { + private final org.elasticsearch.client.ResponseListener responseListener; + private volatile Exception exception; + + FailureTrackingResponseListener(ResponseListener responseListener) { + this.responseListener = responseListener; + } + + /** + * Notifies the caller of a response through the wrapped listener + */ + void onSuccess(org.elasticsearch.client.Response response) { + responseListener.onSuccess(response); + } + + /** + * Tracks one last definitive failure and returns to the caller by notifying the wrapped listener + */ + void onDefinitiveFailure(Exception e) { + trackFailure(e); + responseListener.onFailure(this.exception); + } + + /** + * Tracks an exception, which caused a retry hence we should not return yet to the caller + */ + void trackFailure(Exception e) { + addSuppressedException(this.exception, e); + this.exception = e; + } + } + + /** + * Listener that allows to be notified whenever a failure happens. Useful when sniffing is enabled, so + * that we can sniff on failure. + * The default implementation is a no-op. + */ + public static class FailureListener { + /** + * Notifies that the node provided as argument has just failed + */ + public void onFailure(Node node) { + } + } + + /** + * Contains a reference to a blacklisted node and the time until it is + * revived. We use this so we can do a single pass over the blacklist. + */ + private static class DeadNode implements Comparable { + final Node node; + final org.elasticsearch.client.DeadHostState deadness; + + DeadNode(Node node, org.elasticsearch.client.DeadHostState deadness) { + this.node = node; + this.deadness = deadness; + } + + @Override + public String toString() { + return node.toString(); + } + + @Override + public int compareTo(DeadNode rhs) { + return deadness.compareTo(rhs.deadness); + } + } + + /** + * Adapts an Iterator<DeadNodeAndRevival> into an + * Iterator<Node>. + */ + private static class DeadNodeIteratorAdapter implements Iterator { + private final Iterator itr; + + private DeadNodeIteratorAdapter(Iterator itr) { + this.itr = itr; + } + + @Override + public boolean hasNext() { + return itr.hasNext(); + } + + @Override + public Node next() { + return itr.next().node; + } + + @Override + public void remove() { + itr.remove(); + } + } + + private class InternalRequest { + private final org.elasticsearch.client.Request request; + private final HttpUriRequestBase httpRequest; + private final org.elasticsearch.client.Cancellable cancellable; + private final WarningsHandler warningsHandler; + + InternalRequest(Request request) { + this.request = request; + Map params = new HashMap<>(request.getParameters()); + params.putAll(request.getOptions().getParameters()); + URI uri = buildUri(pathPrefix, request.getEndpoint(), params); + this.httpRequest = createHttpRequest(request.getMethod(), uri, request.getEntity(), + compressionEnabled); + this.cancellable = Cancellable.fromRequest(httpRequest); + setHeaders(httpRequest, request.getOptions().getHeaders()); + setRequestConfig(httpRequest, request.getOptions().getRequestConfig()); + this.warningsHandler = request.getOptions().getWarningsHandler() == null + ? RestClient.this.warningsHandler + : request.getOptions().getWarningsHandler(); + } + + private void setHeaders(HttpRequest req, Collection

requestHeaders) { + // request headers override default headers, so we don't add default headers if they exist as + // request headers + final Set requestNames = new HashSet<>(requestHeaders.size()); + for (Header requestHeader : requestHeaders) { + req.addHeader(requestHeader); + requestNames.add(requestHeader.getName()); + } + for (Header defaultHeader : defaultHeaders) { + if (!requestNames.contains(defaultHeader.getName())) { + req.addHeader(defaultHeader); + } + } + if (compressionEnabled) { + req.addHeader("Accept-Encoding", "gzip"); + } + if (metaHeaderEnabled) { + if (!req.containsHeader(org.elasticsearch.client.RestClientBuilder.META_HEADER_NAME)) { + req.setHeader(org.elasticsearch.client.RestClientBuilder.META_HEADER_NAME, org.elasticsearch.client.RestClientBuilder.META_HEADER_VALUE); + } + } else { + req.removeHeaders(RestClientBuilder.META_HEADER_NAME); + } + } + + private void setRequestConfig(HttpUriRequestBase requestBase, RequestConfig requestConfig) { + if (requestConfig != null) { + requestBase.setConfig(requestConfig); + } + } + + RequestContext createContextForNextAttempt(Node node) { + this.httpRequest.reset(); + return new RequestContext(this, node); + } + } + + private static class RequestContext { + private final Node node; + private final AsyncRequestProducer requestProducer; + private final AsyncResponseConsumer asyncResponseConsumer; + private final HttpClientContext context; + + RequestContext(InternalRequest request, Node node) { + this.node = node; + // we stream the request body if the entity allows for it + AsyncRequestBuilder builder = AsyncRequestBuilder + .create(request.httpRequest.getMethod()) + .setUri(request.httpRequest.getRequestUri()) + .setHttpHost(node.getHost()) + .setHeaders(request.httpRequest.getHeaders()); + + if (request.httpRequest.getEntity() != null) { + builder.setEntity(new BasicAsyncEntityProducer(request.httpRequest.getEntity())); + } + + this.requestProducer = builder.build(); + this.asyncResponseConsumer = request.request.getOptions() + .getHttpAsyncResponseConsumerFactory() + .createHttpAsyncResponseConsumer(); + this.context = HttpClientContext.create(); + } + } + + private static class ResponseOrResponseException { + private final org.elasticsearch.client.Response response; + private final org.elasticsearch.client.ResponseException responseException; + + ResponseOrResponseException(Response response) { + this.response = Objects.requireNonNull(response); + this.responseException = null; + } + + ResponseOrResponseException(ResponseException responseException) { + this.responseException = Objects.requireNonNull(responseException); + this.response = null; + } + } + + /** + * Wrap the exception so the caller's signature shows up in the stack trace, taking care to copy the + * original type and message + * where possible so async and sync code don't have to check different exceptions. + */ + private static Exception extractAndWrapCause(Exception exception) { + if (exception instanceof InterruptedException) { + Thread.currentThread().interrupt(); + throw new RuntimeException("thread waiting for the response was interrupted", exception); + } + if (exception instanceof ExecutionException) { + ExecutionException executionException = (ExecutionException) exception; + Throwable t = executionException.getCause() == null ? executionException : + executionException.getCause(); + if (t instanceof Error) { + throw (Error) t; + } + exception = (Exception) t; + } + if (exception instanceof ConnectTimeoutException) { + ConnectTimeoutException e = new ConnectTimeoutException(exception.getMessage()); + e.initCause(exception); + return e; + } + if (exception instanceof SocketTimeoutException) { + SocketTimeoutException e = new SocketTimeoutException(exception.getMessage()); + e.initCause(exception); + return e; + } + if (exception instanceof ConnectionClosedException) { + ConnectionClosedException e = new ConnectionClosedException(exception.getMessage(), exception); + return e; + } + if (exception instanceof SSLHandshakeException) { + SSLHandshakeException e = new SSLHandshakeException(exception.getMessage()); + e.initCause(exception); + return e; + } + if (exception instanceof ConnectException) { + ConnectException e = new ConnectException(exception.getMessage()); + e.initCause(exception); + return e; + } + if (exception instanceof IOException) { + return new IOException(exception.getMessage(), exception); + } + if (exception instanceof RuntimeException) { + return new RuntimeException(exception.getMessage(), exception); + } + return new RuntimeException("error while performing request", exception); + } + + /** + * A gzip compressing entity that also implements {@code getContent()}. + */ + public static class ContentCompressingEntity extends GzipCompressingEntity { + + public ContentCompressingEntity(HttpEntity entity) { + super(entity); + } + + @Override + public InputStream getContent() throws IOException { + ByteArrayInputOutputStream out = new ByteArrayInputOutputStream(1024); + writeTo(out); + return out.asInput(); + } + } + + /** + * A ByteArrayOutputStream that can be turned into an input stream without copying the underlying buffer. + */ + private static class ByteArrayInputOutputStream extends ByteArrayOutputStream { + ByteArrayInputOutputStream(int size) { + super(size); + } + + public InputStream asInput() { + return new ByteArrayInputStream(this.buf, 0, this.count); + } + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RestClientBuilder.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RestClientBuilder.java new file mode 100644 index 000000000..fee7ff220 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RestClientBuilder.java @@ -0,0 +1,379 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level_client; + + +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.nio.ssl.BasicClientTlsStrategy; +import org.apache.hc.core5.util.Timeout; +import org.apache.hc.core5.util.VersionInfo; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.node.Node; +import org.elasticsearch.client.node.selector.NodeSelector; + +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.io.InputStream; +import java.security.NoSuchAlgorithmException; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.Properties; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +import static org.elasticsearch.client.LanguageRuntimeVersions.getRuntimeMetadata; + +/** + * Helps creating a new {@link RestClient}. Allows to set the most common http client configuration options + * when internally + * creating the underlying {@link org.apache.hc.client5.http.async.HttpAsyncClient}. Also allows to provide + * an externally created + * {@link org.apache.hc.client5.http.async.HttpAsyncClient} in case additional customization is needed. + */ +public final class RestClientBuilder { + public static final int DEFAULT_CONNECT_TIMEOUT_MILLIS = 1000; + public static final int DEFAULT_SOCKET_TIMEOUT_MILLIS = 30000; + public static final int DEFAULT_MAX_CONN_PER_ROUTE = 10; + public static final int DEFAULT_MAX_CONN_TOTAL = 30; + + static final String THREAD_NAME_PREFIX = "elasticsearch-rest-client-"; + private static final String THREAD_NAME_FORMAT = THREAD_NAME_PREFIX + "%d-thread-%d"; + + public static final String VERSION; + static final String META_HEADER_NAME = "X-Elastic-Client-Meta"; + static final String META_HEADER_VALUE; + private static final String USER_AGENT_HEADER_VALUE; + + private static final Header[] EMPTY_HEADERS = new Header[0]; + + private final List nodes; + private CloseableHttpAsyncClient httpClient; + private Header[] defaultHeaders = EMPTY_HEADERS; + private RestClient.FailureListener failureListener; + private SSLContext sslContext; + private String pathPrefix; + private NodeSelector nodeSelector = NodeSelector.ANY; + private boolean strictDeprecationMode = false; + private boolean compressionEnabled = false; + private boolean metaHeaderEnabled = true; + + static { + // Never fail on unknown version, even if an environment messed up their classpath enough that we + // can't find it. + // Better have incomplete telemetry than crashing user applications. + String version = null; + try (InputStream is = RestClient.class.getResourceAsStream("version.properties")) { + if (is != null) { + Properties versions = new Properties(); + versions.load(is); + version = versions.getProperty("elasticsearch-client"); + } + } catch (IOException e) { + // Keep version unknown + } + + if (version == null) { + version = ""; // unknown values are reported as empty strings in X-Elastic-Client-Meta + } + + VERSION = version; + + USER_AGENT_HEADER_VALUE = String.format( + Locale.ROOT, + "elasticsearch-java/%s (Java/%s)", + VERSION.isEmpty() ? "Unknown" : VERSION, + System.getProperty("java.version") + ); + + VersionInfo httpClientVersion = null; + try { + httpClientVersion = VersionInfo.loadVersionInfo( + "org.apache.hc.core5", + HttpAsyncClientBuilder.class.getClassLoader() + + ); + } catch (Exception e) { + // Keep unknown + } + + // Use a single 'p' suffix for all prerelease versions (snapshot, beta, etc). + String metaVersion = version; + int dashPos = metaVersion.indexOf('-'); + if (dashPos > 0) { + metaVersion = metaVersion.substring(0, dashPos) + "p"; + } + + // service, language, transport, followed by additional information + META_HEADER_VALUE = "es=" + + metaVersion + + ",jv=" + + System.getProperty("java.specification.version") + + ",t=" + + metaVersion + + ",hc=" + + (httpClientVersion == null ? "" : httpClientVersion.getRelease()) + + getRuntimeMetadata(); + } + + /** + * Creates a new builder instance and sets the hosts that the client will send requests to. + * + * @throws IllegalArgumentException if {@code nodes} is {@code null} or empty. + */ + RestClientBuilder(List nodes) { + if (nodes == null || nodes.isEmpty()) { + throw new IllegalArgumentException("nodes must not be null or empty"); + } + for (Node node : nodes) { + if (node == null) { + throw new IllegalArgumentException("node cannot be null"); + } + } + this.nodes = nodes; + } + + /** + * Advanced setting, sets the rest client that will be used to handle requests. + * The rest client has to be fully configured, as it will be used as provided. + * + * @throws NullPointerException if {@code httpAsyncClient} is {@code null}. + */ + public RestClientBuilder setCustomRestClient(CloseableHttpAsyncClient httpAsyncClient) { + Objects.requireNonNull(httpAsyncClient, "custom rest client must not be null"); + this.httpClient = httpAsyncClient; + return this; + } + + /** + * Sets the SSL context, which will be applied to all requests. + * + * @throws NullPointerException if {@code httpAsyncClient} is {@code null}. + */ + public RestClientBuilder setSslContext(SSLContext sslContext) { + Objects.requireNonNull(sslContext, "ssl context must not be null"); + this.sslContext = sslContext; + return this; + } + + /** + * Sets the default request headers, which will be sent along with each request. + *

+ * Request-time headers will always overwrite any default headers. + * + * @throws NullPointerException if {@code defaultHeaders} or any header is {@code null}. + */ + public RestClientBuilder setDefaultHeaders(Header[] defaultHeaders) { + Objects.requireNonNull(defaultHeaders, "defaultHeaders must not be null"); + for (Header defaultHeader : defaultHeaders) { + Objects.requireNonNull(defaultHeader, "default header must not be null"); + } + this.defaultHeaders = defaultHeaders; + return this; + } + + + /** + * Sets the {@link RestClient.FailureListener} to be notified for each request failure + * + * @throws NullPointerException if {@code failureListener} is {@code null}. + */ + public RestClientBuilder setFailureListener(RestClient.FailureListener failureListener) { + Objects.requireNonNull(failureListener, "failureListener must not be null"); + this.failureListener = failureListener; + return this; + } + + + /** + * Sets the path's prefix for every request used by the http client. + *

+ * For example, if this is set to "/my/path", then any client request will become "/my/path/" + + * endpoint. + *

+ * In essence, every request's {@code endpoint} is prefixed by this {@code pathPrefix}. The path prefix + * is useful for when + * Elasticsearch is behind a proxy that provides a base path or a proxy that requires all paths to + * start with '/'; + * it is not intended for other purposes and it should not be supplied in other scenarios. + * + * @throws NullPointerException if {@code pathPrefix} is {@code null}. + * @throws IllegalArgumentException if {@code pathPrefix} is empty, or ends with more than one '/'. + */ + public RestClientBuilder setPathPrefix(String pathPrefix) { + this.pathPrefix = cleanPathPrefix(pathPrefix); + return this; + } + + public static String cleanPathPrefix(String pathPrefix) { + Objects.requireNonNull(pathPrefix, "pathPrefix must not be null"); + + if (pathPrefix.isEmpty()) { + throw new IllegalArgumentException("pathPrefix must not be empty"); + } + + String cleanPathPrefix = pathPrefix; + if (!cleanPathPrefix.startsWith("/")) { + cleanPathPrefix = "/" + cleanPathPrefix; + } + + // best effort to ensure that it looks like "/base/path" rather than "/base/path/" + if (cleanPathPrefix.endsWith("/") && cleanPathPrefix.length() > 1) { + cleanPathPrefix = cleanPathPrefix.substring(0, cleanPathPrefix.length() - 1); + + if (cleanPathPrefix.endsWith("/")) { + throw new IllegalArgumentException("pathPrefix is malformed. too many trailing slashes: [" + pathPrefix + "]"); + } + } + return cleanPathPrefix; + } + + /** + * Sets the {@link NodeSelector} to be used for all requests. + * + * @throws NullPointerException if the provided nodeSelector is null + */ + public RestClientBuilder setNodeSelector(NodeSelector nodeSelector) { + Objects.requireNonNull(nodeSelector, "nodeSelector must not be null"); + this.nodeSelector = nodeSelector; + return this; + } + + /** + * Whether the REST client should return any response containing at least + * one warning header as a failure. + */ + public RestClientBuilder setStrictDeprecationMode(boolean strictDeprecationMode) { + this.strictDeprecationMode = strictDeprecationMode; + return this; + } + + /** + * Whether the REST client should compress requests using gzip content encoding and add the + * "Accept-Encoding: gzip" + * header to receive compressed responses. + */ + public RestClientBuilder setCompressionEnabled(boolean compressionEnabled) { + this.compressionEnabled = compressionEnabled; + return this; + } + + /** + * Whether to send a {@code X-Elastic-Client-Meta} header that describes the runtime environment. It + * contains + * information that is similar to what could be found in {@code User-Agent}. Using a separate header + * allows + * applications to use {@code User-Agent} for their own needs, e.g. to identify application version or + * other + * environment information. Defaults to {@code true}. + */ + public RestClientBuilder setMetaHeaderEnabled(boolean metadataEnabled) { + this.metaHeaderEnabled = metadataEnabled; + return this; + } + + /** + * Creates a new {@link RestClient} based on the provided configuration. + */ + public RestClient build() { + if (failureListener == null) { + failureListener = new RestClient.FailureListener(); + } + CloseableHttpAsyncClient httpClient = this.createHttpClient(); + RestClient restClient = new RestClient( + httpClient, + defaultHeaders, + nodes, + pathPrefix, + failureListener, + nodeSelector, + strictDeprecationMode, + compressionEnabled, + metaHeaderEnabled + ); + httpClient.start(); + return restClient; + } + + /** + * Similar to {@code org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor + * .DefaultThreadFactory} but with better thread names. + */ + private static class RestClientThreadFactory implements ThreadFactory { + private static final AtomicLong CLIENT_THREAD_POOL_ID_GENERATOR = new AtomicLong(); + + private final long clientThreadPoolId = CLIENT_THREAD_POOL_ID_GENERATOR.getAndIncrement(); // 0-based + private final AtomicLong clientThreadId = new AtomicLong(); + + @Override + public Thread newThread(Runnable runnable) { + return new Thread( + runnable, + String.format(Locale.ROOT, THREAD_NAME_FORMAT, clientThreadPoolId, + clientThreadId.incrementAndGet()) // 1-based + ); + } + } + + private CloseableHttpAsyncClient createHttpClient() { + // if the user provided a client, using that one + if (this.httpClient != null) { + return this.httpClient; + } + // otherwise, creating a default instance of CloseableHttpAsyncClient + // default timeouts are all infinite + RequestConfig.Builder requestConfigBuilder = RequestConfig.custom() + //.setConnectionRequestTimeout() new name for socket timeout + .setConnectTimeout(Timeout.of(DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); + //.setSocketTimeout(DEFAULT_SOCKET_TIMEOUT_MILLIS); TODO needed? check discussions, which one we + // should remove + + try { + + SSLContext sslContext = this.sslContext != null ? this.sslContext : SSLContext.getDefault(); + + PoolingAsyncClientConnectionManager defaultConnectionManager = + PoolingAsyncClientConnectionManagerBuilder.create() + .setMaxConnPerRoute(DEFAULT_MAX_CONN_PER_ROUTE) + .setMaxConnTotal(DEFAULT_MAX_CONN_TOTAL) + .setTlsStrategy(new BasicClientTlsStrategy(sslContext)) + .build(); + + HttpAsyncClientBuilder httpClientBuilder = HttpAsyncClientBuilder.create() + .setDefaultRequestConfig(requestConfigBuilder.build()) + .setConnectionManager(defaultConnectionManager) + .setUserAgent(USER_AGENT_HEADER_VALUE) + .setTargetAuthenticationStrategy(new DefaultAuthenticationStrategy()) + .setThreadFactory(new RestClientThreadFactory()); + + return httpClientBuilder.build(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException("could not create the default ssl context", e); + } + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/WarningFailureException.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/WarningFailureException.java new file mode 100644 index 000000000..31c373cc6 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/WarningFailureException.java @@ -0,0 +1,62 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level_client; + +import org.elasticsearch.client.Response; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; + +import java.io.IOException; + +import static org.elasticsearch.client.ResponseException.buildMessage; + +/** + * This exception is used to indicate that one or more {@link Response#getWarnings()} exist + * and is typically used when the {@link RestClient} is set to fail by setting + * {@link RestClientBuilder#setStrictDeprecationMode(boolean)} to `true`. + */ +// This class extends RuntimeException in order to deal with wrapping that is done in FutureUtils on exception. +// if the exception is not of type ElasticsearchException or RuntimeException it will be wrapped in a UncategorizedExecutionException +public final class WarningFailureException extends RuntimeException { + + private final Response response; + + public WarningFailureException(Response response) throws IOException { + super(buildMessage(response)); + this.response = response; + } + + /** + * Wrap a {@linkplain WarningFailureException} with another one with the current + * stack trace. This is used during synchronous calls so that the caller + * ends up in the stack trace of the exception thrown. + */ + WarningFailureException(WarningFailureException e) { + super(e.getMessage(), e); + this.response = e.getResponse(); + } + + /** + * Returns the {@link Response} that caused this exception to be thrown. + */ + public Response getResponse() { + return response; + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/WarningsHandler.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/WarningsHandler.java new file mode 100644 index 000000000..3a60e0705 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/WarningsHandler.java @@ -0,0 +1,53 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level_client; + +import java.util.List; + +/** + * Called if there are warnings to determine if those warnings should fail the + * request. + */ +public interface WarningsHandler { + boolean warningsShouldFailRequest(List warnings); + + WarningsHandler PERMISSIVE = new WarningsHandler() { + @Override + public boolean warningsShouldFailRequest(List warnings) { + return false; + } + + @Override + public String toString() { + return "permissive"; + } + }; + WarningsHandler STRICT = new WarningsHandler() { + @Override + public boolean warningsShouldFailRequest(List warnings) { + return false == warnings.isEmpty(); + } + + @Override + public String toString() { + return "strict"; + } + }; +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/BasicAsyncResponseConsumer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/BasicAsyncResponseConsumer.java new file mode 100644 index 000000000..6c3bae2f1 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/BasicAsyncResponseConsumer.java @@ -0,0 +1,60 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level_client.consumer; + + +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.core5.http.io.entity.ByteArrayEntity; +import org.apache.hc.core5.http.message.BasicClassicHttpResponse; +import org.apache.hc.core5.http.nio.entity.AbstractBinAsyncEntityConsumer; +import org.apache.hc.core5.http.nio.support.AbstractAsyncResponseConsumer; +import org.apache.hc.core5.http.protocol.HttpContext; + +public class BasicAsyncResponseConsumer extends AbstractAsyncResponseConsumer { + + private volatile BasicClassicHttpResponse finalResponse; + private volatile HttpResponse response; + private volatile HttpContext context; + + /** + * Creates a new instance of this consumer with the provided buffer limit + */ + public BasicAsyncResponseConsumer(AbstractBinAsyncEntityConsumer consumer) { + super(consumer); + } + + @Override + public void informationResponse(HttpResponse response, HttpContext context) { + this.response = response; + this.context = context; + } + + @Override + protected BasicClassicHttpResponse buildResult(HttpResponse response, ByteArrayEntity entity, + ContentType contentType) { + finalResponse = new BasicClassicHttpResponse(response.getCode(), response.getReasonPhrase()); + finalResponse.setEntity(entity); + finalResponse.setHeaders(response.getHeaders()); + return finalResponse; + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/BufferedByteConsumer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/BufferedByteConsumer.java new file mode 100644 index 000000000..841c59eb4 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/BufferedByteConsumer.java @@ -0,0 +1,76 @@ +/* + * 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. + */ +package co.elastic.clients.transport.rest5_client.low_level_client.consumer; + +import org.apache.hc.core5.http.ContentTooLongException; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.io.entity.ByteArrayEntity; +import org.apache.hc.core5.http.nio.entity.AbstractBinAsyncEntityConsumer; +import org.apache.hc.core5.util.ByteArrayBuffer; + +import java.nio.ByteBuffer; + +import static org.elasticsearch.client.utils.Constants.DEFAULT_BUFFER_INITIAL_CAPACITY; + +public class BufferedByteConsumer extends AbstractBinAsyncEntityConsumer { + + private volatile ByteArrayBuffer buffer; + private final int limit; + private ContentType contentType; + + public BufferedByteConsumer(int bufferLimit) { + super(); + if (bufferLimit <= 0) { + throw new IllegalArgumentException("Buffer limit must be greater than 0"); + } + this.limit = bufferLimit; + this.buffer = new ByteArrayBuffer(DEFAULT_BUFFER_INITIAL_CAPACITY); + } + + @Override + protected void streamStart(final ContentType contentType) { + this.contentType = contentType; + } + + @Override + protected int capacityIncrement() { + return limit; + } + + @Override + protected void data(final ByteBuffer src, final boolean endOfStream) throws ContentTooLongException { + if (src.capacity() > limit) { //TODO why though? the server already has a 100MB limit. also, this method is called multiple times. check if should be src.capacity + buffer.length + throw new ContentTooLongException( + "entity content is too long [" + src.capacity() + "] for the configured buffer limit [" + limit + "]" + ); + } + buffer.append(src); + } + + @Override + protected ByteArrayEntity generateContent() { + return new ByteArrayEntity(buffer.toByteArray(), contentType); + } + + @Override + public void releaseResources() { + buffer.clear(); + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/HttpAsyncResponseConsumerFactory.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/HttpAsyncResponseConsumerFactory.java new file mode 100644 index 000000000..1d962aafc --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/HttpAsyncResponseConsumerFactory.java @@ -0,0 +1,66 @@ +/* + * 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. + */ +package co.elastic.clients.transport.rest5_client.low_level_client.consumer; + +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.nio.AsyncResponseConsumer; +import org.apache.hc.core5.http.nio.support.AbstractAsyncResponseConsumer; + +import static org.elasticsearch.client.utils.Constants.DEFAULT_BUFFER_LIMIT; + +/** + * Factory used to create instances of {@link AsyncResponseConsumer}. Each request retry needs its own + * instance of the + * consumer object. Users can implement this interface and pass their own instance to the specialized + * performRequest methods that accept an {@link HttpAsyncResponseConsumerFactory} instance as argument. + */ +public interface HttpAsyncResponseConsumerFactory { + + /** + * Creates the default type of {@link AsyncResponseConsumer}, + * with a buffered consumer with a limit of 100MB. + */ + HttpAsyncResponseConsumerFactory DEFAULT = + new BasicAsyncResponseConsumerFactory(DEFAULT_BUFFER_LIMIT); + + /** + * Creates the {@link AbstractAsyncResponseConsumer}, called once per request attempt. + */ + AsyncResponseConsumer createHttpAsyncResponseConsumer(); + + /** + * Default factory used to create instances of {@link AsyncResponseConsumer}. + * Creates one instance of {@link BasicAsyncResponseConsumer} for each request attempt, with a + * configurable + * buffer limit which defaults to 100MB. + */ + class BasicAsyncResponseConsumerFactory implements HttpAsyncResponseConsumerFactory { + + private final int bufferLimit; + + public BasicAsyncResponseConsumerFactory(int bufferLimit) { + this.bufferLimit = bufferLimit; + } + + @Override + public AsyncResponseConsumer createHttpAsyncResponseConsumer() { + return new BasicAsyncResponseConsumer(new BufferedByteConsumer(bufferLimit)); + } + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/Node.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/Node.java new file mode 100644 index 000000000..9df6c3eff --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/Node.java @@ -0,0 +1,278 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level_client.node; + +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.client.node.selector.NodeSelector; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.TreeSet; + +/** + * Metadata about an {@link HttpHost} running Elasticsearch. + */ +public class Node { + /** + * Address that this host claims is its primary contact point. + */ + private final HttpHost host; + /** + * Addresses on which the host is listening. These are useful to have + * around because they allow you to find a host based on any address it + * is listening on. + */ + private final Set boundHosts; + /** + * Name of the node as configured by the {@code node.name} attribute. + */ + private final String name; + /** + * Version of Elasticsearch that the node is running or {@code null} + * if we don't know the version. + */ + private final String version; + /** + * Roles that the Elasticsearch process on the host has or {@code null} + * if we don't know what roles the node has. + */ + private final Roles roles; + /** + * Attributes declared on the node. + */ + private final Map> attributes; + + /** + * Create a {@linkplain Node} with metadata. All parameters except + * {@code host} are nullable and implementations of {@link NodeSelector} + * need to decide what to do in their absence. + */ + public Node(HttpHost host, Set boundHosts, String name, String version, Roles roles, Map> attributes) { + if (host == null) { + throw new IllegalArgumentException("host cannot be null"); + } + this.host = host; + this.boundHosts = boundHosts; + this.name = name; + this.version = version; + this.roles = roles; + this.attributes = attributes; + } + + /** + * Create a {@linkplain Node} without any metadata. + */ + public Node(HttpHost host) { + this(host, null, null, null, null, null); + } + + /** + * Contact information for the host. + */ + public HttpHost getHost() { + return host; + } + + /** + * Addresses on which the host is listening. These are useful to have + * around because they allow you to find a host based on any address it + * is listening on. + */ + public Set getBoundHosts() { + return boundHosts; + } + + /** + * The {@code node.name} of the node. + */ + public String getName() { + return name; + } + + /** + * Version of Elasticsearch that the node is running or {@code null} + * if we don't know the version. + */ + public String getVersion() { + return version; + } + + /** + * Roles that the Elasticsearch process on the host has or {@code null} + * if we don't know what roles the node has. + */ + public Roles getRoles() { + return roles; + } + + /** + * Attributes declared on the node. + */ + public Map> getAttributes() { + return attributes; + } + + @Override + public String toString() { + StringBuilder b = new StringBuilder(); + b.append("[host=").append(host); + if (boundHosts != null) { + b.append(", bound=").append(boundHosts); + } + if (name != null) { + b.append(", name=").append(name); + } + if (version != null) { + b.append(", version=").append(version); + } + if (roles != null) { + b.append(", roles=").append(roles); + } + if (attributes != null) { + b.append(", attributes=").append(attributes); + } + return b.append(']').toString(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null || obj.getClass() != getClass()) { + return false; + } + Node other = (Node) obj; + return host.equals(other.host) + && Objects.equals(boundHosts, other.boundHosts) + && Objects.equals(name, other.name) + && Objects.equals(version, other.version) + && Objects.equals(roles, other.roles) + && Objects.equals(attributes, other.attributes); + } + + @Override + public int hashCode() { + return Objects.hash(host, boundHosts, name, version, roles, attributes); + } + + /** + * Role information about an Elasticsearch process. + */ + public static final class Roles { + + private final Set roles; + + public Roles(final Set roles) { + this.roles = new TreeSet<>(roles); + } + + /** + * Returns whether or not the node could be elected master. + */ + public boolean isMasterEligible() { + return roles.contains("master"); + } + + /** + * Returns whether or not the node stores data. + * @deprecated use {@link #hasDataRole()} or {@link #canContainData()} + */ + @Deprecated + public boolean isData() { + return roles.contains("data"); + } + + /** + * @return true if node has the "data" role + */ + public boolean hasDataRole() { + return roles.contains("data"); + } + + /** + * @return true if node has the "data_content" role + */ + public boolean hasDataContentRole() { + return roles.contains("data_content"); + } + + /** + * @return true if node has the "data_hot" role + */ + public boolean hasDataHotRole() { + return roles.contains("data_hot"); + } + + /** + * @return true if node has the "data_warm" role + */ + public boolean hasDataWarmRole() { + return roles.contains("data_warm"); + } + + /** + * @return true if node has the "data_cold" role + */ + public boolean hasDataColdRole() { + return roles.contains("data_cold"); + } + + /** + * @return true if node has the "data_frozen" role + */ + public boolean hasDataFrozenRole() { + return roles.contains("data_frozen"); + } + + /** + * @return true if node stores any type of data + */ + public boolean canContainData() { + return hasDataRole() || roles.stream().anyMatch(role -> role.startsWith("data_")); + } + + /** + * Returns whether or not the node runs ingest pipelines. + */ + public boolean isIngest() { + return roles.contains("ingest"); + } + + @Override + public String toString() { + return String.join(",", roles); + } + + @Override + public boolean equals(Object obj) { + if (obj == null || obj.getClass() != getClass()) { + return false; + } + Roles other = (Roles) obj; + return roles.equals(other.roles); + } + + @Override + public int hashCode() { + return roles.hashCode(); + } + + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/HasAttributeNodeSelector.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/HasAttributeNodeSelector.java new file mode 100644 index 000000000..df3beba49 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/HasAttributeNodeSelector.java @@ -0,0 +1,76 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level_client.node.selector; + +import org.elasticsearch.client.node.Node; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * A {@link NodeSelector} that selects nodes that have a particular value + * for an attribute. + */ +public final class HasAttributeNodeSelector implements NodeSelector { + private final String key; + private final String value; + + public HasAttributeNodeSelector(String key, String value) { + this.key = key; + this.value = value; + } + + @Override + public void select(Iterable nodes) { + Iterator itr = nodes.iterator(); + while (itr.hasNext()) { + Map> allAttributes = itr.next().getAttributes(); + if (allAttributes == null) continue; + List values = allAttributes.get(key); + if (values == null || !values.contains(value)) { + itr.remove(); + } + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + HasAttributeNodeSelector that = (HasAttributeNodeSelector) o; + return Objects.equals(key, that.key) && Objects.equals(value, that.value); + } + + @Override + public int hashCode() { + return Objects.hash(key, value); + } + + @Override + public String toString() { + return key + "=" + value; + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/NodeSelector.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/NodeSelector.java new file mode 100644 index 000000000..2a7d5500e --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/NodeSelector.java @@ -0,0 +1,95 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level_client.node.selector; + +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; +import org.elasticsearch.client.node.Node; + +import java.util.Iterator; + +/** + * Selects nodes that can receive requests. Used to keep requests away + * from master nodes or to send them to nodes with a particular attribute. + * Use with {@link RestClientBuilder#setNodeSelector(NodeSelector)}. + */ +public interface NodeSelector { + /** + * Select the {@link Node}s to which to send requests. This is called with + * a mutable {@link Iterable} of {@linkplain Node}s in the order that the + * rest client would prefer to use them and implementers should remove + * nodes from the that should not receive the request. Implementers may + * iterate the nodes as many times as they need. + *

+ * This may be called twice per request: first for "living" nodes that + * have not been blacklisted by previous errors. If the selector removes + * all nodes from the list or if there aren't any living nodes then the + * {@link RestClient} will call this method with a list of "dead" nodes. + *

+ * Implementers should not rely on the ordering of the nodes. + */ + void select(Iterable nodes); + /* + * We were fairly careful with our choice of Iterable here. The caller has + * a List but reordering the list is likely to break round robin. Luckily + * Iterable doesn't allow any reordering. + */ + + /** + * Selector that matches any node. + */ + NodeSelector ANY = new NodeSelector() { + @Override + public void select(Iterable nodes) { + // Intentionally does nothing + } + + @Override + public String toString() { + return "ANY"; + } + }; + + /** + * Selector that matches any node that has metadata and doesn't + * have the {@code master} role OR it has the data {@code data} + * role. + */ + NodeSelector SKIP_DEDICATED_MASTERS = new NodeSelector() { + @Override + public void select(Iterable nodes) { + Iterator itr = nodes.iterator(); + while (itr.hasNext()) { + Node node = itr.next(); + if (node.getRoles() == null) continue; + if (node.getRoles().isMasterEligible() + && !node.getRoles().canContainData() + && !node.getRoles().isIngest()) { + itr.remove(); + } + } + } + + @Override + public String toString() { + return "SKIP_DEDICATED_MASTERS"; + } + }; +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/PreferHasAttributeNodeSelector.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/PreferHasAttributeNodeSelector.java new file mode 100644 index 000000000..d860a3753 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/PreferHasAttributeNodeSelector.java @@ -0,0 +1,105 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level_client.node.selector; + +import org.elasticsearch.client.node.Node; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Both {@link PreferHasAttributeNodeSelector} and {@link HasAttributeNodeSelector} will work the same + * if there is a {@link Node} with particular attribute in the attributes, + * but {@link PreferHasAttributeNodeSelector} will select another {@link Node}s even if there is no + * {@link Node} + * with particular attribute in the attributes. + */ +public final class PreferHasAttributeNodeSelector implements NodeSelector { + private final String key; + private final String value; + + public PreferHasAttributeNodeSelector(String key, String value) { + this.key = key; + this.value = value; + } + + @Override + public void select(Iterable nodes) { + boolean foundAtLeastOne = false; + + for (Node node : nodes) { + Map> attributes = node.getAttributes(); + + if (attributes == null) { + continue; + } + + List values = attributes.get(key); + + if (values == null) { + continue; + } + + if (values.contains(value)) { + foundAtLeastOne = true; + break; + } + } + + if (foundAtLeastOne) { + Iterator itr = nodes.iterator(); + while (itr.hasNext()) { + Map> attributes = itr.next().getAttributes(); + if (attributes == null) { + continue; + } + List values = attributes.get(key); + + if (values == null || !values.contains(value)) { + itr.remove(); + } + } + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PreferHasAttributeNodeSelector that = (PreferHasAttributeNodeSelector) o; + return Objects.equals(key, that.key) && Objects.equals(value, that.value); + } + + @Override + public int hashCode() { + return Objects.hash(key, value); + } + + @Override + public String toString() { + return key + "=" + value; + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/producer/BasicAsyncEntityProducer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/producer/BasicAsyncEntityProducer.java new file mode 100644 index 000000000..c1732071f --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/producer/BasicAsyncEntityProducer.java @@ -0,0 +1,128 @@ +package co.elastic.clients.transport.rest5_client.low_level_client.producer; + +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.nio.AsyncEntityProducer; +import org.apache.hc.core5.http.nio.DataStreamChannel; +import org.apache.hc.core5.util.Args; + +import java.io.IOException; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; + +import static org.elasticsearch.client.utils.Constants.DEFAULT_BUFFER_INITIAL_CAPACITY; + +/** + * Basic implementation of {@link AsyncEntityProducer} + */ +public class BasicAsyncEntityProducer implements AsyncEntityProducer { + + private final HttpEntity entity; + private final ByteBuffer buffer; + private final AtomicReference channelRef; + private final AtomicReference exceptionRef; + private final String contentType; + private final boolean isChunked; + private boolean eof; + + /** + * Create new basic entity producer + */ + public BasicAsyncEntityProducer(final HttpEntity entity, final int bufferSize) { + this.entity = Args.notNull(entity, "Http Entity"); + this.buffer = ByteBuffer.allocate(bufferSize); + this.channelRef = new AtomicReference<>(); + this.exceptionRef = new AtomicReference<>(); + this.contentType = entity.getContentType(); + this.isChunked = entity.isChunked(); + } + + /** + * Create new basic entity producer with default buffer limit of 100MB + */ + public BasicAsyncEntityProducer(final HttpEntity entity) { + this(entity, DEFAULT_BUFFER_INITIAL_CAPACITY); + } + + @Override + public boolean isRepeatable() { + return entity.isRepeatable(); + } + + @Override + public String getContentType() { + return this.contentType; + } + + @Override + public long getContentLength() { + return entity.getContentLength(); + } + + @Override + public int available() { + return Integer.MAX_VALUE; + } + + @Override + public String getContentEncoding() { + return entity.getContentEncoding(); + } + + @Override + public boolean isChunked() { + return this.isChunked; + } + + @Override + public Set getTrailerNames() { + return entity.getTrailerNames(); + } + + @Override + public void produce(final DataStreamChannel dataStream) throws IOException { + ReadableByteChannel channel = channelRef.get(); + if (channel == null) { + channel = Channels.newChannel(entity.getContent()); + channelRef.getAndSet(channel); + } + if (!eof) { + final int bytesRead = channel.read(buffer); + if (bytesRead < 0) { + eof = true; + } + } + if (buffer.position() > 0) { + ((Buffer) buffer).flip(); + dataStream.write(buffer); + buffer.compact(); + } + if (eof && buffer.position() == 0) { + dataStream.endStream(); + releaseResources(); + } + } + + @Override + public void failed(final Exception cause) { + if (exceptionRef.compareAndSet(null, cause)) { + releaseResources(); + } + } + + @Override + public void releaseResources() { + eof = false; + ReadableByteChannel channel = channelRef.getAndSet(null); + if (channel != null) { + try { + channel.close(); + } catch (IOException e) { + } + } + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/utils/Constants.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/utils/Constants.java new file mode 100644 index 000000000..6089a2f38 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/utils/Constants.java @@ -0,0 +1,7 @@ +package co.elastic.clients.transport.rest5_client.low_level_client.utils; + +public class Constants { + // default buffer limit is 100MB + public static final int DEFAULT_BUFFER_LIMIT = 100 * 1024 * 1024; + public static final int DEFAULT_BUFFER_INITIAL_CAPACITY = 8192; +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java index 066584f60..193a9b336 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java @@ -28,7 +28,7 @@ import co.elastic.clients.transport.JsonEndpoint; import co.elastic.clients.transport.Version; import co.elastic.clients.transport.endpoints.DelegatingJsonEndpoint; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.rest5_client.RestClientTransport; import org.apache.commons.io.FileUtils; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpHost; diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuildersTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuildersTest.java index 3c0d3dcab..daa94b89f 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuildersTest.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuildersTest.java @@ -20,9 +20,8 @@ package co.elastic.clients.elasticsearch._helpers.builders; import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.transport.rest_client.RestClientOptions; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.rest5_client.RestClientOptions; +import co.elastic.clients.transport.rest5_client.RestClientTransport; import org.elasticsearch.client.RequestOptions; import org.junit.jupiter.api.Test; diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java index f54caa27d..6728e6dca 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java @@ -25,7 +25,7 @@ import co.elastic.clients.elasticsearch._helpers.esql.jdbc.ResultSetEsqlAdapter; import co.elastic.clients.elasticsearch._helpers.esql.objects.ObjectsEsqlAdapter; import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.rest5_client.RestClientTransport; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.io.entity.ByteArrayEntity; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java b/java-client/src/test/java/co/elastic/clients/transport5/RequestOptionsTest.java similarity index 98% rename from java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java rename to java-client/src/test/java/co/elastic/clients/transport5/RequestOptionsTest.java index 46e725df9..3a3e50286 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport5/RequestOptionsTest.java @@ -17,11 +17,11 @@ * under the License. */ -package co.elastic.clients.transport; +package co.elastic.clients.transport5; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.rest5_client.RestClientTransport; import com.sun.net.httpserver.HttpServer; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.NameValuePair; diff --git a/java-client/src/test/java/co/elastic/clients/transport/TransportTest.java b/java-client/src/test/java/co/elastic/clients/transport5/TransportTest.java similarity index 97% rename from java-client/src/test/java/co/elastic/clients/transport/TransportTest.java rename to java-client/src/test/java/co/elastic/clients/transport5/TransportTest.java index d01d93961..dec29b338 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/TransportTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport5/TransportTest.java @@ -17,14 +17,14 @@ * under the License. */ -package co.elastic.clients.transport; +package co.elastic.clients.transport5; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.jackson.JacksonJsonpMapper; import co.elastic.clients.transport.http.RepeatableBodyResponse; import co.elastic.clients.transport.http.TransportHttpClient; -import co.elastic.clients.transport.rest_client.RestClientOptions; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.rest5_client.RestClientOptions; +import co.elastic.clients.transport.rest5_client.RestClientTransport; import co.elastic.clients.util.BinaryData; import com.sun.net.httpserver.HttpServer; import org.apache.hc.core5.http.HttpHost; diff --git a/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java b/java-client/src/test/java/co/elastic/clients/transport5/TransportUtilsTest.java similarity index 97% rename from java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java rename to java-client/src/test/java/co/elastic/clients/transport5/TransportUtilsTest.java index 06a475373..bfe836793 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport5/TransportUtilsTest.java @@ -17,12 +17,12 @@ * under the License. */ -package co.elastic.clients.transport; +package co.elastic.clients.transport5; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch.ElasticsearchTestServer; import co.elastic.clients.json.SimpleJsonpMapper; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.rest5_client.RestClientTransport; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.message.BasicHeader; diff --git a/java-client/src/test/java/co/elastic/clients/transport/VersionInfoTest.java b/java-client/src/test/java/co/elastic/clients/transport5/VersionInfoTest.java similarity index 96% rename from java-client/src/test/java/co/elastic/clients/transport/VersionInfoTest.java rename to java-client/src/test/java/co/elastic/clients/transport5/VersionInfoTest.java index 001fcbd41..c324c21ed 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/VersionInfoTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport5/VersionInfoTest.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport; +package co.elastic.clients.transport5; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/java-client/src/test/java/co/elastic/clients/transport/endpoints/BinaryEndpointTest.java b/java-client/src/test/java/co/elastic/clients/transport5/endpoints/BinaryEndpointTest.java similarity index 97% rename from java-client/src/test/java/co/elastic/clients/transport/endpoints/BinaryEndpointTest.java rename to java-client/src/test/java/co/elastic/clients/transport5/endpoints/BinaryEndpointTest.java index 2c4426509..aaf3ea549 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/endpoints/BinaryEndpointTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport5/endpoints/BinaryEndpointTest.java @@ -17,14 +17,14 @@ * under the License. */ -package co.elastic.clients.transport.endpoints; +package co.elastic.clients.transport5.endpoints; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch.ElasticsearchTestServer; import co.elastic.clients.elasticsearch.core.SearchRequest; import co.elastic.clients.json.SimpleJsonpMapper; import co.elastic.clients.transport.TransportOptions; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.rest5_client.RestClientTransport; import com.sun.net.httpserver.HttpServer; import org.apache.commons.io.IOUtils; import org.apache.hc.core5.http.HttpHost; diff --git a/java-client/src/test/java/co/elastic/clients/transport/endpoints/BooleanEndpointTest.java b/java-client/src/test/java/co/elastic/clients/transport5/endpoints/BooleanEndpointTest.java similarity index 96% rename from java-client/src/test/java/co/elastic/clients/transport/endpoints/BooleanEndpointTest.java rename to java-client/src/test/java/co/elastic/clients/transport5/endpoints/BooleanEndpointTest.java index 1c1b3dfc7..c3fbc3465 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/endpoints/BooleanEndpointTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport5/endpoints/BooleanEndpointTest.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.endpoints; +package co.elastic.clients.transport5.endpoints; import co.elastic.clients.elasticsearch.core.ExistsRequest; import co.elastic.clients.elasticsearch.security.SamlCompleteLogoutRequest; diff --git a/java-client/src/test/java/co/elastic/clients/transport/endpoints/EndpointBaseTest.java b/java-client/src/test/java/co/elastic/clients/transport5/endpoints/EndpointBaseTest.java similarity index 98% rename from java-client/src/test/java/co/elastic/clients/transport/endpoints/EndpointBaseTest.java rename to java-client/src/test/java/co/elastic/clients/transport5/endpoints/EndpointBaseTest.java index 296bc3b20..3c5f2b46c 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/endpoints/EndpointBaseTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport5/endpoints/EndpointBaseTest.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.endpoints; +package co.elastic.clients.transport5.endpoints; import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch.core.PingRequest; diff --git a/java-client/src/test/java/co/elastic/clients/transport/endpoints/SimpleEndpointTest.java b/java-client/src/test/java/co/elastic/clients/transport5/endpoints/SimpleEndpointTest.java similarity index 98% rename from java-client/src/test/java/co/elastic/clients/transport/endpoints/SimpleEndpointTest.java rename to java-client/src/test/java/co/elastic/clients/transport5/endpoints/SimpleEndpointTest.java index 263e94ac8..45a0e3df2 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/endpoints/SimpleEndpointTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport5/endpoints/SimpleEndpointTest.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.endpoints; +package co.elastic.clients.transport5.endpoints; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch.core.CountResponse; diff --git a/java-client/src/test/java/co/elastic/clients/transport/http/HeaderMapTest.java b/java-client/src/test/java/co/elastic/clients/transport5/http/HeaderMapTest.java similarity index 98% rename from java-client/src/test/java/co/elastic/clients/transport/http/HeaderMapTest.java rename to java-client/src/test/java/co/elastic/clients/transport5/http/HeaderMapTest.java index 83dee0f8e..9c583a5df 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/http/HeaderMapTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport5/http/HeaderMapTest.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.http; +package co.elastic.clients.transport5.http; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/java-client/src/test/java/co/elastic/clients/transport/instrumentation/OpenTelemetryForElasticsearchTest.java b/java-client/src/test/java/co/elastic/clients/transport5/instrumentation/OpenTelemetryForElasticsearchTest.java similarity index 97% rename from java-client/src/test/java/co/elastic/clients/transport/instrumentation/OpenTelemetryForElasticsearchTest.java rename to java-client/src/test/java/co/elastic/clients/transport5/instrumentation/OpenTelemetryForElasticsearchTest.java index 5c33ff5ec..62236265e 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/instrumentation/OpenTelemetryForElasticsearchTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport5/instrumentation/OpenTelemetryForElasticsearchTest.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.instrumentation; +package co.elastic.clients.transport5.instrumentation; import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; import co.elastic.clients.elasticsearch.ElasticsearchClient; @@ -25,7 +25,9 @@ import co.elastic.clients.elasticsearch.core.SearchRequest; import co.elastic.clients.json.JsonpUtils; import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.instrumentation.Instrumentation; +import co.elastic.clients.transport.instrumentation.OpenTelemetryForElasticsearch; +import co.elastic.clients.transport.rest5_client.RestClientTransport; import com.sun.net.httpserver.HttpServer; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.common.AttributeKey; diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/BasicAsyncResponseConsumerTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/BasicAsyncResponseConsumerTests.java new file mode 100644 index 000000000..f12ec7855 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/BasicAsyncResponseConsumerTests.java @@ -0,0 +1,76 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.ContentTooLongException; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.io.entity.ByteArrayEntity; +import org.apache.hc.core5.http.message.BasicClassicHttpResponse; +import org.apache.hc.core5.http.nio.AsyncResponseConsumer; +import org.apache.hc.core5.http.nio.ContentDecoder; +import org.apache.hc.core5.http.protocol.HttpContext; +import org.elasticsearch.client.RestClientTestCase; +import org.elasticsearch.client.consumer.HttpAsyncResponseConsumerFactory; +import org.junit.Assert; + +import java.nio.ByteBuffer; + +import static org.mockito.Mockito.mock; + +public class BasicAsyncResponseConsumerTests extends RestClientTestCase { + + // maximum buffer that this test ends up allocating is 50MB + private static final int MAX_TEST_BUFFER_SIZE = 50 * 1024 * 1024; + + public void testResponseProcessing() throws Exception { + ContentDecoder contentDecoder = mock(ContentDecoder.class); + HttpContext httpContext = mock(HttpContext.class); + + AsyncResponseConsumer consumer = + new HttpAsyncResponseConsumerFactory.BasicAsyncResponseConsumerFactory(MAX_TEST_BUFFER_SIZE) + .createHttpAsyncResponseConsumer(); + + BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(200, "OK"); + ByteArrayEntity entity = new ByteArrayEntity("test".getBytes(), ContentType.APPLICATION_JSON); + httpResponse.setEntity(entity); + + // everything goes well, no exception thrown + consumer.consumeResponse(httpResponse, entity, httpContext, null); + consumer.consume(ByteBuffer.wrap("test".getBytes())); + } + + public void testBufferLimit() throws Exception { + HttpContext httpContext = mock(HttpContext.class); + + AsyncResponseConsumer consumer = + new HttpAsyncResponseConsumerFactory.BasicAsyncResponseConsumerFactory(MAX_TEST_BUFFER_SIZE) + .createHttpAsyncResponseConsumer(); + + ByteArrayEntity entity = new ByteArrayEntity("test".getBytes(), ContentType.APPLICATION_JSON); + BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(200, "OK"); + httpResponse.setEntity(entity); + + // should throw exception + consumer.consumeResponse(httpResponse, entity, httpContext, null); + Assert.assertThrows(ContentTooLongException.class, + () -> consumer.consume(ByteBuffer.allocate(MAX_TEST_BUFFER_SIZE + 1))); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/ClientsGraalVMThreadsFilter.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/ClientsGraalVMThreadsFilter.java new file mode 100644 index 000000000..03a7e68bf --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/ClientsGraalVMThreadsFilter.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import com.carrotsearch.randomizedtesting.ThreadFilter; + +/** + * The GraalVM spawns extra threads, which causes our thread leak + * detection to fail. Filter these threads out since we can't clean them up. + */ +public class ClientsGraalVMThreadsFilter implements ThreadFilter { + @Override + public boolean reject(Thread t) { + return t.getName().startsWith("Libgraal"); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/DeadHostStateTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/DeadHostStateTests.java new file mode 100644 index 000000000..bd9071f47 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/DeadHostStateTests.java @@ -0,0 +1,136 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import org.elasticsearch.client.DeadHostState; +import org.elasticsearch.client.RestClientTestCase; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.lessThan; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class DeadHostStateTests extends RestClientTestCase { + + private static long[] EXPECTED_TIMEOUTS_SECONDS = new long[]{60, 84, 120, 169, 240, 339, 480, 678, 960, + 1357, 1800}; + + public void testInitialDeadHostStateDefaultTimeSupplier() { + DeadHostState deadHostState = new DeadHostState(DeadHostState.DEFAULT_TIME_SUPPLIER); + long currentTime = System.nanoTime(); + assertThat(deadHostState.getDeadUntilNanos(), greaterThanOrEqualTo(currentTime)); + assertThat(deadHostState.getFailedAttempts(), equalTo(1)); + } + + public void testDeadHostStateFromPreviousDefaultTimeSupplier() { + DeadHostState previous = new DeadHostState(DeadHostState.DEFAULT_TIME_SUPPLIER); + int iters = randomIntBetween(5, 30); + for (int i = 0; i < iters; i++) { + DeadHostState deadHostState = new DeadHostState(previous); + assertThat(deadHostState.getDeadUntilNanos(), greaterThan(previous.getDeadUntilNanos())); + assertThat(deadHostState.getFailedAttempts(), equalTo(previous.getFailedAttempts() + 1)); + previous = deadHostState; + } + } + + public void testCompareToTimeSupplier() { + int numObjects = randomIntBetween(EXPECTED_TIMEOUTS_SECONDS.length, 30); + DeadHostState[] deadHostStates = new DeadHostState[numObjects]; + final AtomicLong time = new AtomicLong(0); + for (int i = 0; i < numObjects; i++) { + if (i == 0) { + // this test requires a strictly increasing timer. This ensures that even if we call this + // time supplier in a very tight + // loop we always notice time moving forward. This does not happen for real timer + // implementations + // (e.g. on Linux clock_gettime provides microsecond resolution). + deadHostStates[i] = new DeadHostState(time::incrementAndGet); + } else { + deadHostStates[i] = new DeadHostState(deadHostStates[i - 1]); + } + } + for (int k = 1; k < deadHostStates.length; k++) { + assertThat(deadHostStates[k - 1].getDeadUntilNanos(), + lessThan(deadHostStates[k].getDeadUntilNanos())); + assertThat(deadHostStates[k - 1], lessThan(deadHostStates[k])); + } + } + + public void testCompareToDifferingTimeSupplier() { + try { + new DeadHostState(DeadHostState.DEFAULT_TIME_SUPPLIER).compareTo(new DeadHostState(() -> 0L)); + fail("expected failure"); + } catch (IllegalArgumentException e) { + assertEquals( + "can't compare DeadHostStates holding different time suppliers as they may be based on " + + "different clocks", + e.getMessage() + ); + } + } + + public void testShallBeRetried() { + final AtomicLong time = new AtomicLong(0); + DeadHostState deadHostState = null; + for (int i = 0; i < EXPECTED_TIMEOUTS_SECONDS.length; i++) { + long expectedTimeoutSecond = EXPECTED_TIMEOUTS_SECONDS[i]; + if (i == 0) { + deadHostState = new DeadHostState(time::get); + } else { + deadHostState = new DeadHostState(deadHostState); + } + for (int j = 0; j < expectedTimeoutSecond; j++) { + time.addAndGet(TimeUnit.SECONDS.toNanos(1)); + assertThat(deadHostState.shallBeRetried(), is(false)); + } + int iters = randomIntBetween(5, 30); + for (int j = 0; j < iters; j++) { + time.addAndGet(TimeUnit.SECONDS.toNanos(1)); + assertThat(deadHostState.shallBeRetried(), is(true)); + } + } + } + + public void testDeadHostStateTimeouts() { + DeadHostState previous = new DeadHostState(() -> 0L); + for (long expectedTimeoutsSecond : EXPECTED_TIMEOUTS_SECONDS) { + assertThat(TimeUnit.NANOSECONDS.toSeconds(previous.getDeadUntilNanos()), + equalTo(expectedTimeoutsSecond)); + previous = new DeadHostState(previous); + } + // check that from here on the timeout does not increase + int iters = randomIntBetween(5, 30); + for (int i = 0; i < iters; i++) { + DeadHostState deadHostState = new DeadHostState(previous); + assertThat( + TimeUnit.NANOSECONDS.toSeconds(deadHostState.getDeadUntilNanos()), + equalTo(EXPECTED_TIMEOUTS_SECONDS[EXPECTED_TIMEOUTS_SECONDS.length - 1]) + ); + previous = deadHostState; + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/FailureTrackingResponseListenerTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/FailureTrackingResponseListenerTests.java new file mode 100644 index 000000000..83bf9a48f --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/FailureTrackingResponseListenerTests.java @@ -0,0 +1,112 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.ProtocolVersion; +import org.apache.hc.core5.http.message.BasicClassicHttpResponse; +import org.apache.hc.core5.http.message.RequestLine; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseListener; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientTestCase; + +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +public class FailureTrackingResponseListenerTests extends RestClientTestCase { + + public void testOnSuccess() { + MockResponseListener responseListener = new MockResponseListener(); + RestClient.FailureTrackingResponseListener listener = + new RestClient.FailureTrackingResponseListener(responseListener); + + final Response response = mockResponse(); + listener.onSuccess(response); + assertSame(response, responseListener.lastResponse.get()); + assertNull(responseListener.lastException.get()); + } + + public void testOnFailure() { + MockResponseListener responseListener = new MockResponseListener(); + RestClient.FailureTrackingResponseListener listener = + new RestClient.FailureTrackingResponseListener(responseListener); + int numIters = randomIntBetween(1, 10); + Exception[] expectedExceptions = new Exception[numIters]; + for (int i = 0; i < numIters; i++) { + RuntimeException runtimeException = new RuntimeException("test" + i); + expectedExceptions[i] = runtimeException; + listener.trackFailure(runtimeException); + assertNull(responseListener.lastResponse.get()); + assertNull(responseListener.lastException.get()); + } + + if (randomBoolean()) { + Response response = mockResponse(); + listener.onSuccess(response); + assertSame(response, responseListener.lastResponse.get()); + assertNull(responseListener.lastException.get()); + } else { + RuntimeException runtimeException = new RuntimeException("definitive"); + listener.onDefinitiveFailure(runtimeException); + assertNull(responseListener.lastResponse.get()); + Throwable exception = responseListener.lastException.get(); + assertSame(runtimeException, exception); + + int i = numIters - 1; + do { + assertNotNull(exception.getSuppressed()); + assertEquals(1, exception.getSuppressed().length); + assertSame(expectedExceptions[i--], exception.getSuppressed()[0]); + exception = exception.getSuppressed()[0]; + } while (i >= 0); + } + } + + private static class MockResponseListener implements ResponseListener { + private final AtomicReference lastResponse = new AtomicReference<>(); + private final AtomicReference lastException = new AtomicReference<>(); + + @Override + public void onSuccess(Response response) { + if (!this.lastResponse.compareAndSet(null, response)) { + throw new IllegalStateException("onSuccess was called multiple times"); + } + } + + @Override + public void onFailure(Exception exception) { + if (!this.lastException.compareAndSet(null, exception)) { + throw new IllegalStateException("onFailure was called multiple times"); + } + } + } + + private static Response mockResponse() { + ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1); + RequestLine requestLine = new RequestLine("GET", "/", protocolVersion); + BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(200, "OK"); + return new Response(requestLine, new HttpHost("localhost", 9200), httpResponse); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/HasAttributeNodeSelectorTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/HasAttributeNodeSelectorTests.java new file mode 100644 index 000000000..24ecc8fe5 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/HasAttributeNodeSelectorTests.java @@ -0,0 +1,78 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + + +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.client.RestClientTestCase; +import org.elasticsearch.client.node.Node; +import org.elasticsearch.client.node.selector.HasAttributeNodeSelector; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; +import static org.junit.Assert.assertEquals; + +public class HasAttributeNodeSelectorTests extends RestClientTestCase { + public void testHasAttribute() { + Node hasAttributeValue = dummyNode(singletonMap("attr", singletonList("val"))); + Node hasAttributeButNotValue = dummyNode(singletonMap("attr", singletonList("notval"))); + Node hasAttributeValueInList = dummyNode(singletonMap("attr", Arrays.asList("val", "notval"))); + Node notHasAttribute = dummyNode(singletonMap("notattr", singletonList("val"))); + List nodes = new ArrayList<>(); + nodes.add(hasAttributeValue); + nodes.add(hasAttributeButNotValue); + nodes.add(hasAttributeValueInList); + nodes.add(notHasAttribute); + List expected = new ArrayList<>(); + expected.add(hasAttributeValue); + expected.add(hasAttributeValueInList); + new HasAttributeNodeSelector("attr", "val").select(nodes); + assertEquals(expected, nodes); + } + + private static Node dummyNode(Map> attributes) { + final Set roles = new TreeSet<>(); + if (randomBoolean()) { + roles.add("master"); + } + if (randomBoolean()) { + roles.add("data"); + } + if (randomBoolean()) { + roles.add("ingest"); + } + return new Node( + new HttpHost("dummy"), + Collections.emptySet(), + randomAsciiAlphanumOfLength(5), + randomAsciiAlphanumOfLength(5), + new Node.Roles(roles), + attributes + ); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/HostsTrackingFailureListener.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/HostsTrackingFailureListener.java new file mode 100644 index 000000000..04b858b74 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/HostsTrackingFailureListener.java @@ -0,0 +1,62 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.node.Node; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +/** + * {@link RestClient.FailureListener} impl that allows to track when it gets called for which host. + */ +class HostsTrackingFailureListener extends RestClient.FailureListener { + private volatile Set httpHosts = new HashSet<>(); + + @Override + public void onFailure(Node node) { + httpHosts.add(node.getHost()); + } + + void assertCalled(List nodes) { + HttpHost[] hosts = new HttpHost[nodes.size()]; + for (int i = 0; i < nodes.size(); i++) { + hosts[i] = nodes.get(i).getHost(); + } + assertCalled(hosts); + } + + void assertCalled(HttpHost... hosts) { + assertEquals(hosts.length, this.httpHosts.size()); + assertThat(this.httpHosts, containsInAnyOrder(hosts)); + this.httpHosts.clear(); + } + + void assertNotCalled() { + assertEquals(0, httpHosts.size()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/NodeSelectorTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/NodeSelectorTests.java new file mode 100644 index 000000000..c525cc262 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/NodeSelectorTests.java @@ -0,0 +1,131 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + + +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.client.RestClientTestCase; +import org.elasticsearch.client.node.Node; +import org.elasticsearch.client.node.Node.Roles; +import org.elasticsearch.client.node.selector.NodeSelector; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import static org.junit.Assert.assertEquals; + +public class NodeSelectorTests extends RestClientTestCase { + public void testAny() { + List nodes = new ArrayList<>(); + int size = between(2, 5); + for (int i = 0; i < size; i++) { + nodes.add(dummyNode(randomBoolean(), randomBoolean(), randomBoolean())); + } + List expected = new ArrayList<>(nodes); + NodeSelector.ANY.select(nodes); + assertEquals(expected, nodes); + } + + public void testNotMasterOnly() { + Node masterOnly = dummyNode(true, false, false); + Node all = dummyNode(true, true, true); + Node masterAndData = dummyNode(true, true, false); + Node masterAndIngest = dummyNode(true, false, true); + Node coordinatingOnly = dummyNode(false, false, false); + Node ingestOnly = dummyNode(false, false, true); + Node data = dummyNode(false, true, randomBoolean()); + Node dataContent = dummyNode(false, false, false, true, false, false, false, false); + Node dataHot = dummyNode(false, false, false, false, true, false, false, false); + Node dataWarm = dummyNode(false, false, false, false, false, true, false, false); + Node dataCold = dummyNode(false, false, false, false, false, false, true, false); + Node dataFrozen = dummyNode(false, false, false, false, false, false, false, true); + List nodes = new ArrayList<>(); + nodes.add(masterOnly); + nodes.add(all); + nodes.add(masterAndData); + nodes.add(masterAndIngest); + nodes.add(coordinatingOnly); + nodes.add(ingestOnly); + nodes.add(data); + nodes.add(dataContent); + nodes.add(dataHot); + nodes.add(dataWarm); + nodes.add(dataCold); + nodes.add(dataFrozen); + Collections.shuffle(nodes, getRandom()); + List expected = new ArrayList<>(nodes); + expected.remove(masterOnly); + NodeSelector.SKIP_DEDICATED_MASTERS.select(nodes); + assertEquals(expected, nodes); + } + + private static Node dummyNode(boolean master, boolean data, boolean ingest) { + return dummyNode(master, data, ingest, false, false, false, false, false); + } + + private static Node dummyNode( + boolean master, + boolean data, + boolean ingest, + boolean dataContent, + boolean dataHot, + boolean dataWarm, + boolean dataCold, + boolean dataFrozen + ) { + final Set roles = new TreeSet<>(); + if (master) { + roles.add("master"); + } + if (data) { + roles.add("data"); + } + if (dataContent) { + roles.add("data_content"); + } + if (dataHot) { + roles.add("data_hot"); + } + if (dataWarm) { + roles.add("data_warm"); + } + if (dataCold) { + roles.add("data_cold"); + } + if (dataFrozen) { + roles.add("data_frozen"); + } + if (ingest) { + roles.add("ingest"); + } + return new Node( + new HttpHost("dummy"), + Collections.emptySet(), + randomAsciiAlphanumOfLength(5), + randomAsciiAlphanumOfLength(5), + new Roles(roles), + Collections.>emptyMap() + ); + } + +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/NodeTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/NodeTests.java new file mode 100644 index 000000000..08f1a791e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/NodeTests.java @@ -0,0 +1,175 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.client.RestClientTestCase; +import org.elasticsearch.client.node.Node; +import org.elasticsearch.client.node.Node.Roles; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.TreeSet; + +import static java.util.Collections.singleton; +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class NodeTests extends RestClientTestCase { + public void testToString() { + Map> attributes = new HashMap<>(); + attributes.put("foo", singletonList("bar")); + attributes.put("baz", Arrays.asList("bort", "zoom")); + assertEquals("[host=http://1]", new Node(new HttpHost("1")).toString()); + assertEquals( + "[host=http://1, attributes={foo=[bar], baz=[bort, zoom]}]", + new Node(new HttpHost("1"), null, null, null, null, attributes).toString() + ); + assertEquals( + "[host=http://1, roles=data,ingest,master]", + new Node(new HttpHost("1"), null, null, null, new Node.Roles(new TreeSet<>(Arrays.asList("master", "data", "ingest"))), null) + .toString() + ); + assertEquals("[host=http://1, version=ver]", new Node(new HttpHost("1"), null, null, "ver", null, null).toString()); + assertEquals("[host=http://1, name=nam]", new Node(new HttpHost("1"), null, "nam", null, null, null).toString()); + assertEquals( + "[host=http://1, bound=[http://1, http://2]]", + new Node(new HttpHost("1"), new HashSet<>(Arrays.asList(new HttpHost("1"), new HttpHost("2"))), null, null, null, null) + .toString() + ); + assertEquals( + "[host=http://1, bound=[http://1, http://2], " + + "name=nam, version=ver, roles=master, attributes={foo=[bar], baz=[bort, zoom]}]", + new Node( + new HttpHost("1"), + new HashSet<>(Arrays.asList(new HttpHost("1"), new HttpHost("2"))), + "nam", + "ver", + new Roles(Collections.singleton("master")), + attributes + ).toString() + ); + } + + public void testEqualsAndHashCode() { + HttpHost host = new HttpHost(randomAsciiAlphanumOfLength(5)); + Node node = new Node( + host, + randomBoolean() ? null : singleton(host), + randomBoolean() ? null : randomAsciiAlphanumOfLength(5), + randomBoolean() ? null : randomAsciiAlphanumOfLength(5), + randomBoolean() ? null : new Roles(new TreeSet<>(Arrays.asList("master", "data", "ingest"))), + randomBoolean() ? null : singletonMap("foo", singletonList("bar")) + ); + assertFalse(node.equals(null)); + assertTrue(node.equals(node)); + assertEquals(node.hashCode(), node.hashCode()); + Node copy = new Node(host, node.getBoundHosts(), node.getName(), node.getVersion(), node.getRoles(), node.getAttributes()); + assertTrue(node.equals(copy)); + assertEquals(node.hashCode(), copy.hashCode()); + assertFalse( + node.equals( + new Node( + new HttpHost(host.toHostString() + "changed"), + node.getBoundHosts(), + node.getName(), + node.getVersion(), + node.getRoles(), + node.getAttributes() + ) + ) + ); + assertFalse( + node.equals( + new Node( + host, + new HashSet<>(Arrays.asList(host, new HttpHost(host.toHostString() + "changed"))), + node.getName(), + node.getVersion(), + node.getRoles(), + node.getAttributes() + ) + ) + ); + assertFalse( + node.equals( + new Node(host, node.getBoundHosts(), node.getName() + "changed", node.getVersion(), node.getRoles(), node.getAttributes()) + ) + ); + assertFalse( + node.equals( + new Node(host, node.getBoundHosts(), node.getName(), node.getVersion() + "changed", node.getRoles(), node.getAttributes()) + ) + ); + assertFalse( + node.equals( + new Node( + host, + node.getBoundHosts(), + node.getName(), + node.getVersion(), + new Roles(Collections.emptySet()), + node.getAttributes() + ) + ) + ); + assertFalse( + node.equals( + new Node( + host, + node.getBoundHosts(), + node.getName(), + node.getVersion(), + node.getRoles(), + singletonMap("bort", singletonList("bing")) + ) + ) + ); + } + + public void testDataRole() { + Roles roles = new Roles(new TreeSet<>(Arrays.asList("data_hot"))); + assertTrue(roles.hasDataHotRole()); + assertTrue(roles.canContainData()); + roles = new Roles(new TreeSet<>(Arrays.asList("data_warm"))); + assertTrue(roles.hasDataWarmRole()); + assertTrue(roles.canContainData()); + roles = new Roles(new TreeSet<>(Arrays.asList("data_cold"))); + assertTrue(roles.hasDataColdRole()); + assertTrue(roles.canContainData()); + roles = new Roles(new TreeSet<>(Arrays.asList("data_frozen"))); + assertTrue(roles.hasDataFrozenRole()); + assertTrue(roles.canContainData()); + roles = new Roles(new TreeSet<>(Arrays.asList("data_content"))); + assertTrue(roles.hasDataContentRole()); + assertTrue(roles.canContainData()); + roles = new Roles(new TreeSet<>(Arrays.asList("data"))); + assertTrue(roles.hasDataRole()); + assertTrue(roles.canContainData()); + roles = new Roles(new TreeSet<>(Arrays.asList("data_foo"))); + assertTrue(roles.canContainData()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/PreferHasAttributeNodeSelectorTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/PreferHasAttributeNodeSelectorTests.java new file mode 100644 index 000000000..1cb8f1acb --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/PreferHasAttributeNodeSelectorTests.java @@ -0,0 +1,89 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + + +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.client.RestClientTestCase; +import org.elasticsearch.client.node.Node; +import org.elasticsearch.client.node.Node.Roles; +import org.elasticsearch.client.node.selector.PreferHasAttributeNodeSelector; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; +import static org.junit.Assert.assertEquals; + +public class PreferHasAttributeNodeSelectorTests extends RestClientTestCase { + public void testFoundPreferHasAttribute() { + Node hasAttributeValue = dummyNode(singletonMap("attr", singletonList("val"))); + Node hasAttributeButNotValue = dummyNode(singletonMap("attr", singletonList("notval"))); + Node hasAttributeValueInList = dummyNode(singletonMap("attr", Arrays.asList("val", "notval"))); + Node notHasAttribute = dummyNode(singletonMap("notattr", singletonList("val"))); + List nodes = new ArrayList<>(); + nodes.add(hasAttributeValue); + nodes.add(hasAttributeButNotValue); + nodes.add(hasAttributeValueInList); + nodes.add(notHasAttribute); + List expected = new ArrayList<>(); + expected.add(hasAttributeValue); + expected.add(hasAttributeValueInList); + new PreferHasAttributeNodeSelector("attr", "val").select(nodes); + assertEquals(expected, nodes); + } + + public void testNotFoundPreferHasAttribute() { + Node notHasAttribute = dummyNode(singletonMap("notattr", singletonList("val"))); + List nodes = new ArrayList<>(); + nodes.add(notHasAttribute); + List expected = new ArrayList<>(); + expected.add(notHasAttribute); + new PreferHasAttributeNodeSelector("attr", "val").select(nodes); + assertEquals(expected, nodes); + } + + private static Node dummyNode(Map> attributes) { + final Set roles = new TreeSet<>(); + if (randomBoolean()) { + roles.add("master"); + } + if (randomBoolean()) { + roles.add("data"); + } + if (randomBoolean()) { + roles.add("ingest"); + } + return new Node( + new HttpHost("dummy"), + Collections.emptySet(), + randomAsciiAlphanumOfLength(5), + randomAsciiAlphanumOfLength(5), + new Roles(roles), + attributes + ); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestLoggerTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestLoggerTests.java new file mode 100644 index 000000000..2df2a9a0f --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestLoggerTests.java @@ -0,0 +1,204 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + + +import org.apache.hc.client5.http.classic.methods.HttpHead; +import org.apache.hc.client5.http.classic.methods.HttpOptions; +import org.apache.hc.client5.http.classic.methods.HttpPatch; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.classic.methods.HttpPut; +import org.apache.hc.client5.http.classic.methods.HttpTrace; +import org.apache.hc.client5.http.classic.methods.HttpUriRequest; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.io.entity.ByteArrayEntity; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.entity.InputStreamEntity; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.http.message.BasicClassicHttpResponse; +import org.apache.hc.core5.http.message.BasicHeader; +import org.elasticsearch.client.HttpDeleteWithEntity; +import org.elasticsearch.client.HttpGetWithEntity; +import org.elasticsearch.client.RequestLogger; +import org.elasticsearch.client.RestClientTestCase; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +import static org.elasticsearch.client.RestClientTestUtil.canHaveBody; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +public class RequestLoggerTests extends RestClientTestCase { + public void testTraceRequest() throws IOException, URISyntaxException, ParseException { + HttpHost host = new HttpHost(randomBoolean() ? "http" : "https", "localhost", 9200); + String expectedEndpoint = "/index/type/_api"; + URI uri; + if (randomBoolean()) { + uri = new URI(expectedEndpoint); + } else { + uri = new URI("index/type/_api"); + } + HttpUriRequest request = randomHttpRequest(uri); + String expected = "curl -iX " + request.getMethod() + " '" + host + expectedEndpoint + "'"; + boolean hasBody = canHaveBody((HttpUriRequestBase) request) && randomBoolean(); + String requestBody = "{ \"field\": \"value\" }"; + if (hasBody) { + expected += " -d '" + requestBody + "'"; + HttpEntity entity; + switch (randomIntBetween(0, 4)) { + case 0: + case 2: + entity = new StringEntity(requestBody, ContentType.APPLICATION_JSON); + break; + case 1: + entity = new InputStreamEntity( + new ByteArrayInputStream(requestBody.getBytes(StandardCharsets.UTF_8)), + ContentType.APPLICATION_JSON + ); + break; + case 3: + entity = new ByteArrayEntity(requestBody.getBytes(StandardCharsets.UTF_8), + ContentType.APPLICATION_JSON); + break; + case 4: + // Evil entity without a charset + entity = new StringEntity(requestBody, ContentType.create("application/json", + (Charset) null)); + break; + default: + throw new UnsupportedOperationException(); + } + request.setEntity(entity); + } + String traceRequest = RequestLogger.buildTraceRequest(request, host); + assertThat(traceRequest, equalTo(expected)); + if (hasBody) { + // check that the body is still readable as most entities are not repeatable + String body = EntityUtils.toString(request.getEntity(), + StandardCharsets.UTF_8); + assertThat(body, equalTo(requestBody)); + } + } + + public void testTraceResponse() throws IOException, ParseException { + int statusCode = randomIntBetween(200, 599); + String reasonPhrase = "REASON"; + BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(statusCode, reasonPhrase); + String expected = "# " + statusCode; + int numHeaders = randomIntBetween(0, 3); + for (int i = 0; i < numHeaders; i++) { + httpResponse.setHeader("header" + i, "value"); + expected += "\n# header" + i + ": value"; + } + expected += "\n#"; + boolean hasBody = getRandom().nextBoolean(); + String responseBody = "{\n \"field\": \"value\"\n}"; + if (hasBody) { + expected += "\n# {"; + expected += "\n# \"field\": \"value\""; + expected += "\n# }"; + HttpEntity entity; + switch (randomIntBetween(0, 2)) { + case 0: + entity = new StringEntity(responseBody, ContentType.APPLICATION_JSON); + break; + case 1: + // test a non repeatable entity + entity = new InputStreamEntity( + new ByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8)), + ContentType.APPLICATION_JSON + ); + break; + case 2: + // Evil entity without a charset + entity = new StringEntity(responseBody, ContentType.create("application/json", + (Charset) null)); + break; + default: + throw new UnsupportedOperationException(); + } + httpResponse.setEntity(entity); + } + String traceResponse = RequestLogger.buildTraceResponse(httpResponse); + assertThat(traceResponse, equalTo(expected)); + if (hasBody) { + // check that the body is still readable as most entities are not repeatable + String body = EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8); + assertThat(body, equalTo(responseBody)); + } + } + + public void testResponseWarnings() throws Exception { + HttpHost host = new HttpHost("localhost", 9200); + HttpUriRequest request = randomHttpRequest(new URI("/index/type/_api")); + int numWarnings = randomIntBetween(1, 5); + StringBuilder expected = new StringBuilder("request [").append(request.getMethod()) + .append(" ") + .append(host) + .append("/index/type/_api] returned ") + .append(numWarnings) + .append(" warnings: "); + Header[] warnings = new Header[numWarnings]; + for (int i = 0; i < numWarnings; i++) { + String warning = "this is warning number " + i; + warnings[i] = new BasicHeader("Warning", warning); + if (i > 0) { + expected.append(","); + } + expected.append("[").append(warning).append("]"); + } + assertEquals(expected.toString(), RequestLogger.buildWarningMessage(request, host, warnings)); + } + + private static HttpUriRequest randomHttpRequest(URI uri) { + int requestType = randomIntBetween(0, 7); + switch (requestType) { + case 0: + return new HttpGetWithEntity(uri); + case 1: + return new HttpPost(uri); + case 2: + return new HttpPut(uri); + case 3: + return new HttpDeleteWithEntity(uri); + case 4: + return new HttpHead(uri); + case 5: + return new HttpTrace(uri); + case 6: + return new HttpOptions(uri); + case 7: + return new HttpPatch(uri); + default: + throw new UnsupportedOperationException(); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestOptionsTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestOptionsTests.java new file mode 100644 index 000000000..f8b7b540b --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestOptionsTests.java @@ -0,0 +1,211 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.util.Timeout; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.WarningsHandler; +import org.elasticsearch.client.consumer.HttpAsyncResponseConsumerFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; + +public class RequestOptionsTests extends RestClientTestCase { + public void testDefault() { + assertEquals(Collections.

emptyList(), RequestOptions.DEFAULT.getHeaders()); + assertEquals(Collections.emptyMap(), RequestOptions.DEFAULT.getParameters()); + assertEquals(HttpAsyncResponseConsumerFactory.DEFAULT, + RequestOptions.DEFAULT.getHttpAsyncResponseConsumerFactory()); + assertEquals(RequestOptions.DEFAULT, RequestOptions.DEFAULT.toBuilder().build()); + } + + public void testAddHeader() { + try { + randomBuilder().addHeader(null, randomAsciiLettersOfLengthBetween(3, 10)); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("header name cannot be null", e.getMessage()); + } + + try { + randomBuilder().addHeader(randomAsciiLettersOfLengthBetween(3, 10), null); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("header value cannot be null", e.getMessage()); + } + + RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); + int numHeaders = between(0, 5); + List
headers = new ArrayList<>(); + for (int i = 0; i < numHeaders; i++) { + Header header = new RequestOptions.ReqHeader(randomAsciiAlphanumOfLengthBetween(5, 10), + randomAsciiAlphanumOfLength(3)); + headers.add(header); + builder.addHeader(header.getName(), header.getValue()); + } + RequestOptions options = builder.build(); + assertEquals(headers, options.getHeaders()); + + try { + options.getHeaders() + .add(new RequestOptions.ReqHeader(randomAsciiAlphanumOfLengthBetween(5, 10), + randomAsciiAlphanumOfLength(3))); + fail("expected failure"); + } catch (UnsupportedOperationException e) { + assertNull(e.getMessage()); + } + } + + public void testSetHttpAsyncResponseConsumerFactory() { + try { + RequestOptions.DEFAULT.toBuilder().setHttpAsyncResponseConsumerFactory(null); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("httpAsyncResponseConsumerFactory cannot be null", e.getMessage()); + } + + HttpAsyncResponseConsumerFactory factory = mock(HttpAsyncResponseConsumerFactory.class); + RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); + builder.setHttpAsyncResponseConsumerFactory(factory); + RequestOptions options = builder.build(); + assertSame(factory, options.getHttpAsyncResponseConsumerFactory()); + } + + public void testAddParameters() { + try { + randomBuilder().addParameter(null, randomAsciiLettersOfLengthBetween(3, 10)); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("parameter key cannot be null", e.getMessage()); + } + + try { + randomBuilder().addParameter(randomAsciiLettersOfLengthBetween(3, 10), null); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("parameter value cannot be null", e.getMessage()); + } + + RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); + int numParameters = between(0, 5); + Map parameters = new HashMap<>(); + for (int i = 0; i < numParameters; i++) { + String key = randomAsciiAlphanumOfLengthBetween(5, 10); + String value = randomAsciiAlphanumOfLength(3); + + parameters.put(key, value); + builder.addParameter(key, value); + } + RequestOptions options = builder.build(); + assertEquals(parameters, options.getParameters()); + } + + public void testSetRequestBuilder() { + RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); + + RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); + int socketTimeout = 10000; + int connectTimeout = 100; + requestConfigBuilder.setConnectionRequestTimeout(Timeout.ofMilliseconds(socketTimeout)).setConnectTimeout(Timeout.ofMilliseconds(connectTimeout)); + RequestConfig requestConfig = requestConfigBuilder.build(); + + builder.setRequestConfig(requestConfig); + RequestOptions options = builder.build(); + assertSame(options.getRequestConfig(), requestConfig); + assertEquals(options.getRequestConfig().getConnectionRequestTimeout(), Timeout.ofMilliseconds(socketTimeout)); + assertEquals(options.getRequestConfig().getConnectTimeout(), Timeout.ofMilliseconds(connectTimeout)); + } + + public void testEqualsAndHashCode() { + RequestOptions request = randomBuilder().build(); + assertEquals(request, request); + + RequestOptions copy = copy(request); + assertEquals(request, copy); + assertEquals(copy, request); + assertEquals(request.hashCode(), copy.hashCode()); + + RequestOptions mutant = mutate(request); + assertNotEquals(request, mutant); + assertNotEquals(mutant, request); + } + + static RequestOptions.Builder randomBuilder() { + RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); + + if (randomBoolean()) { + int headerCount = between(1, 5); + for (int i = 0; i < headerCount; i++) { + builder.addHeader(randomAsciiAlphanumOfLength(3), randomAsciiAlphanumOfLength(3)); + } + } + + if (randomBoolean()) { + builder.setHttpAsyncResponseConsumerFactory(HttpAsyncResponseConsumerFactory.DEFAULT); + } + + if (randomBoolean()) { + builder.setWarningsHandler(randomBoolean() ? WarningsHandler.STRICT : WarningsHandler.PERMISSIVE); + } + + if (randomBoolean()) { + builder.setRequestConfig(RequestConfig.custom().build()); + } + + return builder; + } + + private static RequestOptions copy(RequestOptions options) { + return options.toBuilder().build(); + } + + private static RequestOptions mutate(RequestOptions options) { + RequestOptions.Builder mutant = options.toBuilder(); + int mutationType = between(0, 2); + switch (mutationType) { + case 0: + mutant.addHeader("extra", "m"); + return mutant.build(); + case 1: + mutant.setHttpAsyncResponseConsumerFactory(new HttpAsyncResponseConsumerFactory.BasicAsyncResponseConsumerFactory(5)); + return mutant.build(); + case 2: + mutant.setWarningsHandler(warnings -> { + fail("never called"); + return false; + }); + return mutant.build(); + default: + throw new UnsupportedOperationException("Unknown mutation type [" + mutationType + "]"); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestTests.java new file mode 100644 index 000000000..f638fc2fe --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestTests.java @@ -0,0 +1,249 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.io.entity.ByteArrayEntity; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.RequestOptionsTests; +import org.elasticsearch.client.consumer.HttpAsyncResponseConsumerFactory; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; + +public class RequestTests extends RestClientTestCase { + public void testConstructor() { + final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); + final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); + + try { + new Request(null, endpoint); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("method cannot be null", e.getMessage()); + } + + try { + new Request(method, null); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("endpoint cannot be null", e.getMessage()); + } + + final Request request = new Request(method, endpoint); + assertEquals(method, request.getMethod()); + assertEquals(endpoint, request.getEndpoint()); + } + + public void testAddParameters() { + final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); + final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); + int parametersCount = between(1, 3); + final Map parameters = new HashMap<>(parametersCount); + while (parameters.size() < parametersCount) { + parameters.put(randomAsciiLettersOfLength(5), randomAsciiLettersOfLength(5)); + } + Request request = new Request(method, endpoint); + + try { + request.addParameter(null, "value"); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("url parameter name cannot be null", e.getMessage()); + } + + for (Map.Entry entry : parameters.entrySet()) { + request.addParameter(entry.getKey(), entry.getValue()); + } + assertEquals(parameters, request.getParameters()); + + // Test that adding parameters with a null value is ok. + request.addParameter("is_null", null); + parameters.put("is_null", null); + assertEquals(parameters, request.getParameters()); + + // Test that adding a duplicate parameter fails + String firstValue = randomBoolean() ? null : "value"; + request.addParameter("name", firstValue); + try { + request.addParameter("name", randomBoolean() ? firstValue : "second_value"); + fail("expected failure"); + } catch (IllegalArgumentException e) { + assertEquals("url parameter [name] has already been set to [" + firstValue + "]", e.getMessage()); + } + } + + public void testSetEntity() { + final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); + final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); + final HttpEntity entity = randomBoolean() + ? new StringEntity(randomAsciiLettersOfLengthBetween(1, 100), ContentType.TEXT_PLAIN) + : null; + + Request request = new Request(method, endpoint); + request.setEntity(entity); + assertEquals(entity, request.getEntity()); + } + + public void testSetJsonEntity() throws IOException { + final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); + final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); + + Request request = new Request(method, endpoint); + assertNull(request.getEntity()); + + final String json = randomAsciiLettersOfLengthBetween(1, 100); + request.setJsonEntity(json); + assertEquals(ContentType.APPLICATION_JSON.toString(), request.getEntity().getContentType()); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + request.getEntity().writeTo(os); + assertEquals(json, new String(os.toByteArray(), ContentType.APPLICATION_JSON.getCharset())); + } + + public void testSetOptions() { + final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); + final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); + Request request = new Request(method, endpoint); + + try { + request.setOptions((RequestOptions) null); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("options cannot be null", e.getMessage()); + } + + try { + request.setOptions((RequestOptions.Builder) null); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("options cannot be null", e.getMessage()); + } + + RequestOptions.Builder builder = RequestOptionsTests.randomBuilder(); + request.setOptions(builder); + assertEquals(builder.build(), request.getOptions()); + + builder = RequestOptionsTests.randomBuilder(); + RequestOptions options = builder.build(); + request.setOptions(options); + assertSame(options, request.getOptions()); + } + + public void testEqualsAndHashCode() { + Request request = randomRequest(); + assertEquals(request, request); + + Request copy = copy(request); + assertEquals(request, copy); + assertEquals(copy, request); + assertEquals(request.hashCode(), copy.hashCode()); + + Request mutant = mutate(request); + assertNotEquals(request, mutant); + assertNotEquals(mutant, request); + } + + private static Request randomRequest() { + Request request = new Request( + randomFrom(new String[] { "GET", "PUT", "DELETE", "POST", "HEAD", "OPTIONS" }), + randomAsciiAlphanumOfLength(5) + ); + + int parameterCount = between(0, 5); + for (int i = 0; i < parameterCount; i++) { + request.addParameter(randomAsciiAlphanumOfLength(i), randomAsciiLettersOfLength(3)); + } + + if (randomBoolean()) { + if (randomBoolean()) { + request.setJsonEntity(randomAsciiAlphanumOfLength(10)); + } else { + request.setEntity( + randomFrom( + new HttpEntity[] { + new StringEntity(randomAsciiAlphanumOfLength(10), ContentType.APPLICATION_JSON), + new ByteArrayEntity(randomBytesOfLength(40), ContentType.APPLICATION_JSON) } + ) + ); + } + } + + if (randomBoolean()) { + RequestOptions.Builder options = request.getOptions().toBuilder(); + options.setHttpAsyncResponseConsumerFactory(new HttpAsyncResponseConsumerFactory.BasicAsyncResponseConsumerFactory(1)); + request.setOptions(options); + } + + return request; + } + + private static Request copy(Request request) { + Request copy = new Request(request.getMethod(), request.getEndpoint()); + copyMutables(request, copy); + return copy; + } + + private static Request mutate(Request request) { + if (randomBoolean()) { + // Mutate request or method but keep everything else constant + Request mutant = randomBoolean() + ? new Request(request.getMethod() + "m", request.getEndpoint()) + : new Request(request.getMethod(), request.getEndpoint() + "m"); + copyMutables(request, mutant); + return mutant; + } + Request mutant = copy(request); + int mutationType = between(0, 2); + switch (mutationType) { + case 0: + mutant.addParameter(randomAsciiAlphanumOfLength(mutant.getParameters().size() + 4), "extra"); + return mutant; + case 1: + mutant.setJsonEntity("mutant"); // randomRequest can't produce this value + return mutant; + case 2: + RequestOptions.Builder options = mutant.getOptions().toBuilder(); + options.addHeader("extra", "m"); + mutant.setOptions(options); + return mutant; + default: + throw new UnsupportedOperationException("Unknown mutation type [" + mutationType + "]"); + } + } + + private static void copyMutables(Request from, Request to) { + for (Map.Entry param : from.getParameters().entrySet()) { + to.addParameter(param.getKey(), param.getValue()); + } + to.setEntity(from.getEntity()); + to.setOptions(from.getOptions()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/ResponseExceptionTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/ResponseExceptionTests.java new file mode 100644 index 000000000..83cef07fe --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/ResponseExceptionTests.java @@ -0,0 +1,93 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + + +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.ProtocolVersion; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.entity.InputStreamEntity; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.http.message.BasicClassicHttpResponse; +import org.apache.hc.core5.http.message.RequestLine; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Locale; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +public class ResponseExceptionTests extends RestClientTestCase { + + public void testResponseException() throws IOException, ParseException { + ProtocolVersion protocolVersion = new ProtocolVersion("http", 1, 1); + BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(500, "Internal Server Error"); + + String responseBody = "{\"error\":{\"root_cause\": {}}}"; + boolean hasBody = getRandom().nextBoolean(); + if (hasBody) { + HttpEntity entity; + if (getRandom().nextBoolean()) { + entity = new StringEntity(responseBody, ContentType.APPLICATION_JSON); + } else { + // test a non repeatable entity + entity = new InputStreamEntity( + new ByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8)), + ContentType.APPLICATION_JSON + ); + } + httpResponse.setEntity(entity); + } + + RequestLine requestLine = new RequestLine("GET", "/", protocolVersion); + HttpHost httpHost = new HttpHost("localhost", 9200); + Response response = new Response(requestLine, httpHost, httpResponse); + ResponseException responseException = new ResponseException(response); + + assertSame(response, responseException.getResponse()); + if (hasBody) { + assertEquals(responseBody, EntityUtils.toString(responseException.getResponse().getEntity())); + } else { + assertNull(responseException.getResponse().getEntity()); + } + + String message = String.format( + Locale.ROOT, + "method [%s], host [%s], URI [%s], status line [%s]", + response.getRequestLine().getMethod(), + response.getHost(), + response.getRequestLine().getUri(), + response.getStatusCode() + ); + + if (hasBody) { + message += "\n" + responseBody; + } + assertEquals(message, responseException.getMessage()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientBuilderIntegTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientBuilderIntegTests.java new file mode 100644 index 000000000..50aded05a --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientBuilderIntegTests.java @@ -0,0 +1,227 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsServer; +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseListener; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; +import org.elasticsearch.client.RestClientTestCase; +import org.elasticsearch.mocksocket.MockHttpServer; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.TrustManagerFactory; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.KeyFactory; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.startsWith; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Integration test to validate the builder builds a client with the correct configuration + */ +public class RestClientBuilderIntegTests extends RestClientTestCase { + + private static HttpsServer httpsServer; + + @BeforeClass + public static void startHttpServer() throws Exception { + httpsServer = MockHttpServer.createHttps(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0) + , 0); + httpsServer.setHttpsConfigurator(new HttpsConfigurator(getSslContext())); + httpsServer.createContext("/", new ResponseHandler()); + httpsServer.start(); + } + + private static class ResponseHandler implements HttpHandler { + @Override + public void handle(HttpExchange httpExchange) throws IOException { + httpExchange.sendResponseHeaders(200, -1); + httpExchange.close(); + } + } + + @AfterClass + public static void stopHttpServers() throws IOException { + httpsServer.stop(0); + httpsServer = null; + } + + public void testBuilderUsesDefaultSSLContext() throws Exception { + assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm()); + final SSLContext defaultSSLContext = SSLContext.getDefault(); + try { + try (RestClient client = buildRestClient()) { + try { + client.performRequest(new Request("GET", "/")); + fail("connection should have been rejected due to SSL handshake"); + } catch (Exception e) { + assertThat(e, instanceOf(SSLHandshakeException.class)); + } + } + + SSLContext.setDefault(getSslContext()); + try (RestClient client = buildRestClient()) { + Response response = client.performRequest(new Request("GET", "/")); + assertEquals(200, response.getStatusCode()); + } + } finally { + SSLContext.setDefault(defaultSSLContext); + } + } + + public void testBuilderSetsThreadName() throws Exception { + assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm()); + final SSLContext defaultSSLContext = SSLContext.getDefault(); + try { + SSLContext.setDefault(getSslContext()); + try (RestClient client = buildRestClient()) { + final CountDownLatch latch = new CountDownLatch(1); + client.performRequestAsync(new Request("GET", "/"), new ResponseListener() { + @Override + public void onSuccess(Response response) { + assertThat( + Thread.currentThread().getName(), + allOf( + startsWith(RestClientBuilder.THREAD_NAME_PREFIX), + containsString("elasticsearch"), + containsString("rest-client") + ) + ); + assertEquals(200, response.getStatusCode()); + latch.countDown(); + } + + @Override + public void onFailure(Exception exception) { + throw new AssertionError("unexpected", exception); + } + }); + assertTrue(latch.await(10, TimeUnit.SECONDS)); + } + } finally { + SSLContext.setDefault(defaultSSLContext); + } + } + + private RestClient buildRestClient() { + InetSocketAddress address = httpsServer.getAddress(); + return RestClient.builder(new HttpHost("https", address.getHostString(), address.getPort())).build(); + } + + private static SSLContext getSslContext() throws Exception { + SSLContext sslContext = SSLContext.getInstance(getProtocol()); + try ( + InputStream certFile = RestClientBuilderIntegTests.class.getResourceAsStream("/test.crt"); + InputStream keyStoreFile = RestClientBuilderIntegTests.class.getResourceAsStream( + "/test_truststore.jks") + ) { + // Build a keystore of default type programmatically since we can't use JKS keystores to + // init a KeyManagerFactory in FIPS 140 JVMs. + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(null, "password".toCharArray()); + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec( + Files.readAllBytes(Paths.get(RestClientBuilderIntegTests.class.getResource("/test.der").toURI())) + ); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + keyStore.setKeyEntry( + "mykey", + keyFactory.generatePrivate(privateKeySpec), + "password".toCharArray(), + new Certificate[]{certFactory.generateCertificate(certFile)} + ); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(keyStore, "password".toCharArray()); + KeyStore trustStore = KeyStore.getInstance("JKS"); + trustStore.load(keyStoreFile, "password".toCharArray()); + TrustManagerFactory tmf = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(trustStore); + sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + } + return sslContext; + } + + /** + * The {@link HttpsServer} in the JDK has issues with TLSv1.3 when running in a JDK prior to + * 12.0.1 so we pin to TLSv1.2 when running on an earlier JDK + */ + private static String getProtocol() { + String version = System.getProperty("java.version"); + String[] parts = version.split("-"); + String[] numericComponents; + if (parts.length == 1) { + numericComponents = version.split("\\."); + } else if (parts.length == 2) { + numericComponents = parts[0].split("\\."); + } else { + throw new IllegalArgumentException("Java version string [" + version + "] could not be parsed."); + } + if (numericComponents.length > 0) { + final int major = Integer.valueOf(numericComponents[0]); + if (major > 12) { + return "TLS"; + } else if (major == 12 && numericComponents.length > 2) { + final int minor = Integer.valueOf(numericComponents[1]); + if (minor > 0) { + return "TLS"; + } else { + String patch = numericComponents[2]; + final int index = patch.indexOf("_"); + if (index > -1) { + patch = patch.substring(0, index); + } + + if (Integer.valueOf(patch) >= 1) { + return "TLS"; + } + } + } + } + return "TLSv1.2"; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientBuilderTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientBuilderTests.java new file mode 100644 index 000000000..f8cc00e7e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientBuilderTests.java @@ -0,0 +1,268 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.impl.async.HttpAsyncClients; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.message.BasicHeader; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; +import org.elasticsearch.client.RestClientTestCase; +import org.elasticsearch.client.node.Node; + +import java.io.IOException; +import java.util.Base64; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +public class RestClientBuilderTests extends RestClientTestCase { + + public void testBuild() throws IOException { + try { + RestClient.builder((HttpHost[]) null); + fail("should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("hosts must not be null nor empty", e.getMessage()); + } + + try { + RestClient.builder(new HttpHost[]{}); + fail("should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("hosts must not be null nor empty", e.getMessage()); + } + + try { + RestClient.builder((Node[]) null); + fail("should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("nodes must not be null or empty", e.getMessage()); + } + + try { + RestClient.builder(new Node[]{}); + fail("should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("nodes must not be null or empty", e.getMessage()); + } + + try { + RestClient.builder(new Node(new HttpHost("localhost", 9200)), null); + fail("should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("node cannot be null", e.getMessage()); + } + + try { + RestClient.builder(new HttpHost("localhost", 9200), null); + fail("should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("host cannot be null", e.getMessage()); + } + + try (RestClient restClient = RestClient.builder(new HttpHost("localhost", 9200)).build()) { + assertNotNull(restClient); + } + + try { + RestClient.builder(new HttpHost("localhost", 9200)).setDefaultHeaders(null); + fail("should have failed"); + } catch (NullPointerException e) { + assertEquals("defaultHeaders must not be null", e.getMessage()); + } + + try { + RestClient.builder(new HttpHost("localhost", 9200)).setDefaultHeaders(new Header[]{null}); + fail("should have failed"); + } catch (NullPointerException e) { + assertEquals("default header must not be null", e.getMessage()); + } + + try { + RestClient.builder(new HttpHost("localhost", 9200)).setFailureListener(null); + fail("should have failed"); + } catch (NullPointerException e) { + assertEquals("failureListener must not be null", e.getMessage()); + } + + try { + RestClient.builder(new HttpHost("localhost", 9200)).setCustomRestClient(null); + fail("should have failed"); + } catch (NullPointerException e) { + assertEquals("custom rest client must not be null", e.getMessage()); + } + + try { + RestClient.builder(new HttpHost("localhost", 9200)).setSslContext(null); + fail("should have failed"); + } catch (NullPointerException e) { + assertEquals("ssl context must not be null", e.getMessage()); + } + + int numNodes = randomIntBetween(1, 5); + HttpHost[] hosts = new HttpHost[numNodes]; + for (int i = 0; i < numNodes; i++) { + hosts[i] = new HttpHost("localhost", 9200 + i); + } + RestClientBuilder builder = RestClient.builder(hosts); + CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() + .build(); + if (randomBoolean()) { + builder.setCustomRestClient(httpclient); + } + if (randomBoolean()) { + int numHeaders = randomIntBetween(1, 5); + Header[] headers = new Header[numHeaders]; + for (int i = 0; i < numHeaders; i++) { + headers[i] = new BasicHeader("header" + i, "value"); + } + builder.setDefaultHeaders(headers); + } + if (randomBoolean()) { + String pathPrefix = (randomBoolean() ? "/" : "") + randomAsciiLettersOfLengthBetween(2, 5); + while (pathPrefix.length() < 20 && randomBoolean()) { + pathPrefix += "/" + randomAsciiLettersOfLengthBetween(3, 6); + } + builder.setPathPrefix(pathPrefix + (randomBoolean() ? "/" : "")); + } + try (RestClient restClient = builder.build()) { + assertNotNull(restClient); + } + } + + public void testBuildCloudId() throws IOException { + String host = "us-east-1.aws.found.io"; + String esId = "elasticsearch"; + String kibanaId = "kibana"; + String toEncode = host + "$" + esId + "$" + kibanaId; + String encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(UTF8)); + assertNotNull(RestClient.builder(encodedId)); + assertNotNull(RestClient.builder("humanReadable:" + encodedId)); + + String badId = Base64.getEncoder().encodeToString("foo$bar".getBytes(UTF8)); + try { + RestClient.builder(badId); + fail("should have failed"); + } catch (IllegalStateException e) { + assertEquals("cloudId " + badId + " did not decode to a cluster identifier correctly", + e.getMessage()); + } + + try { + RestClient.builder(badId + ":"); + fail("should have failed"); + } catch (IllegalStateException e) { + assertEquals("cloudId " + badId + ": must begin with a human readable identifier followed by a " + + "colon", e.getMessage()); + } + + RestClient client = RestClient.builder(encodedId).build(); + assertThat(client.getNodes().size(), equalTo(1)); + assertThat(client.getNodes().get(0).getHost().getHostName(), equalTo(esId + "." + host)); + assertThat(client.getNodes().get(0).getHost().getPort(), equalTo(443)); + assertThat(client.getNodes().get(0).getHost().getSchemeName(), equalTo("https")); + client.close(); + } + + public void testBuildCloudIdWithPort() throws IOException { + String host = "us-east-1.aws.found.io"; + String esId = "elasticsearch"; + String kibanaId = "kibana"; + String port = "9443"; + String toEncode = host + ":" + port + "$" + esId + "$" + kibanaId; + String encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(UTF8)); + + RestClient client = RestClient.builder("humanReadable:" + encodedId).build(); + assertThat(client.getNodes().size(), equalTo(1)); + assertThat(client.getNodes().get(0).getHost().getPort(), equalTo(9443)); + assertThat(client.getNodes().get(0).getHost().getHostName(), equalTo(esId + "." + host)); + assertThat(client.getNodes().get(0).getHost().getSchemeName(), equalTo("https")); + client.close(); + + toEncode = host + ":" + "123:foo" + "$" + esId + "$" + kibanaId; + encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(UTF8)); + + try { + RestClient.builder("humanReadable:" + encodedId); + fail("should have failed"); + } catch (IllegalStateException e) { + assertEquals("cloudId " + encodedId + " does not contain a valid port number", e.getMessage()); + } + } + + public void testSetPathPrefixNull() { + try { + RestClient.builder(new HttpHost("localhost", 9200)).setPathPrefix(null); + fail("pathPrefix set to null should fail!"); + } catch (final NullPointerException e) { + assertEquals("pathPrefix must not be null", e.getMessage()); + } + } + + public void testSetPathPrefixEmpty() { + assertSetPathPrefixThrows(""); + } + + public void testSetPathPrefixMalformed() { + assertSetPathPrefixThrows("//"); + assertSetPathPrefixThrows("base/path//"); + } + + private static void assertSetPathPrefixThrows(final String pathPrefix) { + try { + RestClient.builder(new HttpHost("localhost", 9200)).setPathPrefix(pathPrefix); + fail("path prefix [" + pathPrefix + "] should have failed"); + } catch (final IllegalArgumentException e) { + assertThat(e.getMessage(), containsString(pathPrefix)); + } + } + + /** + * This test verifies that we don't change the default value for the connection request timeout as that + * causes problems. + * See https://github.com/elastic/elasticsearch/issues/24069 + */ + public void testDefaultConnectionRequestTimeout() throws IOException { + RestClientBuilder builder = RestClient.builder(new HttpHost("localhost", 9200)); + + RequestConfig requestConfig = RequestConfig.custom().build(); + assertEquals(RequestConfig.DEFAULT.getConnectionRequestTimeout(), + requestConfig.getConnectionRequestTimeout()); + // this way we get notified if the default ever changes + // TODO IT CHANGED from -1 to 3 minutes, does it mean we always need to explicitly set it? + //assertEquals(-1, requestConfig.getConnectionRequestTimeout()); + + CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() + .setDefaultRequestConfig(requestConfig) + .build(); + + try (RestClient restClient = builder.build()) { + assertNotNull(restClient); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientDocumentation.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientDocumentation.java new file mode 100644 index 000000000..7c5745488 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientDocumentation.java @@ -0,0 +1,461 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.impl.async.HttpAsyncClients; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.http.message.BasicHeader; +import org.apache.hc.core5.http.message.RequestLine; +import org.apache.hc.core5.reactor.IOReactorConfig; +import org.apache.hc.core5.ssl.SSLContextBuilder; +import org.apache.hc.core5.ssl.SSLContexts; +import org.apache.hc.core5.util.Timeout; +import org.elasticsearch.client.Cancellable; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseListener; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; +import org.elasticsearch.client.consumer.HttpAsyncResponseConsumerFactory; +import org.elasticsearch.client.node.Node; +import org.elasticsearch.client.node.selector.NodeSelector; + +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.util.Base64; +import java.util.Iterator; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * This class is used to generate the Java low-level REST client documentation. + * You need to wrap your code between two tags like: + * // tag::example[] + * // end::example[] + *

+ * Where example is your tag name. + *

+ * Then in the documentation, you can extract what is between tag and end tags with + * ["source","java",subs="attributes,callouts,macros"] + * -------------------------------------------------- + * include-tagged::{doc-tests}/RestClientDocumentation.java[example] + * -------------------------------------------------- + *

+ * Note that this is not a test class as we are only interested in testing that docs snippets compile. We + * don't want + * to send requests to a node and we don't even have the tools to do it. + */ +@SuppressWarnings("unused") +public class RestClientDocumentation { + private static final String TOKEN = "DUMMY"; + + // tag::rest-client-options-singleton + private static final RequestOptions COMMON_OPTIONS; + + static { + RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); + builder.addHeader("Authorization", "Bearer " + TOKEN); // <1> + builder.setHttpAsyncResponseConsumerFactory( // <2> + HttpAsyncResponseConsumerFactory.DEFAULT); + COMMON_OPTIONS = builder.build(); + } + // end::rest-client-options-singleton + + @SuppressWarnings("unused") + public void usage() throws IOException, InterruptedException, ParseException { + + //tag::rest-client-init + RestClient restClient = RestClient.builder( + new HttpHost("http", "localhost", 9200), + new HttpHost("http", "localhost", 9201)).build(); + //end::rest-client-init + + //tag::rest-client-close + restClient.close(); + //end::rest-client-close + + { + //tag::rest-client-init-default-headers + RestClientBuilder builder = RestClient.builder( + new HttpHost("http", "localhost", 9200)); + Header[] defaultHeaders = new Header[]{new BasicHeader("header", "value")}; + builder.setDefaultHeaders(defaultHeaders); // <1> + //end::rest-client-init-default-headers + } + { + //tag::rest-client-init-node-selector + RestClientBuilder builder = RestClient.builder( + new HttpHost("http", "localhost", 9200)); + builder.setNodeSelector(NodeSelector.SKIP_DEDICATED_MASTERS); // <1> + //end::rest-client-init-node-selector + } + { + //tag::rest-client-init-allocation-aware-selector + RestClientBuilder builder = RestClient.builder( + new HttpHost("http", "localhost", 9200)); + // <1> + builder.setNodeSelector(nodes -> { // <1> + /* + * Prefer any node that belongs to rack_one. If none is around + * we will go to another rack till it's time to try and revive + * some of the nodes that belong to rack_one. + */ + boolean foundOne = false; + for (Node node : nodes) { + String rackId = node.getAttributes().get("rack_id").get(0); + if ("rack_one".equals(rackId)) { + foundOne = true; + break; + } + } + if (foundOne) { + Iterator nodesIt = nodes.iterator(); + while (nodesIt.hasNext()) { + Node node = nodesIt.next(); + String rackId = node.getAttributes().get("rack_id").get(0); + if ("rack_one".equals(rackId) == false) { + nodesIt.remove(); + } + } + } + }); + //end::rest-client-init-allocation-aware-selector + } + { + //tag::rest-client-init-failure-listener + RestClientBuilder builder = RestClient.builder( + new HttpHost("http", "localhost", 9200)); + builder.setFailureListener(new RestClient.FailureListener() { + @Override + public void onFailure(Node node) { + // <1> + } + }); + //end::rest-client-init-failure-listener + } + { + //tag::rest-client-init-request-custom-client + PoolingAsyncClientConnectionManager connectionManager = + PoolingAsyncClientConnectionManagerBuilder.create() + .setMaxConnPerRoute(5) + .build(); + + CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() + .setConnectionManager(connectionManager) + .build(); + RestClientBuilder builder = RestClient.builder( + new HttpHost("http", "localhost", 9200)); + builder.setCustomRestClient(httpclient); + //end::rest-client-init-request-config-callback + } + + { + //tag::rest-client-sync + Request request = new Request( + "GET", // <1> + "/"); // <2> + Response response = restClient.performRequest(request); + //end::rest-client-sync + } + { + //tag::rest-client-async + Request request = new Request( + "GET", // <1> + "/"); // <2> + Cancellable cancellable = restClient.performRequestAsync(request, + new ResponseListener() { + @Override + public void onSuccess(Response response) { + // <3> + } + + @Override + public void onFailure(Exception exception) { + // <4> + } + }); + //end::rest-client-async + } + { + Request request = new Request("GET", "/"); + //tag::rest-client-parameters + request.addParameter("pretty", "true"); + //end::rest-client-parameters + //tag::rest-client-body + request.setEntity(new StringEntity( + "{\"json\":\"text\"}", + ContentType.APPLICATION_JSON)); + //end::rest-client-body + //tag::rest-client-body-shorter + request.setJsonEntity("{\"json\":\"text\"}"); + //end::rest-client-body-shorter + //tag::rest-client-options-set-singleton + request.setOptions(COMMON_OPTIONS); + //end::rest-client-options-set-singleton + { + //tag::rest-client-options-customize-header + RequestOptions.Builder options = COMMON_OPTIONS.toBuilder(); + options.addHeader("cats", "knock things off of other things"); + request.setOptions(options); + //end::rest-client-options-customize-header + } + } + { + HttpEntity[] documents = new HttpEntity[10]; + //tag::rest-client-async-example + final CountDownLatch latch = new CountDownLatch(documents.length); + for (int i = 0; i < documents.length; i++) { + Request request = new Request("PUT", "/posts/doc/" + i); + //let's assume that the documents are stored in an HttpEntity array + request.setEntity(documents[i]); + restClient.performRequestAsync( + request, + new ResponseListener() { + @Override + public void onSuccess(Response response) { + // <1> + latch.countDown(); + } + + @Override + public void onFailure(Exception exception) { + // <2> + latch.countDown(); + } + } + ); + } + latch.await(); + //end::rest-client-async-example + } + { + //tag::rest-client-async-cancel + Request request = new Request("GET", "/posts/_search"); + Cancellable cancellable = restClient.performRequestAsync( + request, + new ResponseListener() { + @Override + public void onSuccess(Response response) { + // <1> + } + + @Override + public void onFailure(Exception exception) { + // <2> + } + } + ); + cancellable.cancel(); + //end::rest-client-async-cancel + } + { + //tag::rest-client-response2 + Response response = restClient.performRequest(new Request("GET", "/")); + RequestLine requestLine = response.getRequestLine(); // <1> + HttpHost host = response.getHost(); // <2> + int statusCode = response.getStatusCode(); // <3> + Header[] headers = response.getHeaders(); // <4> + String responseBody = EntityUtils.toString(response.getEntity()); // <5> + //end::rest-client-response2 + } + } + + @SuppressWarnings("unused") + public void commonConfiguration() throws Exception { + { + //tag::rest-client-config-timeouts + RequestConfig.Builder requestConfigBuilder = RequestConfig.custom() + .setConnectTimeout(Timeout.of(5000, TimeUnit.MILLISECONDS)); + + CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() + .setDefaultRequestConfig(requestConfigBuilder.build()) + .build(); + + RestClientBuilder builder = RestClient.builder( + new HttpHost("localhost", 9200)) + .setCustomRestClient(httpclient); + //end::rest-client-config-timeouts + } + { + //tag::rest-client-config-request-options-timeouts + RequestConfig requestConfig = RequestConfig.custom() + .setConnectTimeout(Timeout.ofMilliseconds(5000)) + .setConnectionRequestTimeout(Timeout.ofMilliseconds(60000)) + .build(); + RequestOptions options = RequestOptions.DEFAULT.toBuilder() + .setRequestConfig(requestConfig) + .build(); + //end::rest-client-config-request-options-timeouts + } + { + //tag::rest-client-config-threads + CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() + .setIOReactorConfig(IOReactorConfig.custom() + .setIoThreadCount(1).build()) + .build(); + + RestClientBuilder builder = RestClient.builder( + new HttpHost("localhost", 9200)) + .setCustomRestClient(httpclient); + //end::rest-client-config-threads + } + { + //tag::rest-client-config-basic-auth + + var creds = Base64.getEncoder().encodeToString("user:test-user-password".getBytes()); + + RestClientBuilder restClient = RestClient.builder(new HttpHost("https", "localhost", + 9200)) + .setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Basic " + creds) + }); + + //end::rest-client-config-basic-auth + } + { + //tag::rest-client-config-disable-preemptive-auth + HttpHost host = new HttpHost("http", "localhost", 9200); + + var creds = Base64.getEncoder().encodeToString("user:test-user-password".getBytes()); + + CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() + .disableAuthCaching() + .build(); + + RestClientBuilder restClient = RestClient.builder(new HttpHost("https", "localhost", + 9200)) + .setCustomRestClient(httpclient) + .setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Basic " + creds) + }); + //end::rest-client-config-disable-preemptive-auth + } + { + String keyStorePass = ""; + //tag::rest-client-config-encrypted-communication + Path trustStorePath = Paths.get("/path/to/truststore.p12"); + KeyStore truststore = KeyStore.getInstance("pkcs12"); + try (InputStream is = Files.newInputStream(trustStorePath)) { + truststore.load(is, keyStorePass.toCharArray()); + } + SSLContextBuilder sslBuilder = SSLContexts.custom() + .loadTrustMaterial(truststore, null); + final SSLContext sslContext = sslBuilder.build(); + RestClientBuilder builder = RestClient.builder( + new HttpHost("https", "localhost", + 9200)) + .setSslContext(sslContext); + //end::rest-client-config-encrypted-communication + } + { + //tag::rest-client-config-trust-ca-pem + Path caCertificatePath = Paths.get("/path/to/ca.crt"); + CertificateFactory factory = + CertificateFactory.getInstance("X.509"); + Certificate trustedCa; + try (InputStream is = Files.newInputStream(caCertificatePath)) { + trustedCa = factory.generateCertificate(is); + } + KeyStore trustStore = KeyStore.getInstance("pkcs12"); + trustStore.load(null, null); + trustStore.setCertificateEntry("ca", trustedCa); + SSLContextBuilder sslContextBuilder = SSLContexts.custom() + .loadTrustMaterial(trustStore, null); + final SSLContext sslContext = sslContextBuilder.build(); + RestClient.builder( + new HttpHost("https", "localhost", + 9200)) + .setSslContext(sslContext); + //end::rest-client-config-trust-ca-pem + } + { + String trustStorePass = ""; + String keyStorePass = ""; + //tag::rest-client-config-mutual-tls-authentication + Path trustStorePath = Paths.get("/path/to/your/truststore.p12"); + Path keyStorePath = Paths.get("/path/to/your/keystore.p12"); + KeyStore trustStore = KeyStore.getInstance("pkcs12"); + KeyStore keyStore = KeyStore.getInstance("pkcs12"); + try (InputStream is = Files.newInputStream(trustStorePath)) { + trustStore.load(is, trustStorePass.toCharArray()); + } + try (InputStream is = Files.newInputStream(keyStorePath)) { + keyStore.load(is, keyStorePass.toCharArray()); + } + SSLContextBuilder sslBuilder = SSLContexts.custom() + .loadTrustMaterial(trustStore, null) + .loadKeyMaterial(keyStore, keyStorePass.toCharArray()); + final SSLContext sslContext = sslBuilder.build(); + RestClient.builder( + new HttpHost("https", "localhost", + 9200)) + .setSslContext(sslContext); + //end::rest-client-config-mutual-tls-authentication + } + { + //tag::rest-client-auth-bearer-token + RestClientBuilder builder = RestClient.builder( + new HttpHost("https", "localhost", + 9200)); + Header[] defaultHeaders = + new Header[]{new BasicHeader("Authorization", + "Bearer u6iuAxZ0RG1Kcm5jVFI4eU4tZU9aVFEwT2F3")}; + builder.setDefaultHeaders(defaultHeaders); + //end::rest-client-auth-bearer-token + } + { + //tag::rest-client-auth-api-key + String apiKeyId = "uqlEyn8B_gQ_jlvwDIvM"; + String apiKeySecret = "HxHWk2m4RN-V_qg9cDpuX"; + String apiKeyAuth = + Base64.getEncoder().encodeToString( + (apiKeyId + ":" + apiKeySecret) + .getBytes(StandardCharsets.UTF_8)); + RestClientBuilder builder = RestClient.builder( + new HttpHost("https", "localhost", + 9200)); + Header[] defaultHeaders = + new Header[]{new BasicHeader("Authorization", + "ApiKey " + apiKeyAuth)}; + builder.setDefaultHeaders(defaultHeaders); + //end::rest-client-auth-api-key + } + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientGzipCompressionTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientGzipCompressionTests.java new file mode 100644 index 000000000..5e917f5cb --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientGzipCompressionTests.java @@ -0,0 +1,257 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseListener; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientTestCase; +import org.elasticsearch.mocksocket.MockHttpServer; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.CompletableFuture; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +import static org.apache.hc.core5.http.HttpHeaders.CONTENT_ENCODING; +import static org.apache.hc.core5.http.HttpHeaders.CONTENT_LENGTH; + +public class RestClientGzipCompressionTests extends RestClientTestCase { + + private static HttpServer httpServer; + + @BeforeClass + public static void startHttpServer() throws Exception { + httpServer = MockHttpServer.createHttp(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + httpServer.createContext("/", new GzipResponseHandler()); + httpServer.start(); + } + + @AfterClass + public static void stopHttpServers() throws IOException { + httpServer.stop(0); + httpServer = null; + } + + /** + * A response handler that accepts gzip-encoded data and replies request and response encoding values + * followed by the request body. The response is compressed if "Accept-Encoding" is "gzip". + */ + private static class GzipResponseHandler implements HttpHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + + // Decode body (if any) + String contentEncoding = exchange.getRequestHeaders().getFirst("Content-Encoding"); + InputStream body = exchange.getRequestBody(); + if ("gzip".equals(contentEncoding)) { + body = new GZIPInputStream(body); + } + byte[] bytes = readAll(body); + + boolean compress = "gzip".equals(exchange.getRequestHeaders().getFirst("Accept-Encoding")); + if (compress) { + exchange.getResponseHeaders().add("Content-Encoding", "gzip"); + } + + // Encode response if needed + ByteArrayOutputStream bao = new ByteArrayOutputStream(); + OutputStream out = bao; + if (compress) { + out = new GZIPOutputStream(out); + } + + // Outputs ## + out.write(String.valueOf(contentEncoding).getBytes(StandardCharsets.UTF_8)); + out.write('#'); + out.write((compress ? "gzip" : "null").getBytes(StandardCharsets.UTF_8)); + out.write('#'); + out.write(bytes); + out.close(); + + bytes = bao.toByteArray(); + + exchange.sendResponseHeaders(200, bytes.length); + + exchange.getResponseBody().write(bytes); + exchange.close(); + } + } + + /** + * Read all bytes of an input stream and close it. + */ + private static byte[] readAll(InputStream in) throws IOException { + byte[] buffer = new byte[1024]; + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + int len = 0; + while ((len = in.read(buffer)) > 0) { + bos.write(buffer, 0, len); + } + in.close(); + return bos.toByteArray(); + } + + private RestClient createClient(boolean enableCompression) { + InetSocketAddress address = httpServer.getAddress(); + return RestClient.builder(new HttpHost("http", address.getHostString(), address.getPort())) + .setCompressionEnabled(enableCompression) + .build(); + } + + public void testUncompressedSync() throws Exception { + RestClient restClient = createClient(false); + + // Send non-compressed request, expect non-compressed response + Request request = new Request("POST", "/"); + request.setEntity(new StringEntity("plain request, plain response", ContentType.TEXT_PLAIN)); + + Response response = restClient.performRequest(request); + + // Server sends a content-length which should be kept + Assert.assertTrue(response.getEntity().getContentLength() > 0); + checkResponse("null#null#plain request, plain response", response); + + restClient.close(); + } + + public void testGzipHeaderSync() throws Exception { + RestClient restClient = createClient(false); + + // Send non-compressed request, expect compressed response + Request request = new Request("POST", "/"); + request.setEntity(new StringEntity("plain request, gzip response", ContentType.TEXT_PLAIN)); + request.setOptions(RequestOptions.DEFAULT.toBuilder().addHeader("Accept-Encoding", "gzip").build()); + + Response response = restClient.performRequest(request); + + // Content-length is unknown because of ungzip. Do not just test -1 as it returns "a negative + // number if unknown" + Assert.assertTrue(response.getEntity().getContentLength() < 0); + checkResponse("null#gzip#plain request, gzip response", response); + + restClient.close(); + } + + public void testGzipHeaderAsync() throws Exception { + RestClient restClient = createClient(false); + + // Send non-compressed request, expect compressed response + Request request = new Request("POST", "/"); + request.setEntity(new StringEntity("plain request, gzip response", ContentType.TEXT_PLAIN)); + request.setOptions(RequestOptions.DEFAULT.toBuilder().addHeader("Accept-Encoding", "gzip").build()); + + FutureResponse futureResponse = new FutureResponse(); + restClient.performRequestAsync(request, futureResponse); + Response response = futureResponse.get(); + + Assert.assertTrue(response.getEntity().getContentLength() < 0); + checkResponse("null#gzip#plain request, gzip response", response); + + restClient.close(); + } + + public void testCompressingClientSync() throws Exception { + RestClient restClient = createClient(true); + + Request request = new Request("POST", "/"); + request.setEntity(new StringEntity("compressing client", ContentType.TEXT_PLAIN)); + + Response response = restClient.performRequest(request); + + Assert.assertTrue(response.getEntity().getContentLength() < 0); + checkResponse("gzip#gzip#compressing client", response); + + restClient.close(); + } + + public void testCompressingClientAsync() throws Exception { + InetSocketAddress address = httpServer.getAddress(); + RestClient restClient = RestClient.builder(new HttpHost("http", address.getHostString(), + address.getPort())) + .setCompressionEnabled(true) + .build(); + + Request request = new Request("POST", "/"); + request.setEntity(new StringEntity("compressing client", ContentType.TEXT_PLAIN)); + + FutureResponse futureResponse = new FutureResponse(); + restClient.performRequestAsync(request, futureResponse); + Response response = futureResponse.get(); + + // Server should report it had a compressed request and sent back a compressed response + Assert.assertTrue(response.getEntity().getContentLength() < 0); + checkResponse("gzip#gzip#compressing client", response); + + restClient.close(); + } + + public static class FutureResponse extends CompletableFuture implements ResponseListener { + @Override + public void onSuccess(Response response) { + this.complete(response); + } + + @Override + public void onFailure(Exception exception) { + this.completeExceptionally(exception); + } + } + + private static void checkResponse(String expected, Response response) throws Exception { + HttpEntity entity = response.getEntity(); + Assert.assertNotNull(entity); + + String content = new String(readAll(entity.getContent()), StandardCharsets.UTF_8); + Assert.assertEquals(expected, content); + + // Original Content-Encoding should be removed on both entity and response + Assert.assertNull(entity.getContentEncoding()); + Assert.assertNull(response.getHeader(CONTENT_ENCODING)); + + // Content-length must be consistent between entity and response + long entityContentLength = entity.getContentLength(); + String headerContentLength = response.getHeader(CONTENT_LENGTH); + + if (entityContentLength < 0) { + Assert.assertNull(headerContentLength); + } else { + Assert.assertEquals(String.valueOf(entityContentLength), headerContentLength); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientMultipleHostsIntegTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientMultipleHostsIntegTests.java new file mode 100644 index 000000000..ac381eda0 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientMultipleHostsIntegTests.java @@ -0,0 +1,402 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.client.Cancellable; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseException; +import org.elasticsearch.client.ResponseListener; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; +import org.elasticsearch.client.RestClientSingleHostTests; +import org.elasticsearch.client.RestClientTestCase; +import org.elasticsearch.client.RestClientTestUtil; +import org.elasticsearch.client.consumer.BasicAsyncResponseConsumer; +import org.elasticsearch.client.consumer.BufferedByteConsumer; +import org.elasticsearch.client.node.Node; +import org.elasticsearch.client.node.selector.NodeSelector; +import org.elasticsearch.mocksocket.MockHttpServer; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.ConnectException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.elasticsearch.client.RestClientTestUtil.getAllStatusCodes; +import static org.elasticsearch.client.RestClientTestUtil.randomErrorNoRetryStatusCode; +import static org.elasticsearch.client.RestClientTestUtil.randomOkStatusCode; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Integration test to check interaction between {@link RestClient} and {@link org.apache.hc.client5.http.async.HttpAsyncClient}. + * Works against real http servers, multiple hosts. Also tests failover by randomly shutting down hosts. + */ +public class RestClientMultipleHostsIntegTests extends RestClientTestCase { + + private static WaitForCancelHandler waitForCancelHandler; + private static HttpServer[] httpServers; + private static HttpHost[] httpHosts; + private static boolean stoppedFirstHost = false; + private static String pathPrefixWithoutLeadingSlash; + private static String pathPrefix; + private static RestClient restClient; + + @BeforeClass + public static void startHttpServer() throws Exception { + if (randomBoolean()) { + pathPrefixWithoutLeadingSlash = "testPathPrefix/" + randomAsciiLettersOfLengthBetween(1, 5); + pathPrefix = "/" + pathPrefixWithoutLeadingSlash; + } else { + pathPrefix = pathPrefixWithoutLeadingSlash = ""; + } + int numHttpServers = randomIntBetween(2, 4); + httpServers = new HttpServer[numHttpServers]; + httpHosts = new HttpHost[numHttpServers]; + waitForCancelHandler = new WaitForCancelHandler(); + for (int i = 0; i < numHttpServers; i++) { + HttpServer httpServer = createHttpServer(); + httpServers[i] = httpServer; + httpHosts[i] = new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()); + } + restClient = buildRestClient(NodeSelector.ANY); + } + + private static RestClient buildRestClient(NodeSelector nodeSelector) { + return buildRestClient(nodeSelector, null); + } + + private static RestClient buildRestClient(NodeSelector nodeSelector, RestClient.FailureListener failureListener) { + RestClientBuilder restClientBuilder = RestClient.builder(httpHosts); + if (pathPrefix.length() > 0) { + restClientBuilder.setPathPrefix((randomBoolean() ? "/" : "") + pathPrefixWithoutLeadingSlash); + } + if (failureListener != null) { + restClientBuilder.setFailureListener(failureListener); + } + restClientBuilder.setNodeSelector(nodeSelector); + return restClientBuilder.build(); + } + + private static HttpServer createHttpServer() throws Exception { + HttpServer httpServer = MockHttpServer.createHttp(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + httpServer.start(); + // returns a different status code depending on the path + for (int statusCode : getAllStatusCodes()) { + httpServer.createContext(pathPrefix + "/" + statusCode, new ResponseHandler(statusCode)); + } + httpServer.createContext(pathPrefix + "/20bytes", new ResponseHandlerWithContent()); + httpServer.createContext(pathPrefix + "/wait", waitForCancelHandler); + return httpServer; + } + + private static WaitForCancelHandler resetWaitHandlers() { + WaitForCancelHandler handler = new WaitForCancelHandler(); + for (HttpServer httpServer : httpServers) { + httpServer.removeContext(pathPrefix + "/wait"); + httpServer.createContext(pathPrefix + "/wait", handler); + } + return handler; + } + + private static class WaitForCancelHandler implements HttpHandler { + private final CountDownLatch requestCameInLatch = new CountDownLatch(1); + private final CountDownLatch cancelHandlerLatch = new CountDownLatch(1); + + void cancelDone() { + cancelHandlerLatch.countDown(); + } + + void awaitRequest() throws InterruptedException { + requestCameInLatch.await(); + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + requestCameInLatch.countDown(); + try { + cancelHandlerLatch.await(); + } catch (InterruptedException ignore) {} finally { + exchange.sendResponseHeaders(200, 0); + exchange.close(); + } + } + } + + private static class ResponseHandler implements HttpHandler { + private final int statusCode; + + ResponseHandler(int statusCode) { + this.statusCode = statusCode; + } + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + httpExchange.getRequestBody().close(); + httpExchange.sendResponseHeaders(statusCode, -1); + httpExchange.close(); + } + } + + private static class ResponseHandlerWithContent implements HttpHandler { + @Override + public void handle(HttpExchange httpExchange) throws IOException { + byte[] body = "01234567890123456789".getBytes(StandardCharsets.UTF_8); + httpExchange.sendResponseHeaders(200, body.length); + try (OutputStream out = httpExchange.getResponseBody()) { + out.write(body); + } + httpExchange.close(); + } + } + + @AfterClass + public static void stopHttpServers() throws IOException { + restClient.close(); + restClient = null; + for (HttpServer httpServer : httpServers) { + httpServer.stop(0); + } + httpServers = null; + } + + @Before + public void stopRandomHost() { + // verify that shutting down some hosts doesn't matter as long as one working host is left behind + if (httpServers.length > 1 && randomBoolean()) { + List updatedHttpServers = new ArrayList<>(httpServers.length - 1); + int nodeIndex = randomIntBetween(0, httpServers.length - 1); + if (0 == nodeIndex) { + stoppedFirstHost = true; + } + for (int i = 0; i < httpServers.length; i++) { + HttpServer httpServer = httpServers[i]; + if (i == nodeIndex) { + httpServer.stop(0); + } else { + updatedHttpServers.add(httpServer); + } + } + httpServers = updatedHttpServers.toArray(new HttpServer[0]); + } + } + + public void testSyncRequests() throws IOException { + int numRequests = randomIntBetween(5, 20); + for (int i = 0; i < numRequests; i++) { + final String method = RestClientTestUtil.randomHttpMethod(getRandom()); + // we don't test status codes that are subject to retries as they interfere with hosts being stopped + final int statusCode = randomBoolean() ? randomOkStatusCode(getRandom()) : randomErrorNoRetryStatusCode(getRandom()); + Response response; + try { + response = restClient.performRequest(new Request(method, "/" + statusCode)); + } catch (ResponseException responseException) { + response = responseException.getResponse(); + } + assertEquals(method, response.getRequestLine().getMethod()); + assertEquals(statusCode, response.getStatusCode()); + assertEquals((pathPrefix.length() > 0 ? pathPrefix : "") + "/" + statusCode, response.getRequestLine().getUri()); + } + } + + public void testAsyncRequests() throws Exception { + int numRequests = randomIntBetween(5, 20); + final CountDownLatch latch = new CountDownLatch(numRequests); + final List responses = new CopyOnWriteArrayList<>(); + for (int i = 0; i < numRequests; i++) { + final String method = RestClientTestUtil.randomHttpMethod(getRandom()); + // we don't test status codes that are subject to retries as they interfere with hosts being stopped + final int statusCode = randomBoolean() ? randomOkStatusCode(getRandom()) : randomErrorNoRetryStatusCode(getRandom()); + restClient.performRequestAsync(new Request(method, "/" + statusCode), new ResponseListener() { + @Override + public void onSuccess(Response response) { + responses.add(new TestResponse(method, statusCode, response)); + latch.countDown(); + } + + @Override + public void onFailure(Exception exception) { + responses.add(new TestResponse(method, statusCode, exception)); + latch.countDown(); + } + }); + } + assertTrue(latch.await(5, TimeUnit.SECONDS)); + + assertEquals(numRequests, responses.size()); + for (TestResponse testResponse : responses) { + Response response = testResponse.getResponse(); + assertEquals(testResponse.method, response.getRequestLine().getMethod()); + assertEquals(testResponse.statusCode, response.getStatusCode()); + assertEquals((pathPrefix.length() > 0 ? pathPrefix : "") + "/" + testResponse.statusCode, response.getRequestLine().getUri()); + } + } + + public void testCancelAsyncRequests() throws Exception { + int numRequests = randomIntBetween(5, 20); + final List responses = new CopyOnWriteArrayList<>(); + final List exceptions = new CopyOnWriteArrayList<>(); + for (int i = 0; i < numRequests; i++) { + CountDownLatch latch = new CountDownLatch(1); + waitForCancelHandler = resetWaitHandlers(); + Cancellable cancellable = restClient.performRequestAsync(new Request("GET", "/wait"), new ResponseListener() { + @Override + public void onSuccess(Response response) { + responses.add(response); + latch.countDown(); + } + + @Override + public void onFailure(Exception exception) { + exceptions.add(exception); + latch.countDown(); + } + }); + if (randomBoolean()) { + // we wait for the request to get to the server-side otherwise we almost always cancel + // the request artificially on the client-side before even sending it + waitForCancelHandler.awaitRequest(); + } + cancellable.cancel(); + waitForCancelHandler.cancelDone(); + assertTrue(latch.await(5, TimeUnit.SECONDS)); + } + assertEquals(0, responses.size()); + assertEquals(numRequests, exceptions.size()); + for (Exception exception : exceptions) { + assertThat(exception, instanceOf(CancellationException.class)); + } + } + + /** + * Test host selector against a real server and + * test what happens after calling + */ + public void testNodeSelector() throws Exception { + try (RestClient restClient = buildRestClient(firstPositionNodeSelector())) { + Request request = new Request("GET", "/200"); + int rounds = between(1, 10); + for (int i = 0; i < rounds; i++) { + /* + * Run the request more than once to verify that the + * NodeSelector overrides the round robin behavior. + */ + if (stoppedFirstHost) { + try { + RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + fail("expected to fail to connect"); + } catch (ConnectException e) { + // Windows isn't consistent here. Sometimes the message is even null! + if (false == System.getProperty("os.name").startsWith("Windows")) { + assertTrue(e.getMessage().contains("Connection refused")); + } + } + } else { + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(httpHosts[0], response.getHost()); + } + } + } + } + + @Ignore("https://github.com/elastic/elasticsearch/issues/87314") + public void testNonRetryableException() throws Exception { + RequestOptions.Builder options = RequestOptions.DEFAULT.toBuilder(); + options.setHttpAsyncResponseConsumerFactory( + // Limit to very short responses to trigger a ContentTooLongException + () -> new BasicAsyncResponseConsumer(new BufferedByteConsumer(10)) + ); + + AtomicInteger failureCount = new AtomicInteger(); + RestClient client = buildRestClient(NodeSelector.ANY, new RestClient.FailureListener() { + @Override + public void onFailure(Node node) { + failureCount.incrementAndGet(); + } + }); + + failureCount.set(0); + Request request = new Request("POST", "/20bytes"); + request.setOptions(options); + try { + RestClientSingleHostTests.performRequestSyncOrAsync(client, request); + fail("Request should not succeed"); + } catch (IOException e) { + assertEquals(stoppedFirstHost ? 2 : 1, failureCount.intValue()); + } + + client.close(); + } + + private static class TestResponse { + private final String method; + private final int statusCode; + private final Object response; + + TestResponse(String method, int statusCode, Object response) { + this.method = method; + this.statusCode = statusCode; + this.response = response; + } + + Response getResponse() { + if (response instanceof Response) { + return (Response) response; + } + if (response instanceof ResponseException) { + return ((ResponseException) response).getResponse(); + } + throw new AssertionError("unexpected response " + response.getClass()); + } + } + + private NodeSelector firstPositionNodeSelector() { + return nodes -> { + for (Iterator itr = nodes.iterator(); itr.hasNext();) { + if (httpHosts[0] != itr.next().getHost()) { + itr.remove(); + } + } + }; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientMultipleHostsTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientMultipleHostsTests.java new file mode 100644 index 000000000..640471c09 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientMultipleHostsTests.java @@ -0,0 +1,341 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import com.carrotsearch.randomizedtesting.generators.RandomNumbers; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseException; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientSingleHostTests; +import org.elasticsearch.client.RestClientTestCase; +import org.elasticsearch.client.node.Node; +import org.elasticsearch.client.node.selector.NodeSelector; +import org.junit.After; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static org.elasticsearch.client.RestClientTestUtil.randomErrorNoRetryStatusCode; +import static org.elasticsearch.client.RestClientTestUtil.randomErrorRetryStatusCode; +import static org.elasticsearch.client.RestClientTestUtil.randomHttpMethod; +import static org.elasticsearch.client.RestClientTestUtil.randomOkStatusCode; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Tests for {@link RestClient} behaviour against multiple hosts: fail-over, blacklisting etc. + * Relies on a mock http client to intercept requests and return desired responses based on request path. + */ +public class RestClientMultipleHostsTests extends RestClientTestCase { + + private ExecutorService exec = Executors.newFixedThreadPool(1); + private List nodes; + private HostsTrackingFailureListener failureListener; + + public RestClient createRestClient(NodeSelector nodeSelector) { + CloseableHttpAsyncClient httpClient = RestClientSingleHostTests.mockHttpClient(exec); + int numNodes = RandomNumbers.randomIntBetween(getRandom(), 2, 5); + nodes = new ArrayList<>(numNodes); + for (int i = 0; i < numNodes; i++) { + nodes.add(new Node(new HttpHost("localhost", 9200 + i))); + } + nodes = Collections.unmodifiableList(nodes); + failureListener = new HostsTrackingFailureListener(); + return new RestClient(httpClient, new Header[0], nodes, null, failureListener, nodeSelector, false, false, false); + } + + /** + * Shutdown the executor so we don't leak threads into other test runs. + */ + @After + public void shutdownExec() { + exec.shutdown(); + } + + public void testRoundRobinOkStatusCodes() throws Exception { + RestClient restClient = createRestClient(NodeSelector.ANY); + int numIters = RandomNumbers.randomIntBetween(getRandom(), 1, 5); + for (int i = 0; i < numIters; i++) { + Set hostsSet = hostsSet(); + for (int j = 0; j < nodes.size(); j++) { + int statusCode = randomOkStatusCode(getRandom()); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync( + restClient, + new Request(randomHttpMethod(getRandom()), "/" + statusCode) + ); + assertEquals(statusCode, response.getStatusCode()); + assertTrue("host not found: " + response.getHost(), hostsSet.remove(response.getHost())); + } + assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); + } + failureListener.assertNotCalled(); + } + + public void testRoundRobinNoRetryErrors() throws Exception { + RestClient restClient = createRestClient(NodeSelector.ANY); + int numIters = RandomNumbers.randomIntBetween(getRandom(), 1, 5); + for (int i = 0; i < numIters; i++) { + Set hostsSet = hostsSet(); + for (int j = 0; j < nodes.size(); j++) { + String method = randomHttpMethod(getRandom()); + int statusCode = randomErrorNoRetryStatusCode(getRandom()); + try { + Response response = RestClientSingleHostTests.performRequestSyncOrAsync( + restClient, + new Request(method, "/" + statusCode) + ); + if (method.equals("HEAD") && statusCode == 404) { + // no exception gets thrown although we got a 404 + assertEquals(404, response.getStatusCode()); + assertEquals(statusCode, response.getStatusCode()); + assertTrue("host not found: " + response.getHost(), hostsSet.remove(response.getHost())); + } else { + fail("request should have failed"); + } + } catch (ResponseException e) { + if (method.equals("HEAD") && statusCode == 404) { + throw e; + } + Response response = e.getResponse(); + assertEquals(statusCode, response.getStatusCode()); + assertTrue("host not found: " + response.getHost(), hostsSet.remove(response.getHost())); + assertEquals(0, e.getSuppressed().length); + } + } + assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); + } + failureListener.assertNotCalled(); + } + + public void testRoundRobinRetryErrors() throws Exception { + RestClient restClient = createRestClient(NodeSelector.ANY); + String retryEndpoint = randomErrorRetryEndpoint(); + try { + RestClientSingleHostTests.performRequestSyncOrAsync(restClient, new Request(randomHttpMethod(getRandom()), retryEndpoint)); + fail("request should have failed"); + } catch (ResponseException e) { + Set hostsSet = hostsSet(); + // first request causes all the hosts to be blacklisted, the returned exception holds one suppressed exception each + failureListener.assertCalled(nodes); + do { + Response response = e.getResponse(); + assertEquals(Integer.parseInt(retryEndpoint.substring(1)), response.getStatusCode()); + assertTrue( + "host [" + response.getHost() + "] not found, most likely used multiple times", + hostsSet.remove(response.getHost()) + ); + if (e.getSuppressed().length > 0) { + assertEquals(1, e.getSuppressed().length); + Throwable suppressed = e.getSuppressed()[0]; + assertThat(suppressed, instanceOf(ResponseException.class)); + e = (ResponseException) suppressed; + } else { + e = null; + } + } while (e != null); + assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); + } catch (IOException e) { + Set hostsSet = hostsSet(); + // first request causes all the hosts to be blacklisted, the returned exception holds one suppressed exception each + failureListener.assertCalled(nodes); + do { + HttpHost httpHost = HttpHost.create(e.getMessage()); + assertTrue("host [" + httpHost + "] not found, most likely used multiple times", hostsSet.remove(httpHost)); + if (e.getSuppressed().length > 0) { + assertEquals(1, e.getSuppressed().length); + Throwable suppressed = e.getSuppressed()[0]; + assertThat(suppressed, instanceOf(IOException.class)); + e = (IOException) suppressed; + } else { + e = null; + } + } while (e != null); + assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); + } + + int numIters = RandomNumbers.randomIntBetween(getRandom(), 2, 5); + for (int i = 1; i <= numIters; i++) { + // check that one different host is resurrected at each new attempt + Set hostsSet = hostsSet(); + for (int j = 0; j < nodes.size(); j++) { + retryEndpoint = randomErrorRetryEndpoint(); + try { + RestClientSingleHostTests.performRequestSyncOrAsync( + restClient, + new Request(randomHttpMethod(getRandom()), retryEndpoint) + ); + fail("request should have failed"); + } catch (ResponseException e) { + Response response = e.getResponse(); + assertThat(response.getStatusCode(), equalTo(Integer.parseInt(retryEndpoint.substring(1)))); + assertTrue( + "host [" + response.getHost() + "] not found, most likely used multiple times", + hostsSet.remove(response.getHost()) + ); + // after the first request, all hosts are blacklisted, a single one gets resurrected each time + failureListener.assertCalled(response.getHost()); + assertEquals(0, e.getSuppressed().length); + } catch (IOException e) { + HttpHost httpHost = HttpHost.create(e.getMessage()); + assertTrue("host [" + httpHost + "] not found, most likely used multiple times", hostsSet.remove(httpHost)); + // after the first request, all hosts are blacklisted, a single one gets resurrected each time + failureListener.assertCalled(httpHost); + assertEquals(0, e.getSuppressed().length); + } + } + assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); + if (getRandom().nextBoolean()) { + // mark one host back alive through a successful request and check that all requests after that are sent to it + HttpHost selectedHost = null; + int iters = RandomNumbers.randomIntBetween(getRandom(), 2, 10); + for (int y = 0; y < iters; y++) { + int statusCode = randomErrorNoRetryStatusCode(getRandom()); + Response response; + try { + response = RestClientSingleHostTests.performRequestSyncOrAsync( + restClient, + new Request(randomHttpMethod(getRandom()), "/" + statusCode) + ); + } catch (ResponseException e) { + response = e.getResponse(); + } + assertThat(response.getStatusCode(), equalTo(statusCode)); + if (selectedHost == null) { + selectedHost = response.getHost(); + } else { + assertThat(response.getHost(), equalTo(selectedHost)); + } + } + failureListener.assertNotCalled(); + // let the selected host catch up on number of failures, it gets selected a consecutive number of times as it's the one + // selected to be retried earlier (due to lower number of failures) till all the hosts have the same number of failures + for (int y = 0; y < i + 1; y++) { + retryEndpoint = randomErrorRetryEndpoint(); + try { + RestClientSingleHostTests.performRequestSyncOrAsync( + restClient, + new Request(randomHttpMethod(getRandom()), retryEndpoint) + ); + fail("request should have failed"); + } catch (ResponseException e) { + Response response = e.getResponse(); + assertThat(response.getStatusCode(), equalTo(Integer.parseInt(retryEndpoint.substring(1)))); + assertThat(response.getHost(), equalTo(selectedHost)); + failureListener.assertCalled(selectedHost); + } catch (IOException e) { + HttpHost httpHost = HttpHost.create(e.getMessage()); + assertThat(httpHost, equalTo(selectedHost)); + failureListener.assertCalled(selectedHost); + } + } + } + } + } + + public void testNodeSelector() throws Exception { + NodeSelector firstPositionOnly = restClientNodes -> { + boolean found = false; + for (Iterator itr = restClientNodes.iterator(); itr.hasNext();) { + if (nodes.get(0) == itr.next()) { + found = true; + } else { + itr.remove(); + } + } + assertTrue(found); + }; + RestClient restClient = createRestClient(firstPositionOnly); + int rounds = between(1, 10); + for (int i = 0; i < rounds; i++) { + /* + * Run the request more than once to verify that the + * NodeSelector overrides the round robin behavior. + */ + Request request = new Request("GET", "/200"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(nodes.get(0).getHost(), response.getHost()); + } + } + + public void testSetNodes() throws Exception { + RestClient restClient = createRestClient(NodeSelector.SKIP_DEDICATED_MASTERS); + List newNodes = new ArrayList<>(nodes.size()); + for (int i = 0; i < nodes.size(); i++) { + Node.Roles roles = i == 0 + ? new Node.Roles(new TreeSet<>(Arrays.asList("data", "ingest"))) + : new Node.Roles(new TreeSet<>(Arrays.asList("master"))); + newNodes.add(new Node(nodes.get(i).getHost(), null, null, null, roles, null)); + } + restClient.setNodes(newNodes); + int rounds = between(1, 10); + for (int i = 0; i < rounds; i++) { + /* + * Run the request more than once to verify that the + * NodeSelector overrides the round robin behavior. + */ + Request request = new Request("GET", "/200"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(newNodes.get(0).getHost(), response.getHost()); + } + } + + private static String randomErrorRetryEndpoint() { + switch (RandomNumbers.randomIntBetween(getRandom(), 0, 3)) { + case 0: + return "/" + randomErrorRetryStatusCode(getRandom()); + case 1: + return "/coe"; + case 2: + return "/soe"; + case 3: + return "/ioe"; + } + throw new UnsupportedOperationException(); + } + + /** + * Build a mutable {@link Set} containing all the {@link Node#getHost() hosts} + * in use by the test. + */ + private Set hostsSet() { + Set hosts = new HashSet<>(); + for (Node node : nodes) { + hosts.add(node.getHost()); + } + return hosts; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientSingleHostIntegTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientSingleHostIntegTests.java new file mode 100644 index 000000000..9d2510f1b --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientSingleHostIntegTests.java @@ -0,0 +1,457 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import org.apache.hc.client5.http.async.methods.SimpleHttpRequest; +import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; +import org.apache.hc.client5.http.impl.async.HttpAsyncClients; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.http.message.BasicHeader; +import org.elasticsearch.client.Cancellable; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseException; +import org.elasticsearch.client.ResponseListener; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; +import org.elasticsearch.client.RestClientSingleHostTests; +import org.elasticsearch.client.RestClientTestCase; +import org.elasticsearch.client.RestClientTestUtil; +import org.elasticsearch.mocksocket.MockHttpServer; +import org.junit.After; +import org.junit.Before; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.elasticsearch.client.RestClientTestUtil.getAllStatusCodes; +import static org.elasticsearch.client.RestClientTestUtil.randomHttpMethod; +import static org.elasticsearch.client.RestClientTestUtil.randomStatusCode; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.startsWith; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/* + * Integration test to check interaction between {@link RestClient} and {@link org.apache.hc.client5.http + * .async.HttpAsyncClient}. + * Works against a real http server, one single host. + */ + +public class RestClientSingleHostIntegTests extends RestClientTestCase { + + private HttpServer httpServer; + private RestClient restClient; + private String pathPrefix; + private Header[] defaultHeaders; + private WaitForCancelHandler waitForCancelHandler; + + @Before + public void startHttpServer() throws Exception { + // set version.properties, just for testing, version won't be updated + System.setProperty("versions.elasticsearch","8.17.0"); + pathPrefix = randomBoolean() ? "/testPathPrefix/" + randomAsciiLettersOfLengthBetween(1, 5) : ""; + httpServer = createHttpServer(); + defaultHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header-default"); + restClient = createRestClient(false, true, true); + } + + private HttpServer createHttpServer() throws Exception { + HttpServer mockServer = + MockHttpServer.createHttp(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + mockServer.start(); + // returns a different status code depending on the path + for (int statusCode : getAllStatusCodes()) { + mockServer.createContext(pathPrefix + "/" + statusCode, new ResponseHandler(statusCode)); + } + waitForCancelHandler = new WaitForCancelHandler(); + mockServer.createContext(pathPrefix + "/wait", waitForCancelHandler); + return mockServer; + } + + private static class WaitForCancelHandler implements HttpHandler { + + private final CountDownLatch cancelHandlerLatch = new CountDownLatch(1); + + void cancelDone() { + cancelHandlerLatch.countDown(); + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + cancelHandlerLatch.await(); + } catch (InterruptedException ignore) { + } finally { + exchange.sendResponseHeaders(200, 0); + exchange.close(); + } + } + } + + private static class ResponseHandler implements HttpHandler { + private final int statusCode; + + ResponseHandler(int statusCode) { + this.statusCode = statusCode; + } + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + // copy request body to response body so we can verify it was sent + StringBuilder body = new StringBuilder(); + try (InputStreamReader reader = new InputStreamReader(httpExchange.getRequestBody(), UTF_8)) { + char[] buffer = new char[256]; + int read; + while ((read = reader.read(buffer)) != -1) { + body.append(buffer, 0, read); + } + } + // copy request headers to response headers so we can verify they were sent + Headers requestHeaders = httpExchange.getRequestHeaders(); + Headers responseHeaders = httpExchange.getResponseHeaders(); + for (Map.Entry> header : requestHeaders.entrySet()) { + responseHeaders.put(header.getKey(), header.getValue()); + } + httpExchange.getRequestBody().close(); + httpExchange.sendResponseHeaders(statusCode, body.length() == 0 ? -1 : body.length()); + if (body.length() > 0) { + try (OutputStream out = httpExchange.getResponseBody()) { + out.write(body.toString().getBytes(UTF_8)); + } + } + httpExchange.close(); + } + } + + private RestClient createRestClient(final boolean useAuth, final boolean usePreemptiveAuth, + final boolean enableMetaHeader) { + HttpHost host = new HttpHost(httpServer.getAddress().getHostString(), + httpServer.getAddress().getPort()); + + final RestClientBuilder restClientBuilder = + RestClient.builder(host).setDefaultHeaders(defaultHeaders); + if (pathPrefix.length() > 0) { + restClientBuilder.setPathPrefix(pathPrefix); + } + + restClientBuilder.setMetaHeaderEnabled(enableMetaHeader); + + + if (useAuth) { + // provide the username/password for every request + var creds = Base64.getEncoder().encodeToString("user:pass".getBytes()); + + HttpAsyncClientBuilder httpclientBuilder = HttpAsyncClients.custom(); + + httpclientBuilder.setDefaultHeaders(Arrays.asList(new BasicHeader("Authorization", + "Basic " + creds))); + + if (!usePreemptiveAuth) { + httpclientBuilder + .disableAuthCaching() + .setTargetAuthenticationStrategy(new DefaultAuthenticationStrategy()); + } + restClientBuilder.setCustomRestClient(httpclientBuilder.build()); + } + + return restClientBuilder.build(); + } + + @After + public void stopHttpServers() throws IOException { + restClient.close(); + restClient = null; + httpServer.stop(0); + httpServer = null; + } + + /* + * Tests sending a bunch of async requests works well (e.g. no TimeoutException from the leased pool) + * See https://github.com/elastic/elasticsearch/issues/24069 + */ + + public void testManyAsyncRequests() throws Exception { + int iters = randomIntBetween(500, 1000); + final CountDownLatch latch = new CountDownLatch(iters); + final List exceptions = new CopyOnWriteArrayList<>(); + for (int i = 0; i < iters; i++) { + Request request = new Request("PUT", "/200"); + request.setEntity(new StringEntity("{}", ContentType.APPLICATION_JSON)); + restClient.performRequestAsync(request, new ResponseListener() { + @Override + public void onSuccess(Response response) { + latch.countDown(); + } + + @Override + public void onFailure(Exception exception) { + exceptions.add(exception); + latch.countDown(); + } + }); + } + + assertTrue("timeout waiting for requests to be sent", latch.await(10, TimeUnit.SECONDS)); + if (exceptions.isEmpty() == false) { + AssertionError error = new AssertionError( + "expected no failures but got some. see suppressed for first 10 of [" + exceptions.size() + "] failures" + ); + for (Exception exception : exceptions.subList(0, Math.min(10, exceptions.size()))) { + error.addSuppressed(exception); + } + throw error; + } + } + + public void testCancelAsyncRequest() throws Exception { + Request request = new Request(randomHttpMethod(getRandom()), "/wait"); + CountDownLatch requestLatch = new CountDownLatch(1); + AtomicReference error = new AtomicReference<>(); + Cancellable cancellable = restClient.performRequestAsync(request, new ResponseListener() { + @Override + public void onSuccess(Response response) { + throw new AssertionError("onResponse called unexpectedly"); + } + + @Override + public void onFailure(Exception exception) { + error.set(exception); + requestLatch.countDown(); + } + }); + cancellable.cancel(); + waitForCancelHandler.cancelDone(); + assertTrue(requestLatch.await(5, TimeUnit.SECONDS)); + assertThat(error.get(), instanceOf(CancellationException.class)); + } + + /** + * This test verifies some assumptions that we rely upon around the way the async http client works + * when reusing the same request + * throughout multiple retries, and the use of the + * {@link org.apache.hc.client5.http.classic.methods.HttpUriRequestBase#abort()} method. + * In fact the low-level REST client reuses the same request instance throughout multiple retries, and + * relies on the http client + * to set the future ref to the request properly so that when abort is called, the proper future gets + * cancelled. + */ + public void testRequestResetAndAbort() throws Exception { + try (CloseableHttpAsyncClient client = HttpAsyncClientBuilder.create().build()) { + client.start(); + HttpHost httpHost = new HttpHost(httpServer.getAddress().getHostString(), + httpServer.getAddress().getPort()); + HttpGet httpGet = new HttpGet(httpHost.toURI() + pathPrefix + "/200"); + + // calling abort before the request is sent is a no-op + httpGet.abort(); + assertTrue(httpGet.isAborted()); + + { + httpGet.reset(); + assertFalse(httpGet.isAborted()); + httpGet.abort(); + Future future = client.execute(SimpleHttpRequest.copy(httpGet), null); + httpGet.setDependency((org.apache.hc.core5.concurrent.Cancellable) future); + try { + future.get(); + fail("expected cancellation exception"); + } catch (CancellationException e) { + // expected + } + assertTrue(future.isCancelled()); + } + { + httpGet.reset(); + Future future = client.execute(SimpleHttpRequest.copy(httpGet), null); + httpGet.setDependency((org.apache.hc.core5.concurrent.Cancellable) future); + + assertFalse(httpGet.isAborted()); + httpGet.abort(); + assertTrue(httpGet.isAborted()); + try { + assertTrue(future.isDone()); + future.get(); + } catch (CancellationException e) { + // expected sometimes - if the future was cancelled before executing successfully + } + } + { + httpGet.reset(); + assertFalse(httpGet.isAborted()); + Future future = client.execute(SimpleHttpRequest.copy(httpGet), null); + httpGet.setDependency((org.apache.hc.core5.concurrent.Cancellable) future); + + assertFalse(httpGet.isAborted()); + assertEquals(200, future.get().getCode()); + assertFalse(future.isCancelled()); + } + } + } + + /** + * End to end test for delete with body. We test it explicitly as it is not supported + * out of the box by {@link org.apache.hc.client5.http.impl.async.HttpAsyncClients}. + * Exercises the test http server ability to send back whatever body it received. + */ + public void testDeleteWithBody() throws Exception { + bodyTest("DELETE"); + } + + /** + * End to end test for get with body. We test it explicitly as it is not supported + * out of the box by {@link org.apache.hc.client5.http.impl.async.HttpAsyncClients}. + * Exercises the test http server ability to send back whatever body it received. + */ + public void testGetWithBody() throws Exception { + bodyTest("GET"); + } + + public void testEncodeParams() throws Exception { + { + Request request = new Request("PUT", "/200"); + request.addParameter("routing", "this/is/the/routing"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(pathPrefix + "/200?routing=this%2Fis%2Fthe%2Frouting", + response.getRequestLine().getUri()); + } + { + Request request = new Request("PUT", "/200"); + request.addParameter("routing", "this|is|the|routing"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(pathPrefix + "/200?routing=this%7Cis%7Cthe%7Crouting", + response.getRequestLine().getUri()); + } + { + Request request = new Request("PUT", "/200"); + request.addParameter("routing", "routing#1"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(pathPrefix + "/200?routing=routing%231", response.getRequestLine().getUri()); + } + { + Request request = new Request("PUT", "/200"); + request.addParameter("routing", "中文"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(pathPrefix + "/200?routing=%E4%B8%AD%E6%96%87", response.getRequestLine().getUri()); + } + { + Request request = new Request("PUT", "/200"); + request.addParameter("routing", "foo bar"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(pathPrefix + "/200?routing=foo%20bar", response.getRequestLine().getUri()); + } + { + Request request = new Request("PUT", "/200"); + request.addParameter("routing", "foo+bar"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(pathPrefix + "/200?routing=foo%2Bbar", response.getRequestLine().getUri()); + } + { + Request request = new Request("PUT", "/200"); + request.addParameter("routing", "foo/bar"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(pathPrefix + "/200?routing=foo%2Fbar", response.getRequestLine().getUri()); + } + { + Request request = new Request("PUT", "/200"); + request.addParameter("routing", "foo^bar"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(pathPrefix + "/200?routing=foo%5Ebar", response.getRequestLine().getUri()); + } + } + + /** + * Verify that credentials are sent on the first request with preemptive auth enabled (default when + * provided with credentials). + */ + public void testPreemptiveAuthEnabled() throws Exception { + final String[] methods = {"POST", "PUT", "GET", "DELETE"}; + + try (RestClient restClient = createRestClient(true, true, true)) { + for (final String method : methods) { + final Response response = bodyTest(restClient, method); + + assertThat(response.getHeader("Authorization"), startsWith("Basic")); + } + } + } + + private Response bodyTest(final String method) throws Exception { + return bodyTest(restClient, method); + } + + private Response bodyTest(final RestClient client, final String method) throws Exception { + int statusCode = randomStatusCode(getRandom()); + return bodyTest(client, method, statusCode, new Header[0]); + } + + private Response bodyTest(RestClient client, String method, int statusCode, Header[] headers) throws Exception { + String requestBody = "{ \"field\": \"value\" }"; + Request request = new Request(method, "/" + statusCode); + request.setJsonEntity(requestBody); + RequestOptions.Builder options = request.getOptions().toBuilder(); + for (Header header : headers) { + options.addHeader(header.getName(), header.getValue()); + } + request.setOptions(options); + Response esResponse; + try { + esResponse = RestClientSingleHostTests.performRequestSyncOrAsync(client, request); + } catch (ResponseException e) { + esResponse = e.getResponse(); + } + assertEquals(method, esResponse.getRequestLine().getMethod()); + assertEquals(statusCode, esResponse.getStatusCode()); + assertEquals(pathPrefix + "/" + statusCode, esResponse.getRequestLine().getUri()); + assertEquals(requestBody, EntityUtils.toString(esResponse.getEntity())); + + return esResponse; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientSingleHostTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientSingleHostTests.java new file mode 100644 index 000000000..a67f677b5 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientSingleHostTests.java @@ -0,0 +1,694 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hc.client5.http.ConnectTimeoutException; +import org.apache.hc.client5.http.classic.methods.HttpHead; +import org.apache.hc.client5.http.classic.methods.HttpOptions; +import org.apache.hc.client5.http.classic.methods.HttpPatch; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.classic.methods.HttpPut; +import org.apache.hc.client5.http.classic.methods.HttpTrace; +import org.apache.hc.client5.http.classic.methods.HttpUriRequest; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.core5.concurrent.FutureCallback; +import org.apache.hc.core5.http.ConnectionClosedException; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpRequest; +import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.http.message.BasicClassicHttpRequest; +import org.apache.hc.core5.http.message.BasicClassicHttpResponse; +import org.apache.hc.core5.http.nio.AsyncDataProducer; +import org.apache.hc.core5.http.nio.AsyncRequestProducer; +import org.apache.hc.core5.http.nio.AsyncResponseConsumer; +import org.apache.hc.core5.net.URIBuilder; +import org.elasticsearch.client.HttpDeleteWithEntity; +import org.elasticsearch.client.HttpGetWithEntity; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseException; +import org.elasticsearch.client.ResponseListener; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientTestUtil; +import org.elasticsearch.client.WarningFailureException; +import org.elasticsearch.client.WarningsHandler; +import org.elasticsearch.client.node.Node; +import org.elasticsearch.client.node.selector.NodeSelector; +import org.elasticsearch.client.producer.BasicAsyncEntityProducer; +import org.junit.After; +import org.junit.Before; +import org.mockito.ArgumentCaptor; +import org.mockito.stubbing.Answer; + +import javax.net.ssl.SSLHandshakeException; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Field; +import java.net.SocketTimeoutException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicReference; + +import static java.util.Collections.singletonList; +import static org.elasticsearch.client.RestClientTestUtil.canHaveBody; +import static org.elasticsearch.client.RestClientTestUtil.getAllErrorStatusCodes; +import static org.elasticsearch.client.RestClientTestUtil.getHttpMethods; +import static org.elasticsearch.client.RestClientTestUtil.getOkStatusCodes; +import static org.elasticsearch.client.RestClientTestUtil.randomStatusCode; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * Tests for basic functionality of {@link RestClient} against one single host: tests http requests being + * sent, headers, + * body, different status codes and corresponding responses/exceptions. + * Relies on a mock http client to intercept requests and return desired responses based on request path. + */ +public class RestClientSingleHostTests extends RestClientTestCase { + private static final Log logger = LogFactory.getLog(RestClientSingleHostTests.class); + + private ExecutorService exec = Executors.newFixedThreadPool(1); + private RestClient restClient; + private Header[] defaultHeaders; + private Node node; + private CloseableHttpAsyncClient httpClient; + private HostsTrackingFailureListener failureListener; + private boolean strictDeprecationMode; + + @Before + public void createRestClient() { + httpClient = mockHttpClient(exec); + defaultHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header-default"); + node = new Node(new HttpHost("localhost", 9200)); + failureListener = new HostsTrackingFailureListener(); + strictDeprecationMode = randomBoolean(); + restClient = new RestClient( + this.httpClient, + defaultHeaders, + singletonList(node), + null, + failureListener, + NodeSelector.ANY, + strictDeprecationMode, + false, + false + ); + } + + @SuppressWarnings("unchecked") + static CloseableHttpAsyncClient mockHttpClient(final ExecutorService exec) { + CloseableHttpAsyncClient httpClient = mock(CloseableHttpAsyncClient.class); + when( + httpClient.execute( + any(AsyncRequestProducer.class), + any(AsyncResponseConsumer.class), + any(HttpClientContext.class), + nullable(FutureCallback.class) + ) + ).thenAnswer((Answer>) invocationOnMock -> { + final AsyncRequestProducer requestProducer = + (AsyncRequestProducer) invocationOnMock.getArguments()[0]; + final FutureCallback futureCallback = + (FutureCallback) invocationOnMock.getArguments()[3]; + // Call the callback asynchronous to better simulate how async http client works + return exec.submit(() -> { + if (futureCallback != null) { + try { + HttpResponse httpResponse = responseOrException(requestProducer); + futureCallback.completed(httpResponse); + } catch (Exception e) { + futureCallback.failed(e); + } + return null; + } + return responseOrException(requestProducer); + }); + }); + return httpClient; + } + + private static HttpResponse responseOrException(AsyncDataProducer requestProducer) throws Exception { + // request is private in BasicRequestProducer, need to make it accessible first + Field requestField = requestProducer.getClass().getDeclaredField("request"); + requestField.setAccessible(true); + final HttpRequest request = (HttpRequest) requestField.get(requestProducer); + final HttpHost httpHost = new HttpHost(request.getAuthority().getHostName(), + request.getAuthority().getPort()); + // return the desired status code or exception depending on the path + switch (request.getPath()) { + case "/soe": + throw new SocketTimeoutException(httpHost.toString()); + case "/coe": + throw new ConnectTimeoutException(httpHost.toString()); + case "/ioe": + throw new IOException(httpHost.toString()); + case "/closed": + throw new ConnectionClosedException(); + case "/handshake": + throw new SSLHandshakeException(""); + case "/uri": + throw new URISyntaxException("", ""); + case "/runtime": + throw new RuntimeException(); + default: + int statusCode = Integer.parseInt(request.getPath().substring(1)); + + final BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(statusCode, ""); + Optional entity = retrieveEntity(requestProducer); + + // return the same body that was sent + if (entity.isPresent()) { + assertTrue("the entity is not repeatable, cannot set it to the response directly", + entity.get().isRepeatable()); + httpResponse.setEntity(entity.get()); + } + // return the same headers that were sent + httpResponse.setHeaders(request.getHeaders()); + return httpResponse; + } + } + + private static Optional retrieveEntity(AsyncDataProducer requestProducer) throws NoSuchFieldException, IllegalAccessException { + // entity is in the dataProducer field, both are private + Field dataProducerField = requestProducer.getClass().getDeclaredField("dataProducer"); + dataProducerField.setAccessible(true); + final BasicAsyncEntityProducer dataProducer = + (BasicAsyncEntityProducer) dataProducerField.get(requestProducer); + + if (dataProducer != null) { + Field entityField = dataProducer.getClass().getDeclaredField("entity"); + entityField.setAccessible(true); + return Optional.ofNullable((HttpEntity) entityField.get(dataProducer)); + } + return Optional.empty(); + } + + /** + * Shutdown the executor so we don't leak threads into other test runs. + */ + @After + public void shutdownExec() { + exec.shutdown(); + } + + /** + * Verifies the content of the {@link HttpRequest} that's internally created and passed through to the + * http client + */ + @SuppressWarnings("unchecked") + public void testInternalHttpRequest() throws Exception { + ArgumentCaptor requestArgumentCaptor = ArgumentCaptor.forClass + (AsyncRequestProducer.class); + int times = 0; + for (String httpMethod : getHttpMethods()) { + HttpRequest expectedRequest = performRandomRequest(httpMethod); + verify(httpClient, times(++times)).execute( + requestArgumentCaptor.capture(), + any(AsyncResponseConsumer.class), + any(HttpClientContext.class), + nullable(FutureCallback.class) + ); + AsyncRequestProducer requestProducer = requestArgumentCaptor.getValue(); + Field requestField = requestProducer.getClass().getDeclaredField("request"); + requestField.setAccessible(true); + final HttpRequest actualRequest = (HttpRequest) requestField.get(requestProducer); + assertEquals(expectedRequest.getRequestUri(), actualRequest.getRequestUri()); + assertArrayEquals(expectedRequest.getHeaders(), actualRequest.getHeaders()); + if (canHaveBody(expectedRequest) && expectedRequest instanceof BasicClassicHttpRequest) { + Optional actualEntity = retrieveEntity(requestProducer); + if (actualEntity.isPresent()) { + HttpEntity expectedEntity = ((BasicClassicHttpRequest) expectedRequest).getEntity(); + assertEquals(EntityUtils.toString(expectedEntity), + EntityUtils.toString(actualEntity.get())); + } + } + } + } + + /** + * End to end test for ok status codes + */ + public void testOkStatusCodes() throws Exception { + for (String method : getHttpMethods()) { + for (int okStatusCode : getOkStatusCodes()) { + Response response = performRequestSyncOrAsync(restClient, new Request(method, + "/" + okStatusCode)); + assertThat(response.getStatusCode(), equalTo(okStatusCode)); + } + } + failureListener.assertNotCalled(); + } + + /** + * End to end test for error status codes: they should cause an exception to be thrown + */ + public void testErrorStatusCodes() throws Exception { + for (String method : getHttpMethods()) { + // error status codes should cause an exception to be thrown + for (int errorStatusCode : getAllErrorStatusCodes()) { + try { + Request request = new Request(method, "/" + errorStatusCode); + Response response = restClient.performRequest(request); + fail("request should have failed"); + } catch (ResponseException e) { + assertEquals(errorStatusCode, e.getResponse().getStatusCode()); + assertExceptionStackContainsCallingMethod(e); + } + } + } + } + + public void testPerformRequestIOExceptions() throws Exception { + for (String method : getHttpMethods()) { + // IOExceptions should be let bubble up + try { + restClient.performRequest(new Request(method, "/ioe")); + fail("request should have failed"); + } catch (IOException e) { + // And we do all that so the thrown exception has our method in the stacktrace + assertExceptionStackContainsCallingMethod(e); + } + failureListener.assertCalled(singletonList(node)); + try { + restClient.performRequest(new Request(method, "/coe")); + fail("request should have failed"); + } catch (ConnectTimeoutException e) { + // And we do all that so the thrown exception has our method in the stacktrace + assertExceptionStackContainsCallingMethod(e); + } + failureListener.assertCalled(singletonList(node)); + try { + restClient.performRequest(new Request(method, "/soe")); + fail("request should have failed"); + } catch (SocketTimeoutException e) { + // And we do all that so the thrown exception has our method in the stacktrace + assertExceptionStackContainsCallingMethod(e); + } + failureListener.assertCalled(singletonList(node)); + try { + restClient.performRequest(new Request(method, "/closed")); + fail("request should have failed"); + } catch (ConnectionClosedException e) { + // And we do all that so the thrown exception has our method in the stacktrace + assertExceptionStackContainsCallingMethod(e); + } + failureListener.assertCalled(singletonList(node)); + try { + restClient.performRequest(new Request(method, "/handshake")); + fail("request should have failed"); + } catch (SSLHandshakeException e) { + // And we do all that so the thrown exception has our method in the stacktrace + assertExceptionStackContainsCallingMethod(e); + } + failureListener.assertCalled(singletonList(node)); + } + } + + public void testPerformRequestRuntimeExceptions() throws Exception { + for (String method : getHttpMethods()) { + try { + restClient.performRequest(new Request(method, "/runtime")); + fail("request should have failed"); + } catch (RuntimeException e) { + // And we do all that so the thrown exception has our method in the stacktrace + assertExceptionStackContainsCallingMethod(e); + } + failureListener.assertCalled(singletonList(node)); + } + } + + public void testPerformRequestExceptions() throws Exception { + for (String method : getHttpMethods()) { + try { + restClient.performRequest(new Request(method, "/uri")); + fail("request should have failed"); + } catch (RuntimeException e) { + assertThat(e.getCause(), instanceOf(URISyntaxException.class)); + // And we do all that so the thrown exception has our method in the stacktrace + assertExceptionStackContainsCallingMethod(e); + } + failureListener.assertCalled(singletonList(node)); + } + } + + /** + * End to end test for request and response body. Exercises the mock http client ability to send back + * whatever body it has received. + */ + public void testBody() throws Exception { + String body = "{ \"field\": \"value\" }"; + StringEntity entity = new StringEntity(body, ContentType.APPLICATION_JSON); + for (String method : Arrays.asList("DELETE", "GET", "PATCH", "POST", "PUT")) { + for (int okStatusCode : getOkStatusCodes()) { + Request request = new Request(method, "/" + okStatusCode); + request.setEntity(entity); + Response response = restClient.performRequest(request); + assertThat(response.getStatusCode(), equalTo(okStatusCode)); + assertThat(EntityUtils.toString(response.getEntity()), equalTo(body)); + } + for (int errorStatusCode : getAllErrorStatusCodes()) { + Request request = new Request(method, "/" + errorStatusCode); + request.setEntity(entity); + try { + restClient.performRequest(request); + fail("request should have failed"); + } catch (ResponseException e) { + Response response = e.getResponse(); + assertThat(response.getStatusCode(), equalTo(errorStatusCode)); + assertThat(EntityUtils.toString(response.getEntity()), equalTo(body)); + assertExceptionStackContainsCallingMethod(e); + } + } + } + for (String method : Arrays.asList("HEAD", "OPTIONS", "TRACE")) { + Request request = new Request(method, "/" + randomStatusCode(getRandom())); + request.setEntity(entity); + try { + performRequestSyncOrAsync(restClient, request); + fail("request should have failed"); + } catch (UnsupportedOperationException e) { + assertThat(e.getMessage(), equalTo(method + " with body is not supported")); + } + } + } + + /** + * End to end test for request and response headers. Exercises the mock http client ability to send back + * whatever headers it has received. + */ + public void testHeaders() throws Exception { + for (String method : getHttpMethods()) { + final Header[] requestHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header"); + final int statusCode = randomStatusCode(getRandom()); + Request request = new Request(method, "/" + statusCode); + RequestOptions.Builder options = request.getOptions().toBuilder(); + for (Header requestHeader : requestHeaders) { + options.addHeader(requestHeader.getName(), requestHeader.getValue()); + } + request.setOptions(options); + Response esResponse; + try { + esResponse = performRequestSyncOrAsync(restClient, request); + } catch (ResponseException e) { + esResponse = e.getResponse(); + } + assertThat(esResponse.getStatusCode(), equalTo(statusCode)); + assertHeaders(defaultHeaders, requestHeaders, esResponse.getHeaders(), + Collections.emptySet()); + assertFalse(esResponse.hasWarnings()); + } + } + + public void testDeprecationWarnings() throws Exception { + String chars = randomAsciiAlphanumOfLength(5); + assertDeprecationWarnings(singletonList("poorly formatted " + chars), singletonList("poorly " + + "formatted " + chars)); + assertDeprecationWarnings(singletonList(formatWarningWithoutDate(chars)), singletonList(chars)); + assertDeprecationWarnings(singletonList(formatWarning(chars)), singletonList(chars)); + assertDeprecationWarnings( + Arrays.asList(formatWarning(chars), "another one", "and another"), + Arrays.asList(chars, "another one", "and another") + ); + assertDeprecationWarnings(Arrays.asList("ignorable one", "and another"), Arrays.asList("ignorable " + + "one", "and another")); + assertDeprecationWarnings(singletonList("exact"), singletonList("exact")); + assertDeprecationWarnings(Collections.emptyList(), Collections.emptyList()); + + String proxyWarning = "112 - \"network down\" \"Sat, 25 Aug 2012 23:34:45 GMT\""; + assertDeprecationWarnings(singletonList(proxyWarning), singletonList(proxyWarning)); + } + + private enum DeprecationWarningOption { + PERMISSIVE { + protected WarningsHandler warningsHandler() { + return WarningsHandler.PERMISSIVE; + } + }, + STRICT { + protected WarningsHandler warningsHandler() { + return WarningsHandler.STRICT; + } + }, + FILTERED { + protected WarningsHandler warningsHandler() { + return new WarningsHandler() { + @Override + public boolean warningsShouldFailRequest(List warnings) { + for (String warning : warnings) { + if (false == warning.startsWith("ignorable")) { + return true; + } + } + return false; + } + }; + } + }, + EXACT { + protected WarningsHandler warningsHandler() { + return new WarningsHandler() { + @Override + public boolean warningsShouldFailRequest(List warnings) { + return false == warnings.equals(Arrays.asList("exact")); + } + }; + } + }; + + protected abstract WarningsHandler warningsHandler(); + } + + private void assertDeprecationWarnings(List warningHeaderTexts, List warningBodyTexts) throws Exception { + String method = randomFrom(getHttpMethods()); + Request request = new Request(method, "/200"); + RequestOptions.Builder options = request.getOptions().toBuilder(); + for (String warningHeaderText : warningHeaderTexts) { + options.addHeader("Warning", warningHeaderText); + } + + final boolean expectFailure; + if (randomBoolean()) { + logger.info("checking strictWarningsMode=[" + strictDeprecationMode + "] and warnings=" + warningBodyTexts); + expectFailure = strictDeprecationMode && false == warningBodyTexts.isEmpty(); + } else { + DeprecationWarningOption warningOption = randomFrom(DeprecationWarningOption.values()); + logger.info("checking warningOption=" + warningOption + " and warnings=" + warningBodyTexts); + options.setWarningsHandler(warningOption.warningsHandler()); + expectFailure = warningOption.warningsHandler().warningsShouldFailRequest(warningBodyTexts); + } + request.setOptions(options); + + Response response; + if (expectFailure) { + try { + performRequestSyncOrAsync(restClient, request); + fail("expected WarningFailureException from warnings"); + return; + } catch (WarningFailureException e) { + if (false == warningBodyTexts.isEmpty()) { + assertThat(e.getMessage(), containsString("\nWarnings: " + warningBodyTexts)); + } + response = e.getResponse(); + } + } else { + response = performRequestSyncOrAsync(restClient, request); + } + assertEquals(false == warningBodyTexts.isEmpty(), response.hasWarnings()); + assertEquals(warningBodyTexts, response.getWarnings()); + } + + /** + * Emulates Elasticsearch's HeaderWarningLogger.formatWarning in simple + * cases. We don't have that available because we're testing against 1.7. + */ + private static String formatWarningWithoutDate(String warningBody) { + final String hash = new String(new byte[40], StandardCharsets.UTF_8).replace('\0', 'e'); + return "299 Elasticsearch-1.2.2-SNAPSHOT-" + hash + " \"" + warningBody + "\""; + } + + private static String formatWarning(String warningBody) { + return formatWarningWithoutDate(warningBody) + " \"Mon, 01 Jan 2001 00:00:00 GMT\""; + } + + private HttpUriRequest performRandomRequest(String method) throws Exception { + String uriAsString = "/" + randomStatusCode(getRandom()); + Request request = new Request(method, uriAsString); + URIBuilder uriBuilder = new URIBuilder(uriAsString); + if (randomBoolean()) { + int numParams = randomIntBetween(1, 3); + for (int i = 0; i < numParams; i++) { + String name = "param-" + i; + String value = randomAsciiAlphanumOfLengthBetween(3, 10); + request.addParameter(name, value); + uriBuilder.addParameter(name, value); + } + } + URI uri = uriBuilder.build(); + + HttpUriRequestBase expectedRequest; + switch (method) { + case "DELETE": + expectedRequest = new HttpDeleteWithEntity(uri); + break; + case "GET": + expectedRequest = new HttpGetWithEntity(uri); + break; + case "HEAD": + expectedRequest = new HttpHead(uri); + break; + case "OPTIONS": + expectedRequest = new HttpOptions(uri); + break; + case "PATCH": + expectedRequest = new HttpPatch(uri); + break; + case "POST": + expectedRequest = new HttpPost(uri); + break; + case "PUT": + expectedRequest = new HttpPut(uri); + break; + case "TRACE": + expectedRequest = new HttpTrace(uri); + break; + default: + throw new UnsupportedOperationException("method not supported: " + method); + } + + if (canHaveBody(expectedRequest) && getRandom().nextBoolean()) { + HttpEntity entity = new StringEntity(randomAsciiAlphanumOfLengthBetween(10, 100), + ContentType.APPLICATION_JSON); + (expectedRequest).setEntity(entity); + request.setEntity(entity); + } + + final Set uniqueNames = new HashSet<>(); + if (randomBoolean()) { + Header[] headers = RestClientTestUtil.randomHeaders(getRandom(), "Header"); + RequestOptions.Builder options = request.getOptions().toBuilder(); + for (Header header : headers) { + options.addHeader(header.getName(), header.getValue()); + expectedRequest.addHeader(new RequestOptions.ReqHeader(header.getName(), header.getValue())); + uniqueNames.add(header.getName()); + } + request.setOptions(options); + } + for (Header defaultHeader : defaultHeaders) { + // request level headers override default headers + if (uniqueNames.contains(defaultHeader.getName()) == false) { + expectedRequest.addHeader(defaultHeader); + } + } + try { + performRequestSyncOrAsync(restClient, request); + } catch (Exception e) { + // all good + } + return expectedRequest; + } + + static Response performRequestSyncOrAsync(RestClient restClient, Request request) throws Exception { + // randomize between sync and async methods + if (randomBoolean()) { + return restClient.performRequest(request); + } else { + final AtomicReference exceptionRef = new AtomicReference<>(); + final AtomicReference responseRef = new AtomicReference<>(); + final CountDownLatch latch = new CountDownLatch(1); + restClient.performRequestAsync(request, new ResponseListener() { + @Override + public void onSuccess(Response response) { + responseRef.set(response); + latch.countDown(); + + } + + @Override + public void onFailure(Exception exception) { + exceptionRef.set(exception); + latch.countDown(); + } + }); + latch.await(); + if (exceptionRef.get() != null) { + throw exceptionRef.get(); + } + return responseRef.get(); + } + } + + /** + * Asserts that the provided {@linkplain Exception} contains the method + * that called this somewhere on its stack. This is + * normally the case for synchronous calls but {@link RestClient} performs + * synchronous calls by performing asynchronous calls and blocking the + * current thread until the call returns so it has to take special care + * to make sure that the caller shows up in the exception. We use this + * assertion to make sure that we don't break that "special care". + */ + private static void assertExceptionStackContainsCallingMethod(Throwable t) { + // 0 is getStackTrace + // 1 is this method + // 2 is the caller, what we want + StackTraceElement myMethod = Thread.currentThread().getStackTrace()[2]; + for (StackTraceElement se : t.getStackTrace()) { + if (se.getClassName().equals(myMethod.getClassName()) && se.getMethodName().equals(myMethod.getMethodName())) { + return; + } + } + StringWriter stack = new StringWriter(); + t.printStackTrace(new PrintWriter(stack)); + fail("didn't find the calling method (looks like " + myMethod + ") in:\n" + stack); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTestCase.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTestCase.java new file mode 100644 index 000000000..507bdfbd0 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTestCase.java @@ -0,0 +1,119 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import com.carrotsearch.randomizedtesting.JUnit3MethodProvider; +import com.carrotsearch.randomizedtesting.MixWithSuiteName; +import com.carrotsearch.randomizedtesting.RandomizedTest; +import com.carrotsearch.randomizedtesting.annotations.SeedDecorators; +import com.carrotsearch.randomizedtesting.annotations.TestMethodProviders; +import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction; +import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters; +import com.carrotsearch.randomizedtesting.annotations.ThreadLeakGroup; +import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering; +import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; +import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies; +import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite; +import org.apache.hc.core5.http.Header; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@TestMethodProviders({ JUnit3MethodProvider.class }) +@SeedDecorators({ MixWithSuiteName.class }) // See LUCENE-3995 for rationale. +@ThreadLeakScope(ThreadLeakScope.Scope.SUITE) +@ThreadLeakGroup(ThreadLeakGroup.Group.MAIN) +@ThreadLeakAction({ ThreadLeakAction.Action.WARN, ThreadLeakAction.Action.INTERRUPT }) +@ThreadLeakZombies(ThreadLeakZombies.Consequence.IGNORE_REMAINING_TESTS) +@ThreadLeakLingering(linger = 5000) // 5 sec lingering +@ThreadLeakFilters(filters = { ClientsGraalVMThreadsFilter.class }) +@TimeoutSuite(millis = 2 * 60 * 60 * 1000) +public abstract class RestClientTestCase extends RandomizedTest { + + /** + * Assert that the actual headers are the expected ones given the original default and request headers. Some headers can be ignored, + * for instance in case the http client is adding its own automatically. + * + * @param defaultHeaders the default headers set to the REST client instance + * @param requestHeaders the request headers sent with a particular request + * @param actualHeaders the actual headers as a result of the provided default and request headers + * @param ignoreHeaders header keys to be ignored as they are not part of default nor request headers, yet they + * will be part of the actual ones + */ + protected static void assertHeaders( + final Header[] defaultHeaders, + final Header[] requestHeaders, + final Header[] actualHeaders, + final Set ignoreHeaders + ) { + final Map> expectedHeaders = new HashMap<>(); + final Set requestHeaderKeys = new HashSet<>(); + for (final Header header : requestHeaders) { + final String name = header.getName(); + addValueToListEntry(expectedHeaders, name, header.getValue()); + requestHeaderKeys.add(name); + } + for (final Header defaultHeader : defaultHeaders) { + final String name = defaultHeader.getName(); + if (requestHeaderKeys.contains(name) == false) { + addValueToListEntry(expectedHeaders, name, defaultHeader.getValue()); + } + } + Set actualIgnoredHeaders = new HashSet<>(); + for (Header responseHeader : actualHeaders) { + final String name = responseHeader.getName(); + if (ignoreHeaders.contains(name)) { + expectedHeaders.remove(name); + actualIgnoredHeaders.add(name); + continue; + } + final String value = responseHeader.getValue(); + final List values = expectedHeaders.get(name); + assertNotNull("found response header [" + name + "] that wasn't originally sent: " + value, values); + assertTrue("found incorrect response header [" + name + "]: " + value, values.remove(value)); + if (values.isEmpty()) { + expectedHeaders.remove(name); + } + } + assertEquals("some headers meant to be ignored were not part of the actual headers", ignoreHeaders, actualIgnoredHeaders); + assertTrue("some headers that were sent weren't returned " + expectedHeaders, expectedHeaders.isEmpty()); + } + + private static void addValueToListEntry(final Map> map, final String name, final String value) { + List values = map.get(name); + if (values == null) { + values = new ArrayList<>(); + map.put(name, values); + } + values.add(value); + } + + public static boolean inFipsJvm() { + return Boolean.parseBoolean(System.getProperty("tests.fips.enabled")); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTestUtil.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTestUtil.java new file mode 100644 index 000000000..91397c67e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTestUtil.java @@ -0,0 +1,119 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + +import com.carrotsearch.randomizedtesting.generators.RandomNumbers; +import com.carrotsearch.randomizedtesting.generators.RandomPicks; +import com.carrotsearch.randomizedtesting.generators.RandomStrings; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpRequest; +import org.apache.hc.core5.http.message.BasicHeader; +import org.elasticsearch.client.HttpDeleteWithEntity; +import org.elasticsearch.client.HttpGetWithEntity; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +final class RestClientTestUtil { + + private static final String[] HTTP_METHODS = new String[]{"DELETE", "HEAD", "GET", "OPTIONS", "PATCH", + "POST", "PUT", "TRACE"}; + private static final List ALL_STATUS_CODES; + private static final List OK_STATUS_CODES = Arrays.asList(200, 201); + private static final List ALL_ERROR_STATUS_CODES; + private static List ERROR_NO_RETRY_STATUS_CODES = Arrays.asList(500,501); + private static List ERROR_RETRY_STATUS_CODES = Arrays.asList(502, 503, 504); + + static { + ALL_ERROR_STATUS_CODES = new ArrayList<>(ERROR_RETRY_STATUS_CODES); + ALL_ERROR_STATUS_CODES.addAll(ERROR_NO_RETRY_STATUS_CODES); + ALL_STATUS_CODES = new ArrayList<>(ALL_ERROR_STATUS_CODES); + ALL_STATUS_CODES.addAll(OK_STATUS_CODES); + } + + private RestClientTestUtil() { + + } + + static boolean canHaveBody(HttpRequest httpRequest) { + return httpRequest.getMethod().contains("PUT") || httpRequest.getMethod().contains("POST") || + httpRequest.getMethod().contains("PATCH") || + httpRequest instanceof HttpDeleteWithEntity || httpRequest instanceof HttpGetWithEntity; + } + + static String[] getHttpMethods() { + return HTTP_METHODS; + } + + static String randomHttpMethod(Random random) { + return RandomPicks.randomFrom(random, HTTP_METHODS); + } + + static int randomStatusCode(Random random) { + return RandomPicks.randomFrom(random, ALL_STATUS_CODES); + } + + static int randomOkStatusCode(Random random) { + return RandomPicks.randomFrom(random, OK_STATUS_CODES); + } + + static int randomErrorNoRetryStatusCode(Random random) { + return RandomPicks.randomFrom(random, List.of(500,501)); + } + + static int randomErrorRetryStatusCode(Random random) { + return RandomPicks.randomFrom(random, ERROR_RETRY_STATUS_CODES); + } + + static List getOkStatusCodes() { + return OK_STATUS_CODES; + } + + static List getAllErrorStatusCodes() { + return ALL_ERROR_STATUS_CODES; + } + + static List getAllStatusCodes() { + return ALL_STATUS_CODES; + } + + /** + * Create a random number of {@link Header}s. + * Generated header names will either be the {@code baseName} plus its index, or exactly the provided + * {@code baseName} so that the + * we test also support for multiple headers with same key and different values. + */ + static Header[] randomHeaders(Random random, final String baseName) { + int numHeaders = RandomNumbers.randomIntBetween(random, 0, 5); + final Header[] headers = new Header[numHeaders]; + for (int i = 0; i < numHeaders; i++) { + String headerName = baseName; + // randomly exercise the code path that supports multiple headers with same key + if (random.nextBoolean()) { + headerName = headerName + i; + } + headers[i] = new BasicHeader(headerName, RandomStrings.randomAsciiLettersOfLengthBetween(random + , 3, 10)); + } + return headers; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTests.java new file mode 100644 index 000000000..9e2a39820 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTests.java @@ -0,0 +1,456 @@ +/* + * 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. + */ + +package co.elastic.clients.transport5.low_level_client; + + +import org.apache.hc.client5.http.auth.AuthCache; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.impl.auth.BasicAuthCache; +import org.apache.hc.client5.http.impl.auth.BasicScheme; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.reactor.IOReactorStatus; +import org.elasticsearch.client.DeadHostState; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseListener; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientTestCase; +import org.elasticsearch.client.node.Node; +import org.elasticsearch.client.node.selector.NodeSelector; + +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Supplier; + +import static java.util.Collections.singletonList; +import static org.hamcrest.Matchers.instanceOf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class RestClientTests extends RestClientTestCase { + + public void testCloseIsIdempotent() throws IOException { + List nodes = singletonList(new Node(new HttpHost("localhost", 9200))); + CloseableHttpAsyncClient closeableHttpAsyncClient = mock(CloseableHttpAsyncClient.class); + RestClient restClient = new RestClient(closeableHttpAsyncClient, new Header[0], nodes, null, null, + null, false, false, false); + restClient.close(); + verify(closeableHttpAsyncClient, times(1)).close(); + restClient.close(); + verify(closeableHttpAsyncClient, times(2)).close(); + restClient.close(); + verify(closeableHttpAsyncClient, times(3)).close(); + } + + public void testPerformAsyncWithUnsupportedMethod() throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + try (RestClient restClient = createRestClient()) { + restClient.performRequestAsync(new Request("unsupported", randomAsciiLettersOfLength(5)), + new ResponseListener() { + @Override + public void onSuccess(Response response) { + throw new UnsupportedOperationException("onSuccess cannot be called when using a mocked" + + " http client"); + } + + @Override + public void onFailure(Exception exception) { + try { + assertThat(exception, instanceOf(UnsupportedOperationException.class)); + assertEquals("http method not supported: unsupported", exception.getMessage()); + } finally { + latch.countDown(); + } + } + }); + assertTrue("time out waiting for request to return", latch.await(1000, TimeUnit.MILLISECONDS)); + } + } + + public void testPerformAsyncWithWrongEndpoint() throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + try (RestClient restClient = createRestClient()) { + restClient.performRequestAsync(new Request("GET", "::http:///"), new ResponseListener() { + @Override + public void onSuccess(Response response) { + throw new UnsupportedOperationException("onSuccess cannot be called when using a mocked" + + " http client"); + } + + @Override + public void onFailure(Exception exception) { + try { + assertThat(exception, instanceOf(IllegalArgumentException.class)); + assertEquals("Expected scheme name at index 0: ::http:///", exception.getMessage()); + } finally { + latch.countDown(); + } + } + }); + assertTrue("time out waiting for request to return", latch.await(1000, TimeUnit.MILLISECONDS)); + } + } + + public void testBuildUriLeavesPathUntouched() { + final Map emptyMap = Collections.emptyMap(); + { + URI uri = RestClient.buildUri("/foo$bar", "/index/type/id", emptyMap); + assertEquals("/foo$bar/index/type/id", uri.getPath()); + } + { + URI uri = RestClient.buildUri("/", "/*", emptyMap); + assertEquals("/*", uri.getPath()); + } + { + URI uri = RestClient.buildUri("/", "*", emptyMap); + assertEquals("/*", uri.getPath()); + } + { + URI uri = RestClient.buildUri(null, "*", emptyMap); + assertEquals("*", uri.getPath()); + } + { + URI uri = RestClient.buildUri("", "*", emptyMap); + assertEquals("*", uri.getPath()); + } + { + URI uri = RestClient.buildUri(null, "/*", emptyMap); + assertEquals("/*", uri.getPath()); + } + { + URI uri = RestClient.buildUri(null, "/foo$bar/ty/pe/i/d", emptyMap); + assertEquals("/foo$bar/ty/pe/i/d", uri.getPath()); + } + { + URI uri = RestClient.buildUri(null, "/index/type/id", Collections.singletonMap("foo$bar", "x/y" + + "/z")); + assertEquals("/index/type/id", uri.getPath()); + assertEquals("foo$bar=x/y/z", uri.getQuery()); + } + } + + public void testSetNodesWrongArguments() throws IOException { + try (RestClient restClient = createRestClient()) { + restClient.setNodes(null); + fail("setNodes should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("node list must not be null or empty", e.getMessage()); + } + try (RestClient restClient = createRestClient()) { + restClient.setNodes(Collections.emptyList()); + fail("setNodes should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("node list must not be null or empty", e.getMessage()); + } + try (RestClient restClient = createRestClient()) { + restClient.setNodes(Collections.singletonList(null)); + fail("setNodes should have failed"); + } catch (NullPointerException e) { + assertEquals("node cannot be null", e.getMessage()); + } + try (RestClient restClient = createRestClient()) { + restClient.setNodes(Arrays.asList(new Node(new HttpHost("localhost", 9200)), null, + new Node(new HttpHost("localhost", 9201)))); + fail("setNodes should have failed"); + } catch (NullPointerException e) { + assertEquals("node cannot be null", e.getMessage()); + } + } + + public void testSetNodesPreservesOrdering() throws Exception { + try (RestClient restClient = createRestClient()) { + List nodes = randomNodes(); + restClient.setNodes(nodes); + assertEquals(nodes, restClient.getNodes()); + } + } + + private static List randomNodes() { + int numNodes = randomIntBetween(1, 10); + List nodes = new ArrayList<>(numNodes); + for (int i = 0; i < numNodes; i++) { + nodes.add(new Node(new HttpHost("host-" + i, 9200))); + } + return nodes; + } + + public void testSetNodesDuplicatedHosts() throws Exception { + try (RestClient restClient = createRestClient()) { + int numNodes = randomIntBetween(1, 10); + List nodes = new ArrayList<>(numNodes); + Node node = new Node(new HttpHost("host", 9200)); + for (int i = 0; i < numNodes; i++) { + nodes.add(node); + } + restClient.setNodes(nodes); + assertEquals(1, restClient.getNodes().size()); + assertEquals(node, restClient.getNodes().get(0)); + } + } + + public void testSelectHosts() throws IOException { + Node n1 = new Node(new HttpHost("1"), null, null, "1", null, null); + Node n2 = new Node(new HttpHost("2"), null, null, "2", null, null); + Node n3 = new Node(new HttpHost("3"), null, null, "3", null, null); + + NodeSelector not1 = new NodeSelector() { + @Override + public void select(Iterable nodes) { + for (Iterator itr = nodes.iterator(); itr.hasNext(); ) { + if ("1".equals(itr.next().getVersion())) { + itr.remove(); + } + } + } + + @Override + public String toString() { + return "NOT 1"; + } + }; + NodeSelector noNodes = new NodeSelector() { + @Override + public void select(Iterable nodes) { + for (Iterator itr = nodes.iterator(); itr.hasNext(); ) { + itr.next(); + itr.remove(); + } + } + + @Override + public String toString() { + return "NONE"; + } + }; + + List nodes = Arrays.asList(n1, n2, n3); + + Map emptyBlacklist = Collections.emptyMap(); + + // Normal cases where the node selector doesn't reject all living nodes + assertSelectLivingHosts(Arrays.asList(n1, n2, n3), nodes, emptyBlacklist, NodeSelector.ANY); + assertSelectLivingHosts(Arrays.asList(n2, n3), nodes, emptyBlacklist, not1); + + /* + * Try a NodeSelector that excludes all nodes. This should + * throw an exception + */ + { + String message = "NodeSelector [NONE] rejected all nodes, living: [" + + "[host=http://1, version=1], [host=http://2, version=2], " + + "[host=http://3, version=3]] and dead: null"; + assertEquals(message, assertSelectAllRejected(nodes, emptyBlacklist, noNodes)); + } + + // Mark all the nodes dead for a few test cases + { + final AtomicLong time = new AtomicLong(0L); + Supplier timeSupplier = time::get; + Map blacklist = new HashMap<>(); + blacklist.put(n1.getHost(), new DeadHostState(timeSupplier)); + blacklist.put(n2.getHost(), new DeadHostState(new DeadHostState(timeSupplier))); + blacklist.put(n3.getHost(), + new DeadHostState(new DeadHostState(new DeadHostState(timeSupplier)))); + + /* + * case when fewer nodes than blacklist, won't result in any IllegalCapacityException + */ + { + List fewerNodeTuple = Arrays.asList(n1, n2); + assertSelectLivingHosts(Arrays.asList(n1), fewerNodeTuple, blacklist, NodeSelector.ANY); + assertSelectLivingHosts(Arrays.asList(n2), fewerNodeTuple, blacklist, not1); + } + + /* + * selectHosts will revive a single host regardless of + * blacklist time. It'll revive the node that is closest + * to being revived that the NodeSelector is ok with. + */ + assertEquals(singletonList(n1), RestClient.selectNodes(nodes, blacklist, new AtomicInteger(), + NodeSelector.ANY)); + assertEquals(singletonList(n2), RestClient.selectNodes(nodes, blacklist, new AtomicInteger(), + not1)); + + /* + * Try a NodeSelector that excludes all nodes. This should + * return a failure, but a different failure than when the + * blacklist is empty so that the caller knows that all of + * their nodes are blacklisted AND blocked. + */ + String message = "NodeSelector [NONE] rejected all nodes, living: [] and dead: [" + + "[host=http://1, version=1], [host=http://2, version=2], " + + "[host=http://3, version=3]]"; + assertEquals(message, assertSelectAllRejected(nodes, blacklist, noNodes)); + + /* + * Now lets wind the clock forward, past the timeout for one of + * the dead nodes. We should return it. + */ + time.set(new DeadHostState(timeSupplier).getDeadUntilNanos()); + assertSelectLivingHosts(Arrays.asList(n1), nodes, blacklist, NodeSelector.ANY); + + /* + * But if the NodeSelector rejects that node then we'll pick the + * first on that the NodeSelector doesn't reject. + */ + assertSelectLivingHosts(Arrays.asList(n2), nodes, blacklist, not1); + + /* + * If we wind the clock way into the future, past any of the + * blacklist timeouts then we function as though the nodes aren't + * in the blacklist at all. + */ + time.addAndGet(DeadHostState.MAX_CONNECTION_TIMEOUT_NANOS); + assertSelectLivingHosts(Arrays.asList(n1, n2, n3), nodes, blacklist, NodeSelector.ANY); + assertSelectLivingHosts(Arrays.asList(n2, n3), nodes, blacklist, not1); + } + } + + private void assertSelectLivingHosts( + List expectedNodes, + List nodes, + Map blacklist, + NodeSelector nodeSelector + ) throws IOException { + int iterations = 1000; + AtomicInteger lastNodeIndex = new AtomicInteger(0); + assertEquals(expectedNodes, RestClient.selectNodes(nodes, blacklist, lastNodeIndex, nodeSelector)); + // Calling it again rotates the set of results + for (int i = 1; i < iterations; i++) { + Collections.rotate(expectedNodes, 1); + assertEquals("iteration " + i, expectedNodes, RestClient.selectNodes(nodes, blacklist, + lastNodeIndex, nodeSelector)); + } + } + + /** + * Assert that {@link RestClient#selectNodes} fails on the provided arguments. + * + * @return the message in the exception thrown by the failure + */ + private static String assertSelectAllRejected( + List nodes, + Map blacklist, + NodeSelector nodeSelector + ) { + try { + RestClient.selectNodes(nodes, blacklist, new AtomicInteger(0), nodeSelector); + throw new AssertionError("expected selectHosts to fail"); + } catch (IOException e) { + return e.getMessage(); + } + } + + private static RestClient createRestClient() { + List nodes = Collections.singletonList(new Node(new HttpHost("localhost", 9200))); + return new RestClient(mock(CloseableHttpAsyncClient.class), new Header[]{}, nodes, null, null, null + , false, false, false); + } + + public void testRoundRobin() throws IOException { + int numNodes = randomIntBetween(2, 10); + AuthCache authCache = new BasicAuthCache(); + List nodes = new ArrayList<>(numNodes); + for (int i = 0; i < numNodes; i++) { + Node node = new Node(new HttpHost("localhost", 9200 + i)); + nodes.add(node); + authCache.put(node.getHost(), new BasicScheme()); + } + + // test the transition from negative to positive values + AtomicInteger lastNodeIndex = new AtomicInteger(-numNodes); + assertNodes(nodes, lastNodeIndex, 50); + assertEquals(-numNodes + 50, lastNodeIndex.get()); + + // test the highest positive values up to MAX_VALUE + lastNodeIndex.set(Integer.MAX_VALUE - numNodes * 10); + assertNodes(nodes, lastNodeIndex, numNodes * 10); + assertEquals(Integer.MAX_VALUE, lastNodeIndex.get()); + + // test the transition from MAX_VALUE to MIN_VALUE + // this is the only time where there is most likely going to be a jump from a node + // to another one that's not necessarily the next one. + assertEquals(Integer.MIN_VALUE, lastNodeIndex.incrementAndGet()); + assertNodes(nodes, lastNodeIndex, 50); + assertEquals(Integer.MIN_VALUE + 50, lastNodeIndex.get()); + } + + public void testIsRunning() { + List nodes = Collections.singletonList(new Node(new HttpHost("localhost", 9200))); + CloseableHttpAsyncClient client = mock(CloseableHttpAsyncClient.class); + RestClient restClient = new RestClient(client, new Header[]{}, nodes, null, null, null, false, + false, false); + + when(client.getStatus()).thenReturn(IOReactorStatus.ACTIVE); + assertTrue(restClient.isRunning()); + + when(client.getStatus()).thenReturn(IOReactorStatus.INACTIVE); + assertFalse(restClient.isRunning()); + } + + private static void assertNodes(List nodes, AtomicInteger lastNodeIndex, int runs) throws IOException { + int distance = lastNodeIndex.get() % nodes.size(); + /* + * Collections.rotate is not super intuitive: distance 1 means that the last element will become + * the first and so on, + * while distance -1 means that the second element will become the first and so on. + */ + int expectedOffset = distance > 0 ? nodes.size() - distance : Math.abs(distance); + for (int i = 0; i < runs; i++) { + Iterable selectedNodes = RestClient.selectNodes( + nodes, + Collections.emptyMap(), + lastNodeIndex, + NodeSelector.ANY + ); + List expectedNodes = nodes; + int index = 0; + for (Node actualNode : selectedNodes) { + Node expectedNode = expectedNodes.get((index + expectedOffset) % expectedNodes.size()); + assertSame(expectedNode, actualNode); + index++; + } + expectedOffset--; + if (expectedOffset < 0) { + expectedOffset += nodes.size(); + } + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest_client/MultiBufferEntityTest.java b/java-client/src/test/java/co/elastic/clients/transport5/rest_client/MultiBufferEntityTest.java similarity index 96% rename from java-client/src/test/java/co/elastic/clients/transport/rest_client/MultiBufferEntityTest.java rename to java-client/src/test/java/co/elastic/clients/transport5/rest_client/MultiBufferEntityTest.java index 75dc4b8cc..720a30ded 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest_client/MultiBufferEntityTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport5/rest_client/MultiBufferEntityTest.java @@ -17,11 +17,12 @@ * under the License. */ -package co.elastic.clients.transport.rest_client; +package co.elastic.clients.transport5.rest_client; import co.elastic.clients.elasticsearch.core.BulkRequest; import co.elastic.clients.json.jackson.JacksonJsonpMapper; import co.elastic.clients.transport.endpoints.BinaryResponse; +import co.elastic.clients.transport.rest5_client.RestClientTransport; import com.sun.net.httpserver.HttpServer; import org.apache.commons.io.IOUtils; import org.apache.hc.core5.http.HttpHost; diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest_client/RestClientOptionsTest.java b/java-client/src/test/java/co/elastic/clients/transport5/rest_client/RestClientOptionsTest.java similarity index 97% rename from java-client/src/test/java/co/elastic/clients/transport/rest_client/RestClientOptionsTest.java rename to java-client/src/test/java/co/elastic/clients/transport5/rest_client/RestClientOptionsTest.java index 2f83b5bc8..61b7a6ea6 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest_client/RestClientOptionsTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport5/rest_client/RestClientOptionsTest.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.rest_client; +package co.elastic.clients.transport5.rest_client; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.JsonpMapper; @@ -25,6 +25,8 @@ import co.elastic.clients.transport.ElasticsearchTransport; import co.elastic.clients.transport.Version; import co.elastic.clients.transport.endpoints.BooleanResponse; +import co.elastic.clients.transport.rest5_client.RestClientOptions; +import co.elastic.clients.transport.rest5_client.RestClientTransport; import com.sun.net.httpserver.Headers; import com.sun.net.httpserver.HttpServer; import org.apache.hc.core5.http.HttpHost; From 1e072c0d7b8d6e9b6980b13f21aa5411d57f8606 Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Tue, 25 Mar 2025 10:22:06 +0100 Subject: [PATCH 05/38] temp --- .../rest_client/MultiBufferEntity.java | 120 ++++++++ .../rest_client/RestClientHttpClient.java | 286 ++++++++++++++++++ .../rest_client/RestClientOptions.java | 262 ++++++++++++++++ .../rest_client/RestClientTransport.java | 48 +++ .../rest_client/SafeResponseConsumer.java | 132 ++++++++ 5 files changed, 848 insertions(+) create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest_client/SafeResponseConsumer.java diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java new file mode 100644 index 000000000..f1a8e81db --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/MultiBufferEntity.java @@ -0,0 +1,120 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest_client; + +import co.elastic.clients.util.NoCopyByteArrayOutputStream; +import org.apache.http.entity.AbstractHttpEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.nio.ContentEncoder; +import org.apache.http.nio.IOControl; +import org.apache.http.nio.entity.HttpAsyncContentProducer; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.WritableByteChannel; +import java.util.Iterator; + +/** + * An HTTP entity based on a sequence of byte buffers. + */ +class MultiBufferEntity extends AbstractHttpEntity implements HttpAsyncContentProducer { + + private final Iterable buffers; + + private Iterator iterator; + private volatile ByteBuffer currentBuffer; + + MultiBufferEntity(Iterable buffers, ContentType contentType) { + this.buffers = buffers; + setChunked(true); + if (contentType != null) { + setContentType(contentType.toString()); + } + init(); + } + + @Override + public void close() throws IOException { + // Reset state, the request may be retried + init(); + } + + private void init() { + this.iterator = buffers.iterator(); + if (this.iterator.hasNext()) { + this.currentBuffer = this.iterator.next().duplicate(); + } else { + this.currentBuffer = null; + } + } + + @Override + public boolean isRepeatable() { + return true; + } + + @Override + public long getContentLength() { + // Use chunked encoding + return -1; + } + + @Override + public boolean isStreaming() { + return false; + } + + @Override + public InputStream getContent() throws IOException, UnsupportedOperationException { + NoCopyByteArrayOutputStream baos = new NoCopyByteArrayOutputStream(); + writeTo(baos); + return baos.asInputStream(); + } + + @Override + public void writeTo(OutputStream out) throws IOException { + WritableByteChannel channel = Channels.newChannel(out); + for (ByteBuffer buffer: buffers) { + channel.write(buffer.duplicate()); + } + } + + @Override + public void produceContent(ContentEncoder encoder, IOControl ioControl) throws IOException { + if (currentBuffer == null) { + encoder.complete(); + return; + } + + encoder.write(currentBuffer); + + if (!currentBuffer.hasRemaining()) { + if (iterator.hasNext()) { + currentBuffer = iterator.next().duplicate(); + } else { + currentBuffer = null; + encoder.complete(); + } + } + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java new file mode 100644 index 000000000..1bcc06b05 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java @@ -0,0 +1,286 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest_client; + +import co.elastic.clients.transport.TransportOptions; +import co.elastic.clients.transport.http.HeaderMap; +import co.elastic.clients.transport.http.TransportHttpClient; +import co.elastic.clients.util.BinaryData; +import co.elastic.clients.util.NoCopyByteArrayOutputStream; +import org.apache.http.Header; +import org.apache.http.HeaderElement; +import org.apache.http.HttpEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.util.EntityUtils; +import org.elasticsearch.client.Cancellable; +import org.elasticsearch.client.ResponseListener; +import org.elasticsearch.client.RestClient; + +import javax.annotation.Nullable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.util.AbstractList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; + +public class RestClientHttpClient implements TransportHttpClient { + + private static final ConcurrentHashMap ContentTypeCache = new ConcurrentHashMap<>(); + + /** + * The {@code Future} implementation returned by async requests. + * It wraps the RestClient's cancellable and propagates cancellation. + */ + private static class RequestFuture extends CompletableFuture { + private volatile Cancellable cancellable; + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + boolean cancelled = super.cancel(mayInterruptIfRunning); + if (cancelled && cancellable != null) { + cancellable.cancel(); + } + return cancelled; + } + } + + private final RestClient restClient; + + public RestClientHttpClient(RestClient restClient) { + this.restClient = restClient; + } + + /** + * Returns the underlying low level Rest Client used by this transport. + */ + public RestClient restClient() { + return this.restClient; + } + + @Override + public RestClientOptions createOptions(@Nullable TransportOptions options) { + return RestClientOptions.of(options); + } + + @Override + public Response performRequest(String endpointId, @Nullable Node node, Request request, + TransportOptions options) throws IOException { + RestClientOptions rcOptions = RestClientOptions.of(options); + org.elasticsearch.client.Request restRequest = createRestRequest(request, rcOptions); + org.elasticsearch.client.Response restResponse = restClient.performRequest(restRequest); + return new RestResponse(restResponse); + } + + @Override + public CompletableFuture performRequestAsync( + String endpointId, @Nullable Node node, Request request, TransportOptions options + ) { + + RequestFuture future = new RequestFuture<>(); + org.elasticsearch.client.Request restRequest; + + try { + RestClientOptions rcOptions = RestClientOptions.of(options); + restRequest = createRestRequest(request, rcOptions); + } catch (Throwable thr) { + // Terminate early + future.completeExceptionally(thr); + return future; + } + + future.cancellable = restClient.performRequestAsync(restRequest, new ResponseListener() { + @Override + public void onSuccess(org.elasticsearch.client.Response response) { + future.complete(new RestResponse(response)); + } + + @Override + public void onFailure(Exception exception) { + future.completeExceptionally(exception); + } + }); + + return future; + } + + @Override + public void close() throws IOException { + this.restClient.close(); + } + + private org.elasticsearch.client.Request createRestRequest(Request request, RestClientOptions options) { + org.elasticsearch.client.Request clientReq = new org.elasticsearch.client.Request( + request.method(), request.path() + ); + + Iterable body = request.body(); + + Map requestHeaders = request.headers(); + if (!requestHeaders.isEmpty()) { + + int headerCount = requestHeaders.size(); + if ((body == null && headerCount != 3) || headerCount != 4) { + if (options == null) { + options = RestClientOptions.initialOptions(); + } + + RestClientOptions.Builder builder = options.toBuilder(); + for (Map.Entry header : requestHeaders.entrySet()) { + builder.setHeader(header.getKey(), header.getValue()); + } + // Original option headers have precedence + for (Map.Entry header : options.headers()) { + builder.setHeader(header.getKey(), header.getValue()); + } + options = builder.build(); + } + } + + if (options != null) { + clientReq.setOptions(options.restClientRequestOptions()); + } + + clientReq.addParameters(request.queryParams()); + + if (body != null) { + ContentType ct = null; + String ctStr; + if ((ctStr = requestHeaders.get(HeaderMap.CONTENT_TYPE)) != null) { + ct = ContentTypeCache.computeIfAbsent(ctStr, ContentType::parse); + } + clientReq.setEntity(new MultiBufferEntity(body, ct)); + } + + // Request parameter intercepted by LLRC + clientReq.addParameter("ignore", "400,401,403,404,405"); + return clientReq; + } + + static class RestResponse implements Response { + private final org.elasticsearch.client.Response restResponse; + + RestResponse(org.elasticsearch.client.Response restResponse) { + this.restResponse = restResponse; + } + + @Override + public Node node() { + return new Node(restResponse.getHost().toURI()); + } + + @Override + public int statusCode() { + return restResponse.getStatusLine().getStatusCode(); + } + + @Override + public String header(String name) { + return restResponse.getHeader(name); + } + + @Override + public List headers(String name) { + Header[] headers = restResponse.getHeaders(); + for (int i = 0; i < headers.length; i++) { + Header header = headers[i]; + if (header.getName().equalsIgnoreCase(name)) { + HeaderElement[] elements = header.getElements(); + return new AbstractList() { + @Override + public String get(int index) { + return elements[index].getValue(); + } + + @Override + public int size() { + return elements.length; + } + }; + } + } + return Collections.emptyList(); + } + + @Nullable + @Override + public BinaryData body() throws IOException { + HttpEntity entity = restResponse.getEntity(); + return entity == null ? null : new HttpEntityBinaryData(restResponse.getEntity()); + } + + @Nullable + @Override + public org.elasticsearch.client.Response originalResponse() { + return this.restResponse; + } + + @Override + public void close() throws IOException { + EntityUtils.consume(restResponse.getEntity()); + } + } + + private static class HttpEntityBinaryData implements BinaryData { + private final HttpEntity entity; + + HttpEntityBinaryData(HttpEntity entity) { + this.entity = entity; + } + + @Override + public String contentType() { + Header h = entity.getContentType(); + return h == null ? "application/octet-stream" : h.getValue(); + } + + @Override + public void writeTo(OutputStream out) throws IOException { + entity.writeTo(out); + } + + @Override + public ByteBuffer asByteBuffer() throws IOException { + NoCopyByteArrayOutputStream out = new NoCopyByteArrayOutputStream(); + entity.writeTo(out); + return out.asByteBuffer(); + } + + @Override + public InputStream asInputStream() throws IOException { + return entity.getContent(); + } + + @Override + public boolean isRepeatable() { + return entity.isRepeatable(); + } + + @Override + public long size() { + long len = entity.getContentLength(); + return len < 0 ? -1 : entity.getContentLength(); + } + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java new file mode 100644 index 000000000..842a45c62 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java @@ -0,0 +1,262 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest_client; + +import co.elastic.clients.transport.TransportOptions; +import co.elastic.clients.transport.Version; +import co.elastic.clients.transport.http.HeaderMap; +import co.elastic.clients.util.LanguageRuntimeVersions; +import co.elastic.clients.util.VisibleForTesting; +import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; +import org.apache.http.util.VersionInfo; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.WarningsHandler; + +import javax.annotation.Nullable; +import java.util.AbstractMap; +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class RestClientOptions implements TransportOptions { + + private final RequestOptions options; + + boolean keepResponseBodyOnException; + + @VisibleForTesting + static final String CLIENT_META_VALUE = getClientMeta(); + @VisibleForTesting + static final String USER_AGENT_VALUE = getUserAgent(); + + static RestClientOptions of(@Nullable TransportOptions options) { + if (options == null) { + return initialOptions(); + } + + if (options instanceof RestClientOptions) { + return (RestClientOptions)options; + } + + final Builder builder = new Builder(RequestOptions.DEFAULT.toBuilder()); + options.headers().forEach(h -> builder.addHeader(h.getKey(), h.getValue())); + options.queryParameters().forEach(builder::setParameter); + builder.onWarnings(options.onWarnings()); + return builder.build(); + } + + public RestClientOptions(RequestOptions options, boolean keepResponseBodyOnException) { + this.keepResponseBodyOnException = keepResponseBodyOnException; + this.options = addBuiltinHeaders(options.toBuilder()).build(); + } + + /** + * Get the wrapped Rest Client request options + */ + public RequestOptions restClientRequestOptions() { + return this.options; + } + + @Override + public Collection> headers() { + return options.getHeaders().stream() + .map(h -> new AbstractMap.SimpleImmutableEntry<>(h.getName(), h.getValue())) + .collect(Collectors.toList()); + } + + @Override + public Map queryParameters() { + return options.getParameters(); + } + + /** + * Called if there are warnings to determine if those warnings should fail the request. + */ + @Override + public Function, Boolean> onWarnings() { + final WarningsHandler handler = options.getWarningsHandler(); + if (handler == null) { + return null; + } + + return warnings -> options.getWarningsHandler().warningsShouldFailRequest(warnings); + } + + @Override + public boolean keepResponseBodyOnException() { + return this.keepResponseBodyOnException; + } + + @Override + public Builder toBuilder() { + return new Builder(options.toBuilder()); + } + + public static class Builder implements TransportOptions.Builder { + + private RequestOptions.Builder builder; + + private boolean keepResponseBodyOnException; + + public Builder(RequestOptions.Builder builder) { + this.builder = builder; + } + + /** + * Get the wrapped Rest Client request options builder. + */ + public RequestOptions.Builder restClientRequestOptionsBuilder() { + return this.builder; + } + + @Override + public TransportOptions.Builder addHeader(String name, String value) { + if (name.equalsIgnoreCase(HeaderMap.CLIENT_META)) { + // Not overridable + return this; + } + if (name.equalsIgnoreCase(HeaderMap.USER_AGENT)) { + // We must remove our own user-agent from the options, or we'll end up with multiple values for the header + builder.removeHeader(HeaderMap.USER_AGENT); + } + builder.addHeader(name, value); + return this; + } + + @Override + public TransportOptions.Builder setHeader(String name, String value) { + if (name.equalsIgnoreCase(HeaderMap.CLIENT_META)) { + // Not overridable + return this; + } + builder.removeHeader(name).addHeader(name, value); + return this; + } + + @Override + public TransportOptions.Builder removeHeader(String name) { + builder.removeHeader(name); + return this; + } + + @Override + public TransportOptions.Builder setParameter(String name, String value) { + // Should be remove and add, but we can't remove. + builder.addParameter(name, value); + return this; + } + + @Override + public TransportOptions.Builder removeParameter(String name) { + throw new UnsupportedOperationException("This implementation does not support removing parameters"); + } + + /** + * Called if there are warnings to determine if those warnings should fail the request. + */ + @Override + public TransportOptions.Builder onWarnings(Function, Boolean> listener) { + if (listener == null) { + builder.setWarningsHandler(null); + } else { + builder.setWarningsHandler(w -> { + if (w != null && !w.isEmpty()) { + return listener.apply(w); + } else { + return false; + } + }); + } + + return this; + } + + @Override + public TransportOptions.Builder keepResponseBodyOnException(boolean value) { + this.keepResponseBodyOnException = value; + return this; + } + + @Override + public RestClientOptions build() { + return new RestClientOptions(addBuiltinHeaders(builder).build(), keepResponseBodyOnException); + } + } + + static RestClientOptions initialOptions() { + return new RestClientOptions(SafeResponseConsumer.DEFAULT_REQUEST_OPTIONS, false); + } + + private static RequestOptions.Builder addBuiltinHeaders(RequestOptions.Builder builder) { + builder.removeHeader(HeaderMap.CLIENT_META); + builder.addHeader(HeaderMap.CLIENT_META, CLIENT_META_VALUE); + if (builder.getHeaders().stream().noneMatch(h -> h.getName().equalsIgnoreCase(HeaderMap.USER_AGENT))) { + builder.addHeader(HeaderMap.USER_AGENT, USER_AGENT_VALUE); + } + if (builder.getHeaders().stream().noneMatch(h -> h.getName().equalsIgnoreCase(HeaderMap.ACCEPT))) { + builder.addHeader(HeaderMap.ACCEPT, RestClientTransport.JSON_CONTENT_TYPE); + } + + return builder; + } + + private static String getUserAgent() { + return String.format( + Locale.ROOT, + "elastic-java/%s (Java/%s)", + Version.VERSION == null ? "Unknown" : Version.VERSION.toString(), + System.getProperty("java.version") + ); + } + + private static String getClientMeta() { + VersionInfo httpClientVersion = null; + try { + httpClientVersion = VersionInfo.loadVersionInfo( + "org.apache.http.nio.client", + HttpAsyncClientBuilder.class.getClassLoader() + ); + } catch (Exception e) { + // Keep unknown + } + + // Use a single 'p' suffix for all prerelease versions (snapshot, beta, etc). + String metaVersion = Version.VERSION == null ? "" : Version.VERSION.toString(); + int dashPos = metaVersion.indexOf('-'); + if (dashPos > 0) { + metaVersion = metaVersion.substring(0, dashPos) + "p"; + } + + // service, language, transport, followed by additional information + return "es=" + + metaVersion + + ",jv=" + + System.getProperty("java.specification.version") + + ",t=" + + metaVersion + + ",hl=2" + + ",hc=" + + (httpClientVersion == null ? "" : httpClientVersion.getRelease()) + + LanguageRuntimeVersions.getRuntimeMetadata(); + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java new file mode 100644 index 000000000..dbadfbe1a --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest_client; + +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransportBase; +import co.elastic.clients.transport.instrumentation.Instrumentation; +import org.elasticsearch.client.RestClient; + +public class RestClientTransport extends ElasticsearchTransportBase { + + private final RestClient restClient; + + public RestClientTransport(RestClient restClient, JsonpMapper jsonpMapper) { + this(restClient, jsonpMapper, null); + } + + public RestClientTransport(RestClient restClient, JsonpMapper jsonpMapper, RestClientOptions options) { + super(new RestClientHttpClient(restClient), options, jsonpMapper, null); + this.restClient = restClient; + } + + public RestClientTransport(RestClient restClient, JsonpMapper jsonpMapper, RestClientOptions options, Instrumentation instrumentation) { + super(new RestClientHttpClient(restClient), options, jsonpMapper, instrumentation); + this.restClient = restClient; + } + + public RestClient restClient() { + return this.restClient; + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/SafeResponseConsumer.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/SafeResponseConsumer.java new file mode 100644 index 000000000..b0cab714c --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/SafeResponseConsumer.java @@ -0,0 +1,132 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest_client; + +import org.apache.http.HttpException; +import org.apache.http.HttpResponse; +import org.apache.http.nio.ContentDecoder; +import org.apache.http.nio.IOControl; +import org.apache.http.nio.protocol.HttpAsyncResponseConsumer; +import org.apache.http.protocol.HttpContext; +import org.elasticsearch.client.HttpAsyncResponseConsumerFactory; +import org.elasticsearch.client.RequestOptions; + +import java.io.IOException; + +/** + * A response consumer that will propagate Errors as RuntimeExceptions to avoid crashing the IOReactor. + */ +public class SafeResponseConsumer implements HttpAsyncResponseConsumer { + + private final HttpAsyncResponseConsumer delegate; + + /** + * A consumer factory that safely wraps the one provided by {@code RequestOptions.DEFAULT}. + */ + public static final HttpAsyncResponseConsumerFactory DEFAULT_FACTORY = () -> new SafeResponseConsumer<>( + RequestOptions.DEFAULT.getHttpAsyncResponseConsumerFactory().createHttpAsyncResponseConsumer() + ); + + /** + * Same as {@code RequestOptions.DEFAULT} with a safe consumer factory + */ + public static final RequestOptions DEFAULT_REQUEST_OPTIONS = RequestOptions.DEFAULT + .toBuilder() + .setHttpAsyncResponseConsumerFactory(DEFAULT_FACTORY) + .build(); + + public SafeResponseConsumer(HttpAsyncResponseConsumer delegate) { + this.delegate = delegate; + } + + @SuppressWarnings("unchecked") + private static void throwUnchecked(Throwable thr) throws T { + throw (T) thr; + } + + @Override + public void responseReceived(HttpResponse response) throws IOException, HttpException { + try { + delegate.responseReceived(response); + } catch(Exception e) { + throwUnchecked(e); + } catch(Throwable e) { + throw new RuntimeException("Error receiving response", e); + } + } + + @Override + public void consumeContent(ContentDecoder decoder, IOControl ioControl) throws IOException { + try { + delegate.consumeContent(decoder, ioControl); + } catch(Exception e) { + throwUnchecked(e); + } catch(Throwable e) { + throw new RuntimeException("Error consuming content", e); + } + } + + @Override + public void responseCompleted(HttpContext context) { + try { + delegate.responseCompleted(context); + } catch(Exception e) { + throwUnchecked(e); + } catch(Throwable e) { + throw new RuntimeException("Error completing response", e); + } + } + + @Override + public void failed(Exception ex) { + try { + delegate.failed(ex); + } catch(Exception e) { + throwUnchecked(e); + } catch(Throwable e) { + throw new RuntimeException("Error handling failure", e); + } + } + + @Override + public Exception getException() { + return delegate.getException(); + } + + @Override + public T getResult() { + return delegate.getResult(); + } + + @Override + public boolean isDone() { + return delegate.isDone(); + } + + @Override + public void close() throws IOException { + delegate.close(); + } + + @Override + public boolean cancel() { + return delegate.cancel(); + } +} From 288b3a5e9b6fb4543c88b54e8284a21436d214e2 Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Tue, 25 Mar 2025 11:20:15 +0100 Subject: [PATCH 06/38] temp --- java-client/build.gradle.kts | 2 + .../builders/ElasticsearchClientBuilder.java | 19 +- .../ElasticsearchClientBuilder.java | 131 ++++ .../rest5_client/RestClientHttpClient.java | 26 +- .../rest5_client/RestClientOptions.java | 4 +- .../rest5_client/RestClientTransport.java | 2 +- .../Cancellable.java | 7 +- .../DeadHostState.java | 2 +- .../Request.java => low_level/ESRequest.java} | 17 +- .../ESResponse.java} | 6 +- .../HttpDeleteWithEntity.java | 2 +- .../HttpGetWithEntity.java | 2 +- .../LanguageRuntimeVersions.java | 2 +- .../RequestLogger.java | 4 +- .../RequestOptions.java | 8 +- .../ResponseException.java | 13 +- .../ResponseListener.java | 8 +- .../RestClient.java | 116 ++- .../RestClientBuilder.java | 9 +- .../WarningFailureException.java | 18 +- .../WarningsHandler.java | 2 +- .../consumer/BasicAsyncResponseConsumer.java | 2 +- .../consumer/BufferedByteConsumer.java | 4 +- .../HttpAsyncResponseConsumerFactory.java | 4 +- .../node/Node.java | 4 +- .../selector/HasAttributeNodeSelector.java | 4 +- .../node/selector/NodeSelector.java | 8 +- .../PreferHasAttributeNodeSelector.java | 4 +- .../producer/BasicAsyncEntityProducer.java | 4 +- .../utils/Constants.java | 2 +- .../rest_client/RestClientOptions.java | 6 + .../documentation/DocTestsTransport.java | 119 --- .../api_conventions/ApiConventionsTest.java | 366 --------- .../api_conventions/LoadingJsonTest.java | 193 ----- .../getting_started/ConnectingTest.java | 191 ----- .../troubleshooting/TroubleShootingTests.java | 93 --- .../documentation/usage/AggregationsTest.java | 107 --- .../documentation/usage/IndexingBulkTest.java | 213 ------ .../documentation/usage/IndexingTest.java | 208 ------ .../clients/documentation/usage/Product.java | 57 -- .../documentation/usage/ReadingTest.java | 97 --- .../documentation/usage/SearchingTest.java | 2 +- .../ElasticsearchTestServer.java | 292 -------- .../_helpers/builders/ClientBuildersTest.java | 71 -- .../bulk/BulkIngesterRetryPolicyTest.java | 544 -------------- .../_helpers/bulk/BulkIngesterTest.java | 623 ---------------- .../esql/EsqlAdapterEndToEndTest.java | 204 ----- .../_helpers/esql/EsqlAdapterTest.java | 119 --- .../experiments/ClientTests.java | 108 --- .../experiments/ParsingTests.java | 76 -- .../experiments/UnionVariant.java | 31 - .../elasticsearch/experiments/api/Bar.java | 82 --- .../experiments/api/DateMathTimeUnit.java | 49 -- .../experiments/api/FooOptRequest.java | 276 ------- .../experiments/api/FooRequest.java | 315 -------- .../experiments/api/FooResponse.java | 27 - .../experiments/api/query2/BoolQuery.java | 173 ----- .../experiments/api/query2/Query.java | 205 ------ .../experiments/api/query2/QueryTest.java | 44 -- .../experiments/api/query2/TermsQuery.java | 107 --- .../experiments/api/query2/Union2.java | 154 ---- .../experiments/base/Client.java | 48 -- .../experiments/base/PrimitiveUtils.java | 41 -- .../experiments/base/Variants.java | 155 ---- .../experiments/containers/SomeUnion.java | 152 ---- .../experiments/containers/SomeUnionTest.java | 84 --- .../containers/SomeUnionVariant.java | 25 - .../experiments/containers/UVariantA.java | 82 --- .../experiments/containers/UVariantB.java | 82 --- .../experiments/generics/GenericClass.java | 123 ---- .../inheritance/InheritanceTest.java | 97 --- .../inheritance/base/BaseClass.java | 77 -- .../inheritance/child/ChildClass.java | 93 --- .../inheritance/final_/FinalClass.java | 98 --- .../experiments/package-info.java | 23 - .../elasticsearch/model/BuiltinTypesTest.java | 273 ------- .../model/ClassStructureTest.java | 361 --------- .../model/CodeAdditionsTests.java | 49 -- .../elasticsearch/model/EndpointTest.java | 94 --- .../clients/elasticsearch/model/EnumTest.java | 61 -- .../model/RequestEncodingTest.java | 59 -- .../elasticsearch/model/TypedKeysTest.java | 299 -------- .../elasticsearch/model/UnionTests.java | 8 +- .../elasticsearch/model/VariantsTest.java | 351 --------- .../elasticsearch/model/package-info.java | 24 - .../spec_issues/SpecIssuesTest.java | 2 +- .../co/elastic/clients/json/JsonDataTest.java | 169 ----- .../json/JsonpDeserializerBaseTest.java | 50 -- .../clients/json/JsonpDeserializerTest.java | 42 -- .../elastic/clients/json/JsonpMapperTest.java | 209 ------ .../json/JsonpMappingExceptionTest.java | 110 --- .../elastic/clients/json/JsonpUtilsTest.java | 331 --------- .../clients/json/LazyDeserializerTest.java | 68 -- .../json/ObjectBuilderDeserializerTest.java | 50 -- .../co/elastic/clients/json/WithJsonTest.java | 2 +- .../jackson/JacksonJsonpGeneratorTest.java | 90 --- .../json/jackson/JacksonJsonpParserTest.java | 193 ----- .../json/jackson/JacksonMapperTest.java | 102 --- .../clients/json/jackson/JsonEnumTest.java | 56 -- .../json/jackson/JsonValueParserTest.java | 79 -- .../clients/testkit/MockHttpClient.java | 156 ---- .../clients/testkit/ModelTestCase.java | 151 ---- .../transport5/RequestOptionsTest.java | 162 ---- .../clients/transport5/TransportTest.java | 157 ---- .../transport5/TransportUtilsTest.java | 120 --- .../clients/transport5/VersionInfoTest.java | 32 - .../endpoints/BinaryEndpointTest.java | 128 ---- .../endpoints/BooleanEndpointTest.java | 37 - .../endpoints/EndpointBaseTest.java | 68 -- .../endpoints/SimpleEndpointTest.java | 71 -- .../transport5/http/HeaderMapTest.java | 78 -- .../OpenTelemetryForElasticsearchTest.java | 277 ------- .../BasicAsyncResponseConsumerTests.java | 76 -- .../ClientsGraalVMThreadsFilter.java | 33 - .../low_level_client/DeadHostStateTests.java | 136 ---- .../FailureTrackingResponseListenerTests.java | 112 --- .../HasAttributeNodeSelectorTests.java | 78 -- .../HostsTrackingFailureListener.java | 62 -- .../low_level_client/NodeSelectorTests.java | 131 ---- .../low_level_client/NodeTests.java | 175 ----- .../PreferHasAttributeNodeSelectorTests.java | 89 --- .../low_level_client/RequestLoggerTests.java | 204 ----- .../low_level_client/RequestOptionsTests.java | 211 ------ .../low_level_client/RequestTests.java | 249 ------- .../ResponseExceptionTests.java | 93 --- .../RestClientBuilderIntegTests.java | 227 ------ .../RestClientBuilderTests.java | 268 ------- .../RestClientDocumentation.java | 461 ------------ .../RestClientGzipCompressionTests.java | 257 ------- .../RestClientMultipleHostsIntegTests.java | 402 ---------- .../RestClientMultipleHostsTests.java | 341 --------- .../RestClientSingleHostIntegTests.java | 457 ------------ .../RestClientSingleHostTests.java | 694 ------------------ .../low_level_client/RestClientTestCase.java | 119 --- .../low_level_client/RestClientTestUtil.java | 119 --- .../low_level_client/RestClientTests.java | 456 ------------ .../rest_client/MultiBufferEntityTest.java | 100 --- .../rest_client/RestClientOptionsTest.java | 204 ----- .../co/elastic/clients/util/DateTimeTest.java | 139 ---- .../util/DuplicateResourceFinderTest.java | 40 - .../elastic/clients/util/NamedValueTest.java | 49 -- .../co/elastic/clients/util/PairTest.java | 45 -- .../databind/ext/CoreXMLSerializers.java | 25 - 143 files changed, 285 insertions(+), 17104 deletions(-) create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/rest5_client/ElasticsearchClientBuilder.java rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/Cancellable.java (93%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/DeadHostState.java (98%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client/Request.java => low_level/ESRequest.java} (91%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client/Response.java => low_level/ESResponse.java} (97%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/HttpDeleteWithEntity.java (95%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/HttpGetWithEntity.java (95%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/LanguageRuntimeVersions.java (98%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/RequestLogger.java (98%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/RequestOptions.java (97%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/ResponseException.java (86%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/ResponseListener.java (87%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/RestClient.java (87%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/RestClientBuilder.java (97%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/WarningFailureException.java (75%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/WarningsHandler.java (95%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/consumer/BasicAsyncResponseConsumer.java (96%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/consumer/BufferedByteConsumer.java (93%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/consumer/HttpAsyncResponseConsumerFactory.java (93%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/node/Node.java (98%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/node/selector/HasAttributeNodeSelector.java (93%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/node/selector/NodeSelector.java (91%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/node/selector/PreferHasAttributeNodeSelector.java (95%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/producer/BasicAsyncEntityProducer.java (94%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{low_level_client => low_level}/utils/Constants.java (73%) delete mode 100644 java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java delete mode 100644 java-client/src/test/java/co/elastic/clients/documentation/api_conventions/ApiConventionsTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/documentation/api_conventions/LoadingJsonTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/documentation/troubleshooting/TroubleShootingTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/documentation/usage/AggregationsTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/documentation/usage/IndexingBulkTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/documentation/usage/IndexingTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/documentation/usage/Product.java delete mode 100644 java-client/src/test/java/co/elastic/clients/documentation/usage/ReadingTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuildersTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/bulk/BulkIngesterTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/ClientTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/ParsingTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/UnionVariant.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/Bar.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/DateMathTimeUnit.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooOptRequest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooRequest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooResponse.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/BoolQuery.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/Query.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/QueryTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/TermsQuery.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/Union2.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/Client.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/PrimitiveUtils.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/Variants.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnion.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnionTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnionVariant.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/UVariantA.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/UVariantB.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/generics/GenericClass.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/InheritanceTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/base/BaseClass.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/child/ChildClass.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/final_/FinalClass.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/package-info.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/BuiltinTypesTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/ClassStructureTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/CodeAdditionsTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/EndpointTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/EnumTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/RequestEncodingTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/TypedKeysTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/VariantsTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/package-info.java delete mode 100644 java-client/src/test/java/co/elastic/clients/json/JsonDataTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/json/JsonpDeserializerBaseTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/json/JsonpDeserializerTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/json/JsonpMapperTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/json/JsonpMappingExceptionTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/json/JsonpUtilsTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/json/LazyDeserializerTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/json/ObjectBuilderDeserializerTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/json/jackson/JacksonJsonpGeneratorTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/json/jackson/JacksonJsonpParserTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/json/jackson/JacksonMapperTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/json/jackson/JsonEnumTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/json/jackson/JsonValueParserTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/testkit/MockHttpClient.java delete mode 100644 java-client/src/test/java/co/elastic/clients/testkit/ModelTestCase.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/RequestOptionsTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/TransportTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/TransportUtilsTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/VersionInfoTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/endpoints/BinaryEndpointTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/endpoints/BooleanEndpointTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/endpoints/EndpointBaseTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/endpoints/SimpleEndpointTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/http/HeaderMapTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/instrumentation/OpenTelemetryForElasticsearchTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/BasicAsyncResponseConsumerTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/ClientsGraalVMThreadsFilter.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/DeadHostStateTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/FailureTrackingResponseListenerTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/HasAttributeNodeSelectorTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/HostsTrackingFailureListener.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/NodeSelectorTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/NodeTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/PreferHasAttributeNodeSelectorTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestLoggerTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestOptionsTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/ResponseExceptionTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientBuilderIntegTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientBuilderTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientDocumentation.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientGzipCompressionTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientMultipleHostsIntegTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientMultipleHostsTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientSingleHostIntegTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientSingleHostTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTestCase.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTestUtil.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/rest_client/MultiBufferEntityTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/transport5/rest_client/RestClientOptionsTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/util/DateTimeTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/util/DuplicateResourceFinderTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/util/NamedValueTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/util/PairTest.java delete mode 100644 java-client/src/test/java/com/fasterxml/jackson/databind/ext/CoreXMLSerializers.java diff --git a/java-client/build.gradle.kts b/java-client/build.gradle.kts index 20438a86a..1af0efc75 100644 --- a/java-client/build.gradle.kts +++ b/java-client/build.gradle.kts @@ -208,6 +208,8 @@ dependencies { // https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-low.html api("org.elasticsearch.client", "elasticsearch-rest-client", elasticsearchVersion) + api("org.apache.httpcomponents.client5","httpclient5","5.4") + // Apache 2.0 // https://search.maven.org/artifact/com.google.code.findbugs/jsr305 api("com.google.code.findbugs:jsr305:3.0.2") diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java index d36f085ba..524b10275 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java @@ -22,13 +22,13 @@ import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.JsonpMapper; import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.rest5_client.RestClientOptions; -import co.elastic.clients.transport.rest5_client.RestClientTransport; +import co.elastic.clients.transport.rest_client.RestClientOptions; +import co.elastic.clients.transport.rest_client.RestClientTransport; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.json.JsonMapper; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.message.BasicHeader; +import org.apache.http.Header; +import org.apache.http.HttpHost; +import org.apache.http.message.BasicHeader; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; @@ -90,11 +90,7 @@ public ElasticsearchClient build() { // defaulting to localhost if (this.host == null) { - try { - this.host = HttpHost.create("http://localhost:9200"); - } catch (URISyntaxException e) { - // can't throw - } + this.host = HttpHost.create("http://localhost:9200"); } RestClientBuilder restClientBuilder = RestClient.builder(host); @@ -125,7 +121,8 @@ public ElasticsearchClient build() { this.mapper = new JacksonJsonpMapper(mapper); } - RestClientTransport transport = new RestClientTransport(restClientBuilder.build(), mapper, transportOptions); + RestClientTransport transport = new RestClientTransport(restClientBuilder.build(), mapper, + transportOptions); return new ElasticsearchClient(transport); } } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/rest5_client/ElasticsearchClientBuilder.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/rest5_client/ElasticsearchClientBuilder.java new file mode 100644 index 000000000..4e673dedd --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/rest5_client/ElasticsearchClientBuilder.java @@ -0,0 +1,131 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch._helpers.builders.rest5_client; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.rest5_client.RestClientOptions; +import co.elastic.clients.transport.rest5_client.RestClientTransport; +import co.elastic.clients.transport.rest5_client.low_level.RestClient; +import co.elastic.clients.transport.rest5_client.low_level.RestClientBuilder; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.message.BasicHeader; + +import javax.net.ssl.SSLContext; +import java.net.URISyntaxException; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.Optional; + +// TODO do we want separate builder subclasses to make sure that only 1 auth method has been provided? +public class ElasticsearchClientBuilder { + + private HttpHost host; + private String username; + private String password; + private String token; + private String apiKey; + private SSLContext sslContext; + private JsonpMapper mapper; + private RestClientOptions transportOptions; + + public ElasticsearchClientBuilder host(String url) throws URISyntaxException { + this.host = HttpHost.create(url); + return this; + } + + public ElasticsearchClientBuilder usernameAndPassword(String username, String password) { + this.username = username; + this.password = password; + return this; + } + + public ElasticsearchClientBuilder token(String token) { + this.token = token; + return this; + } + + public ElasticsearchClientBuilder apiKey(String apiKey) { + this.apiKey = apiKey; + return this; + } + + public ElasticsearchClientBuilder sslContext(SSLContext sslContext) { + this.sslContext = sslContext; + return this; + } + + public ElasticsearchClientBuilder jsonMapper(JsonpMapper mapper) { + this.mapper = mapper; + return this; + } + + public ElasticsearchClientBuilder transportOptions(RestClientOptions transportOptions) { + this.transportOptions = transportOptions; + return this; + } + + public ElasticsearchClient build() { + + // defaulting to localhost + if (this.host == null) { + try { + this.host = HttpHost.create("http://localhost:9200"); + } catch (URISyntaxException e) { + // can't throw + } + } + + RestClientBuilder restClientBuilder = RestClient.builder(host); + + if (this.username != null && this.password != null) { + var cred = Base64.getEncoder().encodeToString((username + ":" + password).getBytes()); + restClientBuilder.setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Basic " + cred) + }); + } else if (this.apiKey != null) { + restClientBuilder.setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "ApiKey " + apiKey) + }); + } else if (this.token != null) { + restClientBuilder.setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Bearer " + token) + }); + } + + try { + restClientBuilder.setSslContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + + if (this.mapper == null) { + ObjectMapper mapper = JsonMapper.builder().build(); + this.mapper = new JacksonJsonpMapper(mapper); + } + + RestClientTransport transport = new RestClientTransport(restClientBuilder.build(), mapper, transportOptions); + return new ElasticsearchClient(transport); + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientHttpClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientHttpClient.java index 53a5da2e5..cb2633680 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientHttpClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientHttpClient.java @@ -22,6 +22,11 @@ import co.elastic.clients.transport.TransportOptions; import co.elastic.clients.transport.http.HeaderMap; import co.elastic.clients.transport.http.TransportHttpClient; +import co.elastic.clients.transport.rest5_client.low_level.Cancellable; +import co.elastic.clients.transport.rest5_client.low_level.ESRequest; +import co.elastic.clients.transport.rest5_client.low_level.ESResponse; +import co.elastic.clients.transport.rest5_client.low_level.ResponseListener; +import co.elastic.clients.transport.rest5_client.low_level.RestClient; import co.elastic.clients.util.BinaryData; import co.elastic.clients.util.NoCopyByteArrayOutputStream; import org.apache.hc.core5.http.ContentType; @@ -30,9 +35,6 @@ import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.message.BasicHeaderValueParser; -import org.elasticsearch.client.Cancellable; -import org.elasticsearch.client.ResponseListener; -import org.elasticsearch.client.RestClient; import javax.annotation.Nullable; import java.io.IOException; @@ -89,8 +91,8 @@ public RestClientOptions createOptions(@Nullable TransportOptions options) { public Response performRequest(String endpointId, @Nullable Node node, Request request, TransportOptions options) throws IOException { RestClientOptions rcOptions = RestClientOptions.of(options); - org.elasticsearch.client.Request restRequest = createRestRequest(request, rcOptions); - org.elasticsearch.client.Response restResponse = restClient.performRequest(restRequest); + ESRequest restRequest = createRestRequest(request, rcOptions); + ESResponse restResponse = restClient.performRequest(restRequest); return new RestResponse(restResponse); } @@ -100,7 +102,7 @@ public CompletableFuture performRequestAsync( ) { RequestFuture future = new RequestFuture<>(); - org.elasticsearch.client.Request restRequest; + ESRequest restRequest; try { RestClientOptions rcOptions = RestClientOptions.of(options); @@ -113,7 +115,7 @@ public CompletableFuture performRequestAsync( future.cancellable = restClient.performRequestAsync(restRequest, new ResponseListener() { @Override - public void onSuccess(org.elasticsearch.client.Response response) { + public void onSuccess(ESResponse response) { future.complete(new RestResponse(response)); } @@ -131,8 +133,8 @@ public void close() throws IOException { this.restClient.close(); } - private org.elasticsearch.client.Request createRestRequest(Request request, RestClientOptions options) { - org.elasticsearch.client.Request clientReq = new org.elasticsearch.client.Request( + private ESRequest createRestRequest(Request request, RestClientOptions options) { + ESRequest clientReq = new ESRequest( request.method(), request.path() ); @@ -178,9 +180,9 @@ private org.elasticsearch.client.Request createRestRequest(Request request, Rest } static class RestResponse implements Response { - private final org.elasticsearch.client.Response restResponse; + private final ESResponse restResponse; - RestResponse(org.elasticsearch.client.Response restResponse) { + RestResponse(ESResponse restResponse) { this.restResponse = restResponse; } @@ -232,7 +234,7 @@ public BinaryData body() throws IOException { @Nullable @Override - public org.elasticsearch.client.Response originalResponse() { + public ESResponse originalResponse() { return this.restResponse; } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientOptions.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientOptions.java index 5be7ee405..f861edef0 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientOptions.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientOptions.java @@ -22,12 +22,12 @@ import co.elastic.clients.transport.TransportOptions; import co.elastic.clients.transport.Version; import co.elastic.clients.transport.http.HeaderMap; +import co.elastic.clients.transport.rest5_client.low_level.RequestOptions; +import co.elastic.clients.transport.rest5_client.low_level.WarningsHandler; import co.elastic.clients.util.LanguageRuntimeVersions; import co.elastic.clients.util.VisibleForTesting; import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; import org.apache.hc.core5.util.VersionInfo; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.WarningsHandler; import javax.annotation.Nullable; import java.util.AbstractMap; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientTransport.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientTransport.java index 65e78249e..2fb481c09 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientTransport.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientTransport.java @@ -22,7 +22,7 @@ import co.elastic.clients.json.JsonpMapper; import co.elastic.clients.transport.ElasticsearchTransportBase; import co.elastic.clients.transport.instrumentation.Instrumentation; -import org.elasticsearch.client.RestClient; +import co.elastic.clients.transport.rest5_client.low_level.RestClient; public class RestClientTransport extends ElasticsearchTransportBase { diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Cancellable.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Cancellable.java similarity index 93% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Cancellable.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Cancellable.java index 70bd0c2a4..77992fcfa 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Cancellable.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Cancellable.java @@ -16,20 +16,17 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client; +package co.elastic.clients.transport.rest5_client.low_level; import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; import org.apache.hc.core5.concurrent.CancellableDependency; -import org.elasticsearch.client.Request; -import org.elasticsearch.client.ResponseListener; -import org.elasticsearch.client.RestClient; import java.util.concurrent.CancellationException; /** * Represents an operation that can be cancelled. * Returned when executing async requests through - * {@link RestClient#performRequestAsync(Request, ResponseListener)}, so that the request + * {@link RestClient#performRequestAsync(ESRequest, ResponseListener)}, so that the request * can be cancelled if needed. Cancelling a request will result in calling * {@link HttpUriRequestBase#abort()} on the underlying * request object, which will in turn cancel its corresponding {@link java.util.concurrent.Future}. diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/DeadHostState.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/DeadHostState.java similarity index 98% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/DeadHostState.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/DeadHostState.java index eb109bb73..7024413f8 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/DeadHostState.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/DeadHostState.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client; +package co.elastic.clients.transport.rest5_client.low_level; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Request.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ESRequest.java similarity index 91% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Request.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ESRequest.java index d35b0d985..aa13589b9 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Request.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ESRequest.java @@ -17,13 +17,12 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client; +package co.elastic.clients.transport.rest5_client.low_level; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.io.entity.StringEntity; -import org.elasticsearch.client.RequestOptions; import java.util.HashMap; import java.util.Map; @@ -34,20 +33,20 @@ /** * HTTP Request to Elasticsearch. */ -public final class Request { +public final class ESRequest { private final String method; private final String endpoint; private final Map parameters = new HashMap<>(); private HttpEntity entity; - private org.elasticsearch.client.RequestOptions options = org.elasticsearch.client.RequestOptions.DEFAULT; + private RequestOptions options = RequestOptions.DEFAULT; /** - * Create the {@linkplain Request}. + * Create the {@linkplain ESRequest}. * @param method the HTTP method * @param endpoint the path of the request (without scheme, host, port, or prefix) */ - public Request(String method, String endpoint) { + public ESRequest(String method, String endpoint) { this.method = Objects.requireNonNull(method, "method cannot be null"); this.endpoint = Objects.requireNonNull(endpoint, "endpoint cannot be null"); } @@ -127,7 +126,7 @@ public HttpEntity getEntity() { * Set the portion of an HTTP request to Elasticsearch that can be * manipulated without changing Elasticsearch's behavior. */ - public void setOptions(org.elasticsearch.client.RequestOptions options) { + public void setOptions(RequestOptions options) { Objects.requireNonNull(options, "options cannot be null"); this.options = options; } @@ -136,7 +135,7 @@ public void setOptions(org.elasticsearch.client.RequestOptions options) { * Set the portion of an HTTP request to Elasticsearch that can be * manipulated without changing Elasticsearch's behavior. */ - public void setOptions(org.elasticsearch.client.RequestOptions.Builder options) { + public void setOptions(RequestOptions.Builder options) { Objects.requireNonNull(options, "options cannot be null"); this.options = options.build(); } @@ -174,7 +173,7 @@ public boolean equals(Object obj) { return true; } - Request other = (Request) obj; + ESRequest other = (ESRequest) obj; return method.equals(other.method) && endpoint.equals(other.endpoint) && parameters.equals(other.parameters) diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Response.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ESResponse.java similarity index 97% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Response.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ESResponse.java index 83c2a1537..caf55dc81 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/Response.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ESResponse.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client; +package co.elastic.clients.transport.rest5_client.low_level; import org.apache.hc.core5.http.ClassicHttpResponse; @@ -37,13 +37,13 @@ * Holds an elasticsearch response. It wraps the {@link BasicClassicHttpResponse} returned and associates * it with its corresponding {@link RequestLine} and {@link HttpHost}. */ -public class Response { +public class ESResponse { private final RequestLine requestLine; private final HttpHost host; private final ClassicHttpResponse response; - Response(RequestLine requestLine, HttpHost host, ClassicHttpResponse response) { + ESResponse(RequestLine requestLine, HttpHost host, ClassicHttpResponse response) { Objects.requireNonNull(requestLine, "requestLine cannot be null"); Objects.requireNonNull(host, "host cannot be null"); Objects.requireNonNull(response, "response cannot be null"); diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/HttpDeleteWithEntity.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpDeleteWithEntity.java similarity index 95% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/HttpDeleteWithEntity.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpDeleteWithEntity.java index 7357da1bb..761bd0c6f 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/HttpDeleteWithEntity.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpDeleteWithEntity.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client; +package co.elastic.clients.transport.rest5_client.low_level; import org.apache.hc.client5.http.classic.methods.HttpDelete; import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/HttpGetWithEntity.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpGetWithEntity.java similarity index 95% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/HttpGetWithEntity.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpGetWithEntity.java index c798da031..05fb654d4 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/HttpGetWithEntity.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpGetWithEntity.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client; +package co.elastic.clients.transport.rest5_client.low_level; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/LanguageRuntimeVersions.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/LanguageRuntimeVersions.java similarity index 98% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/LanguageRuntimeVersions.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/LanguageRuntimeVersions.java index c2c4b3a32..dd2800d42 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/LanguageRuntimeVersions.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/LanguageRuntimeVersions.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client; +package co.elastic.clients.transport.rest5_client.low_level; import java.lang.reflect.Field; import java.lang.reflect.Method; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RequestLogger.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestLogger.java similarity index 98% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RequestLogger.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestLogger.java index 0d225d23e..06c309b53 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RequestLogger.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestLogger.java @@ -17,8 +17,9 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client; +package co.elastic.clients.transport.rest5_client.low_level; +import co.elastic.clients.transport.rest5_client.low_level.node.Node; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hc.client5.http.classic.methods.HttpUriRequest; @@ -29,7 +30,6 @@ import org.apache.hc.core5.http.ParseException; import org.apache.hc.core5.http.io.entity.BufferedHttpEntity; import org.apache.hc.core5.http.io.entity.EntityUtils; -import org.elasticsearch.client.node.Node; import java.io.BufferedReader; import java.io.IOException; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RequestOptions.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptions.java similarity index 97% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RequestOptions.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptions.java index a729918a5..079e37bc2 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RequestOptions.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptions.java @@ -17,15 +17,13 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client; +package co.elastic.clients.transport.rest5_client.low_level; +import co.elastic.clients.transport.rest5_client.low_level.consumer.HttpAsyncResponseConsumerFactory; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.nio.AsyncResponseConsumer; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.WarningsHandler; -import org.elasticsearch.client.consumer.HttpAsyncResponseConsumerFactory; import java.util.ArrayList; import java.util.Collections; @@ -114,7 +112,7 @@ public HttpAsyncResponseConsumerFactory getHttpAsyncResponseConsumerFactory() { /** * How this request should handle warnings. If null (the default) then * this request will default to the behavior dictacted by - * {@link org.elasticsearch.client.RestClientBuilder#setStrictDeprecationMode}. + * {@link RestClientBuilder#setStrictDeprecationMode}. *

* This can be set to {@link WarningsHandler#PERMISSIVE} if the client * should ignore all warnings which is the same behavior as setting diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/ResponseException.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseException.java similarity index 86% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/ResponseException.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseException.java index bca172de8..3fa18cb96 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/ResponseException.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseException.java @@ -17,13 +17,12 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client; +package co.elastic.clients.transport.rest5_client.low_level; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.ParseException; import org.apache.hc.core5.http.io.entity.BufferedHttpEntity; import org.apache.hc.core5.http.io.entity.EntityUtils; -import org.elasticsearch.client.Response; import java.io.IOException; import java.util.Locale; @@ -34,14 +33,14 @@ */ public final class ResponseException extends IOException { - private final Response response; + private final ESResponse response; - public ResponseException(Response response) throws IOException { + public ResponseException(ESResponse response) throws IOException { super(buildMessage(response)); this.response = response; } - static String buildMessage(Response response) throws IOException { + static String buildMessage(ESResponse response) throws IOException { String message = String.format( Locale.ROOT, "method [%s], host [%s], URI [%s], status line [%s]", @@ -71,9 +70,9 @@ static String buildMessage(Response response) throws IOException { } /** - * Returns the {@link Response} that caused this exception to be thrown. + * Returns the {@link ESResponse} that caused this exception to be thrown. */ - public Response getResponse() { + public ESResponse getResponse() { return response; } } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/ResponseListener.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseListener.java similarity index 87% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/ResponseListener.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseListener.java index 0bdcb311d..5994b107c 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/ResponseListener.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseListener.java @@ -17,11 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client; - -import org.elasticsearch.client.Response; -import org.elasticsearch.client.ResponseException; -import org.elasticsearch.client.RestClient; +package co.elastic.clients.transport.rest5_client.low_level; /** * Listener to be provided when calling async performRequest methods provided by {@link RestClient}. @@ -37,7 +33,7 @@ public interface ResponseListener { /** * Method invoked if the request yielded a successful response */ - void onSuccess(Response response); + void onSuccess(ESResponse response); /** * Method invoked if the request failed. There are two main categories of failures: connection failures (usually diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RestClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClient.java similarity index 87% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RestClient.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClient.java index 7c2a30df6..5dcb7c154 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RestClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClient.java @@ -16,8 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client; +package co.elastic.clients.transport.rest5_client.low_level; +import co.elastic.clients.transport.rest5_client.low_level.node.Node; +import co.elastic.clients.transport.rest5_client.low_level.node.selector.NodeSelector; +import co.elastic.clients.transport.rest5_client.low_level.producer.BasicAsyncEntityProducer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hc.client5.http.ClientProtocolException; @@ -50,17 +53,6 @@ import org.apache.hc.core5.http.nio.support.AsyncRequestBuilder; import org.apache.hc.core5.net.URIBuilder; import org.apache.hc.core5.reactor.IOReactorStatus; -import org.elasticsearch.client.Cancellable; -import org.elasticsearch.client.Request; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.ResponseException; -import org.elasticsearch.client.ResponseListener; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.WarningFailureException; -import org.elasticsearch.client.WarningsHandler; -import org.elasticsearch.client.node.Node; -import org.elasticsearch.client.node.selector.NodeSelector; -import org.elasticsearch.client.producer.BasicAsyncEntityProducer; import javax.net.ssl.SSLHandshakeException; import java.io.ByteArrayInputStream; @@ -101,12 +93,12 @@ /** * Client that connects to an Elasticsearch cluster through HTTP. *

- * Must be created using {@link org.elasticsearch.client.RestClientBuilder}, which allows to set all the different options or just + * Must be created using {@link RestClientBuilder}, which allows to set all the different options or just * rely on defaults. * The hosts that are part of the cluster need to be provided at creation time, but can also be replaced later * by calling {@link #setNodes(Collection)}. *

- * The method {@link #performRequest(org.elasticsearch.client.Request)} allows to send a request to the cluster. When + * The method {@link #performRequest(ESRequest)} allows to send a request to the cluster. When * sending a request, a host gets selected out of the provided ones in a round-robin fashion. Failing hosts * are marked dead and * retried after a certain amount of time (minimum 1 minute, maximum 30 minutes), depending on how many @@ -133,11 +125,11 @@ public class RestClient implements Closeable { final List

defaultHeaders; private final String pathPrefix; private final AtomicInteger lastNodeIndex = new AtomicInteger(0); - private final ConcurrentMap blacklist = new ConcurrentHashMap<>(); + private final ConcurrentMap blacklist = new ConcurrentHashMap<>(); private final FailureListener failureListener; private final NodeSelector nodeSelector; private volatile List nodes; - private final org.elasticsearch.client.WarningsHandler warningsHandler; + private final WarningsHandler warningsHandler; private final boolean compressionEnabled; private final boolean metaHeaderEnabled; @@ -157,21 +149,21 @@ public class RestClient implements Closeable { this.failureListener = failureListener; this.pathPrefix = pathPrefix; this.nodeSelector = nodeSelector; - this.warningsHandler = strictDeprecationMode ? org.elasticsearch.client.WarningsHandler.STRICT : org.elasticsearch.client.WarningsHandler.PERMISSIVE; + this.warningsHandler = strictDeprecationMode ? WarningsHandler.STRICT : WarningsHandler.PERMISSIVE; this.compressionEnabled = compressionEnabled; this.metaHeaderEnabled = metaHeaderEnabled; setNodes(nodes); } /** - * Returns a new {@link org.elasticsearch.client.RestClientBuilder} to help with {@link RestClient} creation. + * Returns a new {@link RestClientBuilder} to help with {@link RestClient} creation. * Creates a new builder instance and sets the nodes that the client will send requests to. * * @param cloudId a valid elastic cloud cloudId that will route to a cluster. The cloudId is located in * the user console https://cloud.elastic.co and will resemble a string like the following * optionalHumanReadableName:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRlbGFzdGljc2VhcmNoJGtpYmFuYQ== */ - public static org.elasticsearch.client.RestClientBuilder builder(String cloudId) { + public static RestClientBuilder builder(String cloudId) { // there is an optional first portion of the cloudId that is a human readable string, but it is not // used. if (cloudId.contains(":")) { @@ -212,18 +204,18 @@ public static org.elasticsearch.client.RestClientBuilder builder(String cloudId) } /** - * Returns a new {@link org.elasticsearch.client.RestClientBuilder} to help with {@link RestClient} creation. + * Returns a new {@link RestClientBuilder} to help with {@link RestClient} creation. * Creates a new builder instance and sets the hosts that the client will send requests to. *

* Prefer this to {@link #builder(HttpHost...)} if you have metadata up front about the nodes. * If you don't either one is fine. */ - public static org.elasticsearch.client.RestClientBuilder builder(Node... nodes) { - return new org.elasticsearch.client.RestClientBuilder(nodes == null ? null : Arrays.asList(nodes)); + public static RestClientBuilder builder(Node... nodes) { + return new RestClientBuilder(nodes == null ? null : Arrays.asList(nodes)); } /** - * Returns a new {@link org.elasticsearch.client.RestClientBuilder} to help with {@link RestClient} creation. + * Returns a new {@link RestClientBuilder} to help with {@link RestClient} creation. * Creates a new builder instance and sets the nodes that the client will send requests to. *

* You can use this if you do not have metadata up front about the nodes. If you do, prefer @@ -231,12 +223,12 @@ public static org.elasticsearch.client.RestClientBuilder builder(Node... nodes) * * @see Node#Node(HttpHost) */ - public static org.elasticsearch.client.RestClientBuilder builder(HttpHost... hosts) { + public static RestClientBuilder builder(HttpHost... hosts) { if (hosts == null || hosts.length == 0) { throw new IllegalArgumentException("hosts must not be null nor empty"); } List nodes = Arrays.stream(hosts).map(Node::new).collect(Collectors.toList()); - return new org.elasticsearch.client.RestClientBuilder(nodes); + return new RestClientBuilder(nodes); } /** @@ -304,16 +296,16 @@ public boolean isRunning() { * @return the response returned by Elasticsearch * @throws IOException in case of a problem or the connection was aborted * @throws ClientProtocolException in case of an http protocol error - * @throws org.elasticsearch.client.ResponseException in case Elasticsearch responded with a status code that indicated an + * @throws ResponseException in case Elasticsearch responded with a status code that indicated an * error */ - public org.elasticsearch.client.Response performRequest(org.elasticsearch.client.Request request) throws IOException { + public ESResponse performRequest(ESRequest request) throws IOException { InternalRequest internalRequest = new InternalRequest(request); return performRequest(nextNodes(), internalRequest, null); } - private org.elasticsearch.client.Response performRequest(final Iterator nodes, final InternalRequest request, - Exception previousException) + private ESResponse performRequest(final Iterator nodes, final InternalRequest request, + Exception previousException) throws IOException { RequestContext context = request.createContextForNextAttempt(nodes.next()); ClassicHttpResponse httpResponse; @@ -322,7 +314,7 @@ private org.elasticsearch.client.Response performRequest(final Iterator no context.asyncResponseConsumer, context.context, null).get(); } catch (Exception e) { - org.elasticsearch.client.RequestLogger.logFailedRequest(logger, request.httpRequest, context.node, e); + RequestLogger.logFailedRequest(logger, request.httpRequest, context.node, e); onFailure(context.node); Exception cause = extractAndWrapCause(e); addSuppressedException(previousException, cause); @@ -352,7 +344,7 @@ private org.elasticsearch.client.Response performRequest(final Iterator no private ResponseOrResponseException convertResponse(InternalRequest request, Node node, ClassicHttpResponse httpResponse) throws IOException { - org.elasticsearch.client.RequestLogger.logResponse(logger, request.httpRequest, node.getHost(), httpResponse); + RequestLogger.logResponse(logger, request.httpRequest, node.getHost(), httpResponse); int statusCode = httpResponse.getCode(); HttpEntity entity = httpResponse.getEntity(); @@ -371,7 +363,7 @@ private ResponseOrResponseException convertResponse(InternalRequest request, Nod } } - org.elasticsearch.client.Response response = new org.elasticsearch.client.Response(new RequestLine(request.httpRequest), node.getHost(), httpResponse); + ESResponse response = new ESResponse(new RequestLine(request.httpRequest), node.getHost(), httpResponse); if (isCorrectServerResponse(statusCode)) { onResponse(node); if (request.warningsHandler.warningsShouldFailRequest(response.getWarnings())) { @@ -379,7 +371,7 @@ private ResponseOrResponseException convertResponse(InternalRequest request, Nod } return new ResponseOrResponseException(response); } - org.elasticsearch.client.ResponseException responseException = new org.elasticsearch.client.ResponseException(response); + ResponseException responseException = new ResponseException(response); if (isRetryStatus(statusCode)) { // mark host dead and retry against next one onFailure(node); @@ -393,7 +385,7 @@ private ResponseOrResponseException convertResponse(InternalRequest request, Nod /** * Sends a request to the Elasticsearch cluster that the client points to. * The request is executed asynchronously and the provided - * {@link org.elasticsearch.client.ResponseListener} gets notified upon request completion or + * {@link ResponseListener} gets notified upon request completion or * failure. Selects a host out of the provided ones in a round-robin * fashion. Failing hosts are marked dead and retried after a certain * amount of time (minimum 1 minute, maximum 30 minutes), depending on how @@ -403,10 +395,10 @@ private ResponseOrResponseException convertResponse(InternalRequest request, Nod * them does, in which case an {@link IOException} will be thrown. * * @param request the request to perform - * @param responseListener the {@link org.elasticsearch.client.ResponseListener} to notify when the + * @param responseListener the {@link ResponseListener} to notify when the * request is completed or fails */ - public org.elasticsearch.client.Cancellable performRequestAsync(org.elasticsearch.client.Request request, org.elasticsearch.client.ResponseListener responseListener) { + public Cancellable performRequestAsync(ESRequest request, ResponseListener responseListener) { try { FailureTrackingResponseListener failureTrackingResponseListener = new FailureTrackingResponseListener(responseListener); @@ -415,7 +407,7 @@ public org.elasticsearch.client.Cancellable performRequestAsync(org.elasticsearc return internalRequest.cancellable; } catch (Exception e) { responseListener.onFailure(e); - return org.elasticsearch.client.Cancellable.NO_OP; + return Cancellable.NO_OP; } } @@ -452,7 +444,7 @@ public void completed(ClassicHttpResponse httpResponse) { @Override public void failed(Exception failure) { try { - org.elasticsearch.client.RequestLogger.logFailedRequest(logger, request.httpRequest, context.node, + RequestLogger.logFailedRequest(logger, request.httpRequest, context.node, failure); onFailure(context.node); if (isRetryableException(failure) && nodes.hasNext()) { @@ -468,7 +460,7 @@ public void failed(Exception failure) { @Override public void cancelled() { - listener.onDefinitiveFailure(org.elasticsearch.client.Cancellable.newCancellationException()); + listener.onDefinitiveFailure(Cancellable.newCancellationException()); } }); // needed to be able to cancel asnyc requests @@ -500,7 +492,7 @@ private Iterator nextNodes() throws IOException { */ static Iterable selectNodes( List nodes, - Map blacklist, + Map blacklist, AtomicInteger lastNodeIndex, NodeSelector nodeSelector ) throws IOException { @@ -513,7 +505,7 @@ static Iterable selectNodes( deadNodes = new ArrayList<>(blacklist.size()); new ArrayList<>(blacklist.size()); for (Node node : nodes) { - org.elasticsearch.client.DeadHostState deadness = blacklist.get(node.getHost()); + DeadHostState deadness = blacklist.get(node.getHost()); if (deadness == null || deadness.shallBeRetried()) { livingNodes.add(node); } else { @@ -574,7 +566,7 @@ static Iterable selectNodes( * Receives as an argument the host that was used for the successful request. */ private void onResponse(Node node) { - org.elasticsearch.client.DeadHostState removedHost = this.blacklist.remove(node.getHost()); + DeadHostState removedHost = this.blacklist.remove(node.getHost()); if (logger.isDebugEnabled() && removedHost != null) { logger.debug("removed [" + node + "] from blacklist"); } @@ -585,9 +577,9 @@ private void onResponse(Node node) { * Receives as an argument the host that was used for the failed attempt. */ private void onFailure(Node node) { - org.elasticsearch.client.DeadHostState previousDeadHostState = blacklist.putIfAbsent( + DeadHostState previousDeadHostState = blacklist.putIfAbsent( node.getHost(), - new org.elasticsearch.client.DeadHostState(org.elasticsearch.client.DeadHostState.DEFAULT_TIME_SUPPLIER) + new DeadHostState(DeadHostState.DEFAULT_TIME_SUPPLIER) ); if (previousDeadHostState == null) { if (logger.isDebugEnabled()) { @@ -595,7 +587,7 @@ private void onFailure(Node node) { } } else { blacklist.replace(node.getHost(), previousDeadHostState, - new org.elasticsearch.client.DeadHostState(previousDeadHostState)); + new DeadHostState(previousDeadHostState)); if (logger.isDebugEnabled()) { logger.debug("updated [" + node + "] already in blacklist"); } @@ -648,10 +640,10 @@ private static void addSuppressedException(Exception suppressedException, Except private static HttpUriRequestBase createHttpRequest(String method, URI uri, HttpEntity entity, boolean compressionEnabled) { switch (method.toUpperCase(Locale.ROOT)) { - case org.elasticsearch.client.HttpDeleteWithEntity.METHOD_NAME: - return addRequestBody(new org.elasticsearch.client.HttpDeleteWithEntity(uri), entity, compressionEnabled); - case org.elasticsearch.client.HttpGetWithEntity.METHOD_NAME: - return addRequestBody(new org.elasticsearch.client.HttpGetWithEntity(uri), entity, compressionEnabled); + case HttpDeleteWithEntity.METHOD_NAME: + return addRequestBody(new HttpDeleteWithEntity(uri), entity, compressionEnabled); + case HttpGetWithEntity.METHOD_NAME: + return addRequestBody(new HttpGetWithEntity(uri), entity, compressionEnabled); case HttpHead.METHOD_NAME: return addRequestBody(new HttpHead(uri), entity, compressionEnabled); case HttpOptions.METHOD_NAME: @@ -690,7 +682,7 @@ private static HttpUriRequestBase addRequestBody(HttpUriRequestBase httpRequest, private static boolean canHaveBody(HttpRequest httpRequest) { return httpRequest.getMethod().contains("PUT") || httpRequest.getMethod().contains("POST") || httpRequest.getMethod().contains("PATCH") || - httpRequest instanceof org.elasticsearch.client.HttpDeleteWithEntity || httpRequest instanceof org.elasticsearch.client.HttpGetWithEntity; + httpRequest instanceof HttpDeleteWithEntity || httpRequest instanceof HttpGetWithEntity; } static URI buildUri(String pathPrefix, String path, Map params) { @@ -727,7 +719,7 @@ static URI buildUri(String pathPrefix, String path, Map params) * only when we got a response (successful or not to be retried) or there are no hosts to retry against. */ static class FailureTrackingResponseListener { - private final org.elasticsearch.client.ResponseListener responseListener; + private final ResponseListener responseListener; private volatile Exception exception; FailureTrackingResponseListener(ResponseListener responseListener) { @@ -737,7 +729,7 @@ static class FailureTrackingResponseListener { /** * Notifies the caller of a response through the wrapped listener */ - void onSuccess(org.elasticsearch.client.Response response) { + void onSuccess(ESResponse response) { responseListener.onSuccess(response); } @@ -777,9 +769,9 @@ public void onFailure(Node node) { */ private static class DeadNode implements Comparable { final Node node; - final org.elasticsearch.client.DeadHostState deadness; + final DeadHostState deadness; - DeadNode(Node node, org.elasticsearch.client.DeadHostState deadness) { + DeadNode(Node node, DeadHostState deadness) { this.node = node; this.deadness = deadness; } @@ -823,12 +815,12 @@ public void remove() { } private class InternalRequest { - private final org.elasticsearch.client.Request request; + private final ESRequest request; private final HttpUriRequestBase httpRequest; - private final org.elasticsearch.client.Cancellable cancellable; + private final Cancellable cancellable; private final WarningsHandler warningsHandler; - InternalRequest(Request request) { + InternalRequest(ESRequest request) { this.request = request; Map params = new HashMap<>(request.getParameters()); params.putAll(request.getOptions().getParameters()); @@ -860,8 +852,8 @@ private void setHeaders(HttpRequest req, Collection

requestHeaders) { req.addHeader("Accept-Encoding", "gzip"); } if (metaHeaderEnabled) { - if (!req.containsHeader(org.elasticsearch.client.RestClientBuilder.META_HEADER_NAME)) { - req.setHeader(org.elasticsearch.client.RestClientBuilder.META_HEADER_NAME, org.elasticsearch.client.RestClientBuilder.META_HEADER_VALUE); + if (!req.containsHeader(RestClientBuilder.META_HEADER_NAME)) { + req.setHeader(RestClientBuilder.META_HEADER_NAME, RestClientBuilder.META_HEADER_VALUE); } } else { req.removeHeaders(RestClientBuilder.META_HEADER_NAME); @@ -908,10 +900,10 @@ private static class RequestContext { } private static class ResponseOrResponseException { - private final org.elasticsearch.client.Response response; - private final org.elasticsearch.client.ResponseException responseException; + private final ESResponse response; + private final ResponseException responseException; - ResponseOrResponseException(Response response) { + ResponseOrResponseException(ESResponse response) { this.response = Objects.requireNonNull(response); this.responseException = null; } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RestClientBuilder.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilder.java similarity index 97% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RestClientBuilder.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilder.java index fee7ff220..4c8000a1b 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/RestClientBuilder.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilder.java @@ -17,9 +17,11 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client; +package co.elastic.clients.transport.rest5_client.low_level; +import co.elastic.clients.transport.rest5_client.low_level.node.Node; +import co.elastic.clients.transport.rest5_client.low_level.node.selector.NodeSelector; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; @@ -30,9 +32,6 @@ import org.apache.hc.core5.http.nio.ssl.BasicClientTlsStrategy; import org.apache.hc.core5.util.Timeout; import org.apache.hc.core5.util.VersionInfo; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.node.Node; -import org.elasticsearch.client.node.selector.NodeSelector; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -46,7 +45,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; -import static org.elasticsearch.client.LanguageRuntimeVersions.getRuntimeMetadata; +import static co.elastic.clients.transport.rest5_client.low_level.LanguageRuntimeVersions.getRuntimeMetadata; /** * Helps creating a new {@link RestClient}. Allows to set the most common http client configuration options diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/WarningFailureException.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/WarningFailureException.java similarity index 75% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/WarningFailureException.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/WarningFailureException.java index 31c373cc6..e0e8dfbbf 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/WarningFailureException.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/WarningFailureException.java @@ -17,18 +17,14 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client; - -import org.elasticsearch.client.Response; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; +package co.elastic.clients.transport.rest5_client.low_level; import java.io.IOException; -import static org.elasticsearch.client.ResponseException.buildMessage; +import static co.elastic.clients.transport.rest5_client.low_level.ResponseException.buildMessage; /** - * This exception is used to indicate that one or more {@link Response#getWarnings()} exist + * This exception is used to indicate that one or more {@link ESResponse#getWarnings()} exist * and is typically used when the {@link RestClient} is set to fail by setting * {@link RestClientBuilder#setStrictDeprecationMode(boolean)} to `true`. */ @@ -36,9 +32,9 @@ // if the exception is not of type ElasticsearchException or RuntimeException it will be wrapped in a UncategorizedExecutionException public final class WarningFailureException extends RuntimeException { - private final Response response; + private final ESResponse response; - public WarningFailureException(Response response) throws IOException { + public WarningFailureException(ESResponse response) throws IOException { super(buildMessage(response)); this.response = response; } @@ -54,9 +50,9 @@ public WarningFailureException(Response response) throws IOException { } /** - * Returns the {@link Response} that caused this exception to be thrown. + * Returns the {@link ESResponse} that caused this exception to be thrown. */ - public Response getResponse() { + public ESResponse getResponse() { return response; } } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/WarningsHandler.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/WarningsHandler.java similarity index 95% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/WarningsHandler.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/WarningsHandler.java index 3a60e0705..d79854763 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/WarningsHandler.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/WarningsHandler.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client; +package co.elastic.clients.transport.rest5_client.low_level; import java.util.List; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/BasicAsyncResponseConsumer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/BasicAsyncResponseConsumer.java similarity index 96% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/BasicAsyncResponseConsumer.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/BasicAsyncResponseConsumer.java index 6c3bae2f1..da7ae514d 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/BasicAsyncResponseConsumer.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/BasicAsyncResponseConsumer.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client.consumer; +package co.elastic.clients.transport.rest5_client.low_level.consumer; import org.apache.hc.core5.http.ClassicHttpResponse; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/BufferedByteConsumer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/BufferedByteConsumer.java similarity index 93% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/BufferedByteConsumer.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/BufferedByteConsumer.java index 841c59eb4..2ad0f046d 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/BufferedByteConsumer.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/BufferedByteConsumer.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client.consumer; +package co.elastic.clients.transport.rest5_client.low_level.consumer; import org.apache.hc.core5.http.ContentTooLongException; import org.apache.hc.core5.http.ContentType; @@ -26,7 +26,7 @@ import java.nio.ByteBuffer; -import static org.elasticsearch.client.utils.Constants.DEFAULT_BUFFER_INITIAL_CAPACITY; +import static co.elastic.clients.transport.rest5_client.low_level.utils.Constants.DEFAULT_BUFFER_INITIAL_CAPACITY; public class BufferedByteConsumer extends AbstractBinAsyncEntityConsumer { diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/HttpAsyncResponseConsumerFactory.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/HttpAsyncResponseConsumerFactory.java similarity index 93% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/HttpAsyncResponseConsumerFactory.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/HttpAsyncResponseConsumerFactory.java index 1d962aafc..1d94ca171 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/consumer/HttpAsyncResponseConsumerFactory.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/HttpAsyncResponseConsumerFactory.java @@ -16,13 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client.consumer; +package co.elastic.clients.transport.rest5_client.low_level.consumer; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.nio.AsyncResponseConsumer; import org.apache.hc.core5.http.nio.support.AbstractAsyncResponseConsumer; -import static org.elasticsearch.client.utils.Constants.DEFAULT_BUFFER_LIMIT; +import static co.elastic.clients.transport.rest5_client.low_level.utils.Constants.DEFAULT_BUFFER_LIMIT; /** * Factory used to create instances of {@link AsyncResponseConsumer}. Each request retry needs its own diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/Node.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/Node.java similarity index 98% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/Node.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/Node.java index 9df6c3eff..32ec1e845 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/Node.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/Node.java @@ -17,10 +17,10 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client.node; +package co.elastic.clients.transport.rest5_client.low_level.node; +import co.elastic.clients.transport.rest5_client.low_level.node.selector.NodeSelector; import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.node.selector.NodeSelector; import java.util.List; import java.util.Map; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/HasAttributeNodeSelector.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/HasAttributeNodeSelector.java similarity index 93% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/HasAttributeNodeSelector.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/HasAttributeNodeSelector.java index df3beba49..20062ad95 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/HasAttributeNodeSelector.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/HasAttributeNodeSelector.java @@ -17,9 +17,9 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client.node.selector; +package co.elastic.clients.transport.rest5_client.low_level.node.selector; -import org.elasticsearch.client.node.Node; +import co.elastic.clients.transport.rest5_client.low_level.node.Node; import java.util.Iterator; import java.util.List; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/NodeSelector.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/NodeSelector.java similarity index 91% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/NodeSelector.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/NodeSelector.java index 2a7d5500e..1231e7785 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/NodeSelector.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/NodeSelector.java @@ -17,11 +17,11 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client.node.selector; +package co.elastic.clients.transport.rest5_client.low_level.node.selector; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.node.Node; +import co.elastic.clients.transport.rest5_client.low_level.RestClient; +import co.elastic.clients.transport.rest5_client.low_level.RestClientBuilder; +import co.elastic.clients.transport.rest5_client.low_level.node.Node; import java.util.Iterator; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/PreferHasAttributeNodeSelector.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/PreferHasAttributeNodeSelector.java similarity index 95% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/PreferHasAttributeNodeSelector.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/PreferHasAttributeNodeSelector.java index d860a3753..91a69977a 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/node/selector/PreferHasAttributeNodeSelector.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/PreferHasAttributeNodeSelector.java @@ -17,9 +17,9 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level_client.node.selector; +package co.elastic.clients.transport.rest5_client.low_level.node.selector; -import org.elasticsearch.client.node.Node; +import co.elastic.clients.transport.rest5_client.low_level.node.Node; import java.util.Iterator; import java.util.List; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/producer/BasicAsyncEntityProducer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/producer/BasicAsyncEntityProducer.java similarity index 94% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/producer/BasicAsyncEntityProducer.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/producer/BasicAsyncEntityProducer.java index c1732071f..40250139a 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/producer/BasicAsyncEntityProducer.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/producer/BasicAsyncEntityProducer.java @@ -1,4 +1,4 @@ -package co.elastic.clients.transport.rest5_client.low_level_client.producer; +package co.elastic.clients.transport.rest5_client.low_level.producer; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.nio.AsyncEntityProducer; @@ -13,7 +13,7 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicReference; -import static org.elasticsearch.client.utils.Constants.DEFAULT_BUFFER_INITIAL_CAPACITY; +import static co.elastic.clients.transport.rest5_client.low_level.utils.Constants.DEFAULT_BUFFER_INITIAL_CAPACITY; /** * Basic implementation of {@link AsyncEntityProducer} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/utils/Constants.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/utils/Constants.java similarity index 73% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/utils/Constants.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/utils/Constants.java index 6089a2f38..f731168de 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level_client/utils/Constants.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/utils/Constants.java @@ -1,4 +1,4 @@ -package co.elastic.clients.transport.rest5_client.low_level_client.utils; +package co.elastic.clients.transport.rest5_client.low_level.utils; public class Constants { // default buffer limit is 100MB diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java index 842a45c62..707c23dcc 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java @@ -102,6 +102,12 @@ public Function, Boolean> onWarnings() { return warnings -> options.getWarningsHandler().warningsShouldFailRequest(warnings); } + @Override + public void updateToken(String token) { + // TODO not many choices here + throw new UnsupportedOperationException("Operation unsupported, use rest5 client"); + } + @Override public boolean keepResponseBodyOnException() { return this.keepResponseBodyOnException; diff --git a/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java b/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java deleted file mode 100644 index b3a6befee..000000000 --- a/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.documentation; - -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.TransportOptions; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.function.Function; - -/** - * A transport implementation that always returns the same result. Used for doc snippets where we can to check - * compilation and do very simple tests. - */ -public class DocTestsTransport implements ElasticsearchTransport { - - private final JsonpMapper mapper = new JacksonJsonpMapper( - new ObjectMapper().setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE) - ); - - private final ThreadLocal result = new ThreadLocal<>(); - - private final TransportOptions options = new TransportOptions() { - @Override - public Collection> headers() { - return Collections.emptyList(); - } - - @Override - public Map queryParameters() { - return Collections.emptyMap(); - } - - @Override - public Function, Boolean> onWarnings() { - return null; - } - - @Override - public void updateToken(String token) { - - } - - @Override - public boolean keepResponseBodyOnException() { - return false; - } - - @Override - public Builder toBuilder() { - return null; - } - }; - - public void setResult(Object result) { - this.result.set(result); - } - - @Override - @SuppressWarnings("unchecked") - public ResponseT performRequest( - RequestT request, - Endpoint endpoint, - @Nullable TransportOptions options - ) throws IOException { - return (ResponseT) result.get(); - } - - @Override - @SuppressWarnings("unchecked") - public CompletableFuture performRequestAsync(RequestT request, Endpoint endpoint, @Nullable TransportOptions options) { - CompletableFuture future = new CompletableFuture<>(); - future.complete((ResponseT) result.get()); - return future; - } - - @Override - public JsonpMapper jsonpMapper() { - return mapper; - } - - @Override - public TransportOptions options() { - return options; - } - - @Override - public void close() throws IOException { - } -} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/api_conventions/ApiConventionsTest.java b/java-client/src/test/java/co/elastic/clients/documentation/api_conventions/ApiConventionsTest.java deleted file mode 100644 index 17ac641c6..000000000 --- a/java-client/src/test/java/co/elastic/clients/documentation/api_conventions/ApiConventionsTest.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.documentation.api_conventions; - -import co.elastic.clients.documentation.DocTestsTransport; -import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._types.NodeStatistics; -import co.elastic.clients.elasticsearch._types.SortOrder; -import co.elastic.clients.elasticsearch._types.aggregations.Aggregation; -import co.elastic.clients.elasticsearch._types.query_dsl.Query; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.indices.Alias; -import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; -import co.elastic.clients.elasticsearch.indices.CreateIndexResponse; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.util.ApiTypeHelper; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import jakarta.json.JsonArray; -import jakarta.json.JsonObject; -import jakarta.json.JsonValue; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.StringReader; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ApiConventionsTest extends Assertions { - - private static class SomeApplicationData {} - - private DocTestsTransport transport = new DocTestsTransport(); - Logger logger = LoggerFactory.getLogger(this.getClass()); - - public void blockingAndAsync() throws Exception { - - //tag::blocking-and-async - // Synchronous blocking client - ElasticsearchClient client = new ElasticsearchClient(transport); - - if (client.exists(b -> b.index("products").id("foo")).value()) { - logger.info("product exists"); - } - - // Asynchronous non-blocking client - ElasticsearchAsyncClient asyncClient = - new ElasticsearchAsyncClient(transport); - - asyncClient - .exists(b -> b.index("products").id("foo")) - .whenComplete((response, exception) -> { - if (exception != null) { - logger.error("Failed to index", exception); - } else { - logger.info("Product exists"); - } - }); - //end::blocking-and-async - - } - - public void builders() throws Exception { - ElasticsearchClient client = new ElasticsearchClient(transport); - - //tag::builders - CreateIndexResponse createResponse = client.indices().create( - new CreateIndexRequest.Builder() - .index("my-index") - .aliases("foo", - new Alias.Builder().isWriteIndex(true).build() - ) - .build() - ); - //end::builders - } - - public void builderLambdas() throws Exception { - ElasticsearchClient client = new ElasticsearchClient(transport); - - //tag::builder-lambdas - CreateIndexResponse createResponse = client.indices() - .create(createIndexBuilder -> createIndexBuilder - .index("my-index") - .aliases("foo", aliasBuilder -> aliasBuilder - .isWriteIndex(true) - ) - ); - //end::builder-lambdas - } - - public void builderLambdasShort() throws Exception { - ElasticsearchClient client = new ElasticsearchClient(transport); - - //tag::builder-lambdas-short - CreateIndexResponse createResponse = client.indices() - .create(c -> c - .index("my-index") - .aliases("foo", a -> a - .isWriteIndex(true) - ) - ); - //end::builder-lambdas-short - } - - public void builderIntervals() throws Exception { - ObjectMapper mapper = new ObjectMapper(); - mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); - ElasticsearchClient client = new ElasticsearchClient(transport); - - //tag::builder-intervals - SearchResponse results = client - .search(b0 -> b0 - .query(b1 -> b1 - .intervals(b2 -> b2 - .field("my_text") - .allOf(b3 -> b3 - .ordered(true) - .intervals(b4 -> b4 - .match(b5 -> b5 - .query("my favorite food") - .maxGaps(0) - .ordered(true) - ) - ) - .intervals(b4 -> b4 - .anyOf(b5 -> b5 - .intervals(b6 -> b6 - .match(b7 -> b7 - .query("hot water") - ) - ) - .intervals(b6 -> b6 - .match(b7 -> b7 - .query("cold porridge") - ) - ) - ) - ) - ) - ) - ), - SomeApplicationData.class // <1> - ); - //end::builder-intervals - } - - @Test - public void variantCreation() { - //tag::variant-creation - Query query = new Query.Builder() - .term(t -> t // <1> - .field("name") // <2> - .value(v -> v.stringValue("foo")) - ) - .build(); // <3> - //end::variant-creation - - //tag::variant-navigation - assertEquals("foo", query.term().value().stringValue()); - //end::variant-navigation - - //tag::variant-kind - if (query.isTerm()) { // <1> - doSomething(query.term()); - } - - switch(query._kind()) { // <2> - case Term: - doSomething(query.term()); - break; - case Intervals: - doSomething(query.intervals()); - break; - default: - doSomething(query._kind(), query._get()); // <3> - } - //end::variant-kind - } - - //tag::custom-variant-types - public static class SphereDistanceAggregate { - private final List buckets; - @JsonCreator - public SphereDistanceAggregate( - @JsonProperty("buckets") List buckets - ) { - this.buckets = buckets; - } - public List buckets() { - return buckets; - }; - } - - public static class Bucket { - private final double key; - private final double docCount; - @JsonCreator - public Bucket( - @JsonProperty("key") double key, - @JsonProperty("doc_count") double docCount) { - this.key = key; - this.docCount = docCount; - } - public double key() { - return key; - } - public double docCount() { - return docCount; - } - } - //end::custom-variant-types - - @Test - public void customVariants() throws Exception { - - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0},\n" + - "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]},\n" + - "\"aggregations\":{\"sphere-distance#neighbors\":{\"buckets\":[{\"key\": 1.0,\"doc_count\":1}]}}}"; - - transport.setResult(SearchResponse.of(b -> b.withJson( - transport.jsonpMapper().jsonProvider().createParser(new StringReader(json)), - transport.jsonpMapper()) - )); - - //tag::custom-variant-creation - Map params = new HashMap<>(); // <1> - params.put("interval", 10); - params.put("scale", "log"); - params.put("origin", new Double[]{145.0, 12.5, 1649.0}); - - SearchRequest request = SearchRequest.of(r -> r - .index("stars") - .aggregations("neighbors", agg -> agg - ._custom("sphere-distance", params) // <2> - ) - ); - //end::custom-variant-creation - - { - //tag::custom-variant-navigation-json - SearchResponse response = esClient.search(request, Void.class); // <1> - - JsonData neighbors = response - .aggregations().get("neighbors") - ._custom(); // <2> - - JsonArray buckets = neighbors.toJson() // <3> - .asJsonObject() - .getJsonArray("buckets"); - - for (JsonValue item : buckets) { - JsonObject bucket = item.asJsonObject(); - double key = bucket.getJsonNumber("key").doubleValue(); - double docCount = bucket.getJsonNumber("doc_count").longValue(); - doSomething(key, docCount); - } - //end::custom-variant-navigation-json - } - - { - //tag::custom-variant-navigation-typed - SearchResponse response = esClient.search(request, Void.class); - - SphereDistanceAggregate neighbors = response - .aggregations().get("neighbors") - ._custom() - .to(SphereDistanceAggregate.class); // <1> - - for (Bucket bucket : neighbors.buckets()) { - doSomething(bucket.key(), bucket.docCount()); - } - //end::custom-variant-navigation-typed - } - } - - @Test - public void collections() { - //tag::collections-list - // Prepare a list of index names - List names = Arrays.asList("idx-a", "idx-b", "idx-c"); - - // Prepare cardinality aggregations for fields "foo" and "bar" - Map cardinalities = new HashMap<>(); - cardinalities.put("foo-count", Aggregation.of(a -> a.cardinality(c -> c.field("foo")))); - cardinalities.put("bar-count", Aggregation.of(a -> a.cardinality(c -> c.field("bar")))); - - // Prepare an aggregation that computes the average of the "size" field - final Aggregation avgSize = Aggregation.of(a -> a.avg(v -> v.field("size"))); - - SearchRequest search = SearchRequest.of(r -> r - // Index list: - // - add all elements of a list - .index(names) - // - add a single element - .index("idx-d") - // - add a vararg list of elements - .index("idx-e", "idx-f", "idx-g") - - // Sort order list: add elements defined by builder lambdas - .sort(s -> s.field(f -> f.field("foo").order(SortOrder.Asc))) - .sort(s -> s.field(f -> f.field("bar").order(SortOrder.Desc))) - - // Aggregation map: - // - add all entries of an existing map - .aggregations(cardinalities) - // - add a key/value entry - .aggregations("avg-size", avgSize) - // - add a key/value defined by a builder lambda - .aggregations("price-histogram", - a -> a.histogram(h -> h.field("price"))) - ); - //end::collections-list - - } - - @Test - public void optionalCollections() { - //tag::optional-collections - NodeStatistics stats = NodeStatistics.of(b -> b - .total(1) - .failed(0) - .successful(1) - ); - - // The `failures` list was not provided. - // - it's not null - assertNotNull(stats.failures()); - // - it's empty - assertEquals(0, stats.failures().size()); - // - and if needed we can know it was actually not defined - assertFalse(ApiTypeHelper.isDefined(stats.failures())); - //end::optional-collections - } - - private void doSomething(Object... o) { - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/api_conventions/LoadingJsonTest.java b/java-client/src/test/java/co/elastic/clients/documentation/api_conventions/LoadingJsonTest.java deleted file mode 100644 index f0a579ea6..000000000 --- a/java-client/src/test/java/co/elastic/clients/documentation/api_conventions/LoadingJsonTest.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.documentation.api_conventions; - -import co.elastic.clients.documentation.DocTestsTransport; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; -import co.elastic.clients.elasticsearch._types.aggregations.CalendarInterval; -import co.elastic.clients.elasticsearch.core.IndexRequest; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; -import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; -import co.elastic.clients.elasticsearch.indices.CreateIndexResponse; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.json.JsonData; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -public class LoadingJsonTest extends ModelTestCase { - - private final DocTestsTransport transport = new DocTestsTransport(); - private final ElasticsearchClient client = new ElasticsearchClient(transport); - - private static final SearchResponse searchResponse = SearchResponse.of(b -> b - .aggregations(new HashMap<>()) - .took(0) - .timedOut(false) - .hits(h -> h - .total(t -> t.value(0).relation(TotalHitsRelation.Eq)) - .hits(new ArrayList<>()) - ) - .shards(s -> s - .total(1) - .failed(0) - .successful(1) - ) - ); - - @Test - public void loadIndexDefinition() throws IOException { - - transport.setResult(CreateIndexResponse.of(b -> b - .index("some-index") - .shardsAcknowledged(true) - .acknowledged(true) - )); - - //tag::load-index - InputStream input = this.getClass() - .getResourceAsStream("some-index.json"); //<1> - - CreateIndexRequest req = CreateIndexRequest.of(b -> b - .index("some-index") - .withJson(input) //<2> - ); - - boolean created = client.indices().create(req).acknowledged(); - //end::load-index - } - - @Disabled - @Test - public void ingestDocument() throws IOException { - - File dataDir = null; - - //tag::ingest-data - FileReader file = new FileReader(new File(dataDir, "document-1.json")); - - IndexRequest req; //<1> - - req = IndexRequest.of(b -> b - .index("some-index") - .withJson(file) - ); - - client.index(req); - //end::ingest-data - } - - @Test - public void query1() throws IOException { - transport.setResult(searchResponse); - - //tag::query - Reader queryJson = new StringReader( - "{" + - " \"query\": {" + - " \"range\": {" + - " \"@timestamp\": {" + - " \"gt\": \"now-1w\"" + - " }" + - " }" + - " }" + - "}"); - - SearchRequest aggRequest = SearchRequest.of(b -> b - .withJson(queryJson) //<1> - .aggregations("max-cpu", a1 -> a1 //<2> - .dateHistogram(h -> h - .field("@timestamp") - .calendarInterval(CalendarInterval.Hour) - ) - .aggregations("max", a2 -> a2 - .max(m -> m.field("host.cpu.usage")) - ) - ) - .size(0) - ); - - Map aggs = client - .search(aggRequest, Void.class) //<3> - .aggregations(); - //end::query - } - - @Test - public void query2() throws IOException { - transport.setResult(searchResponse); - - //tag::query-and-agg - Reader queryJson = new StringReader( - "{" + - " \"query\": {" + - " \"range\": {" + - " \"@timestamp\": {" + - " \"gt\": \"now-1w\"" + - " }" + - " }" + - " }," + - " \"size\": 100" + //<1> - "}"); - - Reader aggregationJson = new StringReader( - "{" + - " \"size\": 0, " + //<2> - " \"aggregations\": {" + - " \"hours\": {" + - " \"date_histogram\": {" + - " \"field\": \"@timestamp\"," + - " \"interval\": \"hour\"" + - " }," + - " \"aggregations\": {" + - " \"max-cpu\": {" + - " \"max\": {" + - " \"field\": \"host.cpu.usage\"" + - " }" + - " }" + - " }" + - " }" + - " }" + - "}"); - - SearchRequest aggRequest = SearchRequest.of(b -> b - .withJson(queryJson) //<3> - .withJson(aggregationJson) //<4> - .ignoreUnavailable(true) //<5> - ); - - Map aggs = client - .search(aggRequest, Void.class) - .aggregations(); - //end::query-and-agg - } -} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java b/java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java deleted file mode 100644 index 255fc79ff..000000000 --- a/java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * 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. - */ - -//TODO rewrite -package co.elastic.clients.documentation.getting_started; - -public class ConnectingTest { - - /*@Disabled // we don't have a running ES - @Test - public void createClient() throws Exception { - //tag::create-client - // URL and API key - String serverUrl = "https://localhost:9200"; - String apiKey = "VnVhQ2ZHY0JDZGJrU..."; - - // Create the low-level client - RestClient restClient = RestClient - .builder(HttpHost.create(serverUrl)) - .setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "ApiKey " + apiKey) - }) - .build(); - - // Create the transport with a Jackson mapper - ElasticsearchTransport transport = new RestClientTransport( - restClient, new JacksonJsonpMapper()); - - // And create the API client - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - // Use the client... - - // Close the client, also closing the underlying transport object and network connections. - esClient.close(); - //end::create-client - - //tag::first-request - SearchResponse search = esClient.search(s -> s - .index("products") - .query(q -> q - .term(t -> t - .field("name") - .value(v -> v.stringValue("bicycle")) - )), - Product.class); - - for (Hit hit: search.hits().hits()) { - processProduct(hit.source()); - } - //end::first-request - } - - @Disabled // we don't have a running ES - @Test - public void createClientWithOpenTelemetry() throws Exception { - //tag::create-client-otel - // URL and API key - String serverUrl = "https://localhost:9200"; - String apiKey = "VnVhQ2ZHY0JDZGJrU..."; - - // Create the low-level client - RestClient restClient = RestClient - .builder(HttpHost.create(serverUrl)) - .setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "ApiKey " + apiKey) - }) - .build(); - // Create and configure custom OpenTelemetry instance - OpenTelemetry customOtel = OpenTelemetrySdk.builder().build(); - - // Create Instrumentation instance using the custom OpenTelemetry instance - // Second constructor argument allows to enable/disable search body capturing - OpenTelemetryForElasticsearch esOtelInstrumentation = - new OpenTelemetryForElasticsearch(customOtel, false); - - // Create the transport with the custom Instrumentation instance - ElasticsearchTransport transport = new RestClientTransport( - restClient, new JacksonJsonpMapper(), null, esOtelInstrumentation - ); - - // And create the API client - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - // Use the client... - - // Close the client, also closing the underlying transport object and network connections. - esClient.close(); - //end::create-client-otel - } - - @Disabled // we don't have a running ES - @Test - public void createSecureClientCert() throws Exception { - - // Create the low-level client - String host = "localhost"; - int port = 9200; - String login = "elastic"; - String password = "changeme"; - - //tag::create-secure-client-cert - File certFile = new File("/path/to/http_ca.crt"); - - SSLContext sslContext = TransportUtils - .sslContextFromHttpCaCrt(certFile); // <1> - - BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); // <2> - credsProv.setCredentials( - AuthScope.ANY, new UsernamePasswordCredentials(login, password) - ); - - RestClient restClient = RestClient - .builder(new HttpHost(host, port, "https")) // <3> - .setHttpClientConfigCallback(hc -> hc - .setSSLContext(sslContext) // <4> - .setDefaultCredentialsProvider(credsProv) - ) - .build(); - - // Create the transport and the API client - ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - // Use the client... - - // Close the client, also closing the underlying transport object and network connections. - esClient.close(); - //end::create-secure-client-cert - } - - @Disabled // we don't have a running ES - @Test - public void createSecureClientFingerPrint() throws Exception { - - // Create the low-level client - String host = "localhost"; - int port = 9200; - String login = "elastic"; - String password = "changeme"; - - //tag::create-secure-client-fingerprint - String fingerprint = ""; - - SSLContext sslContext = TransportUtils - .sslContextFromCaFingerprint(fingerprint); // <1> - - BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); // <2> - credsProv.setCredentials( - AuthScope.ANY, new UsernamePasswordCredentials(login, password) - ); - - RestClient restClient = RestClient - .builder(new HttpHost(host, port, "https")) // <3> - .setHttpClientConfigCallback(hc -> hc - .setSSLContext(sslContext) // <4> - .setDefaultCredentialsProvider(credsProv) - ) - .build(); - - // Create the transport and the API client - ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - // Use the client... - - // Close the client, also closing the underlying transport object and network connections. - esClient.close(); - //end::create-secure-client-fingerprint - } - - private void processProduct(Product p) {}*/ - -} - diff --git a/java-client/src/test/java/co/elastic/clients/documentation/troubleshooting/TroubleShootingTests.java b/java-client/src/test/java/co/elastic/clients/documentation/troubleshooting/TroubleShootingTests.java deleted file mode 100644 index 7c1478244..000000000 --- a/java-client/src/test/java/co/elastic/clients/documentation/troubleshooting/TroubleShootingTests.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.documentation.troubleshooting; - -import co.elastic.clients.documentation.DocTestsTransport; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpMapperFeatures; -import jakarta.json.stream.JsonGenerator; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.StringWriter; -import java.util.Collections; - -public class TroubleShootingTests extends Assertions { - - @Test - public void testMapProperty() { - - SearchResponse searchResponse = new SearchResponse.Builder() - .aggregations( - "price", _2 -> _2 - .avg(_3 -> _3.value(3.14)) - ) - // Required properties on a SearchResponse - .took(1) - .shards(_1 -> _1.successful(1).failed(0).total(1)) - .hits(_1 -> _1 - .total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)) - .hits(Collections.emptyList()) - ) - .timedOut(false) - .build(); - - String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + - "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]},\"aggregations\":{\"avg#price\":{\"value\":3.14}}}"; - - DocTestsTransport transport = new DocTestsTransport(); - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - { - //tag::aggregation-typed-keys - JsonpMapper mapper = esClient._jsonpMapper(); - - StringWriter writer = new StringWriter(); - try (JsonGenerator generator = mapper.jsonProvider().createGenerator(writer)) { - mapper.serialize(searchResponse, generator); - } - String result = writer.toString(); - - // The aggregation property provides the "avg" type and "price" name - assertTrue(result.contains("\"aggregations\":{\"avg#price\":{\"value\":3.14}}}")); - //end::aggregation-typed-keys - } - - { - //tag::aggregation-no-typed-keys - // Create a new mapper with the typed_keys feature disabled - JsonpMapper mapper = esClient._jsonpMapper() - .withAttribute(JsonpMapperFeatures.SERIALIZE_TYPED_KEYS, false); - - StringWriter writer = new StringWriter(); - try (JsonGenerator generator = mapper.jsonProvider().createGenerator(writer)) { - mapper.serialize(searchResponse, generator); - } - String result = writer.toString(); - - // The aggregation only provides the "price" name - assertTrue(result.contains("\"aggregations\":{\"price\":{\"value\":3.14}}}")); - //end::aggregation-no-typed-keys - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/usage/AggregationsTest.java b/java-client/src/test/java/co/elastic/clients/documentation/usage/AggregationsTest.java deleted file mode 100644 index c8635f0b4..000000000 --- a/java-client/src/test/java/co/elastic/clients/documentation/usage/AggregationsTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.documentation.usage; - -import co.elastic.clients.documentation.DocTestsTransport; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._types.aggregations.HistogramBucket; -import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery; -import co.elastic.clients.elasticsearch._types.query_dsl.Query; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.json.JsonData; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; - -public class AggregationsTest extends ModelTestCase { - - private final DocTestsTransport transport = new DocTestsTransport(); - private final ElasticsearchClient esClient = new ElasticsearchClient(transport); - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - private static final SearchResponse searchResponse = SearchResponse.of(b -> b - .aggregations(new HashMap<>()) - .took(0) - .timedOut(false) - .hits(h -> h - .total(t -> t.value(0).relation(TotalHitsRelation.Eq)) - .hits(new ArrayList<>()) - ) - .shards(s -> s - .total(1) - .failed(0) - .successful(1) - ) - .aggregations("price-histogram", a -> a.histogram(h -> h - .buckets(bu -> bu.array(Collections.singletonList(HistogramBucket.of(hb -> hb - .key(50).docCount(1) - )))) - )) - ); - - @Test - public void priceHistogram() throws Exception { - - transport.setResult(searchResponse); - - //tag::price-histo-request - String searchText = "bike"; - - Query query = MatchQuery.of(m -> m - .field("name") - .query(searchText) - )._toQuery(); - - SearchResponse response = esClient.search(b -> b - .index("products") - .size(0) // <1> - .query(query) // <2> - .aggregations("price-histogram", a -> a // <3> - .histogram(h -> h // <4> - .field("price") - .interval(50.0) - ) - ), - Void.class // <5> - ); - //end::price-histo-request - - //tag::price-histo-response - List buckets = response.aggregations() - .get("price-histogram") // <1> - .histogram() // <2> - .buckets().array(); // <3> - - for (HistogramBucket bucket: buckets) { - logger.info("There are " + bucket.docCount() + - " bikes under " + bucket.key()); - } - - //end::price-histo-response - } -} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/usage/IndexingBulkTest.java b/java-client/src/test/java/co/elastic/clients/documentation/usage/IndexingBulkTest.java deleted file mode 100644 index 1e6006978..000000000 --- a/java-client/src/test/java/co/elastic/clients/documentation/usage/IndexingBulkTest.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.documentation.usage; - -import co.elastic.clients.documentation.DocTestsTransport; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._helpers.bulk.BulkIngester; -import co.elastic.clients.elasticsearch._helpers.bulk.BulkListener; -import co.elastic.clients.elasticsearch.core.BulkRequest; -import co.elastic.clients.elasticsearch.core.BulkResponse; -import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.util.BinaryData; -import co.elastic.clients.util.ContentType; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.jupiter.api.Test; - -import java.io.File; -import java.io.FileInputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.TimeUnit; - -public class IndexingBulkTest extends ModelTestCase { - - private final DocTestsTransport transport = new DocTestsTransport(); - private final ElasticsearchClient esClient = new ElasticsearchClient(transport); - - private final Log logger = LogFactory.getLog(this.getClass()); - - BulkResponse result = BulkResponse.of(r -> r - .errors(false) - .items(Collections.emptyList()) - .took(1) - ); - - private List fetchProducts() { - List list = new ArrayList<>(); - list.add(new Product("bk-1", "City Bike", 123.0)); - list.add(new Product("bk-2", "Mountain Bike", 134.0)); - return list; - } - - @Test - public void indexBulk() throws Exception { - transport.setResult(result); - - //tag::bulk-objects - List products = fetchProducts(); - - BulkRequest.Builder br = new BulkRequest.Builder(); - - for (Product product : products) { - br.operations(op -> op //<1> - .index(idx -> idx //<2> - .index("products") //<3> - .id(product.getSku()) - .document(product) - ) - ); - } - - BulkResponse result = esClient.bulk(br.build()); - - // Log errors, if any - if (result.errors()) { - logger.error("Bulk had errors"); - for (BulkResponseItem item: result.items()) { - if (item.error() != null) { - logger.error(item.error().reason()); - } - } - } - //end::bulk-objects - } - - @Test - public void indexBulkJson() throws Exception { - transport.setResult(result); - - File logDir = new File("."); - - //tag::bulk-json - // List json log files in the log directory - File[] logFiles = logDir.listFiles( - file -> file.getName().matches("log-.*\\.json") - ); - - BulkRequest.Builder br = new BulkRequest.Builder(); - - for (File file: logFiles) { - FileInputStream input = new FileInputStream(file); - BinaryData data = BinaryData.of(IOUtils.toByteArray(input), ContentType.APPLICATION_JSON); - - br.operations(op -> op - .index(idx -> idx - .index("logs") - .document(data) - ) - ); - } - //end::bulk-json - } - - @Test - public void useBulkIndexer() throws Exception { - - File logDir = new File("."); - File[] logFiles = logDir.listFiles( - file -> file.getName().matches("log-.*\\.json") - ); - - //tag::bulk-ingester-setup - BulkIngester ingester = BulkIngester.of(b -> b - .client(esClient) // <1> - .maxOperations(100) // <2> - .flushInterval(1, TimeUnit.SECONDS) // <3> - ); - - for (File file: logFiles) { - FileInputStream input = new FileInputStream(file); - BinaryData data = BinaryData.of(IOUtils.toByteArray(input), ContentType.APPLICATION_JSON); - - ingester.add(op -> op // <4> - .index(idx -> idx - .index("logs") - .document(data) - ) - ); - } - - ingester.close(); // <5> - //end::bulk-ingester-setup - - } - - @Test - public void useBulkIndexerWithContext() throws Exception { - - File[] logFiles = new File[]{}; - - //tag::bulk-ingester-context - BulkListener listener = new BulkListener() { // <1> - @Override - public void beforeBulk(long executionId, BulkRequest request, List contexts) { - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, BulkResponse response) { - // The request was accepted, but may contain failed items. - // The "context" list gives the file name for each bulk item. - logger.debug("Bulk request " + executionId + " completed"); - for (int i = 0; i < contexts.size(); i++) { - BulkResponseItem item = response.items().get(i); - if (item.error() != null) { - // Inspect the failure cause - logger.error("Failed to index file " + contexts.get(i) + " - " + item.error().reason()); - } - } - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, Throwable failure) { - // The request could not be sent - logger.debug("Bulk request " + executionId + " failed", failure); - } - }; - - BulkIngester ingester = BulkIngester.of(b -> b - .client(esClient) - .maxOperations(100) - .flushInterval(1, TimeUnit.SECONDS) - .listener(listener) // <2> - ); - - for (File file: logFiles) { - FileInputStream input = new FileInputStream(file); - BinaryData data = BinaryData.of(IOUtils.toByteArray(input), ContentType.APPLICATION_JSON); - - ingester.add(op -> op - .index(idx -> idx - .index("logs") - .document(data) - ), - file.getName() // <3> - ); - } - - ingester.close(); - //end::bulk-ingester-context - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/usage/IndexingTest.java b/java-client/src/test/java/co/elastic/clients/documentation/usage/IndexingTest.java deleted file mode 100644 index 8d2573532..000000000 --- a/java-client/src/test/java/co/elastic/clients/documentation/usage/IndexingTest.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.documentation.usage; - -import co.elastic.clients.documentation.DocTestsTransport; -import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._types.Result; -import co.elastic.clients.elasticsearch.core.IndexRequest; -import co.elastic.clients.elasticsearch.core.IndexResponse; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.json.JsonData; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Reader; -import java.io.StringReader; - -public class IndexingTest extends ModelTestCase { - - private final DocTestsTransport transport = new DocTestsTransport(); - private final ElasticsearchClient esClient = new ElasticsearchClient(transport); - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - IndexResponse result = IndexResponse.of(r -> r - .index("product") - .id("bk-1") - .version(1) - .primaryTerm(1L) - .seqNo(1L) - .result(Result.Created) - .shards(s -> s.total(1).successful(1).failed(0)) - ); - - @Test - @Disabled - public void createIndex() throws Exception { - //tag::create-products-index - esClient.indices().create(c -> c - .index("products") - ); - //end::create-products-index - } - - @Test - @Disabled - public void deleteIndex() throws Exception { - //tag::delete-products-index - esClient.indices().delete(d -> d - .index("products") - ); - //end::delete-products-index - } - - @Test - public void singleDocumentDSL() throws Exception { - - // Stub response - transport.setResult(result); - - //tag::single-doc-dsl - Product product = new Product("bk-1", "City bike", 123.0); - - IndexResponse response = esClient.index(i -> i - .index("products") - .id(product.getSku()) - .document(product) - ); - - logger.info("Indexed with version " + response.version()); - //end::single-doc-dsl - } - - @Test - public void singleDocumentDSLwithOf() throws Exception { - - // Stub response - transport.setResult(result); - - //tag::single-doc-dsl-of - Product product = new Product("bk-1", "City bike", 123.0); - - IndexRequest request = IndexRequest.of(i -> i - .index("products") - .id(product.getSku()) - .document(product) - ); - - IndexResponse response = esClient.index(request); - - logger.info("Indexed with version " + response.version()); - //end::single-doc-dsl-of - } - - @Test - public void singleDocumentBuilder() throws Exception { - - // Stub response - transport.setResult(result); - - //tag::single-doc-builder - Product product = new Product("bk-1", "City bike", 123.0); - - IndexRequest.Builder indexReqBuilder = new IndexRequest.Builder<>(); - indexReqBuilder.index("product"); - indexReqBuilder.id(product.getSku()); - indexReqBuilder.document(product); - - IndexResponse response = esClient.index(indexReqBuilder.build()); - - logger.info("Indexed with version " + response.version()); - //end::single-doc-builder - } - - @Test - public void singleDocumentDSLAsync() throws Exception { - - // Stub response - transport.setResult(result); - - //tag::single-doc-dsl-async - ElasticsearchAsyncClient esAsyncClient = new ElasticsearchAsyncClient(transport); - - Product product = new Product("bk-1", "City bike", 123.0); - - esAsyncClient.index(i -> i - .index("products") - .id(product.getSku()) - .document(product) - ).whenComplete((response, exception) -> { - if (exception != null) { - logger.error("Failed to index", exception); - } else { - logger.info("Indexed with version " + response.version()); - } - }); - //end::single-doc-dsl-async - } - - @Test - public void singleDocumentJson() throws Exception { - // Stub response - transport.setResult(result); - - //tag::single-doc-json - Reader input = new StringReader( - "{'@timestamp': '2022-04-08T13:55:32Z', 'level': 'warn', 'message': 'Some log message'}" - .replace('\'', '"')); - - IndexRequest request = IndexRequest.of(i -> i - .index("logs") - .withJson(input) - ); - - IndexResponse response = esClient.index(request); - - logger.info("Indexed with version " + response.version()); - //end::single-doc-json - - assertEquals("warn", request.document().toJson().asJsonObject().getString("level")); - assertEquals( - "{\"@timestamp\":\"2022-04-08T13:55:32Z\",\"level\":\"warn\",\"message\":\"Some log message\"}", - toJson(request) - ); - } - - @Test - public void deleteDocument() throws Exception { - //tag::single-doc-delete - esClient.delete(d -> d.index("products").id("bk-1")); - //end::single-doc-delete - } - - @Test - @Disabled - public void updateDoc() throws Exception { - //tag::single-doc-update - Product product = new Product("bk-1", "City bike", 123.0); - - esClient.update(u -> u - .index("products") - .id("bk-1") - .upsert(product), - Product.class - ); - //end::single-doc-update - } -} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/usage/Product.java b/java-client/src/test/java/co/elastic/clients/documentation/usage/Product.java deleted file mode 100644 index 29d4c2310..000000000 --- a/java-client/src/test/java/co/elastic/clients/documentation/usage/Product.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.documentation.usage; - -public class Product { - private String sku; - private String name; - private double price; - - public Product() {} - public Product(String sku, String name, double price) { - this.sku = sku; - this.name = name; - this.price = price; - } - - public String getSku() { - return sku; - } - - public void setSku(String sku) { - this.sku = sku; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public double getPrice() { - return this.price; - } - - public void setPrice(double price) { - this.price = price; - } -} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/usage/ReadingTest.java b/java-client/src/test/java/co/elastic/clients/documentation/usage/ReadingTest.java deleted file mode 100644 index 15a6c8ba8..000000000 --- a/java-client/src/test/java/co/elastic/clients/documentation/usage/ReadingTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.documentation.usage; - -import co.elastic.clients.documentation.DocTestsTransport; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.core.GetResponse; -import co.elastic.clients.testkit.ModelTestCase; -import com.fasterxml.jackson.databind.node.ObjectNode; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ReadingTest extends ModelTestCase { - - private final DocTestsTransport transport = new DocTestsTransport(); - private final ElasticsearchClient esClient = new ElasticsearchClient(transport); - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - @Test - public void getById() throws Exception { - - transport.setResult(GetResponse.of(r -> r - .found(true) - .index("products") - .id("bk-1") - .version(1L) - .seqNo(0L) - .primaryTerm(0L) - .source(new Product("bk-1", "City Bike", 123.0)) - )); - - //tag::get-by-id - GetResponse response = esClient.get(g -> g - .index("products") // <1> - .id("bk-1"), - Product.class // <2> - ); - - if (response.found()) { - Product product = response.source(); - logger.info("Product name " + product.getName()); - } else { - logger.info ("Product not found"); - } - //end::get-by-id - - } - - @Test - public void getByIdJson() throws Exception { - - transport.setResult(GetResponse.of(r -> r - .found(true) - .index("products") - .id("bk-1") - .version(1L) - .seqNo(0L) - .primaryTerm(0L) - .source(fromJson("{\"name\":\"City Bike\"}", ObjectNode.class, transport.jsonpMapper())) - )); - - //tag::get-by-id-json - GetResponse response = esClient.get(g -> g - .index("products") - .id("bk-1"), - ObjectNode.class // <1> - ); - - if (response.found()) { - ObjectNode json = response.source(); - String name = json.get("name").asText(); - logger.info("Product name " + name); - } else { - logger.info("Product not found"); - } - //end::get-by-id-json - } -} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/usage/SearchingTest.java b/java-client/src/test/java/co/elastic/clients/documentation/usage/SearchingTest.java index 1e3f7a988..b0179e037 100644 --- a/java-client/src/test/java/co/elastic/clients/documentation/usage/SearchingTest.java +++ b/java-client/src/test/java/co/elastic/clients/documentation/usage/SearchingTest.java @@ -167,7 +167,7 @@ public void searchTemplate() throws Exception { .id("query-script") // <1> .script(s -> s .lang("mustache") - .source(so -> so.scriptString("{\"query\":{\"match\":{\"{{field}}\":\"{{value}}\"}}}")) + .source("{\"query\":{\"match\":{\"{{field}}\":\"{{value}}\"}}}") )); //end::search-template-script diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java deleted file mode 100644 index 193a9b336..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.JsonEndpoint; -import co.elastic.clients.transport.Version; -import co.elastic.clients.transport.endpoints.DelegatingJsonEndpoint; -import co.elastic.clients.transport.rest5_client.RestClientTransport; -import org.apache.commons.io.FileUtils; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.message.BasicHeader; -import org.elasticsearch.client.RestClient; -import org.testcontainers.elasticsearch.ElasticsearchContainer; -import org.testcontainers.images.builder.ImageFromDockerfile; -import org.testcontainers.shaded.org.apache.commons.io.IOUtils; -import org.testcontainers.utility.DockerImageName; - -import javax.net.ssl.SSLContext; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.time.Duration; -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.Base64; -import java.util.Optional; - -public class ElasticsearchTestServer implements AutoCloseable { - - private final String[] plugins; - private volatile ElasticsearchContainer container; - private final JsonpMapper mapper = new JsonbJsonpMapper(); - private RestClient restClient; - private ElasticsearchTransport transport; - private ElasticsearchClient client; - - private static ElasticsearchTestServer global; - - private static final String artifactsApiUrl = "https://artifacts-api.elastic.co/v1/versions/"; - - public static synchronized ElasticsearchTestServer global() { - if (global == null) { - - // Try localhost:9200 - try { - String localUrl = "http://localhost:9200"; - HttpURLConnection connection = (HttpURLConnection) new URL(localUrl).openConnection(); - connection.setRequestProperty("Authorization", "Basic " + - Base64.getEncoder().encodeToString("elastic:changeme".getBytes(StandardCharsets.UTF_8))); - - try (InputStream input = connection.getInputStream()) { - String content = IOUtils.toString(input, StandardCharsets.UTF_8); - if (content.contains("You Know, for Search")) { - System.out.println("Found a running ES server at http://localhost:9200/"); - - global = new ElasticsearchTestServer(); - global.setup(localUrl, null); - } - } - } catch (Exception e) { - // Create container - System.out.println("Starting global ES test server."); - global = new ElasticsearchTestServer(); - global.start(); - } - - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - System.out.println("Stopping global ES test server."); - global.close(); - })); - } - return global; - } - - public ElasticsearchTestServer(String... plugins) { - this.plugins = plugins; - } - - protected void setup(String url, SSLContext sslContext) { - try { - HttpHost host = HttpHost.create(url); - - var pwd = Base64.getEncoder().encodeToString("elastic:changeme".getBytes()); - - - restClient = RestClient.builder(HttpHost.create(url)) - .setSslContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())) - .setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "Basic " + pwd) - }) - //.setCompressionEnabled(true) - .build(); - } catch (Exception e) { - throw new RuntimeException(e); - } - transport = new RestClientTransport(restClient, mapper); - client = new ElasticsearchClient(transport); - } - - private Version selectLatestVersion(Version version, String info) { - if (info.contains(version.toString())) { - return version; - } - // if no version X.Y.0 was found, we give up - if (version.maintenance() == 0) { - throw new RuntimeException("Elasticsearch server container version: " + version + " not yet " + - "available"); - } - return selectLatestVersion(new Version(version.major(), version.minor(), version.maintenance() - 1, - false), info); - } - - private String fetchAndWriteVersionInfo(File file) throws IOException { - String versionInfo = IOUtils.toString(new URL(artifactsApiUrl), StandardCharsets.UTF_8); - FileUtils.writeStringToFile(file, versionInfo, StandardCharsets.UTF_8); - return versionInfo; - } - - private Version getLatestAvailableServerVersion(Version version) { - try { - // check if there's cached information - ClassLoader classLoader = getClass().getClassLoader(); - URL location = classLoader.getResource("./co/elastic/clients/version.json"); - - // writing the info on file before returning - if (location == null) { - File file = new File(classLoader.getResource("./co/elastic/clients").getFile() + "/version" + - ".json"); - String versionInfo = fetchAndWriteVersionInfo(file); - return selectLatestVersion(version, versionInfo); - } - - File file = new File(location.getFile()); - - // info file was found, but it's expired - if (Instant.ofEpochMilli(file.lastModified()).isBefore(Instant.now().minus(24, - ChronoUnit.HOURS))) { - String versionInfo = fetchAndWriteVersionInfo(file); - return selectLatestVersion(version, versionInfo); - } - - // info file exists and it has new info - String versionInfo = FileUtils.readFileToString(file, StandardCharsets.UTF_8); - return selectLatestVersion(version, versionInfo); - - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public synchronized ElasticsearchTestServer start() { - if (this.client != null) { - return this; - } - - Version version = getLatestAvailableServerVersion(Version.VERSION); - - // using specific stable version for tests with plugins - if (plugins.length > 0) { - version = Version.VERSION.major() < 8 ? new Version(7, 17, 25, false) : new Version(8, 16, 0, - false); - } - - String esImage = "docker.elastic.co/elasticsearch/elasticsearch:" + version; - - DockerImageName image; - if (plugins.length == 0) { - image = DockerImageName.parse(esImage); - } else { - String esWithPluginsImage = new ImageFromDockerfile() - .withDockerfileFromBuilder(b -> { - b.from(esImage); - for (String plugin : plugins) { - b.run("/usr/share/elasticsearch/bin/elasticsearch-plugin", "install", plugin); - } - } - ).get(); - - image = DockerImageName - .parse(esWithPluginsImage) - .asCompatibleSubstituteFor("docker.elastic.co/elasticsearch/elasticsearch"); - } - - container = new ElasticsearchContainer(image) - .withEnv("ES_JAVA_OPTS", "-Xms256m -Xmx256m") - .withEnv("path.repo", "/tmp") // for snapshots - .withStartupTimeout(Duration.ofSeconds(30)) - .withPassword("changeme"); - container.start(); - - boolean useTLS = version.major() >= 8; - - SSLContext sslContext = useTLS ? container.createSslContextFromCa() : null; - String url = (useTLS ? "https://" : "http://") + container.getHttpHostAddress(); - - setup(url, sslContext); - - return this; - } - - /** - * Send a request to a server and return the response as JSON. Useful to debug response format issues. - */ - public static JsonData getJsonResponse(ElasticsearchClient client, Req request) throws IOException { - - JsonEndpoint endpoint; - - try { - @SuppressWarnings("unchecked") - JsonEndpoint endpoint0 = (JsonEndpoint) request.getClass() - .getDeclaredField("_ENDPOINT").get(null); - endpoint = endpoint0; - } catch (IllegalAccessException | NoSuchFieldException e) { - throw new RuntimeException(e); - } - - DelegatingJsonEndpoint jsonEndpoint = - new DelegatingJsonEndpoint(endpoint) { - @Override - public JsonpDeserializer responseDeserializer() { - return JsonData._DESERIALIZER; - } - }; - - return client._transport().performRequest(request, jsonEndpoint, client._transportOptions()); - } - - @Override - public void close() { - if (this == global) { - // Closed with a shutdown hook - return; - } - - if (container != null) { - container.stop(); - } - container = null; - } - - public ElasticsearchContainer container() { - return this.container; - } - - public RestClient restClient() { - return restClient; - } - - public ElasticsearchTransport transport() { - return transport; - } - - public JsonpMapper mapper() { - return mapper; - } - - public ElasticsearchClient client() { - return client; - } - - public ElasticsearchAsyncClient asyncClient() { - return new ElasticsearchAsyncClient(client._transport(), client._transportOptions()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuildersTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuildersTest.java deleted file mode 100644 index daa94b89f..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/builders/ClientBuildersTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch._helpers.builders; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.transport.rest5_client.RestClientOptions; -import co.elastic.clients.transport.rest5_client.RestClientTransport; -import org.elasticsearch.client.RequestOptions; -import org.junit.jupiter.api.Test; - -import javax.net.ssl.SSLContext; -import java.io.IOException; -import java.net.URISyntaxException; -import java.security.NoSuchAlgorithmException; - -import static org.junit.Assert.assertTrue; - -public class ClientBuildersTest { - - @Test - public void build() throws IOException, URISyntaxException, NoSuchAlgorithmException { - - // create client with helper - ElasticsearchClient client = new ElasticsearchClientBuilder() - .host("url") - .usernameAndPassword("elastic", "changeme") - .sslContext(SSLContext.getDefault()) - .build(); - - RestClientOptions options = new RestClientOptions(RequestOptions.DEFAULT, true); - - client = client.withTransportOptions(options); - - // checking options correctness - assertTrue(client._transport().getClass().equals(RestClientTransport.class)); - assertTrue(client._transportOptions().keepResponseBodyOnException()); - assertTrue(client._transportOptions().headers().size() == 3); - - //assertTrue(client._transport().options().keepResponseBodyOnException()); TODO ? - - // token update utility - - client._transportOptions().updateToken("token"); - assertTrue(client._transportOptions().headers().size() == 4); - assertTrue(client._transportOptions().headers().stream().anyMatch(h -> h.getKey().equals( - "Authorization"))); - } - - @Test - public void altSearchBuild() { - // Standard search - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java deleted file mode 100644 index dede24b9c..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java +++ /dev/null @@ -1,544 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch._helpers.bulk; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._types.ErrorCause; -import co.elastic.clients.elasticsearch.core.BulkRequest; -import co.elastic.clients.elasticsearch.core.BulkResponse; -import co.elastic.clients.elasticsearch.core.bulk.BulkOperation; -import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; -import co.elastic.clients.elasticsearch.core.bulk.CreateOperation; -import co.elastic.clients.elasticsearch.core.bulk.DeleteOperation; -import co.elastic.clients.elasticsearch.core.bulk.IndexOperation; -import co.elastic.clients.elasticsearch.core.bulk.OperationType; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.SimpleJsonpMapper; -import co.elastic.clients.transport.BackoffPolicy; -import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.TransportOptions; -import org.jetbrains.annotations.Nullable; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class BulkIngesterRetryPolicyTest { - - protected static ElasticsearchClient client; - protected static TestTransport transport; - protected static CountingListener listener; - - private BulkOperation create = BulkOperation.of(b -> b.create(c -> c.index("foo").id("1").document("1"))); - private BulkOperation index = BulkOperation.of(b -> b.index(c -> c.index("fooo").id("2").document("2"))); - private BulkOperation indexFail = BulkOperation.of(b -> b.index(c -> c.index("fail").id("2").document( - "2"))); - private BulkOperation delete = BulkOperation.of(b -> b.delete(c -> c.index("foooo").id("3"))); - private BulkOperation deleteFail = BulkOperation.of(b -> b.delete(c -> c.index("fail").id("3"))); - - @BeforeEach - public void setup() { - transport = new TestTransport(); - client = new ElasticsearchClient(transport); - listener = new CountingListener(); - } - - @Test - public void retryTestNoScheduledFlushNoContext() throws Exception { - - // First test, partial success, other will succeed after retrying - { - BulkIngester ingester = newBasicBulkIngester(listener); - - ingester.add(create); - ingester.add(index); - ingester.add(index); - - ingester.close(); - - // 1 instant success, 2 retried, but succeeded. can be either 2 or 3 depending on the retries, - // if they get scheduled at the same exact time - assertTrue(listener.requests.get() == 2 || listener.requests.get() == 3); - // eventually all 3 have to succeed - assertTrue(listener.successOperations.get() == 3); - - // 1 for the create and first try for the indexes, 2 + 2 for both index retries, - // which could be scheduled at the same time, so from 3 to 5 - assertTrue(listener.sentRequestsTotal.get() >= 3 && listener.sentRequestsTotal.get() <= 5); - } - - // Second test, all requests will succeed after retrying - { - transport.reset(); - listener.reset(); - - BulkIngester ingester = newBasicBulkIngester(listener); - - ingester.add(index); - ingester.add(index); - ingester.add(index); - ingester.add(index); - - ingester.close(); - - // between 1 and 4, depending on scheduler - assertTrue(listener.requests.get() >= 1 && listener.requests.get() <= 4); - // eventually all 4 have to succeed - assertTrue(listener.successOperations.get() == 4); - // between 3 and 9, depending on scheduler - assertTrue(listener.sentRequestsTotal.get() >= 3 && listener.sentRequestsTotal.get() <= 9); - } - - // Third test, only one retryable (will succeed), other permanent failures - { - transport.reset(); - listener.reset(); - - BulkIngester ingester = newBasicBulkIngester(listener); - - ingester.add(index); - ingester.add(delete); - ingester.add(delete); - - ingester.close(); - - // 2 failed will be handled together, then 1 retry - assertTrue(listener.requests.get() == 2); - - assertTrue(listener.successOperations.get() == 1); - assertTrue(listener.errorOperations.get() == 2); - // 1 initial + 2 retries - assertTrue(listener.sentRequestsTotal.get() == 3); - } - - // Fourth test, all requests will be retried until policy allows, then fail - { - transport.reset(); - listener.reset(); - - BulkIngester ingester = newBasicBulkIngester(listener); - - ingester.add(indexFail); - ingester.add(indexFail); - ingester.add(indexFail); - - ingester.close(); - - // from 1 to 3 depending on scheduling - assertTrue(listener.requests.get() >= 1 && listener.requests.get() <= 3); - - assertTrue(listener.successOperations.get() == 0); - assertTrue(listener.errorOperations.get() == 3); - // between 8 and 24, depending on scheduler - assertTrue(listener.sentRequestsTotal.get() >= 8 && listener.sentRequestsTotal.get() <= 24); - } - - // Fifth test, one exception that will make everything else fail, no retries triggered - { - transport.reset(); - listener.reset(); - - BulkIngester ingester = newBasicBulkIngester(listener); - - ingester.add(index); - ingester.add(create); - ingester.add(deleteFail); - - ingester.close(); - - // just the one - assertTrue(listener.requests.get() == 1); - - assertTrue(listener.successOperations.get() == 0); - assertTrue(listener.errorOperations.get() == 3); - - // just the one - assertTrue(listener.sentRequestsTotal.get() == 1); - } - - // Sixth test, a mix of everything - { - transport.reset(); - listener.reset(); - - BulkIngester ingester = newBasicBulkIngester(listener); - - ingester.add(create); - ingester.add(index); - ingester.add(indexFail); - ingester.add(delete); - ingester.add(create); - ingester.add(index); - ingester.add(indexFail); - ingester.add(delete); - - ingester.close(); - - // from 2 to 4 depending on scheduling - assertTrue(listener.requests.get() >= 1 && listener.successOperations.get() <= 4); - - assertTrue(listener.successOperations.get() == 4); - assertTrue(listener.errorOperations.get() == 4); - - // between 8 and 18, depending on scheduler - assertTrue(listener.sentRequestsTotal.get() >= 8 && listener.sentRequestsTotal.get() <= 18); - } - - transport.close(); - } - - @Test - public void retryTestFlushAndContextExponentialBackoff() throws Exception { - - // One success, other will succeed after retrying, other will fail eventually - { - BulkIngester ingester = newBulkIngesterWithFlushAndContextAndLongExponential(listener); - - ingester.add(create, 1); - ingester.add(indexFail, 2); - ingester.add(index, 3); - - ingester.close(); - - // should be 3 separate requests sent, one instant, one after a few retries, the last one error. - assertTrue(listener.requests.get() == 3); - // 2 will succeed, one will fail - assertTrue(listener.successOperations.get() == 2); - assertTrue(listener.errorOperations.get() == 1); - // between 8 and 10, depending on scheduler (first one + 2 retries for index + 8 retries for - // indexfail) - assertTrue(listener.sentRequestsTotal.get() >= 8 && listener.sentRequestsTotal.get() <= 11); - // checking order of contexts after send confirmed - Iterator iter = listener.sentContexts.iterator(); - // first one being completed is create - assertTrue(iter.next().equals(1)); - // second one is index, which will take only 2 retries - assertTrue(iter.next().equals(3)); - // last one is indexFail, taking 8 retries to fail - assertTrue(iter.next().equals(2)); - } - - transport.close(); - } - - @Test - public void retryTestNoFlushAndContextExponentialBackoff() throws Exception { - - // One success, other will succeed after retrying, other will fail eventually - { - BulkIngester ingester = newBulkIngesterNoFlushAndContextAndLongExponential(listener); - - ingester.add(create, 1); - ingester.add(indexFail, 2); - ingester.add(index, 3); - - ingester.close(); - - // should be 3 separate requests sent, one instant, one after a few retries, the last one error. - assertTrue(listener.requests.get() == 3); - // 2 will succeed, one will fail - assertTrue(listener.successOperations.get() == 2); - assertTrue(listener.errorOperations.get() == 1); - // between 8 and 10, depending on scheduler (first one + 2 retries for index + 8 retries for - // indexfail) - assertTrue(listener.sentRequestsTotal.get() >= 8 && listener.sentRequestsTotal.get() <= 11); - // checking order of contexts after send confirmed - Iterator iter = listener.sentContexts.iterator(); - // first one being completed is create - assertTrue(iter.next().equals(1)); - // second one is index, which will take only 2 retries - assertTrue(iter.next().equals(3)); - // last one is indexFail, taking 8 retries to fail - assertTrue(iter.next().equals(2)); - } - - transport.close(); - } - - @Test - public void retryMultiThreadStressTest() throws InterruptedException, IOException { - - // DISCLAIMER: this configuration is highly inefficient and only used here to showcase an extreme - // situation where the number of adding threads greatly exceeds the number of concurrent requests - // handled by the ingester. It's strongly recommended to always tweak maxConcurrentRequests - // accordingly. - BulkIngester ingester = BulkIngester.of(b -> b - .client(client) - .listener(listener) - .flushInterval(5, TimeUnit.SECONDS) - .backoffPolicy(BackoffPolicy.constantBackoff(50L, 8))); - - ExecutorService executor = Executors.newFixedThreadPool(50); - - // sends create operations, but once every 1000, one index operation will be sent, - // and once every 5000 an indexFail - for (int i = 0; i < 100000; i++) { - int ii = i; - Runnable thread = () -> { - int finalI = ii; - if (ii % 1000 == 0) { - ingester.add(index, ii); - } else if (ii % 5000 == 0) { - ingester.add(indexFail, ii); - } else { - ingester.add(create, ii); - } - }; - executor.submit(thread); - } - - executor.awaitTermination(10, TimeUnit.SECONDS); - ingester.close(); - - // all operations will succeed eventually, so the total has to be 100000 - assertTrue(listener.successOperations.get() == 100000); - assertTrue(listener.sentContexts.size() == 100000); - assertTrue(listener.errorOperations.get() == 0); - // it's difficult to predict how many requests will be sent, but considering they will be sent - // in batches of 1000, without retries it should be exactly 100, considering that 100 out of - // 100000 will be retried 3 times and 20 will be retried 8 times, if they don't get batched together - // with the others it could result in a total of 560, which is highly unlikely. - // more reasonably there will be between 100 and 300 requests sent. - assertTrue(listener.sentRequestsTotal.get() >= 100 && listener.sentRequestsTotal.get() <= 300); - // same reasoning - assertTrue(listener.requests.get() >= 100 && listener.requests.get() <= 300); - - transport.close(); - } - - - private static class TestTransport implements ElasticsearchTransport { - public final AtomicInteger requestsStarted = new AtomicInteger(); - public final AtomicInteger requestsCompleted = new AtomicInteger(); - public final AtomicInteger operations = new AtomicInteger(); - - public ConcurrentHashMap retryFailures = new ConcurrentHashMap<>(); - - - private final ExecutorService executor = Executors.newCachedThreadPool(); - - @Override - public ResponseT performRequest( - RequestT request, - Endpoint endpoint, - @Nullable TransportOptions options - ) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture performRequestAsync(RequestT request, Endpoint endpoint, @Nullable TransportOptions options) { - - BulkRequest bulk = (BulkRequest) request; - requestsStarted.incrementAndGet(); - operations.addAndGet(bulk.operations().size()); - - if (bulk.operations().isEmpty()) { - System.out.println("No operations!"); - } - - // For testing purposes, different result depending on the operation type. - // Create will always succeed - // Index will always return 429 for 2 times, then 200. Index with index name "fail" will only - // return 429. - // Delete will always return 404. Delete with index name "fail" will throw transport exception. - - try { - - List items = new ArrayList<>(); - for (BulkOperation op : bulk.operations()) { - OperationType operationType = OperationType.Create; - ErrorCause error = null; - int status = 200; - String index = null; - switch (op._kind()) { - case Index: - index = ((IndexOperation) op._get()).index(); - operationType = OperationType.Index; - retryFailures.putIfAbsent(op, 0); - boolean isStillRetrying = retryFailures.computeIfPresent(op, (k, v) -> v + 1) > 2; - error = isStillRetrying && !index.equals("fail") ? null : - ErrorCause.of(e -> e.reason("some error")); - status = isStillRetrying && !index.equals("fail") ? 200 : 429; - break; - case Delete: - index = ((DeleteOperation) op._get()).index(); - if (index.equals("fail")) { - throw new RuntimeException("error"); - } - operationType = OperationType.Delete; - error = ErrorCause.of(e -> e.reason("some error")); - status = 404; - break; - default: - index = ((CreateOperation) op._get()).index(); - break; - } - ErrorCause finalError = error; - int finalStatus = status; - OperationType finalOperationType = operationType; - String finalIndex = index; - items.add(BulkResponseItem.of(b -> b - .index(finalIndex) - .operationType(finalOperationType) - .status(finalStatus) - .error(finalError))); - } - - CompletableFuture response = new CompletableFuture<>(); - executor.submit(() -> { - requestsCompleted.incrementAndGet(); - response.complete(BulkResponse.of(r -> r.errors(false).items(items).took(3))); - }); - - @SuppressWarnings("unchecked") - CompletableFuture result = (CompletableFuture) response; - return result; - } catch (RuntimeException e) { - CompletableFuture future = new CompletableFuture<>(); - future.completeExceptionally(e); - executor.submit(() -> { - future.completeExceptionally(e); - }); - return future; - } - } - - @Override - public JsonpMapper jsonpMapper() { - return SimpleJsonpMapper.INSTANCE; - } - - @Override - public TransportOptions options() { - return null; - } - - @Override - public void close() throws IOException { - executor.shutdown(); - try { - executor.awaitTermination(1, TimeUnit.SECONDS); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - - public void reset() { - requestsStarted.set(0); - requestsCompleted.set(0); - operations.set(0); - retryFailures = new ConcurrentHashMap<>(); - } - } - - private static class CountingListener implements BulkListener { - public final AtomicInteger sentRequestsTotal = new AtomicInteger(); - public final AtomicInteger successOperations = new AtomicInteger(); - public final AtomicInteger errorOperations = new AtomicInteger(); - public final AtomicInteger requests = new AtomicInteger(); - public final ConcurrentLinkedQueue sentContexts = new ConcurrentLinkedQueue<>(); - - @Override - public void beforeBulk(long executionId, BulkRequest request, List contexts) { - sentRequestsTotal.incrementAndGet(); - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, - BulkResponse response) { - for (BulkResponseItem item : response.items()) { - if (item.error() != null) { - errorOperations.incrementAndGet(); - } else { - successOperations.incrementAndGet(); - } - } - if (contexts.stream().anyMatch(Objects::nonNull)) { - sentContexts.addAll(contexts); - } - requests.incrementAndGet(); - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, - Throwable failure) { - failure.printStackTrace(); - errorOperations.addAndGet(request.operations().size()); - if (contexts.stream().anyMatch(Objects::nonNull)) { - sentContexts.addAll(contexts); - } - requests.incrementAndGet(); - } - - public void reset() { - successOperations.set(0); - errorOperations.set(0); - requests.set(0); - sentRequestsTotal.set(0); - } - } - - private BulkIngester newBasicBulkIngester(BulkListener listener) { - return BulkIngester.of(b -> b - .client(client) - .maxOperations(10) - .maxConcurrentRequests(10) - .listener(listener) - .backoffPolicy(BackoffPolicy.constantBackoff(50L, 8)) - ); - } - - private BulkIngester newBulkIngesterWithFlushAndContextAndLongExponential(BulkListener listener) { - return BulkIngester.of(b -> b - .client(client) - .maxOperations(10) - .maxConcurrentRequests(10) - .listener(listener) - .flushInterval(1000, TimeUnit.MILLISECONDS) - .backoffPolicy(BackoffPolicy.exponentialBackoff(100L, 8)) - ); - } - - private BulkIngester newBulkIngesterNoFlushAndContextAndLongExponential(BulkListener listener) { - return BulkIngester.of(b -> b - .client(client) - .maxOperations(10) - .maxConcurrentRequests(10) - .listener(listener) - .backoffPolicy(BackoffPolicy.exponentialBackoff(100L, 8)) - ); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/bulk/BulkIngesterTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/bulk/BulkIngesterTest.java deleted file mode 100644 index 76a48b9fa..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/bulk/BulkIngesterTest.java +++ /dev/null @@ -1,623 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch._helpers.bulk; - -import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.ElasticsearchTestServer; -import co.elastic.clients.elasticsearch.core.BulkRequest; -import co.elastic.clients.elasticsearch.core.BulkResponse; -import co.elastic.clients.elasticsearch.core.bulk.BulkOperation; -import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; -import co.elastic.clients.elasticsearch.core.bulk.OperationType; -import co.elastic.clients.elasticsearch.end_to_end.RequestTest; -import co.elastic.clients.elasticsearch.indices.IndicesStatsResponse; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.SimpleJsonpMapper; -import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.TransportOptions; -import org.jetbrains.annotations.Nullable; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -class BulkIngesterTest extends Assertions { - - private static final BulkResponseItem successItem = BulkResponseItem.of(i -> i - .index("foo") - .status(200) - .operationType(OperationType.Delete) - ); - - private static final BulkOperation operation = BulkOperation.of(op -> op - .delete(d -> d.index("foo").id("bar")) - ); - - private void printStats(BulkIngester ingester) { - System.out.printf("Ingester - operations: %d (%d), requests: %d (%d)%n", - ingester.operationsCount(), ingester.operationContentionsCount(), - ingester.requestCount(), ingester.requestContentionsCount() - ); - } - - private void printStats(CountingListener listener) { - System.out.printf("Listener - operations: %d, requests: %d%n", - listener.operations.get(), - listener.requests.get() - ); - } - - private void printStats(TestTransport transport) { - System.out.printf("Transport - operations: %d, requests: %d (%d completed)%n", - transport.operations.get(), - transport.requestsStarted.get(), - transport.requestsCompleted.get() - ); - } - - @Test - public void basicTestFlush() throws Exception { - // Prime numbers, so that we have leftovers to flush before shutting down - multiThreadTest(7, 3, 5, 101, true); - } - - @Test - public void basicTestFlushWithInternalScheduler() throws Exception { - // Prime numbers, so that we have leftovers to flush before shutting down - multiThreadTest(7, 3, 5, 101, false); - } - - @Test - public void basicTestNoFlush() throws Exception { - // Will have nothing to flush on close. - multiThreadTest(10, 3, 5, 100, true); - } - - @Test - public void basicTestNoFlushWithInternalScheduler() throws Exception { - // Will have nothing to flush on close. - multiThreadTest(10, 3, 5, 100, false); - } - - private void multiThreadTest(int maxOperations, int maxRequests, int numThreads, int numOperations, - boolean externalScheduler) throws Exception { - - CountingListener listener = new CountingListener(); - TestTransport transport = new TestTransport(); - ElasticsearchAsyncClient client = new ElasticsearchAsyncClient(transport); - ScheduledExecutorService scheduler; - if (externalScheduler) { - scheduler = Executors.newSingleThreadScheduledExecutor(r -> { - Thread t = Executors.defaultThreadFactory().newThread(r); - t.setName("my-bulk-ingester-executor#"); - t.setDaemon(true); - return t; - }); - } else { - scheduler = null; - } - - BulkIngester ingester = BulkIngester.of(b -> b - .client(client) - .maxOperations(maxOperations) - .maxConcurrentRequests(maxRequests) - .scheduler(scheduler) - .listener(listener) - ); - - CountDownLatch latch = new CountDownLatch(numThreads); - for (int i = 0; i < numThreads; i++) { - new Thread(() -> { - try { - Thread.sleep((long)(Math.random() * 100)); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - for (int j = 0; j < numOperations; j++) { - ingester.add(operation); - } - - latch.countDown(); - }).start(); - } - - latch.await(); - - ingester.close(); - transport.close(); - if (scheduler != null) scheduler.shutdownNow(); - - printStats(ingester); - printStats(listener); - printStats(transport); - - int expectedOperations = numThreads * numOperations; - assertEquals(expectedOperations, ingester.operationsCount()); - assertEquals(expectedOperations, listener.operations.get()); - assertEquals(expectedOperations, transport.operations.get()); - - int expectedRequests = expectedOperations / maxOperations + ((expectedOperations % maxOperations == 0) ? 0 : 1) ; - - assertEquals(expectedRequests, ingester.requestCount()); - assertEquals(expectedRequests, listener.requests.get()); - assertEquals(expectedRequests, transport.requestsStarted.get()); - } - - @Test - public void multiThreadStressTest() throws InterruptedException, IOException { - - String index = "bulk-ingester-stress-test"; - ElasticsearchClient client = ElasticsearchTestServer.global().client(); - - // DISCLAIMER: this configuration is highly inefficient and only used here to showcase an extreme - // situation where the number of adding threads greatly exceeds the number of concurrent requests - // handled by the ingester. It's strongly recommended to always tweak maxConcurrentRequests accordingly. - BulkIngester ingester = BulkIngester.of(b -> b - .client(client) - .globalSettings(s -> s.index(index)) - .flushInterval(5, TimeUnit.SECONDS) - ); - - RequestTest.AppData appData = new RequestTest.AppData(); - appData.setIntValue(42); - appData.setMsg("Some message"); - - ExecutorService executor = Executors.newFixedThreadPool(50); - - for (int i = 0; i < 100000; i++) { - int ii = i; - Runnable thread = () -> { - int finalI = ii; - ingester.add(_1 -> _1 - .create(_2 -> _2 - .id(String.valueOf(finalI)) - .document(appData) - )); - }; - executor.submit(thread); - } - - executor.awaitTermination(10,TimeUnit.SECONDS); - ingester.close(); - - client.indices().refresh(); - - IndicesStatsResponse indexStats = client.indices().stats(g -> g.index(index)); - - assertTrue(indexStats.indices().get(index).primaries().docs().count()==100000); - } - - @Test - public void sizeLimitTest() throws Exception { - TestTransport transport = new TestTransport(); - - long operationSize = IngesterOperation.of(new RetryableBulkOperation<>(operation, null, null), transport.jsonpMapper()).size(); - - BulkIngester ingester = BulkIngester.of(b -> b - .client(new ElasticsearchAsyncClient(transport)) - // Set size limit just above operation's size, leading to 2 operations per request - .maxSize(operationSize + 1) - ); - - for (int i = 0; i < 10; i++) { - ingester.add(operation); - } - - ingester.close(); - transport.close(); - - assertEquals(10, ingester.operationsCount()); - assertEquals(5, ingester.requestCount()); - } - - @Test - public void periodicFlushTest() throws Exception { - TestTransport transport = new TestTransport(); - - BulkIngester ingester = BulkIngester.of(b -> b - .client(new ElasticsearchAsyncClient(transport)) - // Flush every 50 ms - .flushInterval(50, TimeUnit.MILLISECONDS) - // Disable other flushing limits - .maxSize(-1) - .maxOperations(-1) - .maxConcurrentRequests(Integer.MAX_VALUE-1) - ); - - // Add an operation every 100 ms to give time - // to the flushing timer to kick in. - for (int i = 0; i < 10; i++) { - ingester.add(operation); - Thread.sleep(100); - } - - ingester.close(); - transport.close(); - - // We should have one operation per request - assertEquals(10, ingester.operationsCount()); - assertEquals(10, ingester.requestCount()); - } - - @Test - public void failingListener() throws Exception { - TestTransport transport = new TestTransport(); - AtomicInteger failureCount = new AtomicInteger(); - AtomicReference> lastContexts = new AtomicReference<>(); - AtomicReference lastRequest = new AtomicReference<>(); - - BulkListener listener = new BulkListener() { - @Override - public void beforeBulk(long executionId, BulkRequest request, List contexts) { - // So that we can test that it's non-empty - lastContexts.set(contexts); - lastRequest.set(request); - - if (executionId == 1) { - // Fail before the request is sent - failureCount.incrementAndGet(); - throw new RuntimeException("Before bulk failure"); - } - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, BulkResponse response) { - if (executionId == 2) { - // Fail after the request is sent - failureCount.incrementAndGet(); - throw new RuntimeException("After bulk failure"); - } - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, Throwable failure) { - - } - }; - - BulkIngester ingester = BulkIngester.of(b -> b - .client(new ElasticsearchAsyncClient(transport)) - // Flush every 50 ms - .flushInterval(50, TimeUnit.MILLISECONDS) - // Disable other flushing limits - .maxSize(-1) - .maxOperations(-1) - .maxConcurrentRequests(Integer.MAX_VALUE - 1) - .listener(listener) - ); - - // Add an operation every 100 ms to give time - // to the flushing timer to kick in. - for (int i = 0; i < 10; i++) { - ingester.add(operation); - Thread.sleep(100); - } - - ingester.close(); - transport.close(); - - // We should have one operation per request - assertEquals(10, ingester.operationsCount()); - assertEquals(10, ingester.requestCount()); - // Transport hasn't seen the request where beforeBulk failed - assertEquals(9, transport.requestsStarted.get()); - - assertEquals(2, failureCount.get()); - - // Also test context list when no values were provided - assertTrue(lastRequest.get().operations().size() > 0); - assertEquals(lastRequest.get().operations().size(), lastContexts.get().size()); - } - - @Test - public void withContextValues() throws Exception { - TestTransport transport = new TestTransport(); - List allRequests = Collections.synchronizedList(new ArrayList<>()); - List> allContexts = Collections.synchronizedList(new ArrayList<>()); - - BulkListener listener = new BulkListener() { - @Override - public void beforeBulk(long executionId, BulkRequest request, List contexts) { - allRequests.add(request); - allContexts.add(contexts); - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, BulkResponse response) { - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, Throwable failure) { - } - }; - - BulkIngester ingester = BulkIngester.of(b -> b - .client(new ElasticsearchAsyncClient(transport)) - // Split every 10 operations - .maxOperations(10) - .listener(listener) - ); - - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - // Set a context only after 5, so that we test filling with nulls. - Integer context = j < 5 ? null : i*10 + j; - ingester.add(operation, context); - } - } - - ingester.close(); - transport.close(); - - // We should have 10 operations per request - assertEquals(100, ingester.operationsCount()); - assertEquals(10, ingester.requestCount()); - - for (int i = 0; i < 10; i++) { - List contexts = allContexts.get(i); - for (int j = 0; j < 10; j++) { - if (j < 5) { - assertNull(contexts.get(j)); - } else { - assertEquals(contexts.get(j), i*10 + j); - } - } - } - } - - @Test - public void testGlobalSettings() throws Exception { - AtomicReference storedRequest = new AtomicReference<>(); - - TestTransport transport = new TestTransport(); - CountingListener listener = new CountingListener() { - @Override - public void beforeBulk(long executionId, BulkRequest request, List contexts) { - super.beforeBulk(executionId, request, contexts); - storedRequest.set(request); - } - }; - - BulkIngester ingester = BulkIngester.of(b -> b - .client(new ElasticsearchAsyncClient(transport)) - .listener(listener) - .globalSettings(s -> s - .index("foo") - .routing("bar") - ) - ); - - ingester.add(operation); - - ingester.close(); - transport.close(); - - assertEquals(1, ingester.operationsCount()); - assertEquals(1, ingester.requestCount()); - - assertEquals("foo", storedRequest.get().index()); - assertEquals("bar", storedRequest.get().routing()); - } - - @Test - public void pipelineTest() { - String json = "{\"create\":{\"_id\":\"some_id\",\"_index\":\"some_idx\",\"pipeline\":\"pipe\",\"require_alias\":true}}"; - JsonpMapper mapper = new SimpleJsonpMapper(); - - BulkOperation create = BulkOperation.of(o -> o.create(c -> c - .pipeline("pipe") - .requireAlias(true) - .index("some_idx") - .id("some_id") - .document("Some doc") - )); - - String createStr = JsonpUtils.toJsonString(create, mapper); - assertEquals(json, createStr); - - BulkOperation create1 = IngesterOperation.of(new RetryableBulkOperation<>(create, null, null), mapper) - .repeatableOperation().operation(); - - String create1Str = JsonpUtils.toJsonString(create1, mapper); - assertEquals(json, create1Str); - } - - @Test - public void endToEndTest() throws Exception { - String index = "bulk-ingester-test"; - ElasticsearchClient client = ElasticsearchTestServer.global().client(); - - BulkIngester ingester = BulkIngester.of(b -> b - .client(client) - .globalSettings(s -> s.index(index)) - ); - - RequestTest.AppData appData = new RequestTest.AppData(); - appData.setIntValue(42); - appData.setMsg("Some message"); - - ingester.add(_1 -> _1 - .create(_2 -> _2 - .id("abc") - .document(appData) - )); - - ingester.add(_1 -> _1 - .create(_2 -> _2 - .id("def") - .document(appData) - )); - - ingester.add(_1 -> _1 - .update(_2 -> _2 - .id("gh") - .action(_3 -> _3 - .docAsUpsert(true) - .doc(appData)) - )); - - // Closing waits until all pending requests are completed - ingester.close(); - - for (String id : Arrays.asList("abc", "def", "gh")) { - assertEquals( - 42, - client.get(b -> b - .index(index) - .id(id), - RequestTest.AppData.class - ).source().getIntValue() - ); - } - - client.indices().delete(d -> d.index(index)); - - } - - @Test - public void testConfigValidation() { - - BulkIngester.Builder b = new BulkIngester.Builder<>(); - - assertThrows(IllegalArgumentException.class, () -> { - b.flushInterval(-1, TimeUnit.MILLISECONDS); - }); - - assertThrows(IllegalArgumentException.class, () -> { - b.maxConcurrentRequests(0); - }); - - assertThrows(IllegalArgumentException.class, () -> { - b.maxSize(-2); - }); - - assertThrows(IllegalArgumentException.class, () -> { - b.maxOperations(-2); - }); - - assertThrows(IllegalStateException.class, () -> { - b.maxSize(-1).maxOperations(-1).build(); - }); - } - - //----------------------------------------------------------------------------------------------------------------- - - private static class CountingListener implements BulkListener { - public final AtomicInteger operations = new AtomicInteger(); - public final AtomicInteger requests = new AtomicInteger(); - @Override - public void beforeBulk(long executionId, BulkRequest request, List contexts) { - - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, BulkResponse response) { - operations.addAndGet(request.operations().size()); - requests.incrementAndGet(); - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, Throwable failure) { - failure.printStackTrace(); - operations.addAndGet(request.operations().size()); - requests.incrementAndGet(); - } - } - - private static class TestTransport implements ElasticsearchTransport { - public final AtomicInteger requestsStarted = new AtomicInteger(); - public final AtomicInteger requestsCompleted = new AtomicInteger(); - public final AtomicInteger operations = new AtomicInteger(); - - private final ExecutorService executor = Executors.newCachedThreadPool(); - - @Override - public ResponseT performRequest( - RequestT request, - Endpoint endpoint, - @Nullable TransportOptions options - ) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture performRequestAsync(RequestT request, Endpoint endpoint, @Nullable TransportOptions options) { - - BulkRequest bulk = (BulkRequest) request; - requestsStarted.incrementAndGet(); - operations.addAndGet(bulk.operations().size()); - - if (bulk.operations().size() == 0) { - System.out.println("No operations!"); - } - - List items = new ArrayList<>(); - for (int i = 0; i < bulk.operations().size(); i++) { - items.add(successItem); - } - - CompletableFuture response = new CompletableFuture<>(); - executor.submit(() -> { - requestsCompleted.incrementAndGet(); - response.complete(BulkResponse.of(r -> r.errors(false).items(items).took(3))); - }); - - @SuppressWarnings("unchecked") - CompletableFuture result = (CompletableFuture)response; - return result; - } - - @Override - public JsonpMapper jsonpMapper() { - return SimpleJsonpMapper.INSTANCE; - } - - @Override - public TransportOptions options() { - return null; - } - - @Override - public void close() throws IOException { - executor.shutdown(); - try { - executor.awaitTermination(1, TimeUnit.SECONDS); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java deleted file mode 100644 index 6728e6dca..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch._helpers.esql; - -import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.ElasticsearchTestServer; -import co.elastic.clients.elasticsearch._helpers.esql.jdbc.ResultSetEsqlAdapter; -import co.elastic.clients.elasticsearch._helpers.esql.objects.ObjectsEsqlAdapter; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.rest5_client.RestClientTransport; -import org.apache.hc.core5.http.ContentType; -import org.apache.hc.core5.http.io.entity.ByteArrayEntity; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import com.fasterxml.jackson.databind.annotation.JsonNaming; -import org.apache.commons.io.IOUtils; - -import org.elasticsearch.client.Request; -import org.elasticsearch.client.RestClient; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.io.InputStream; -import java.sql.ResultSet; -import java.sql.Timestamp; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -public class EsqlAdapterEndToEndTest extends Assertions { - - static ElasticsearchClient esClient; - - @BeforeAll - public static void setup() throws Exception { - ElasticsearchClient global = ElasticsearchTestServer.global().client(); - RestClient restClient = ((RestClientTransport) global._transport()).restClient(); - esClient = new ElasticsearchClient(new RestClientTransport(restClient, new JacksonJsonpMapper())); - - esClient.indices().delete(d -> d.index("employees").ignoreUnavailable(true)); - - Request request = new Request("POST", "/employees/_bulk?refresh=true"); - - InputStream resourceAsStream = EsqlAdapterTest.class.getResourceAsStream("employees.ndjson"); - byte[] bytes = IOUtils.toByteArray(resourceAsStream); - request.setEntity(new ByteArrayEntity(bytes, ContentType.APPLICATION_JSON)); - - restClient.performRequest(request); - } - - @Test - public void resultSetTest() throws Exception { - - ResultSet rs = esClient.esql().query( - ResultSetEsqlAdapter.INSTANCE, - "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | SORT emp_no | LIMIT 300", - // Testing parameters. Note that FROM and LIMIT do not accept parameters - "10042", "10002" - ); - - { - assertTrue(rs.next()); - assertEquals("10002", rs.getString("emp_no")); - - // Single valued fields come back as single value even if other rows have multiple values - @SuppressWarnings("unchecked") - String job = (String) rs.getObject("job_positions"); - assertEquals("Senior Team Lead", job); - } - - { - assertTrue(rs.next()); - assertEquals("10042", rs.getString("emp_no")); - - java.sql.Date hireDate = rs.getDate("hire_date"); - assertEquals("1993-03-21", hireDate.toString()); - - Timestamp hireDate1 = rs.getTimestamp("hire_date"); - assertEquals( - "1993-03-21T00:00:00Z[UTC]", - DateTimeFormatter.ISO_DATE_TIME.format(hireDate1.toInstant().atZone(ZoneId.of("UTC"))) - ); - - @SuppressWarnings("unchecked") - List jobs = (List) rs.getObject("job_positions"); - - assertEquals(4, jobs.size()); - assertEquals("Architect", jobs.get(0)); - } - - assertFalse(rs.next()); - } - - @Test - public void objectsTest() throws Exception { - Iterable result = esClient.esql().query( - ObjectsEsqlAdapter.of(EmpData.class), - "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | SORT emp_no | LIMIT 300", - // Testing parameters. Note that FROM and LIMIT do not accept parameters - "10042", "10002" - ); - - Iterator it = result.iterator(); - - { - EmpData emp = it.next(); - assertEquals("10002", emp.empNo); - List jobPositions = emp.jobPositions; - // In addition to the value, this tests that single strings are correctly deserialized as a list - assertEquals(Arrays.asList("Senior Team Lead"), emp.jobPositions); - } - - { - EmpData emp = it.next(); - assertEquals("10042", emp.empNo); - assertEquals(4, emp.jobPositions.size()); - assertTrue(emp.jobPositions.contains("Architect")); - assertTrue(emp.jobPositions.contains("Business Analyst")); - assertTrue(emp.jobPositions.contains("Internship")); - assertTrue(emp.jobPositions.contains("Junior Developer")); - - assertEquals("1993-03-21T00:00:00Z[UTC]", - DateTimeFormatter.ISO_DATE_TIME.format(emp.hireDate.toInstant().atZone(ZoneId.of("UTC"))) - ); - } - - assertFalse(it.hasNext()); - - } - - @Test - public void asyncObjects() throws Exception { - - ElasticsearchAsyncClient asyncClient = new ElasticsearchAsyncClient(esClient._transport(), esClient._transportOptions()); - - - CompletableFuture> future = asyncClient.esql().query( - ObjectsEsqlAdapter.of(EmpData.class), - "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | SORT emp_no | LIMIT 300", - // Testing parameters. Note that FROM and LIMIT do not accept parameters - "10042", "10002" - ); - - future.thenApply(result -> { - Iterator it = result.iterator(); - - { - EmpData emp = it.next(); - assertEquals("10002", emp.empNo); - List jobPositions = emp.jobPositions; - // In addition to the value, this tests that single strings are correctly deserialized as a list - assertEquals(Arrays.asList("Senior Team Lead"), emp.jobPositions); - } - - { - EmpData emp = it.next(); - assertEquals("10042", emp.empNo); - assertEquals(4, emp.jobPositions.size()); - assertTrue(emp.jobPositions.contains("Architect")); - assertTrue(emp.jobPositions.contains("Business Analyst")); - assertTrue(emp.jobPositions.contains("Internship")); - assertTrue(emp.jobPositions.contains("Junior Developer")); - - assertEquals("1993-03-21T00:00:00Z[UTC]", - DateTimeFormatter.ISO_DATE_TIME.format(emp.hireDate.toInstant().atZone(ZoneId.of("UTC"))) - ); - } - - assertFalse(it.hasNext()); - return null; - } - ).get(); - } - - @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) - @JsonIgnoreProperties(ignoreUnknown = true) - public static class EmpData { - public String empNo; - public java.util.Date hireDate; - public List jobPositions; - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterTest.java deleted file mode 100644 index e3afd3ee0..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterTest.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch._helpers.esql; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._helpers.esql.jdbc.ResultSetEsqlAdapter; -import co.elastic.clients.elasticsearch._helpers.esql.objects.ObjectsEsqlAdapter; -import co.elastic.clients.elasticsearch.esql.EsqlFormat; -import co.elastic.clients.json.JsonpMappingException; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.testkit.MockHttpClient; -import co.elastic.clients.transport.endpoints.BinaryResponse; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.sql.ResultSet; -import java.sql.Types; - -public class EsqlAdapterTest extends Assertions { - - String json = "{\n" + - " \"took\": 10," + - " \"columns\": [\n" + - "\t{\"name\": \"avg_salary\", \"type\": \"double\"},\n" + - "\t{\"name\": \"lang\", \t\"type\": \"keyword\"}\n" + - " ],\n" + - " \"values\": [\n" + - "\t[43760.0, \"Spanish\"],\n" + - "\t[48644.0, \"French\"],\n" + - "\t[48832.0, \"German\"]\n" + - " ]\n" + - "}\n"; - - ElasticsearchClient esClient = new MockHttpClient() - .add("/_query", "application/json", json) - .client(new JacksonJsonpMapper()); // object deserializer needs a buffering mapper - - public static class Data { - public double avg_salary; - public String lang; - } - - @Test - public void testMissingColumns() throws IOException { - String badJson = "{\n" + - " \"took\": 10," + - " \"values\": [\n" + - "\t[43760.0, \"Spanish\"],\n" + - "\t[48644.0, \"French\"],\n" + - "\t[48832.0, \"German\"]\n" + - " ]\n" + - "}\n"; - - ElasticsearchClient esClient = new MockHttpClient() - .add("/_query", "application/json", badJson) - .client(new JacksonJsonpMapper()); - - JsonpMappingException jsonMappingException = assertThrows(JsonpMappingException.class, () -> { - esClient.esql().query( - ResultSetEsqlAdapter.INSTANCE, - "FROM employees | STATS avg_salary = AVG(salary) by country" - ); - }); - assertTrue(jsonMappingException.getMessage().contains("Expecting a 'columns' property")); - } - - @Test - public void testObjectDeserializer() throws IOException { - - BinaryResponse response = esClient.esql().query(q -> q - .query("FROM foo") - .format(EsqlFormat.Json) - ); - - Iterable data = esClient.esql().query( - new ObjectsEsqlAdapter<>(Data.class), - "FROM employees | STATS avg_salary = AVG(salary) by country" - ); - - for (Data d: data) { - System.out.println(d.lang + " " + d.avg_salary); - } - } - - @Test - public void testResultSetAdapter() throws Exception { - - ResultSet resultSet = esClient.esql().query( - ResultSetEsqlAdapter.INSTANCE, - "FROM employees | STATS avg_salary = AVG(salary) by country" - ); - - assertEquals(2, resultSet.getMetaData().getColumnCount()); - assertEquals(Types.DOUBLE, resultSet.getMetaData().getColumnType(1)); - assertEquals(Types.VARCHAR, resultSet.getMetaData().getColumnType(2)); - - while (resultSet.next()) { - System.out.println(resultSet.getDouble("avg_salary") + " " + resultSet.getString(2)); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/ClientTests.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/ClientTests.java deleted file mode 100644 index 2b5d9332a..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/ClientTests.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments; - -import co.elastic.clients.elasticsearch.experiments.api.Bar; -import co.elastic.clients.elasticsearch.experiments.api.FooRequest; -import co.elastic.clients.elasticsearch.experiments.api.FooResponse; -import co.elastic.clients.elasticsearch.experiments.api.query2.Query; -import co.elastic.clients.elasticsearch.experiments.api.query2.TermsQuery; -import co.elastic.clients.elasticsearch.experiments.base.Client; -import co.elastic.clients.transport.Endpoint; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.Collections; - -public class ClientTests { - - @Test - public void testClient() throws Exception { - - Client client = new Client(){ - @Override - protected ResponseT performRequest( - RequestT request, Endpoint endpoint - ) throws IOException { - // don't care for now, we're testing compilation - return null; - } - }; - - client.foo(fb -> fb - .name("z") - .value(1) - .routing("fooo") - .query(q -> q - .bool(b-> b - .add_must(m -> m.terms((TermsQuery) null)) - ) - //.terms(tq -> tq.term("")) - .meta(Collections.emptyMap()) - ) - ); - - // Builders everywhere - FooResponse r1 = client.foo( - FooRequest.builder() - .name("z") - .value(1) - .bar(Bar.builder() - .name("Raise the bar") - .build() - ) - .build() - ); - - // Illustrates creating an object outside of the client call - TermsQuery filter = TermsQuery.builder() - .field("foo") - .term("bar") - .build(); - - Query filter2 = new Query.Builder() - .terms(t -> t - .field("foo") - .term("bar") - ).build(); - - // Fluid lambda-based builders - FooResponse r2 = client.foo(f -> f - .name("z") - .value(1) - .bar(bar -> bar - .name("Raise the bar") - ) - .query(q -> q - .bool(b -> b - .add_must(q1 -> q1.terms(filter)) - .add_must(q1 -> q1 - .terms(t -> t.field("a").term("b")) - ) - .add_must(q1 -> q1 - .terms(t -> t.field("a").term("b")) - ) - .minimumShouldMatch(2) - ) - ) - ); - } -} - diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/ParsingTests.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/ParsingTests.java deleted file mode 100644 index af207e644..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/ParsingTests.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments; - -import co.elastic.clients.elasticsearch.experiments.api.FooRequest; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import jakarta.json.spi.JsonProvider; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import jakarta.json.stream.JsonParsingException; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; - -public class ParsingTests extends Assertions { - - @Test - public void testFoo() throws Exception { - - try { - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - FooRequest foo = FooRequest.builder() - .name("z") - .value(1) - .indices("a", "b", "c") - .bar(b -> b - .name("Raise the bar") - ) - .build(); - - JsonProvider provider = JsonpUtils.provider(); - JsonGenerator generator = provider.createGenerator(baos); - foo.serialize(generator, new JsonbJsonpMapper()); - - generator.close(); - String str = baos.toString(); - - assertEquals("{\"name\":\"z\",\"value\":1,\"indices\":[\"a\",\"b\",\"c\"],\"bar\":{\"name\":\"Raise the bar\"}}", str); - - JsonParser parser = provider.createParser(new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8))); - - FooRequest foo2 = FooRequest.parser().deserialize(parser, new JsonbJsonpMapper()); - - assertEquals(foo.name(), foo2.name()); - assertEquals(foo.value(), foo2.value()); - assertNull(foo2.size()); - assertEquals(foo.indices(), foo2.indices()); - assertEquals("Raise the bar", foo.bar().name()); - } catch (JsonParsingException je) { - throw new JsonParsingException(je.getMessage() + " at " + je.getLocation(), je, je.getLocation()); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/UnionVariant.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/UnionVariant.java deleted file mode 100644 index 34090cb9c..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/UnionVariant.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments; - -/** - * An implementation of a variant type. - */ -public interface UnionVariant { - - /** - * Get the type of this object when used as a variant - */ - Tag _variantType(); -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/Bar.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/Bar.java deleted file mode 100644 index e7718e037..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/Bar.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.api; - -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import javax.annotation.Nullable; - -public class Bar implements JsonpSerializable { - - private final String name; - - @Nullable - public String name() { - return this.name; - } - - public Bar(Bar.Builder builder) { - this.name = builder.name; - } - - @Override - public void serialize(JsonGenerator builder, JsonpMapper mapper) { - builder.writeStartObject(); - if (this.name != null) builder.write("name", this.name); - builder.writeEnd(); - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder implements ObjectBuilder { - private String name; - - public Bar.Builder name(@Nullable String name) { - this.name = name; - return this; - } - - public Bar build() { - return new Bar(this); - } - } - - private static final JsonpDeserializer PARSER; - - public static JsonpDeserializer parser() { - return PARSER; - } - - static { - ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); - - op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); - - PARSER = new ObjectBuilderDeserializer<>(op); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/DateMathTimeUnit.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/DateMathTimeUnit.java deleted file mode 100644 index a03cbe1e2..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/DateMathTimeUnit.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.api; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializer; - -public enum DateMathTimeUnit implements JsonEnum { - - Year("Y"), - Month("M"), - Day("D"), - Hour("h"), - Minute("m"), - Second("s"); - - private final String jsonValue; - - DateMathTimeUnit(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonpDeserializer PARSER; - - static { - PARSER = new Deserializer<>(DateMathTimeUnit.values()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooOptRequest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooOptRequest.java deleted file mode 100644 index 7a4c4827a..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooOptRequest.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.api; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.endpoints.SimpleEndpoint; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.OptionalInt; - -import static java.util.Objects.requireNonNull; - -// Implementing ToXContent is optional, only if there's a request body -public class FooOptRequest implements JsonpSerializable { - - //=========================================== - // Fields and getters - //=========================================== - - //------------------------------------------- - // A required String - - private final String name; - - @Nonnull - public final String name() { - return this.name; - } - - //------------------------------------------- - // An optional String - - private final String routing; - - @Nonnull - public final Optional routing() { - return Optional.ofNullable(this.routing); - } - - //------------------------------------------- - // A required primitive type - - private final int value; - - public int value() { - return this.value; - } - - //------------------------------------------- - // An optional primitive type - private final OptionalInt size; - - /** - * Description for field {@code size} - */ - @Nonnull - public final OptionalInt size() { - return this.size; - } - - //------------------------------------------- - // An optional array - - private final List indices; - - @Nonnull - public final Optional> indices() { - return Optional.ofNullable(this.indices); - } - - //------------------------------------------- - // An optional sub-object - - private final Bar bar; - - @Nonnull - public Optional bar() { - return Optional.ofNullable(this.bar); - } - - public FooOptRequest(Builder builder) { - this.name = builder.name; - this.routing = builder.routing; - this.value = builder.value; - this.size = builder.size == null ? OptionalInt.empty() : OptionalInt.of(builder.size); - this.indices = builder.indices; - this.bar = builder.bar; - } - - //=========================================== - // Serialization - //=========================================== - - - @Override - public void serialize(JsonGenerator builder, JsonpMapper mapper) { - builder.writeStartObject(); - - // Classic approach is to use the deserialization field's preferred name: - // - // if (buckets.isPresent()) builder.field(INT_FIELD.getPreferredName(), buckets.getAsInt()); - // - // In a generated code context we can use the string constant, which also avoids declaring ParseField if we - // only serialize (e.g. requests) - - // required field - builder.write("name", this.name); - - // optional field - if (this.routing != null) builder.write("routing", this.routing); - - // required field - builder.write("value", value); - - // optional field - if (this.size.isPresent()) builder.write("size", this.size.getAsInt()); - - // We could just call this and let the builder will handle it by itself with: - // - // if (this.indices != null) builder.field("indices", this.indices); - // - // But the logic is a bit involved (like checking circular dependencies) so we use a more direct implementation: - if (this.indices != null) { - builder.writeKey("indices").writeStartArray(); - for (String str : this.indices) builder.write(str); - builder.writeEnd(); - } - - if (this.bar != null) { - builder.writeKey("bar"); - this.bar.serialize(builder, mapper); - } - - builder.writeEnd(); - } - - //=========================================== - // Builder - //=========================================== - - public static Builder builder() { - return new Builder(); - } - - // Constructor with required fields - public static Builder builder(String name, int size) { - Builder result = new Builder(); - result.name(name); - result.size(size); - return result; - } - - public static class Builder implements ObjectBuilder { - private String name; - private String routing; - private int value; - private boolean value$isSet = false; - private Integer size; - private List indices; - private Bar bar; - - public final Builder name(@Nonnull String v) { - this.name = requireNonNull(v); - return this; - } - - public final Builder routing(@Nullable String v) { - this.routing = v; - return this; - } - - public final Builder value(int v) { - this.value = v; - this.value$isSet = true; - return this; - } - - public final Builder size(@Nullable Integer v) { - this.size = v; - return this; - } - - public final Builder indices(@Nullable List v) { - indices = v; - return this; - } - - // Convenience variant with varargs - public final Builder indices(String... v) { - indices = Arrays.asList(v); - return this; - } - - public Builder bar(@Nullable Bar v) { - bar = v; - return this; - } - - public Builder bar(@Nullable Bar.Builder v) { - bar = v.build(); - return this; - } - - public FooOptRequest build() { - requireNonNull(this.name, "Name was not set"); - requireTrue(this.value$isSet, "Value was not set"); - return new FooOptRequest(this); - } - } - - //=========================================== - // Deserialization - //=========================================== - -// // Only expose the most general interface to hide implementation details that may change over time. -// public static final ContextParser PARSER; -// -// static { -// ObjectParser op = -// new ObjectParser<>(FooOptRequest.class.getName(), FooOptRequest.Builder::new); -// -// op.declareString(Builder::name, new ParseField("name")); -// op.declareString(Builder::routing, new ParseField("routing")); -// -// op.declareInt(Builder::value, new ParseField("value")); -// op.declareInt(Builder::size, new ParseField("size")); -// -// op.declareStringArray(Builder::indices, new ParseField("indices")); -// op.declareObject(Builder::bar, Bar.PARSER, new ParseField("bar")); -// -// PARSER = new ObjectBuilderParser<>(op); -// } - - public static final Endpoint ENDPOINT = - new SimpleEndpoint( - "foo", - r -> "POST", - r -> "/foo", - SimpleEndpoint.emptyMap(), - SimpleEndpoint.emptyMap(), - SimpleEndpoint.emptyMap(), - true, - FooResponse.PARSER - ) { - }; - - public static void requireTrue(boolean v, String message) { - if (!v) throw new IllegalStateException(message); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooRequest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooRequest.java deleted file mode 100644 index 6c802c66a..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooRequest.java +++ /dev/null @@ -1,315 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.api; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.elasticsearch.experiments.api.query2.Query; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.endpoints.SimpleEndpoint; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Arrays; -import java.util.List; -import java.util.function.Function; - -import static java.util.Objects.requireNonNull; - -// Implementing ToXContent is optional, only if there's a request body -public class FooRequest implements JsonpSerializable { - - //=========================================== - // Fields and getters - //=========================================== - - //------------------------------------------- - // A required String - - private final String name; - - @Nonnull - public final String name() { - return this.name; - } - - //------------------------------------------- - // An optional String - - private final String routing; - - @Nullable - public final String routing() { - return this.routing; - } - - //------------------------------------------- - // A required primitive type - - private final int value; - - public int value() { - return this.value; - } - - //------------------------------------------- - // An optional primitive type, represented as a nullable boxed value - - private final Integer size; - - /** - * Description for field {@code size} - */ - @Nullable - public final Integer size() { - return this.size; - } - - //------------------------------------------- - // An optional array - - private final List indices; - - /** - * A string[] property - */ - @Nullable - public final List indices() { - return this.indices; - } - - //------------------------------------------- - // An optional sub-object - - private final Bar bar; - - @Nullable - public Bar bar() { - return this.bar; - } - - //------------------------------------------- - // An optional query - - private final Query query; - - @Nullable - public Query query() { - return this.query; - } - - //------------------------------------------- - - public FooRequest(Builder builder) { - this.name = builder.name; - this.routing = builder.routing; - this.value = builder.value; - this.size = builder.size; - this.indices = builder.indices; - this.bar = builder.bar; - this.query = builder.query; - } - - - //=========================================== - // Builder - //=========================================== - - public static class Builder implements ObjectBuilder { - protected String name; - protected String routing; - protected int value; - protected boolean value$isSet = false; - protected Integer size; - protected List indices; - protected Bar bar; - protected Query query; - - public final Builder name(@Nonnull String v) { - this.name = requireNonNull(v); - return this; - } - - public final Builder routing(String v) { - this.routing = v; - return this; - } - - public final Builder value(int v) { - this.value = v; - this.value$isSet = true; - return this; - } - - public final Builder size(@Nullable Integer v) { - this.size = v; - return this; - } - - public final Builder indices(@Nullable List v) { - indices = v; - return this; - } - - // Convenience variant with varargs - public final Builder indices(String... v) { - indices = Arrays.asList(v); - return this; - } - - public Builder bar(@Nullable Bar v) { - bar = v; - return this; - } - - public Builder bar(Function> b) { - return bar(b.apply(new Bar.Builder()).build()); - } - - public Builder query(Query v) { - this.query = v; - return this; - } - - public Builder query(Function> b) { - return query(b.apply(new Query.Builder()).build()); - } - - public FooRequest build() { - requireNonNull(this.name, "'name' was not set"); - requireTrue(this.value$isSet, "'value' was not set"); - return new FooRequest(this); - } - } - - public static Builder builder() { - return new Builder(); - } - - // Constructor with required fields - public static Builder builder(String name, int size) { - Builder result = new Builder(); - result.name(name); - result.size(size); - return result; - } - - //=========================================== - // Serialization - //=========================================== - - @Override - public void serialize(JsonGenerator builder, JsonpMapper mapper) { - builder.writeStartObject(); - - // Classic approach is to use the deserialization field's preferred name: - // - // if (buckets.isPresent()) builder.field(INT_FIELD.getPreferredName(), buckets.getAsInt()); - // - // In a generated code context we can use the string constant, which also avoids declaring ParseField if we - // only serialize (e.g. requests) - - // required field - builder.write("name", this.name); - - // optional field - if (this.routing != null) builder.write("routing", this.routing); - - // required field - builder.write("value", value); - - // optional field - if (this.size != null) builder.write("size", this.size.intValue()); - - // We could just call this and let the builder will handle it by itself with: - // - // if (this.indices != null) builder.field("indices", this.indices); - // - // But the logic is a bit involved (like checking circular dependencies) so we use a more direct implementation: - if (this.indices != null) { - builder.writeKey("indices").writeStartArray(); - for (String str : this.indices) builder.write(str); - builder.writeEnd(); - } - - if (this.bar != null) { - builder.writeKey("bar"); - this.bar.serialize(builder, mapper); - } - - if (this.query != null) { - builder.writeKey("query"); - this.query.serialize(builder, mapper); - } - - builder.writeEnd(); - } - - //=========================================== - // Deserialization - // (formally not needed for requests) - //=========================================== - - private static final JsonpDeserializer PARSER; - - public static JsonpDeserializer parser() { - return PARSER; - } - - static { - ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); - - op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); - op.add(Builder::routing, JsonpDeserializer.stringDeserializer(), "routing"); - op.add(Builder::value, "value"); // primitive type - op.add(Builder::size, "size"); - op.add(Builder::indices, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), "indices"); - op.add(Builder::bar, Bar.parser(), "bar"); - op.add(Builder::query, Query.parser(), "query"); - - PARSER = new ObjectBuilderDeserializer<>(op); - } - - //=========================================== - // Endpoint - //=========================================== - - public static final Endpoint ENDPOINT = - new SimpleEndpoint<>( - "foo", - r -> "POST", - r -> "/foo", - SimpleEndpoint.emptyMap(), - SimpleEndpoint.emptyMap(), - SimpleEndpoint.emptyMap(), - true, - FooResponse.PARSER - ); - - public static void requireTrue(boolean v, String message) { - if (!v) throw new IllegalStateException(message); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooResponse.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooResponse.java deleted file mode 100644 index ffd5369db..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooResponse.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.api; - -import co.elastic.clients.json.JsonpDeserializer; - -public class FooResponse { - - public static JsonpDeserializer PARSER = null; -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/BoolQuery.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/BoolQuery.java deleted file mode 100644 index 116f8d2a0..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/BoolQuery.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.api.query2; - -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.function.Function; - -public class BoolQuery implements Query.Variant, JsonpSerializable { - - private final Collection should; - private final Collection must; - private final Union2 minimumShouldMatch; - - public BoolQuery(BoolQuery.Builder builder) { - this.should = builder.should; - this.must = builder.must; - this.minimumShouldMatch = builder.minimumShouldMatch; - } - - @Override - public Query.Kind _variantType() { - return Query.Kind.Bool; - } - - public Collection should() { - return should; - } - - public Collection must() { - return must; - } - - public Union2 minimumShouldMatch() { - return minimumShouldMatch; - } - - @Override - public void serialize(JsonGenerator builder, JsonpMapper mapper) { - builder.writeStartObject(); - - if (should != null) { - builder.writeKey("should"); - builder.writeStartArray(); - for (Query v: should) v.serialize(builder, mapper); - builder.writeEnd(); - } - - if (should != null) { - builder.writeKey("must"); - builder.writeStartArray(); - for (Query v: must) v.serialize(builder, mapper); - builder.writeEnd(); - } - - if (minimumShouldMatch != null) { - builder.writeKey("minimum_should_match"); - // Unions have to be expanded inline as serialization depends on the value type. - this.minimumShouldMatch.serialize(builder, mapper, - (v, b, p) -> builder.write(v), - (v, b, p) -> builder.write(v) - ); - } - - builder.writeEnd(); - } - - public static class Builder implements ObjectBuilder { - - private Collection should; - private Collection must; - private Union2 minimumShouldMatch; - - public BoolQuery.Builder should(Collection v) { - this.should = v; - return this; - } - - public BoolQuery.Builder add_should(@Nullable Query v) { - if (v == null) return this; - if (this.should == null) this.should = new ArrayList<>(); - this.should.add(v); - return this; - } - - public BoolQuery.Builder add_should(Function> v) { - return add_should(v.apply(new Query.Builder()).build()); - } - - public BoolQuery.Builder must(Collection v) { - this.must = v; - return this; - } - - public BoolQuery.Builder add_must(@Nullable Query v) { - if (v == null) return this; - if (this.must == null) this.must = new ArrayList<>(); - this.must.add(v); - return this; - } - - public BoolQuery.Builder add_must(Function> v) { - return add_must(v.apply(new Query.Builder()).build()); - } - - // Expand all union members - // TODO: check unions with nested structures and fluent builders - public BoolQuery.Builder minimumShouldMatch(int v) { - return minimumShouldMatch(Union2.ofA(v)); - } - - public BoolQuery.Builder minimumShouldMatch(String v) { - return minimumShouldMatch(Union2.ofB(v)); - } - - public BoolQuery.Builder minimumShouldMatch(Union2 v) { - this.minimumShouldMatch = v; - return this; - } - - @Override - public BoolQuery build() { - return new BoolQuery(this); - } - } - - private static final JsonpDeserializer PARSER; - - public static JsonpDeserializer parser() { - return PARSER; - } - - static { - ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); - - op.add(Builder::must, JsonpDeserializer.arrayDeserializer(Query.parser()), "must"); - op.add(Builder::should, JsonpDeserializer.arrayDeserializer(Query.parser()), "should"); - - op.add(Builder::minimumShouldMatch, new Union2.JsonpParser<>( - JsonpDeserializer.integerDeserializer(), - JsonpDeserializer.stringDeserializer() - ), "minimum_should_match"); - - PARSER = new ObjectBuilderDeserializer<>(op); - } - -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/Query.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/Query.java deleted file mode 100644 index d1ae929ba..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/Query.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.api.query2; - -import co.elastic.clients.elasticsearch.experiments.UnionVariant; -import co.elastic.clients.json.BuildFunctionDeserializer; -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.TaggedUnion; -import co.elastic.clients.util.TaggedUnionUtils; -import jakarta.json.JsonValue; -import jakarta.json.stream.JsonGenerator; - -import java.util.Map; -import java.util.function.Function; - -public class Query implements TaggedUnion, JsonpSerializable { - - public interface Variant extends UnionVariant, JsonpSerializable { - default Query _toQuery() { - return new Query(this); - } - } - - public enum Kind implements JsonEnum { - Bool("bool"), - Terms("terms"); - - private final String jsonValue; - - Kind(String jsonValue) { - this.jsonValue = jsonValue; - } - - @Override - public String jsonValue() { - return null; - } - } - - private static final String BOOL = "bool"; - private static final String TERMS = "terms"; - - private final Kind _variantType; - private final Variant _variantValue; - - @Override - public Kind _kind() { - return _variantType; - } - - @Override - public Variant _get() { - return _variantValue; - } - - // A container-level property that lives besides the variant, like "meta" and "aggs" in aggregations - private Map meta; - - public Query(Variant value) { - this._variantType = value._variantType(); - this._variantValue = value; - } - - private Query(Builder builder) { - this._variantType = builder.$tag; - this._variantValue = builder.$variant; - - this.meta = builder.meta; - } - - // Accessors to container properties - public Map meta() { - return this.meta; - } - - public BoolQuery bool() { - return TaggedUnionUtils.get(this, Kind.Bool); - } - - public TermsQuery terms() { - return TaggedUnionUtils.get(this, Kind.Terms); - } - - @Override - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - generator.writeKey(_variantType.jsonValue); - if (_variantValue instanceof JsonpSerializable) { - ((JsonpSerializable) _variantValue).serialize(generator, mapper); - } else { - // Other serialization - } - if (meta != null) { - generator.writeStartObject("meta"); - for (Map.Entry e: meta.entrySet()) { - generator.write(e.getKey(), e.getValue()); - } - generator.writeEnd(); - } - generator.writeEnd(); - } - - public static class Builder { - - private Variant $variant; - private Kind $tag; - private Map meta; - - // Container properties - public Builder meta(Map value) { - this.meta = value; - return this; - } - - // Variants - // - // We return a container builder and not a builder. This is because a union accepts a single variant and we - // don't want to allow choosing more than one yet we still want to be able to set container-level properties - - public ContainerBuilder bool(BoolQuery v) { - this.$variant = v; - this.$tag = Kind.Bool; - return new ContainerBuilder(); - } - - // If we don't have container properties, the container builder is not necessary - public ObjectBuilder foo() { - return this::build; - } - - public ContainerBuilder bool(Function> f) { - return this.bool(f.apply(new BoolQuery.Builder()).build()); - } - - public ContainerBuilder terms(TermsQuery v) { - this.$variant = v; - this.$tag = Kind.Terms; - return new ContainerBuilder(); - } - - public ContainerBuilder terms(Function> f) { - return this.terms(f.apply(new TermsQuery.Builder()).build()); - } - - // Protected, only called by the container - protected Query build() { - return new Query(this); - } - - /** - * A builder that only contains container-level properties. If we don't have such properties, this - * can be replaced with an {@code ObjectBuilder} - */ - public class ContainerBuilder implements ObjectBuilder { - - public ContainerBuilder meta(Map value) { - Builder.this.meta(value); - return this; - } - - public Query build() { - return Builder.this.build(); - } - } - } - - private static volatile JsonpDeserializer PARSER; - - public static JsonpDeserializer parser() { - if (PARSER == null) { - ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); - op.add(Builder::bool, BoolQuery.parser(), "bool"); - op.add(Builder::terms, TermsQuery.parser(), "terms"); - // parser for "meta" (a map) - - PARSER = new BuildFunctionDeserializer<>(op, Builder::build); - } - - return PARSER; - } - - -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/QueryTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/QueryTest.java deleted file mode 100644 index 313905268..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/QueryTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.api.query2; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.util.Collection; - -public class QueryTest extends Assertions { - @Test - public void testQuery() { - BoolQuery bq = new BoolQuery.Builder().build(); - - Query q = new Query(bq); - - assertEquals(Query.Kind.Bool, q._kind()); - - Query.Variant v = q._get(); - assertEquals(Query.Kind.Bool, v._variantType()); - - Query q1 = v._toQuery(); - - Collection must = q.bool().must(); - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/TermsQuery.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/TermsQuery.java deleted file mode 100644 index 3037faced..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/TermsQuery.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.api.query2; - -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -public class TermsQuery implements JsonpSerializable, Query.Variant { - - private final String field; - private final String term; - - public TermsQuery(TermsQuery.Builder builder) { - this.field = builder.field; - this.term = builder.term; - } - - @Override - public Query.Kind _variantType() { - return Query.Kind.Terms; - } - - public String field() { - return this.field; - } - - public String term() { - return this.term; - } - - @Override - public void serialize(JsonGenerator builder, JsonpMapper mapper) { - // We only serialize our content. It's the enclosing class responsibility to output the variant's discriminant. - // This allows using this class in non-variant contexts. - builder.writeStartObject(); - if (this.field != null) { - builder.write("field", this.field); - } - - if (this.term != null) { - builder.write("term", this.term); - } - - builder.writeEnd(); - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder implements ObjectBuilder { - - private String field; - private String term; - - public Builder field(String v) { - this.field = v; - return this; - } - - public Builder term(String v) { - this.term = v; - return this; - } - - @Override - public TermsQuery build() { - return new TermsQuery(this); - } - } - - private static final JsonpDeserializer PARSER; - - public static JsonpDeserializer parser() { - return PARSER; - } - - static { - ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); - op.add(Builder::field, JsonpDeserializer.stringDeserializer(), "field"); - op.add(Builder::term, JsonpDeserializer.stringDeserializer(), "term"); - - PARSER = new ObjectBuilderDeserializer<>(op); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/Union2.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/Union2.java deleted file mode 100644 index 004c1703a..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/Union2.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.api.query2; - -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpDeserializerBase; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.util.TriConsumer; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import jakarta.json.stream.JsonParser.Event; -import jakarta.json.stream.JsonParsingException; - -/** - * A tagged union (also known as variant, sum type or coproduct) with two members. - * - * The union's value is one (and only one) of the possible variants. The variant in use is defined by the - * {@link #tag()}'s value. - * - * @param type of the first variant - * @param type of the second variant - */ - -// Design note: we cannot require A and B, and by extension Union2, to implement JsonpSerializable as they can be builtin types -// like String or Integer - -public class Union2 { - - /** - * The variant tag. - */ - public enum Tag{A, B}; - - private final Tag tag; - private final Object value; - - private Union2(Tag tag, Object value) { - this.tag = tag; - this.value = value; - } - - /** - * Creates a variant {@code A}. - */ - public static Union2 ofA(A value) { - return new Union2<>(Tag.A, value); - } - - /** - * Creates a variant {@code B}. - */ - public static Union2 ofB(B value) { - return new Union2<>(Tag.B, value); - } - - /** - * Get the variant's tag of this union. - * - * @return the variant's tag - */ - public Tag tag() { - return tag; - } - - /** - * Get the variant {@code A} of this union. - * - * @return the variant's value - * @throws IllegalStateException if the union is not holding a variant {@code A} - */ - public A a() { - return getVariant(Tag.A); - } - - /** - * Get the variant {@code B} of this union. - * - * @return the variant's value - * @throws IllegalStateException if the union is not holding a variant {@code B} - */ - public B b() { - return getVariant(Tag.B); - } - - private T getVariant(Tag tag) { - if (this.tag != tag) throw new IllegalStateException("Union holds variant " + tag); - - @SuppressWarnings("unchecked") - T result = (T)value; - - return result; - } - - //----------------------------------------------------------------------------------------------- - // Serialization / deserialization - - public void serialize( - JsonGenerator builder, JsonpMapper params, - TriConsumer a, - TriConsumer b - ) { - switch (this.tag) { - case A: - a.accept(this.a(), builder, params); - case B: - b.accept(this.b(), builder, params); - } - } - - public static class JsonpParser extends JsonpDeserializerBase> { - - private final JsonpDeserializer parserA; - private final JsonpDeserializer parserB; - - public JsonpParser( - JsonpDeserializer parserA, - JsonpDeserializer parserB - ) { - super(allAcceptedEvents(parserA, parserB)); - this.parserA = parserA; - this.parserB = parserB; - } - - @Override - public Union2 deserialize(JsonParser parser, JsonpMapper mapper, Event event) { - if (parserA.accepts(event)) { - return Union2.ofA(parserA.deserialize(parser, mapper, event)); - - } else if (parserB.accepts(event)) { - return Union2.ofB(parserB.deserialize(parser, mapper, event)); - - } else { - throw new JsonParsingException("Unexpected event '" + event + "'", parser.getLocation()); - } - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/Client.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/Client.java deleted file mode 100644 index f67b25981..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/Client.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.base; - -import co.elastic.clients.elasticsearch.experiments.api.FooRequest; -import co.elastic.clients.elasticsearch.experiments.api.FooResponse; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.Transport; -import co.elastic.clients.util.ObjectBuilder; - -import java.io.IOException; -import java.util.function.Function; - -public class Client { - - private Transport transport; - - public FooResponse foo(FooRequest request) throws IOException { - return performRequest(request, FooRequest.ENDPOINT); - } - - public FooResponse foo(Function> b) throws IOException { - return foo(b.apply(new FooRequest.Builder()).build()); - } - - protected ResponseT performRequest( - RequestT request, Endpoint endpoint - ) throws IOException { - return transport.performRequest(request, endpoint, null); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/PrimitiveUtils.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/PrimitiveUtils.java deleted file mode 100644 index a9e95d9a3..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/PrimitiveUtils.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.base; - -/** - * Support functions for primitive fields in generated classes - */ -public class PrimitiveUtils { - public static int checkedValue(int value, boolean isSet) { - mustBeSet(isSet); - return value; - } - - public static long checkedValue(long value, boolean isSet) { - mustBeSet(isSet); - return value; - } - - private static void mustBeSet(boolean isSet) { - if (!isSet) { - throw new IllegalStateException("Value is not set"); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/Variants.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/Variants.java deleted file mode 100644 index 6edd823a9..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/Variants.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.base; - -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import jakarta.json.stream.JsonParsingException; - -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; - -/** - * Describes the variants of a transport class, providing their name and parsers. It is representation-agnostic. - */ -public class Variants { - - private Function, Builder> builderFunc; - - private Map, String> variantNames; - private Map> parsers; - - /** - * Builds a new {@code Variants} from a builder-creation function. This approach allows the object to be built lazily, - * which is needed for recursive variant data structures (e.g. a query can be a boolean query that itself contains - * other queries). - * - * This is required because cyclic dependencies between static class initialization code can lead to unexpected - * behaviour (a subclass static init may be called while static init of the parent class is not finished). - */ - public Variants(Function, Builder> b) { - this.builderFunc = b; - } - - public Variants(Builder builder) { - this.variantNames = builder.variantNames; - this.parsers = builder.parsers; - } - - public String variantName(Class clazz) { - build(); - return variantNames.get(clazz); - } - - public JsonpDeserializer variantParser(String name) { - build(); - return parsers.get(name); - } - - private void build() { - if (builderFunc != null) { - Builder builder = builderFunc.apply(new Builder<>()); - this.variantNames = builder.variantNames; - this.parsers = builder.parsers; - this.builderFunc = null; - } - } - - //------------------------------------------------------------------------------------------------------------------- - - public static Builder builder() { - return new Builder<>(); - } - - public static class Builder { - private final Map, String> variantNames = new HashMap<>(); - private final Map> parsers = new HashMap<>(); - - public Builder add(String name, Class clazz, JsonpDeserializer parser) { - variantNames.put(clazz, name); - parsers.put(name, parser); - return this; - } - - public Variants build() { - return new Variants<>(this); - } - } - - //------------------------------------------------------------------------------------------------------------------- - - /** - * Variant serializer/deserializer using externally tagged JSON. - *
emptyList(), RequestOptions.DEFAULT.getHeaders()); - assertEquals(Collections.emptyMap(), RequestOptions.DEFAULT.getParameters()); - assertEquals(HttpAsyncResponseConsumerFactory.DEFAULT, - RequestOptions.DEFAULT.getHttpAsyncResponseConsumerFactory()); - assertEquals(RequestOptions.DEFAULT, RequestOptions.DEFAULT.toBuilder().build()); - } - - public void testAddHeader() { - try { - randomBuilder().addHeader(null, randomAsciiLettersOfLengthBetween(3, 10)); - fail("expected failure"); - } catch (NullPointerException e) { - assertEquals("header name cannot be null", e.getMessage()); - } - - try { - randomBuilder().addHeader(randomAsciiLettersOfLengthBetween(3, 10), null); - fail("expected failure"); - } catch (NullPointerException e) { - assertEquals("header value cannot be null", e.getMessage()); - } - - RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); - int numHeaders = between(0, 5); - List
headers = new ArrayList<>(); - for (int i = 0; i < numHeaders; i++) { - Header header = new RequestOptions.ReqHeader(randomAsciiAlphanumOfLengthBetween(5, 10), - randomAsciiAlphanumOfLength(3)); - headers.add(header); - builder.addHeader(header.getName(), header.getValue()); - } - RequestOptions options = builder.build(); - assertEquals(headers, options.getHeaders()); - - try { - options.getHeaders() - .add(new RequestOptions.ReqHeader(randomAsciiAlphanumOfLengthBetween(5, 10), - randomAsciiAlphanumOfLength(3))); - fail("expected failure"); - } catch (UnsupportedOperationException e) { - assertNull(e.getMessage()); - } - } - - public void testSetHttpAsyncResponseConsumerFactory() { - try { - RequestOptions.DEFAULT.toBuilder().setHttpAsyncResponseConsumerFactory(null); - fail("expected failure"); - } catch (NullPointerException e) { - assertEquals("httpAsyncResponseConsumerFactory cannot be null", e.getMessage()); - } - - HttpAsyncResponseConsumerFactory factory = mock(HttpAsyncResponseConsumerFactory.class); - RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); - builder.setHttpAsyncResponseConsumerFactory(factory); - RequestOptions options = builder.build(); - assertSame(factory, options.getHttpAsyncResponseConsumerFactory()); - } - - public void testAddParameters() { - try { - randomBuilder().addParameter(null, randomAsciiLettersOfLengthBetween(3, 10)); - fail("expected failure"); - } catch (NullPointerException e) { - assertEquals("parameter key cannot be null", e.getMessage()); - } - - try { - randomBuilder().addParameter(randomAsciiLettersOfLengthBetween(3, 10), null); - fail("expected failure"); - } catch (NullPointerException e) { - assertEquals("parameter value cannot be null", e.getMessage()); - } - - RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); - int numParameters = between(0, 5); - Map parameters = new HashMap<>(); - for (int i = 0; i < numParameters; i++) { - String key = randomAsciiAlphanumOfLengthBetween(5, 10); - String value = randomAsciiAlphanumOfLength(3); - - parameters.put(key, value); - builder.addParameter(key, value); - } - RequestOptions options = builder.build(); - assertEquals(parameters, options.getParameters()); - } - - public void testSetRequestBuilder() { - RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); - - RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); - int socketTimeout = 10000; - int connectTimeout = 100; - requestConfigBuilder.setConnectionRequestTimeout(Timeout.ofMilliseconds(socketTimeout)).setConnectTimeout(Timeout.ofMilliseconds(connectTimeout)); - RequestConfig requestConfig = requestConfigBuilder.build(); - - builder.setRequestConfig(requestConfig); - RequestOptions options = builder.build(); - assertSame(options.getRequestConfig(), requestConfig); - assertEquals(options.getRequestConfig().getConnectionRequestTimeout(), Timeout.ofMilliseconds(socketTimeout)); - assertEquals(options.getRequestConfig().getConnectTimeout(), Timeout.ofMilliseconds(connectTimeout)); - } - - public void testEqualsAndHashCode() { - RequestOptions request = randomBuilder().build(); - assertEquals(request, request); - - RequestOptions copy = copy(request); - assertEquals(request, copy); - assertEquals(copy, request); - assertEquals(request.hashCode(), copy.hashCode()); - - RequestOptions mutant = mutate(request); - assertNotEquals(request, mutant); - assertNotEquals(mutant, request); - } - - static RequestOptions.Builder randomBuilder() { - RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); - - if (randomBoolean()) { - int headerCount = between(1, 5); - for (int i = 0; i < headerCount; i++) { - builder.addHeader(randomAsciiAlphanumOfLength(3), randomAsciiAlphanumOfLength(3)); - } - } - - if (randomBoolean()) { - builder.setHttpAsyncResponseConsumerFactory(HttpAsyncResponseConsumerFactory.DEFAULT); - } - - if (randomBoolean()) { - builder.setWarningsHandler(randomBoolean() ? WarningsHandler.STRICT : WarningsHandler.PERMISSIVE); - } - - if (randomBoolean()) { - builder.setRequestConfig(RequestConfig.custom().build()); - } - - return builder; - } - - private static RequestOptions copy(RequestOptions options) { - return options.toBuilder().build(); - } - - private static RequestOptions mutate(RequestOptions options) { - RequestOptions.Builder mutant = options.toBuilder(); - int mutationType = between(0, 2); - switch (mutationType) { - case 0: - mutant.addHeader("extra", "m"); - return mutant.build(); - case 1: - mutant.setHttpAsyncResponseConsumerFactory(new HttpAsyncResponseConsumerFactory.BasicAsyncResponseConsumerFactory(5)); - return mutant.build(); - case 2: - mutant.setWarningsHandler(warnings -> { - fail("never called"); - return false; - }); - return mutant.build(); - default: - throw new UnsupportedOperationException("Unknown mutation type [" + mutationType + "]"); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestTests.java deleted file mode 100644 index f638fc2fe..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestTests.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import org.apache.hc.core5.http.ContentType; -import org.apache.hc.core5.http.HttpEntity; -import org.apache.hc.core5.http.io.entity.ByteArrayEntity; -import org.apache.hc.core5.http.io.entity.StringEntity; -import org.elasticsearch.client.Request; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RequestOptionsTests; -import org.elasticsearch.client.consumer.HttpAsyncResponseConsumerFactory; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.fail; - -public class RequestTests extends RestClientTestCase { - public void testConstructor() { - final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); - final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); - - try { - new Request(null, endpoint); - fail("expected failure"); - } catch (NullPointerException e) { - assertEquals("method cannot be null", e.getMessage()); - } - - try { - new Request(method, null); - fail("expected failure"); - } catch (NullPointerException e) { - assertEquals("endpoint cannot be null", e.getMessage()); - } - - final Request request = new Request(method, endpoint); - assertEquals(method, request.getMethod()); - assertEquals(endpoint, request.getEndpoint()); - } - - public void testAddParameters() { - final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); - final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); - int parametersCount = between(1, 3); - final Map parameters = new HashMap<>(parametersCount); - while (parameters.size() < parametersCount) { - parameters.put(randomAsciiLettersOfLength(5), randomAsciiLettersOfLength(5)); - } - Request request = new Request(method, endpoint); - - try { - request.addParameter(null, "value"); - fail("expected failure"); - } catch (NullPointerException e) { - assertEquals("url parameter name cannot be null", e.getMessage()); - } - - for (Map.Entry entry : parameters.entrySet()) { - request.addParameter(entry.getKey(), entry.getValue()); - } - assertEquals(parameters, request.getParameters()); - - // Test that adding parameters with a null value is ok. - request.addParameter("is_null", null); - parameters.put("is_null", null); - assertEquals(parameters, request.getParameters()); - - // Test that adding a duplicate parameter fails - String firstValue = randomBoolean() ? null : "value"; - request.addParameter("name", firstValue); - try { - request.addParameter("name", randomBoolean() ? firstValue : "second_value"); - fail("expected failure"); - } catch (IllegalArgumentException e) { - assertEquals("url parameter [name] has already been set to [" + firstValue + "]", e.getMessage()); - } - } - - public void testSetEntity() { - final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); - final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); - final HttpEntity entity = randomBoolean() - ? new StringEntity(randomAsciiLettersOfLengthBetween(1, 100), ContentType.TEXT_PLAIN) - : null; - - Request request = new Request(method, endpoint); - request.setEntity(entity); - assertEquals(entity, request.getEntity()); - } - - public void testSetJsonEntity() throws IOException { - final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); - final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); - - Request request = new Request(method, endpoint); - assertNull(request.getEntity()); - - final String json = randomAsciiLettersOfLengthBetween(1, 100); - request.setJsonEntity(json); - assertEquals(ContentType.APPLICATION_JSON.toString(), request.getEntity().getContentType()); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - request.getEntity().writeTo(os); - assertEquals(json, new String(os.toByteArray(), ContentType.APPLICATION_JSON.getCharset())); - } - - public void testSetOptions() { - final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); - final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); - Request request = new Request(method, endpoint); - - try { - request.setOptions((RequestOptions) null); - fail("expected failure"); - } catch (NullPointerException e) { - assertEquals("options cannot be null", e.getMessage()); - } - - try { - request.setOptions((RequestOptions.Builder) null); - fail("expected failure"); - } catch (NullPointerException e) { - assertEquals("options cannot be null", e.getMessage()); - } - - RequestOptions.Builder builder = RequestOptionsTests.randomBuilder(); - request.setOptions(builder); - assertEquals(builder.build(), request.getOptions()); - - builder = RequestOptionsTests.randomBuilder(); - RequestOptions options = builder.build(); - request.setOptions(options); - assertSame(options, request.getOptions()); - } - - public void testEqualsAndHashCode() { - Request request = randomRequest(); - assertEquals(request, request); - - Request copy = copy(request); - assertEquals(request, copy); - assertEquals(copy, request); - assertEquals(request.hashCode(), copy.hashCode()); - - Request mutant = mutate(request); - assertNotEquals(request, mutant); - assertNotEquals(mutant, request); - } - - private static Request randomRequest() { - Request request = new Request( - randomFrom(new String[] { "GET", "PUT", "DELETE", "POST", "HEAD", "OPTIONS" }), - randomAsciiAlphanumOfLength(5) - ); - - int parameterCount = between(0, 5); - for (int i = 0; i < parameterCount; i++) { - request.addParameter(randomAsciiAlphanumOfLength(i), randomAsciiLettersOfLength(3)); - } - - if (randomBoolean()) { - if (randomBoolean()) { - request.setJsonEntity(randomAsciiAlphanumOfLength(10)); - } else { - request.setEntity( - randomFrom( - new HttpEntity[] { - new StringEntity(randomAsciiAlphanumOfLength(10), ContentType.APPLICATION_JSON), - new ByteArrayEntity(randomBytesOfLength(40), ContentType.APPLICATION_JSON) } - ) - ); - } - } - - if (randomBoolean()) { - RequestOptions.Builder options = request.getOptions().toBuilder(); - options.setHttpAsyncResponseConsumerFactory(new HttpAsyncResponseConsumerFactory.BasicAsyncResponseConsumerFactory(1)); - request.setOptions(options); - } - - return request; - } - - private static Request copy(Request request) { - Request copy = new Request(request.getMethod(), request.getEndpoint()); - copyMutables(request, copy); - return copy; - } - - private static Request mutate(Request request) { - if (randomBoolean()) { - // Mutate request or method but keep everything else constant - Request mutant = randomBoolean() - ? new Request(request.getMethod() + "m", request.getEndpoint()) - : new Request(request.getMethod(), request.getEndpoint() + "m"); - copyMutables(request, mutant); - return mutant; - } - Request mutant = copy(request); - int mutationType = between(0, 2); - switch (mutationType) { - case 0: - mutant.addParameter(randomAsciiAlphanumOfLength(mutant.getParameters().size() + 4), "extra"); - return mutant; - case 1: - mutant.setJsonEntity("mutant"); // randomRequest can't produce this value - return mutant; - case 2: - RequestOptions.Builder options = mutant.getOptions().toBuilder(); - options.addHeader("extra", "m"); - mutant.setOptions(options); - return mutant; - default: - throw new UnsupportedOperationException("Unknown mutation type [" + mutationType + "]"); - } - } - - private static void copyMutables(Request from, Request to) { - for (Map.Entry param : from.getParameters().entrySet()) { - to.addParameter(param.getKey(), param.getValue()); - } - to.setEntity(from.getEntity()); - to.setOptions(from.getOptions()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/ResponseExceptionTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/ResponseExceptionTests.java deleted file mode 100644 index 83cef07fe..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/ResponseExceptionTests.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - - -import org.apache.hc.core5.http.ContentType; -import org.apache.hc.core5.http.HttpEntity; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.ParseException; -import org.apache.hc.core5.http.ProtocolVersion; -import org.apache.hc.core5.http.io.entity.EntityUtils; -import org.apache.hc.core5.http.io.entity.InputStreamEntity; -import org.apache.hc.core5.http.io.entity.StringEntity; -import org.apache.hc.core5.http.message.BasicClassicHttpResponse; -import org.apache.hc.core5.http.message.RequestLine; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.ResponseException; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Locale; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; - -public class ResponseExceptionTests extends RestClientTestCase { - - public void testResponseException() throws IOException, ParseException { - ProtocolVersion protocolVersion = new ProtocolVersion("http", 1, 1); - BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(500, "Internal Server Error"); - - String responseBody = "{\"error\":{\"root_cause\": {}}}"; - boolean hasBody = getRandom().nextBoolean(); - if (hasBody) { - HttpEntity entity; - if (getRandom().nextBoolean()) { - entity = new StringEntity(responseBody, ContentType.APPLICATION_JSON); - } else { - // test a non repeatable entity - entity = new InputStreamEntity( - new ByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8)), - ContentType.APPLICATION_JSON - ); - } - httpResponse.setEntity(entity); - } - - RequestLine requestLine = new RequestLine("GET", "/", protocolVersion); - HttpHost httpHost = new HttpHost("localhost", 9200); - Response response = new Response(requestLine, httpHost, httpResponse); - ResponseException responseException = new ResponseException(response); - - assertSame(response, responseException.getResponse()); - if (hasBody) { - assertEquals(responseBody, EntityUtils.toString(responseException.getResponse().getEntity())); - } else { - assertNull(responseException.getResponse().getEntity()); - } - - String message = String.format( - Locale.ROOT, - "method [%s], host [%s], URI [%s], status line [%s]", - response.getRequestLine().getMethod(), - response.getHost(), - response.getRequestLine().getUri(), - response.getStatusCode() - ); - - if (hasBody) { - message += "\n" + responseBody; - } - assertEquals(message, responseException.getMessage()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientBuilderIntegTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientBuilderIntegTests.java deleted file mode 100644 index 50aded05a..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientBuilderIntegTests.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; -import com.sun.net.httpserver.HttpsConfigurator; -import com.sun.net.httpserver.HttpsServer; -import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.Request; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.ResponseListener; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.RestClientTestCase; -import org.elasticsearch.mocksocket.MockHttpServer; -import org.junit.AfterClass; -import org.junit.BeforeClass; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLHandshakeException; -import javax.net.ssl.TrustManagerFactory; -import java.io.IOException; -import java.io.InputStream; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.KeyFactory; -import java.security.KeyStore; -import java.security.cert.Certificate; -import java.security.cert.CertificateFactory; -import java.security.spec.PKCS8EncodedKeySpec; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.startsWith; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * Integration test to validate the builder builds a client with the correct configuration - */ -public class RestClientBuilderIntegTests extends RestClientTestCase { - - private static HttpsServer httpsServer; - - @BeforeClass - public static void startHttpServer() throws Exception { - httpsServer = MockHttpServer.createHttps(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0) - , 0); - httpsServer.setHttpsConfigurator(new HttpsConfigurator(getSslContext())); - httpsServer.createContext("/", new ResponseHandler()); - httpsServer.start(); - } - - private static class ResponseHandler implements HttpHandler { - @Override - public void handle(HttpExchange httpExchange) throws IOException { - httpExchange.sendResponseHeaders(200, -1); - httpExchange.close(); - } - } - - @AfterClass - public static void stopHttpServers() throws IOException { - httpsServer.stop(0); - httpsServer = null; - } - - public void testBuilderUsesDefaultSSLContext() throws Exception { - assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm()); - final SSLContext defaultSSLContext = SSLContext.getDefault(); - try { - try (RestClient client = buildRestClient()) { - try { - client.performRequest(new Request("GET", "/")); - fail("connection should have been rejected due to SSL handshake"); - } catch (Exception e) { - assertThat(e, instanceOf(SSLHandshakeException.class)); - } - } - - SSLContext.setDefault(getSslContext()); - try (RestClient client = buildRestClient()) { - Response response = client.performRequest(new Request("GET", "/")); - assertEquals(200, response.getStatusCode()); - } - } finally { - SSLContext.setDefault(defaultSSLContext); - } - } - - public void testBuilderSetsThreadName() throws Exception { - assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm()); - final SSLContext defaultSSLContext = SSLContext.getDefault(); - try { - SSLContext.setDefault(getSslContext()); - try (RestClient client = buildRestClient()) { - final CountDownLatch latch = new CountDownLatch(1); - client.performRequestAsync(new Request("GET", "/"), new ResponseListener() { - @Override - public void onSuccess(Response response) { - assertThat( - Thread.currentThread().getName(), - allOf( - startsWith(RestClientBuilder.THREAD_NAME_PREFIX), - containsString("elasticsearch"), - containsString("rest-client") - ) - ); - assertEquals(200, response.getStatusCode()); - latch.countDown(); - } - - @Override - public void onFailure(Exception exception) { - throw new AssertionError("unexpected", exception); - } - }); - assertTrue(latch.await(10, TimeUnit.SECONDS)); - } - } finally { - SSLContext.setDefault(defaultSSLContext); - } - } - - private RestClient buildRestClient() { - InetSocketAddress address = httpsServer.getAddress(); - return RestClient.builder(new HttpHost("https", address.getHostString(), address.getPort())).build(); - } - - private static SSLContext getSslContext() throws Exception { - SSLContext sslContext = SSLContext.getInstance(getProtocol()); - try ( - InputStream certFile = RestClientBuilderIntegTests.class.getResourceAsStream("/test.crt"); - InputStream keyStoreFile = RestClientBuilderIntegTests.class.getResourceAsStream( - "/test_truststore.jks") - ) { - // Build a keystore of default type programmatically since we can't use JKS keystores to - // init a KeyManagerFactory in FIPS 140 JVMs. - KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - keyStore.load(null, "password".toCharArray()); - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec( - Files.readAllBytes(Paths.get(RestClientBuilderIntegTests.class.getResource("/test.der").toURI())) - ); - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - keyStore.setKeyEntry( - "mykey", - keyFactory.generatePrivate(privateKeySpec), - "password".toCharArray(), - new Certificate[]{certFactory.generateCertificate(certFile)} - ); - KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(keyStore, "password".toCharArray()); - KeyStore trustStore = KeyStore.getInstance("JKS"); - trustStore.load(keyStoreFile, "password".toCharArray()); - TrustManagerFactory tmf = - TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(trustStore); - sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); - } - return sslContext; - } - - /** - * The {@link HttpsServer} in the JDK has issues with TLSv1.3 when running in a JDK prior to - * 12.0.1 so we pin to TLSv1.2 when running on an earlier JDK - */ - private static String getProtocol() { - String version = System.getProperty("java.version"); - String[] parts = version.split("-"); - String[] numericComponents; - if (parts.length == 1) { - numericComponents = version.split("\\."); - } else if (parts.length == 2) { - numericComponents = parts[0].split("\\."); - } else { - throw new IllegalArgumentException("Java version string [" + version + "] could not be parsed."); - } - if (numericComponents.length > 0) { - final int major = Integer.valueOf(numericComponents[0]); - if (major > 12) { - return "TLS"; - } else if (major == 12 && numericComponents.length > 2) { - final int minor = Integer.valueOf(numericComponents[1]); - if (minor > 0) { - return "TLS"; - } else { - String patch = numericComponents[2]; - final int index = patch.indexOf("_"); - if (index > -1) { - patch = patch.substring(0, index); - } - - if (Integer.valueOf(patch) >= 1) { - return "TLS"; - } - } - } - } - return "TLSv1.2"; - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientBuilderTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientBuilderTests.java deleted file mode 100644 index f8cc00e7e..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientBuilderTests.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import org.apache.hc.client5.http.config.RequestConfig; -import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.client5.http.impl.async.HttpAsyncClients; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.message.BasicHeader; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.RestClientTestCase; -import org.elasticsearch.client.node.Node; - -import java.io.IOException; -import java.util.Base64; - -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; - -public class RestClientBuilderTests extends RestClientTestCase { - - public void testBuild() throws IOException { - try { - RestClient.builder((HttpHost[]) null); - fail("should have failed"); - } catch (IllegalArgumentException e) { - assertEquals("hosts must not be null nor empty", e.getMessage()); - } - - try { - RestClient.builder(new HttpHost[]{}); - fail("should have failed"); - } catch (IllegalArgumentException e) { - assertEquals("hosts must not be null nor empty", e.getMessage()); - } - - try { - RestClient.builder((Node[]) null); - fail("should have failed"); - } catch (IllegalArgumentException e) { - assertEquals("nodes must not be null or empty", e.getMessage()); - } - - try { - RestClient.builder(new Node[]{}); - fail("should have failed"); - } catch (IllegalArgumentException e) { - assertEquals("nodes must not be null or empty", e.getMessage()); - } - - try { - RestClient.builder(new Node(new HttpHost("localhost", 9200)), null); - fail("should have failed"); - } catch (IllegalArgumentException e) { - assertEquals("node cannot be null", e.getMessage()); - } - - try { - RestClient.builder(new HttpHost("localhost", 9200), null); - fail("should have failed"); - } catch (IllegalArgumentException e) { - assertEquals("host cannot be null", e.getMessage()); - } - - try (RestClient restClient = RestClient.builder(new HttpHost("localhost", 9200)).build()) { - assertNotNull(restClient); - } - - try { - RestClient.builder(new HttpHost("localhost", 9200)).setDefaultHeaders(null); - fail("should have failed"); - } catch (NullPointerException e) { - assertEquals("defaultHeaders must not be null", e.getMessage()); - } - - try { - RestClient.builder(new HttpHost("localhost", 9200)).setDefaultHeaders(new Header[]{null}); - fail("should have failed"); - } catch (NullPointerException e) { - assertEquals("default header must not be null", e.getMessage()); - } - - try { - RestClient.builder(new HttpHost("localhost", 9200)).setFailureListener(null); - fail("should have failed"); - } catch (NullPointerException e) { - assertEquals("failureListener must not be null", e.getMessage()); - } - - try { - RestClient.builder(new HttpHost("localhost", 9200)).setCustomRestClient(null); - fail("should have failed"); - } catch (NullPointerException e) { - assertEquals("custom rest client must not be null", e.getMessage()); - } - - try { - RestClient.builder(new HttpHost("localhost", 9200)).setSslContext(null); - fail("should have failed"); - } catch (NullPointerException e) { - assertEquals("ssl context must not be null", e.getMessage()); - } - - int numNodes = randomIntBetween(1, 5); - HttpHost[] hosts = new HttpHost[numNodes]; - for (int i = 0; i < numNodes; i++) { - hosts[i] = new HttpHost("localhost", 9200 + i); - } - RestClientBuilder builder = RestClient.builder(hosts); - CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() - .build(); - if (randomBoolean()) { - builder.setCustomRestClient(httpclient); - } - if (randomBoolean()) { - int numHeaders = randomIntBetween(1, 5); - Header[] headers = new Header[numHeaders]; - for (int i = 0; i < numHeaders; i++) { - headers[i] = new BasicHeader("header" + i, "value"); - } - builder.setDefaultHeaders(headers); - } - if (randomBoolean()) { - String pathPrefix = (randomBoolean() ? "/" : "") + randomAsciiLettersOfLengthBetween(2, 5); - while (pathPrefix.length() < 20 && randomBoolean()) { - pathPrefix += "/" + randomAsciiLettersOfLengthBetween(3, 6); - } - builder.setPathPrefix(pathPrefix + (randomBoolean() ? "/" : "")); - } - try (RestClient restClient = builder.build()) { - assertNotNull(restClient); - } - } - - public void testBuildCloudId() throws IOException { - String host = "us-east-1.aws.found.io"; - String esId = "elasticsearch"; - String kibanaId = "kibana"; - String toEncode = host + "$" + esId + "$" + kibanaId; - String encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(UTF8)); - assertNotNull(RestClient.builder(encodedId)); - assertNotNull(RestClient.builder("humanReadable:" + encodedId)); - - String badId = Base64.getEncoder().encodeToString("foo$bar".getBytes(UTF8)); - try { - RestClient.builder(badId); - fail("should have failed"); - } catch (IllegalStateException e) { - assertEquals("cloudId " + badId + " did not decode to a cluster identifier correctly", - e.getMessage()); - } - - try { - RestClient.builder(badId + ":"); - fail("should have failed"); - } catch (IllegalStateException e) { - assertEquals("cloudId " + badId + ": must begin with a human readable identifier followed by a " + - "colon", e.getMessage()); - } - - RestClient client = RestClient.builder(encodedId).build(); - assertThat(client.getNodes().size(), equalTo(1)); - assertThat(client.getNodes().get(0).getHost().getHostName(), equalTo(esId + "." + host)); - assertThat(client.getNodes().get(0).getHost().getPort(), equalTo(443)); - assertThat(client.getNodes().get(0).getHost().getSchemeName(), equalTo("https")); - client.close(); - } - - public void testBuildCloudIdWithPort() throws IOException { - String host = "us-east-1.aws.found.io"; - String esId = "elasticsearch"; - String kibanaId = "kibana"; - String port = "9443"; - String toEncode = host + ":" + port + "$" + esId + "$" + kibanaId; - String encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(UTF8)); - - RestClient client = RestClient.builder("humanReadable:" + encodedId).build(); - assertThat(client.getNodes().size(), equalTo(1)); - assertThat(client.getNodes().get(0).getHost().getPort(), equalTo(9443)); - assertThat(client.getNodes().get(0).getHost().getHostName(), equalTo(esId + "." + host)); - assertThat(client.getNodes().get(0).getHost().getSchemeName(), equalTo("https")); - client.close(); - - toEncode = host + ":" + "123:foo" + "$" + esId + "$" + kibanaId; - encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(UTF8)); - - try { - RestClient.builder("humanReadable:" + encodedId); - fail("should have failed"); - } catch (IllegalStateException e) { - assertEquals("cloudId " + encodedId + " does not contain a valid port number", e.getMessage()); - } - } - - public void testSetPathPrefixNull() { - try { - RestClient.builder(new HttpHost("localhost", 9200)).setPathPrefix(null); - fail("pathPrefix set to null should fail!"); - } catch (final NullPointerException e) { - assertEquals("pathPrefix must not be null", e.getMessage()); - } - } - - public void testSetPathPrefixEmpty() { - assertSetPathPrefixThrows(""); - } - - public void testSetPathPrefixMalformed() { - assertSetPathPrefixThrows("//"); - assertSetPathPrefixThrows("base/path//"); - } - - private static void assertSetPathPrefixThrows(final String pathPrefix) { - try { - RestClient.builder(new HttpHost("localhost", 9200)).setPathPrefix(pathPrefix); - fail("path prefix [" + pathPrefix + "] should have failed"); - } catch (final IllegalArgumentException e) { - assertThat(e.getMessage(), containsString(pathPrefix)); - } - } - - /** - * This test verifies that we don't change the default value for the connection request timeout as that - * causes problems. - * See https://github.com/elastic/elasticsearch/issues/24069 - */ - public void testDefaultConnectionRequestTimeout() throws IOException { - RestClientBuilder builder = RestClient.builder(new HttpHost("localhost", 9200)); - - RequestConfig requestConfig = RequestConfig.custom().build(); - assertEquals(RequestConfig.DEFAULT.getConnectionRequestTimeout(), - requestConfig.getConnectionRequestTimeout()); - // this way we get notified if the default ever changes - // TODO IT CHANGED from -1 to 3 minutes, does it mean we always need to explicitly set it? - //assertEquals(-1, requestConfig.getConnectionRequestTimeout()); - - CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() - .setDefaultRequestConfig(requestConfig) - .build(); - - try (RestClient restClient = builder.build()) { - assertNotNull(restClient); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientDocumentation.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientDocumentation.java deleted file mode 100644 index 7c5745488..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientDocumentation.java +++ /dev/null @@ -1,461 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import org.apache.hc.client5.http.config.RequestConfig; -import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.client5.http.impl.async.HttpAsyncClients; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; -import org.apache.hc.core5.http.ContentType; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.HttpEntity; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.ParseException; -import org.apache.hc.core5.http.io.entity.EntityUtils; -import org.apache.hc.core5.http.io.entity.StringEntity; -import org.apache.hc.core5.http.message.BasicHeader; -import org.apache.hc.core5.http.message.RequestLine; -import org.apache.hc.core5.reactor.IOReactorConfig; -import org.apache.hc.core5.ssl.SSLContextBuilder; -import org.apache.hc.core5.ssl.SSLContexts; -import org.apache.hc.core5.util.Timeout; -import org.elasticsearch.client.Cancellable; -import org.elasticsearch.client.Request; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.ResponseListener; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.consumer.HttpAsyncResponseConsumerFactory; -import org.elasticsearch.client.node.Node; -import org.elasticsearch.client.node.selector.NodeSelector; - -import javax.net.ssl.SSLContext; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.security.KeyStore; -import java.security.cert.Certificate; -import java.security.cert.CertificateFactory; -import java.util.Base64; -import java.util.Iterator; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * This class is used to generate the Java low-level REST client documentation. - * You need to wrap your code between two tags like: - * // tag::example[] - * // end::example[] - *

- * Where example is your tag name. - *

- * Then in the documentation, you can extract what is between tag and end tags with - * ["source","java",subs="attributes,callouts,macros"] - * -------------------------------------------------- - * include-tagged::{doc-tests}/RestClientDocumentation.java[example] - * -------------------------------------------------- - *

- * Note that this is not a test class as we are only interested in testing that docs snippets compile. We - * don't want - * to send requests to a node and we don't even have the tools to do it. - */ -@SuppressWarnings("unused") -public class RestClientDocumentation { - private static final String TOKEN = "DUMMY"; - - // tag::rest-client-options-singleton - private static final RequestOptions COMMON_OPTIONS; - - static { - RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); - builder.addHeader("Authorization", "Bearer " + TOKEN); // <1> - builder.setHttpAsyncResponseConsumerFactory( // <2> - HttpAsyncResponseConsumerFactory.DEFAULT); - COMMON_OPTIONS = builder.build(); - } - // end::rest-client-options-singleton - - @SuppressWarnings("unused") - public void usage() throws IOException, InterruptedException, ParseException { - - //tag::rest-client-init - RestClient restClient = RestClient.builder( - new HttpHost("http", "localhost", 9200), - new HttpHost("http", "localhost", 9201)).build(); - //end::rest-client-init - - //tag::rest-client-close - restClient.close(); - //end::rest-client-close - - { - //tag::rest-client-init-default-headers - RestClientBuilder builder = RestClient.builder( - new HttpHost("http", "localhost", 9200)); - Header[] defaultHeaders = new Header[]{new BasicHeader("header", "value")}; - builder.setDefaultHeaders(defaultHeaders); // <1> - //end::rest-client-init-default-headers - } - { - //tag::rest-client-init-node-selector - RestClientBuilder builder = RestClient.builder( - new HttpHost("http", "localhost", 9200)); - builder.setNodeSelector(NodeSelector.SKIP_DEDICATED_MASTERS); // <1> - //end::rest-client-init-node-selector - } - { - //tag::rest-client-init-allocation-aware-selector - RestClientBuilder builder = RestClient.builder( - new HttpHost("http", "localhost", 9200)); - // <1> - builder.setNodeSelector(nodes -> { // <1> - /* - * Prefer any node that belongs to rack_one. If none is around - * we will go to another rack till it's time to try and revive - * some of the nodes that belong to rack_one. - */ - boolean foundOne = false; - for (Node node : nodes) { - String rackId = node.getAttributes().get("rack_id").get(0); - if ("rack_one".equals(rackId)) { - foundOne = true; - break; - } - } - if (foundOne) { - Iterator nodesIt = nodes.iterator(); - while (nodesIt.hasNext()) { - Node node = nodesIt.next(); - String rackId = node.getAttributes().get("rack_id").get(0); - if ("rack_one".equals(rackId) == false) { - nodesIt.remove(); - } - } - } - }); - //end::rest-client-init-allocation-aware-selector - } - { - //tag::rest-client-init-failure-listener - RestClientBuilder builder = RestClient.builder( - new HttpHost("http", "localhost", 9200)); - builder.setFailureListener(new RestClient.FailureListener() { - @Override - public void onFailure(Node node) { - // <1> - } - }); - //end::rest-client-init-failure-listener - } - { - //tag::rest-client-init-request-custom-client - PoolingAsyncClientConnectionManager connectionManager = - PoolingAsyncClientConnectionManagerBuilder.create() - .setMaxConnPerRoute(5) - .build(); - - CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() - .setConnectionManager(connectionManager) - .build(); - RestClientBuilder builder = RestClient.builder( - new HttpHost("http", "localhost", 9200)); - builder.setCustomRestClient(httpclient); - //end::rest-client-init-request-config-callback - } - - { - //tag::rest-client-sync - Request request = new Request( - "GET", // <1> - "/"); // <2> - Response response = restClient.performRequest(request); - //end::rest-client-sync - } - { - //tag::rest-client-async - Request request = new Request( - "GET", // <1> - "/"); // <2> - Cancellable cancellable = restClient.performRequestAsync(request, - new ResponseListener() { - @Override - public void onSuccess(Response response) { - // <3> - } - - @Override - public void onFailure(Exception exception) { - // <4> - } - }); - //end::rest-client-async - } - { - Request request = new Request("GET", "/"); - //tag::rest-client-parameters - request.addParameter("pretty", "true"); - //end::rest-client-parameters - //tag::rest-client-body - request.setEntity(new StringEntity( - "{\"json\":\"text\"}", - ContentType.APPLICATION_JSON)); - //end::rest-client-body - //tag::rest-client-body-shorter - request.setJsonEntity("{\"json\":\"text\"}"); - //end::rest-client-body-shorter - //tag::rest-client-options-set-singleton - request.setOptions(COMMON_OPTIONS); - //end::rest-client-options-set-singleton - { - //tag::rest-client-options-customize-header - RequestOptions.Builder options = COMMON_OPTIONS.toBuilder(); - options.addHeader("cats", "knock things off of other things"); - request.setOptions(options); - //end::rest-client-options-customize-header - } - } - { - HttpEntity[] documents = new HttpEntity[10]; - //tag::rest-client-async-example - final CountDownLatch latch = new CountDownLatch(documents.length); - for (int i = 0; i < documents.length; i++) { - Request request = new Request("PUT", "/posts/doc/" + i); - //let's assume that the documents are stored in an HttpEntity array - request.setEntity(documents[i]); - restClient.performRequestAsync( - request, - new ResponseListener() { - @Override - public void onSuccess(Response response) { - // <1> - latch.countDown(); - } - - @Override - public void onFailure(Exception exception) { - // <2> - latch.countDown(); - } - } - ); - } - latch.await(); - //end::rest-client-async-example - } - { - //tag::rest-client-async-cancel - Request request = new Request("GET", "/posts/_search"); - Cancellable cancellable = restClient.performRequestAsync( - request, - new ResponseListener() { - @Override - public void onSuccess(Response response) { - // <1> - } - - @Override - public void onFailure(Exception exception) { - // <2> - } - } - ); - cancellable.cancel(); - //end::rest-client-async-cancel - } - { - //tag::rest-client-response2 - Response response = restClient.performRequest(new Request("GET", "/")); - RequestLine requestLine = response.getRequestLine(); // <1> - HttpHost host = response.getHost(); // <2> - int statusCode = response.getStatusCode(); // <3> - Header[] headers = response.getHeaders(); // <4> - String responseBody = EntityUtils.toString(response.getEntity()); // <5> - //end::rest-client-response2 - } - } - - @SuppressWarnings("unused") - public void commonConfiguration() throws Exception { - { - //tag::rest-client-config-timeouts - RequestConfig.Builder requestConfigBuilder = RequestConfig.custom() - .setConnectTimeout(Timeout.of(5000, TimeUnit.MILLISECONDS)); - - CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() - .setDefaultRequestConfig(requestConfigBuilder.build()) - .build(); - - RestClientBuilder builder = RestClient.builder( - new HttpHost("localhost", 9200)) - .setCustomRestClient(httpclient); - //end::rest-client-config-timeouts - } - { - //tag::rest-client-config-request-options-timeouts - RequestConfig requestConfig = RequestConfig.custom() - .setConnectTimeout(Timeout.ofMilliseconds(5000)) - .setConnectionRequestTimeout(Timeout.ofMilliseconds(60000)) - .build(); - RequestOptions options = RequestOptions.DEFAULT.toBuilder() - .setRequestConfig(requestConfig) - .build(); - //end::rest-client-config-request-options-timeouts - } - { - //tag::rest-client-config-threads - CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() - .setIOReactorConfig(IOReactorConfig.custom() - .setIoThreadCount(1).build()) - .build(); - - RestClientBuilder builder = RestClient.builder( - new HttpHost("localhost", 9200)) - .setCustomRestClient(httpclient); - //end::rest-client-config-threads - } - { - //tag::rest-client-config-basic-auth - - var creds = Base64.getEncoder().encodeToString("user:test-user-password".getBytes()); - - RestClientBuilder restClient = RestClient.builder(new HttpHost("https", "localhost", - 9200)) - .setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "Basic " + creds) - }); - - //end::rest-client-config-basic-auth - } - { - //tag::rest-client-config-disable-preemptive-auth - HttpHost host = new HttpHost("http", "localhost", 9200); - - var creds = Base64.getEncoder().encodeToString("user:test-user-password".getBytes()); - - CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() - .disableAuthCaching() - .build(); - - RestClientBuilder restClient = RestClient.builder(new HttpHost("https", "localhost", - 9200)) - .setCustomRestClient(httpclient) - .setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "Basic " + creds) - }); - //end::rest-client-config-disable-preemptive-auth - } - { - String keyStorePass = ""; - //tag::rest-client-config-encrypted-communication - Path trustStorePath = Paths.get("/path/to/truststore.p12"); - KeyStore truststore = KeyStore.getInstance("pkcs12"); - try (InputStream is = Files.newInputStream(trustStorePath)) { - truststore.load(is, keyStorePass.toCharArray()); - } - SSLContextBuilder sslBuilder = SSLContexts.custom() - .loadTrustMaterial(truststore, null); - final SSLContext sslContext = sslBuilder.build(); - RestClientBuilder builder = RestClient.builder( - new HttpHost("https", "localhost", - 9200)) - .setSslContext(sslContext); - //end::rest-client-config-encrypted-communication - } - { - //tag::rest-client-config-trust-ca-pem - Path caCertificatePath = Paths.get("/path/to/ca.crt"); - CertificateFactory factory = - CertificateFactory.getInstance("X.509"); - Certificate trustedCa; - try (InputStream is = Files.newInputStream(caCertificatePath)) { - trustedCa = factory.generateCertificate(is); - } - KeyStore trustStore = KeyStore.getInstance("pkcs12"); - trustStore.load(null, null); - trustStore.setCertificateEntry("ca", trustedCa); - SSLContextBuilder sslContextBuilder = SSLContexts.custom() - .loadTrustMaterial(trustStore, null); - final SSLContext sslContext = sslContextBuilder.build(); - RestClient.builder( - new HttpHost("https", "localhost", - 9200)) - .setSslContext(sslContext); - //end::rest-client-config-trust-ca-pem - } - { - String trustStorePass = ""; - String keyStorePass = ""; - //tag::rest-client-config-mutual-tls-authentication - Path trustStorePath = Paths.get("/path/to/your/truststore.p12"); - Path keyStorePath = Paths.get("/path/to/your/keystore.p12"); - KeyStore trustStore = KeyStore.getInstance("pkcs12"); - KeyStore keyStore = KeyStore.getInstance("pkcs12"); - try (InputStream is = Files.newInputStream(trustStorePath)) { - trustStore.load(is, trustStorePass.toCharArray()); - } - try (InputStream is = Files.newInputStream(keyStorePath)) { - keyStore.load(is, keyStorePass.toCharArray()); - } - SSLContextBuilder sslBuilder = SSLContexts.custom() - .loadTrustMaterial(trustStore, null) - .loadKeyMaterial(keyStore, keyStorePass.toCharArray()); - final SSLContext sslContext = sslBuilder.build(); - RestClient.builder( - new HttpHost("https", "localhost", - 9200)) - .setSslContext(sslContext); - //end::rest-client-config-mutual-tls-authentication - } - { - //tag::rest-client-auth-bearer-token - RestClientBuilder builder = RestClient.builder( - new HttpHost("https", "localhost", - 9200)); - Header[] defaultHeaders = - new Header[]{new BasicHeader("Authorization", - "Bearer u6iuAxZ0RG1Kcm5jVFI4eU4tZU9aVFEwT2F3")}; - builder.setDefaultHeaders(defaultHeaders); - //end::rest-client-auth-bearer-token - } - { - //tag::rest-client-auth-api-key - String apiKeyId = "uqlEyn8B_gQ_jlvwDIvM"; - String apiKeySecret = "HxHWk2m4RN-V_qg9cDpuX"; - String apiKeyAuth = - Base64.getEncoder().encodeToString( - (apiKeyId + ":" + apiKeySecret) - .getBytes(StandardCharsets.UTF_8)); - RestClientBuilder builder = RestClient.builder( - new HttpHost("https", "localhost", - 9200)); - Header[] defaultHeaders = - new Header[]{new BasicHeader("Authorization", - "ApiKey " + apiKeyAuth)}; - builder.setDefaultHeaders(defaultHeaders); - //end::rest-client-auth-api-key - } - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientGzipCompressionTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientGzipCompressionTests.java deleted file mode 100644 index 5e917f5cb..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientGzipCompressionTests.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; -import com.sun.net.httpserver.HttpServer; -import org.apache.hc.core5.http.ContentType; -import org.apache.hc.core5.http.HttpEntity; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.io.entity.StringEntity; -import org.elasticsearch.client.Request; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.ResponseListener; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientTestCase; -import org.elasticsearch.mocksocket.MockHttpServer; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; -import java.util.concurrent.CompletableFuture; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; - -import static org.apache.hc.core5.http.HttpHeaders.CONTENT_ENCODING; -import static org.apache.hc.core5.http.HttpHeaders.CONTENT_LENGTH; - -public class RestClientGzipCompressionTests extends RestClientTestCase { - - private static HttpServer httpServer; - - @BeforeClass - public static void startHttpServer() throws Exception { - httpServer = MockHttpServer.createHttp(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); - httpServer.createContext("/", new GzipResponseHandler()); - httpServer.start(); - } - - @AfterClass - public static void stopHttpServers() throws IOException { - httpServer.stop(0); - httpServer = null; - } - - /** - * A response handler that accepts gzip-encoded data and replies request and response encoding values - * followed by the request body. The response is compressed if "Accept-Encoding" is "gzip". - */ - private static class GzipResponseHandler implements HttpHandler { - @Override - public void handle(HttpExchange exchange) throws IOException { - - // Decode body (if any) - String contentEncoding = exchange.getRequestHeaders().getFirst("Content-Encoding"); - InputStream body = exchange.getRequestBody(); - if ("gzip".equals(contentEncoding)) { - body = new GZIPInputStream(body); - } - byte[] bytes = readAll(body); - - boolean compress = "gzip".equals(exchange.getRequestHeaders().getFirst("Accept-Encoding")); - if (compress) { - exchange.getResponseHeaders().add("Content-Encoding", "gzip"); - } - - // Encode response if needed - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - OutputStream out = bao; - if (compress) { - out = new GZIPOutputStream(out); - } - - // Outputs ## - out.write(String.valueOf(contentEncoding).getBytes(StandardCharsets.UTF_8)); - out.write('#'); - out.write((compress ? "gzip" : "null").getBytes(StandardCharsets.UTF_8)); - out.write('#'); - out.write(bytes); - out.close(); - - bytes = bao.toByteArray(); - - exchange.sendResponseHeaders(200, bytes.length); - - exchange.getResponseBody().write(bytes); - exchange.close(); - } - } - - /** - * Read all bytes of an input stream and close it. - */ - private static byte[] readAll(InputStream in) throws IOException { - byte[] buffer = new byte[1024]; - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - int len = 0; - while ((len = in.read(buffer)) > 0) { - bos.write(buffer, 0, len); - } - in.close(); - return bos.toByteArray(); - } - - private RestClient createClient(boolean enableCompression) { - InetSocketAddress address = httpServer.getAddress(); - return RestClient.builder(new HttpHost("http", address.getHostString(), address.getPort())) - .setCompressionEnabled(enableCompression) - .build(); - } - - public void testUncompressedSync() throws Exception { - RestClient restClient = createClient(false); - - // Send non-compressed request, expect non-compressed response - Request request = new Request("POST", "/"); - request.setEntity(new StringEntity("plain request, plain response", ContentType.TEXT_PLAIN)); - - Response response = restClient.performRequest(request); - - // Server sends a content-length which should be kept - Assert.assertTrue(response.getEntity().getContentLength() > 0); - checkResponse("null#null#plain request, plain response", response); - - restClient.close(); - } - - public void testGzipHeaderSync() throws Exception { - RestClient restClient = createClient(false); - - // Send non-compressed request, expect compressed response - Request request = new Request("POST", "/"); - request.setEntity(new StringEntity("plain request, gzip response", ContentType.TEXT_PLAIN)); - request.setOptions(RequestOptions.DEFAULT.toBuilder().addHeader("Accept-Encoding", "gzip").build()); - - Response response = restClient.performRequest(request); - - // Content-length is unknown because of ungzip. Do not just test -1 as it returns "a negative - // number if unknown" - Assert.assertTrue(response.getEntity().getContentLength() < 0); - checkResponse("null#gzip#plain request, gzip response", response); - - restClient.close(); - } - - public void testGzipHeaderAsync() throws Exception { - RestClient restClient = createClient(false); - - // Send non-compressed request, expect compressed response - Request request = new Request("POST", "/"); - request.setEntity(new StringEntity("plain request, gzip response", ContentType.TEXT_PLAIN)); - request.setOptions(RequestOptions.DEFAULT.toBuilder().addHeader("Accept-Encoding", "gzip").build()); - - FutureResponse futureResponse = new FutureResponse(); - restClient.performRequestAsync(request, futureResponse); - Response response = futureResponse.get(); - - Assert.assertTrue(response.getEntity().getContentLength() < 0); - checkResponse("null#gzip#plain request, gzip response", response); - - restClient.close(); - } - - public void testCompressingClientSync() throws Exception { - RestClient restClient = createClient(true); - - Request request = new Request("POST", "/"); - request.setEntity(new StringEntity("compressing client", ContentType.TEXT_PLAIN)); - - Response response = restClient.performRequest(request); - - Assert.assertTrue(response.getEntity().getContentLength() < 0); - checkResponse("gzip#gzip#compressing client", response); - - restClient.close(); - } - - public void testCompressingClientAsync() throws Exception { - InetSocketAddress address = httpServer.getAddress(); - RestClient restClient = RestClient.builder(new HttpHost("http", address.getHostString(), - address.getPort())) - .setCompressionEnabled(true) - .build(); - - Request request = new Request("POST", "/"); - request.setEntity(new StringEntity("compressing client", ContentType.TEXT_PLAIN)); - - FutureResponse futureResponse = new FutureResponse(); - restClient.performRequestAsync(request, futureResponse); - Response response = futureResponse.get(); - - // Server should report it had a compressed request and sent back a compressed response - Assert.assertTrue(response.getEntity().getContentLength() < 0); - checkResponse("gzip#gzip#compressing client", response); - - restClient.close(); - } - - public static class FutureResponse extends CompletableFuture implements ResponseListener { - @Override - public void onSuccess(Response response) { - this.complete(response); - } - - @Override - public void onFailure(Exception exception) { - this.completeExceptionally(exception); - } - } - - private static void checkResponse(String expected, Response response) throws Exception { - HttpEntity entity = response.getEntity(); - Assert.assertNotNull(entity); - - String content = new String(readAll(entity.getContent()), StandardCharsets.UTF_8); - Assert.assertEquals(expected, content); - - // Original Content-Encoding should be removed on both entity and response - Assert.assertNull(entity.getContentEncoding()); - Assert.assertNull(response.getHeader(CONTENT_ENCODING)); - - // Content-length must be consistent between entity and response - long entityContentLength = entity.getContentLength(); - String headerContentLength = response.getHeader(CONTENT_LENGTH); - - if (entityContentLength < 0) { - Assert.assertNull(headerContentLength); - } else { - Assert.assertEquals(String.valueOf(entityContentLength), headerContentLength); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientMultipleHostsIntegTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientMultipleHostsIntegTests.java deleted file mode 100644 index ac381eda0..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientMultipleHostsIntegTests.java +++ /dev/null @@ -1,402 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; -import com.sun.net.httpserver.HttpServer; -import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.Cancellable; -import org.elasticsearch.client.Request; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.ResponseException; -import org.elasticsearch.client.ResponseListener; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.RestClientSingleHostTests; -import org.elasticsearch.client.RestClientTestCase; -import org.elasticsearch.client.RestClientTestUtil; -import org.elasticsearch.client.consumer.BasicAsyncResponseConsumer; -import org.elasticsearch.client.consumer.BufferedByteConsumer; -import org.elasticsearch.client.node.Node; -import org.elasticsearch.client.node.selector.NodeSelector; -import org.elasticsearch.mocksocket.MockHttpServer; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Ignore; - -import java.io.IOException; -import java.io.OutputStream; -import java.net.ConnectException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.CancellationException; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.elasticsearch.client.RestClientTestUtil.getAllStatusCodes; -import static org.elasticsearch.client.RestClientTestUtil.randomErrorNoRetryStatusCode; -import static org.elasticsearch.client.RestClientTestUtil.randomOkStatusCode; -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * Integration test to check interaction between {@link RestClient} and {@link org.apache.hc.client5.http.async.HttpAsyncClient}. - * Works against real http servers, multiple hosts. Also tests failover by randomly shutting down hosts. - */ -public class RestClientMultipleHostsIntegTests extends RestClientTestCase { - - private static WaitForCancelHandler waitForCancelHandler; - private static HttpServer[] httpServers; - private static HttpHost[] httpHosts; - private static boolean stoppedFirstHost = false; - private static String pathPrefixWithoutLeadingSlash; - private static String pathPrefix; - private static RestClient restClient; - - @BeforeClass - public static void startHttpServer() throws Exception { - if (randomBoolean()) { - pathPrefixWithoutLeadingSlash = "testPathPrefix/" + randomAsciiLettersOfLengthBetween(1, 5); - pathPrefix = "/" + pathPrefixWithoutLeadingSlash; - } else { - pathPrefix = pathPrefixWithoutLeadingSlash = ""; - } - int numHttpServers = randomIntBetween(2, 4); - httpServers = new HttpServer[numHttpServers]; - httpHosts = new HttpHost[numHttpServers]; - waitForCancelHandler = new WaitForCancelHandler(); - for (int i = 0; i < numHttpServers; i++) { - HttpServer httpServer = createHttpServer(); - httpServers[i] = httpServer; - httpHosts[i] = new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()); - } - restClient = buildRestClient(NodeSelector.ANY); - } - - private static RestClient buildRestClient(NodeSelector nodeSelector) { - return buildRestClient(nodeSelector, null); - } - - private static RestClient buildRestClient(NodeSelector nodeSelector, RestClient.FailureListener failureListener) { - RestClientBuilder restClientBuilder = RestClient.builder(httpHosts); - if (pathPrefix.length() > 0) { - restClientBuilder.setPathPrefix((randomBoolean() ? "/" : "") + pathPrefixWithoutLeadingSlash); - } - if (failureListener != null) { - restClientBuilder.setFailureListener(failureListener); - } - restClientBuilder.setNodeSelector(nodeSelector); - return restClientBuilder.build(); - } - - private static HttpServer createHttpServer() throws Exception { - HttpServer httpServer = MockHttpServer.createHttp(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); - httpServer.start(); - // returns a different status code depending on the path - for (int statusCode : getAllStatusCodes()) { - httpServer.createContext(pathPrefix + "/" + statusCode, new ResponseHandler(statusCode)); - } - httpServer.createContext(pathPrefix + "/20bytes", new ResponseHandlerWithContent()); - httpServer.createContext(pathPrefix + "/wait", waitForCancelHandler); - return httpServer; - } - - private static WaitForCancelHandler resetWaitHandlers() { - WaitForCancelHandler handler = new WaitForCancelHandler(); - for (HttpServer httpServer : httpServers) { - httpServer.removeContext(pathPrefix + "/wait"); - httpServer.createContext(pathPrefix + "/wait", handler); - } - return handler; - } - - private static class WaitForCancelHandler implements HttpHandler { - private final CountDownLatch requestCameInLatch = new CountDownLatch(1); - private final CountDownLatch cancelHandlerLatch = new CountDownLatch(1); - - void cancelDone() { - cancelHandlerLatch.countDown(); - } - - void awaitRequest() throws InterruptedException { - requestCameInLatch.await(); - } - - @Override - public void handle(HttpExchange exchange) throws IOException { - requestCameInLatch.countDown(); - try { - cancelHandlerLatch.await(); - } catch (InterruptedException ignore) {} finally { - exchange.sendResponseHeaders(200, 0); - exchange.close(); - } - } - } - - private static class ResponseHandler implements HttpHandler { - private final int statusCode; - - ResponseHandler(int statusCode) { - this.statusCode = statusCode; - } - - @Override - public void handle(HttpExchange httpExchange) throws IOException { - httpExchange.getRequestBody().close(); - httpExchange.sendResponseHeaders(statusCode, -1); - httpExchange.close(); - } - } - - private static class ResponseHandlerWithContent implements HttpHandler { - @Override - public void handle(HttpExchange httpExchange) throws IOException { - byte[] body = "01234567890123456789".getBytes(StandardCharsets.UTF_8); - httpExchange.sendResponseHeaders(200, body.length); - try (OutputStream out = httpExchange.getResponseBody()) { - out.write(body); - } - httpExchange.close(); - } - } - - @AfterClass - public static void stopHttpServers() throws IOException { - restClient.close(); - restClient = null; - for (HttpServer httpServer : httpServers) { - httpServer.stop(0); - } - httpServers = null; - } - - @Before - public void stopRandomHost() { - // verify that shutting down some hosts doesn't matter as long as one working host is left behind - if (httpServers.length > 1 && randomBoolean()) { - List updatedHttpServers = new ArrayList<>(httpServers.length - 1); - int nodeIndex = randomIntBetween(0, httpServers.length - 1); - if (0 == nodeIndex) { - stoppedFirstHost = true; - } - for (int i = 0; i < httpServers.length; i++) { - HttpServer httpServer = httpServers[i]; - if (i == nodeIndex) { - httpServer.stop(0); - } else { - updatedHttpServers.add(httpServer); - } - } - httpServers = updatedHttpServers.toArray(new HttpServer[0]); - } - } - - public void testSyncRequests() throws IOException { - int numRequests = randomIntBetween(5, 20); - for (int i = 0; i < numRequests; i++) { - final String method = RestClientTestUtil.randomHttpMethod(getRandom()); - // we don't test status codes that are subject to retries as they interfere with hosts being stopped - final int statusCode = randomBoolean() ? randomOkStatusCode(getRandom()) : randomErrorNoRetryStatusCode(getRandom()); - Response response; - try { - response = restClient.performRequest(new Request(method, "/" + statusCode)); - } catch (ResponseException responseException) { - response = responseException.getResponse(); - } - assertEquals(method, response.getRequestLine().getMethod()); - assertEquals(statusCode, response.getStatusCode()); - assertEquals((pathPrefix.length() > 0 ? pathPrefix : "") + "/" + statusCode, response.getRequestLine().getUri()); - } - } - - public void testAsyncRequests() throws Exception { - int numRequests = randomIntBetween(5, 20); - final CountDownLatch latch = new CountDownLatch(numRequests); - final List responses = new CopyOnWriteArrayList<>(); - for (int i = 0; i < numRequests; i++) { - final String method = RestClientTestUtil.randomHttpMethod(getRandom()); - // we don't test status codes that are subject to retries as they interfere with hosts being stopped - final int statusCode = randomBoolean() ? randomOkStatusCode(getRandom()) : randomErrorNoRetryStatusCode(getRandom()); - restClient.performRequestAsync(new Request(method, "/" + statusCode), new ResponseListener() { - @Override - public void onSuccess(Response response) { - responses.add(new TestResponse(method, statusCode, response)); - latch.countDown(); - } - - @Override - public void onFailure(Exception exception) { - responses.add(new TestResponse(method, statusCode, exception)); - latch.countDown(); - } - }); - } - assertTrue(latch.await(5, TimeUnit.SECONDS)); - - assertEquals(numRequests, responses.size()); - for (TestResponse testResponse : responses) { - Response response = testResponse.getResponse(); - assertEquals(testResponse.method, response.getRequestLine().getMethod()); - assertEquals(testResponse.statusCode, response.getStatusCode()); - assertEquals((pathPrefix.length() > 0 ? pathPrefix : "") + "/" + testResponse.statusCode, response.getRequestLine().getUri()); - } - } - - public void testCancelAsyncRequests() throws Exception { - int numRequests = randomIntBetween(5, 20); - final List responses = new CopyOnWriteArrayList<>(); - final List exceptions = new CopyOnWriteArrayList<>(); - for (int i = 0; i < numRequests; i++) { - CountDownLatch latch = new CountDownLatch(1); - waitForCancelHandler = resetWaitHandlers(); - Cancellable cancellable = restClient.performRequestAsync(new Request("GET", "/wait"), new ResponseListener() { - @Override - public void onSuccess(Response response) { - responses.add(response); - latch.countDown(); - } - - @Override - public void onFailure(Exception exception) { - exceptions.add(exception); - latch.countDown(); - } - }); - if (randomBoolean()) { - // we wait for the request to get to the server-side otherwise we almost always cancel - // the request artificially on the client-side before even sending it - waitForCancelHandler.awaitRequest(); - } - cancellable.cancel(); - waitForCancelHandler.cancelDone(); - assertTrue(latch.await(5, TimeUnit.SECONDS)); - } - assertEquals(0, responses.size()); - assertEquals(numRequests, exceptions.size()); - for (Exception exception : exceptions) { - assertThat(exception, instanceOf(CancellationException.class)); - } - } - - /** - * Test host selector against a real server and - * test what happens after calling - */ - public void testNodeSelector() throws Exception { - try (RestClient restClient = buildRestClient(firstPositionNodeSelector())) { - Request request = new Request("GET", "/200"); - int rounds = between(1, 10); - for (int i = 0; i < rounds; i++) { - /* - * Run the request more than once to verify that the - * NodeSelector overrides the round robin behavior. - */ - if (stoppedFirstHost) { - try { - RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); - fail("expected to fail to connect"); - } catch (ConnectException e) { - // Windows isn't consistent here. Sometimes the message is even null! - if (false == System.getProperty("os.name").startsWith("Windows")) { - assertTrue(e.getMessage().contains("Connection refused")); - } - } - } else { - Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); - assertEquals(httpHosts[0], response.getHost()); - } - } - } - } - - @Ignore("https://github.com/elastic/elasticsearch/issues/87314") - public void testNonRetryableException() throws Exception { - RequestOptions.Builder options = RequestOptions.DEFAULT.toBuilder(); - options.setHttpAsyncResponseConsumerFactory( - // Limit to very short responses to trigger a ContentTooLongException - () -> new BasicAsyncResponseConsumer(new BufferedByteConsumer(10)) - ); - - AtomicInteger failureCount = new AtomicInteger(); - RestClient client = buildRestClient(NodeSelector.ANY, new RestClient.FailureListener() { - @Override - public void onFailure(Node node) { - failureCount.incrementAndGet(); - } - }); - - failureCount.set(0); - Request request = new Request("POST", "/20bytes"); - request.setOptions(options); - try { - RestClientSingleHostTests.performRequestSyncOrAsync(client, request); - fail("Request should not succeed"); - } catch (IOException e) { - assertEquals(stoppedFirstHost ? 2 : 1, failureCount.intValue()); - } - - client.close(); - } - - private static class TestResponse { - private final String method; - private final int statusCode; - private final Object response; - - TestResponse(String method, int statusCode, Object response) { - this.method = method; - this.statusCode = statusCode; - this.response = response; - } - - Response getResponse() { - if (response instanceof Response) { - return (Response) response; - } - if (response instanceof ResponseException) { - return ((ResponseException) response).getResponse(); - } - throw new AssertionError("unexpected response " + response.getClass()); - } - } - - private NodeSelector firstPositionNodeSelector() { - return nodes -> { - for (Iterator itr = nodes.iterator(); itr.hasNext();) { - if (httpHosts[0] != itr.next().getHost()) { - itr.remove(); - } - } - }; - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientMultipleHostsTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientMultipleHostsTests.java deleted file mode 100644 index 640471c09..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientMultipleHostsTests.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import com.carrotsearch.randomizedtesting.generators.RandomNumbers; -import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.Request; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.ResponseException; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientSingleHostTests; -import org.elasticsearch.client.RestClientTestCase; -import org.elasticsearch.client.node.Node; -import org.elasticsearch.client.node.selector.NodeSelector; -import org.junit.After; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import static org.elasticsearch.client.RestClientTestUtil.randomErrorNoRetryStatusCode; -import static org.elasticsearch.client.RestClientTestUtil.randomErrorRetryStatusCode; -import static org.elasticsearch.client.RestClientTestUtil.randomHttpMethod; -import static org.elasticsearch.client.RestClientTestUtil.randomOkStatusCode; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * Tests for {@link RestClient} behaviour against multiple hosts: fail-over, blacklisting etc. - * Relies on a mock http client to intercept requests and return desired responses based on request path. - */ -public class RestClientMultipleHostsTests extends RestClientTestCase { - - private ExecutorService exec = Executors.newFixedThreadPool(1); - private List nodes; - private HostsTrackingFailureListener failureListener; - - public RestClient createRestClient(NodeSelector nodeSelector) { - CloseableHttpAsyncClient httpClient = RestClientSingleHostTests.mockHttpClient(exec); - int numNodes = RandomNumbers.randomIntBetween(getRandom(), 2, 5); - nodes = new ArrayList<>(numNodes); - for (int i = 0; i < numNodes; i++) { - nodes.add(new Node(new HttpHost("localhost", 9200 + i))); - } - nodes = Collections.unmodifiableList(nodes); - failureListener = new HostsTrackingFailureListener(); - return new RestClient(httpClient, new Header[0], nodes, null, failureListener, nodeSelector, false, false, false); - } - - /** - * Shutdown the executor so we don't leak threads into other test runs. - */ - @After - public void shutdownExec() { - exec.shutdown(); - } - - public void testRoundRobinOkStatusCodes() throws Exception { - RestClient restClient = createRestClient(NodeSelector.ANY); - int numIters = RandomNumbers.randomIntBetween(getRandom(), 1, 5); - for (int i = 0; i < numIters; i++) { - Set hostsSet = hostsSet(); - for (int j = 0; j < nodes.size(); j++) { - int statusCode = randomOkStatusCode(getRandom()); - Response response = RestClientSingleHostTests.performRequestSyncOrAsync( - restClient, - new Request(randomHttpMethod(getRandom()), "/" + statusCode) - ); - assertEquals(statusCode, response.getStatusCode()); - assertTrue("host not found: " + response.getHost(), hostsSet.remove(response.getHost())); - } - assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); - } - failureListener.assertNotCalled(); - } - - public void testRoundRobinNoRetryErrors() throws Exception { - RestClient restClient = createRestClient(NodeSelector.ANY); - int numIters = RandomNumbers.randomIntBetween(getRandom(), 1, 5); - for (int i = 0; i < numIters; i++) { - Set hostsSet = hostsSet(); - for (int j = 0; j < nodes.size(); j++) { - String method = randomHttpMethod(getRandom()); - int statusCode = randomErrorNoRetryStatusCode(getRandom()); - try { - Response response = RestClientSingleHostTests.performRequestSyncOrAsync( - restClient, - new Request(method, "/" + statusCode) - ); - if (method.equals("HEAD") && statusCode == 404) { - // no exception gets thrown although we got a 404 - assertEquals(404, response.getStatusCode()); - assertEquals(statusCode, response.getStatusCode()); - assertTrue("host not found: " + response.getHost(), hostsSet.remove(response.getHost())); - } else { - fail("request should have failed"); - } - } catch (ResponseException e) { - if (method.equals("HEAD") && statusCode == 404) { - throw e; - } - Response response = e.getResponse(); - assertEquals(statusCode, response.getStatusCode()); - assertTrue("host not found: " + response.getHost(), hostsSet.remove(response.getHost())); - assertEquals(0, e.getSuppressed().length); - } - } - assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); - } - failureListener.assertNotCalled(); - } - - public void testRoundRobinRetryErrors() throws Exception { - RestClient restClient = createRestClient(NodeSelector.ANY); - String retryEndpoint = randomErrorRetryEndpoint(); - try { - RestClientSingleHostTests.performRequestSyncOrAsync(restClient, new Request(randomHttpMethod(getRandom()), retryEndpoint)); - fail("request should have failed"); - } catch (ResponseException e) { - Set hostsSet = hostsSet(); - // first request causes all the hosts to be blacklisted, the returned exception holds one suppressed exception each - failureListener.assertCalled(nodes); - do { - Response response = e.getResponse(); - assertEquals(Integer.parseInt(retryEndpoint.substring(1)), response.getStatusCode()); - assertTrue( - "host [" + response.getHost() + "] not found, most likely used multiple times", - hostsSet.remove(response.getHost()) - ); - if (e.getSuppressed().length > 0) { - assertEquals(1, e.getSuppressed().length); - Throwable suppressed = e.getSuppressed()[0]; - assertThat(suppressed, instanceOf(ResponseException.class)); - e = (ResponseException) suppressed; - } else { - e = null; - } - } while (e != null); - assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); - } catch (IOException e) { - Set hostsSet = hostsSet(); - // first request causes all the hosts to be blacklisted, the returned exception holds one suppressed exception each - failureListener.assertCalled(nodes); - do { - HttpHost httpHost = HttpHost.create(e.getMessage()); - assertTrue("host [" + httpHost + "] not found, most likely used multiple times", hostsSet.remove(httpHost)); - if (e.getSuppressed().length > 0) { - assertEquals(1, e.getSuppressed().length); - Throwable suppressed = e.getSuppressed()[0]; - assertThat(suppressed, instanceOf(IOException.class)); - e = (IOException) suppressed; - } else { - e = null; - } - } while (e != null); - assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); - } - - int numIters = RandomNumbers.randomIntBetween(getRandom(), 2, 5); - for (int i = 1; i <= numIters; i++) { - // check that one different host is resurrected at each new attempt - Set hostsSet = hostsSet(); - for (int j = 0; j < nodes.size(); j++) { - retryEndpoint = randomErrorRetryEndpoint(); - try { - RestClientSingleHostTests.performRequestSyncOrAsync( - restClient, - new Request(randomHttpMethod(getRandom()), retryEndpoint) - ); - fail("request should have failed"); - } catch (ResponseException e) { - Response response = e.getResponse(); - assertThat(response.getStatusCode(), equalTo(Integer.parseInt(retryEndpoint.substring(1)))); - assertTrue( - "host [" + response.getHost() + "] not found, most likely used multiple times", - hostsSet.remove(response.getHost()) - ); - // after the first request, all hosts are blacklisted, a single one gets resurrected each time - failureListener.assertCalled(response.getHost()); - assertEquals(0, e.getSuppressed().length); - } catch (IOException e) { - HttpHost httpHost = HttpHost.create(e.getMessage()); - assertTrue("host [" + httpHost + "] not found, most likely used multiple times", hostsSet.remove(httpHost)); - // after the first request, all hosts are blacklisted, a single one gets resurrected each time - failureListener.assertCalled(httpHost); - assertEquals(0, e.getSuppressed().length); - } - } - assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); - if (getRandom().nextBoolean()) { - // mark one host back alive through a successful request and check that all requests after that are sent to it - HttpHost selectedHost = null; - int iters = RandomNumbers.randomIntBetween(getRandom(), 2, 10); - for (int y = 0; y < iters; y++) { - int statusCode = randomErrorNoRetryStatusCode(getRandom()); - Response response; - try { - response = RestClientSingleHostTests.performRequestSyncOrAsync( - restClient, - new Request(randomHttpMethod(getRandom()), "/" + statusCode) - ); - } catch (ResponseException e) { - response = e.getResponse(); - } - assertThat(response.getStatusCode(), equalTo(statusCode)); - if (selectedHost == null) { - selectedHost = response.getHost(); - } else { - assertThat(response.getHost(), equalTo(selectedHost)); - } - } - failureListener.assertNotCalled(); - // let the selected host catch up on number of failures, it gets selected a consecutive number of times as it's the one - // selected to be retried earlier (due to lower number of failures) till all the hosts have the same number of failures - for (int y = 0; y < i + 1; y++) { - retryEndpoint = randomErrorRetryEndpoint(); - try { - RestClientSingleHostTests.performRequestSyncOrAsync( - restClient, - new Request(randomHttpMethod(getRandom()), retryEndpoint) - ); - fail("request should have failed"); - } catch (ResponseException e) { - Response response = e.getResponse(); - assertThat(response.getStatusCode(), equalTo(Integer.parseInt(retryEndpoint.substring(1)))); - assertThat(response.getHost(), equalTo(selectedHost)); - failureListener.assertCalled(selectedHost); - } catch (IOException e) { - HttpHost httpHost = HttpHost.create(e.getMessage()); - assertThat(httpHost, equalTo(selectedHost)); - failureListener.assertCalled(selectedHost); - } - } - } - } - } - - public void testNodeSelector() throws Exception { - NodeSelector firstPositionOnly = restClientNodes -> { - boolean found = false; - for (Iterator itr = restClientNodes.iterator(); itr.hasNext();) { - if (nodes.get(0) == itr.next()) { - found = true; - } else { - itr.remove(); - } - } - assertTrue(found); - }; - RestClient restClient = createRestClient(firstPositionOnly); - int rounds = between(1, 10); - for (int i = 0; i < rounds; i++) { - /* - * Run the request more than once to verify that the - * NodeSelector overrides the round robin behavior. - */ - Request request = new Request("GET", "/200"); - Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); - assertEquals(nodes.get(0).getHost(), response.getHost()); - } - } - - public void testSetNodes() throws Exception { - RestClient restClient = createRestClient(NodeSelector.SKIP_DEDICATED_MASTERS); - List newNodes = new ArrayList<>(nodes.size()); - for (int i = 0; i < nodes.size(); i++) { - Node.Roles roles = i == 0 - ? new Node.Roles(new TreeSet<>(Arrays.asList("data", "ingest"))) - : new Node.Roles(new TreeSet<>(Arrays.asList("master"))); - newNodes.add(new Node(nodes.get(i).getHost(), null, null, null, roles, null)); - } - restClient.setNodes(newNodes); - int rounds = between(1, 10); - for (int i = 0; i < rounds; i++) { - /* - * Run the request more than once to verify that the - * NodeSelector overrides the round robin behavior. - */ - Request request = new Request("GET", "/200"); - Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); - assertEquals(newNodes.get(0).getHost(), response.getHost()); - } - } - - private static String randomErrorRetryEndpoint() { - switch (RandomNumbers.randomIntBetween(getRandom(), 0, 3)) { - case 0: - return "/" + randomErrorRetryStatusCode(getRandom()); - case 1: - return "/coe"; - case 2: - return "/soe"; - case 3: - return "/ioe"; - } - throw new UnsupportedOperationException(); - } - - /** - * Build a mutable {@link Set} containing all the {@link Node#getHost() hosts} - * in use by the test. - */ - private Set hostsSet() { - Set hosts = new HashSet<>(); - for (Node node : nodes) { - hosts.add(node.getHost()); - } - return hosts; - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientSingleHostIntegTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientSingleHostIntegTests.java deleted file mode 100644 index 9d2510f1b..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientSingleHostIntegTests.java +++ /dev/null @@ -1,457 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import com.sun.net.httpserver.Headers; -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; -import com.sun.net.httpserver.HttpServer; -import org.apache.hc.client5.http.async.methods.SimpleHttpRequest; -import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; -import org.apache.hc.client5.http.classic.methods.HttpGet; -import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy; -import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; -import org.apache.hc.client5.http.impl.async.HttpAsyncClients; -import org.apache.hc.core5.http.ContentType; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.io.entity.EntityUtils; -import org.apache.hc.core5.http.io.entity.StringEntity; -import org.apache.hc.core5.http.message.BasicHeader; -import org.elasticsearch.client.Cancellable; -import org.elasticsearch.client.Request; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.ResponseException; -import org.elasticsearch.client.ResponseListener; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.RestClientSingleHostTests; -import org.elasticsearch.client.RestClientTestCase; -import org.elasticsearch.client.RestClientTestUtil; -import org.elasticsearch.mocksocket.MockHttpServer; -import org.junit.After; -import org.junit.Before; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.Arrays; -import java.util.Base64; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CancellationException; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.elasticsearch.client.RestClientTestUtil.getAllStatusCodes; -import static org.elasticsearch.client.RestClientTestUtil.randomHttpMethod; -import static org.elasticsearch.client.RestClientTestUtil.randomStatusCode; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.startsWith; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/* - * Integration test to check interaction between {@link RestClient} and {@link org.apache.hc.client5.http - * .async.HttpAsyncClient}. - * Works against a real http server, one single host. - */ - -public class RestClientSingleHostIntegTests extends RestClientTestCase { - - private HttpServer httpServer; - private RestClient restClient; - private String pathPrefix; - private Header[] defaultHeaders; - private WaitForCancelHandler waitForCancelHandler; - - @Before - public void startHttpServer() throws Exception { - // set version.properties, just for testing, version won't be updated - System.setProperty("versions.elasticsearch","8.17.0"); - pathPrefix = randomBoolean() ? "/testPathPrefix/" + randomAsciiLettersOfLengthBetween(1, 5) : ""; - httpServer = createHttpServer(); - defaultHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header-default"); - restClient = createRestClient(false, true, true); - } - - private HttpServer createHttpServer() throws Exception { - HttpServer mockServer = - MockHttpServer.createHttp(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); - mockServer.start(); - // returns a different status code depending on the path - for (int statusCode : getAllStatusCodes()) { - mockServer.createContext(pathPrefix + "/" + statusCode, new ResponseHandler(statusCode)); - } - waitForCancelHandler = new WaitForCancelHandler(); - mockServer.createContext(pathPrefix + "/wait", waitForCancelHandler); - return mockServer; - } - - private static class WaitForCancelHandler implements HttpHandler { - - private final CountDownLatch cancelHandlerLatch = new CountDownLatch(1); - - void cancelDone() { - cancelHandlerLatch.countDown(); - } - - @Override - public void handle(HttpExchange exchange) throws IOException { - try { - cancelHandlerLatch.await(); - } catch (InterruptedException ignore) { - } finally { - exchange.sendResponseHeaders(200, 0); - exchange.close(); - } - } - } - - private static class ResponseHandler implements HttpHandler { - private final int statusCode; - - ResponseHandler(int statusCode) { - this.statusCode = statusCode; - } - - @Override - public void handle(HttpExchange httpExchange) throws IOException { - // copy request body to response body so we can verify it was sent - StringBuilder body = new StringBuilder(); - try (InputStreamReader reader = new InputStreamReader(httpExchange.getRequestBody(), UTF_8)) { - char[] buffer = new char[256]; - int read; - while ((read = reader.read(buffer)) != -1) { - body.append(buffer, 0, read); - } - } - // copy request headers to response headers so we can verify they were sent - Headers requestHeaders = httpExchange.getRequestHeaders(); - Headers responseHeaders = httpExchange.getResponseHeaders(); - for (Map.Entry> header : requestHeaders.entrySet()) { - responseHeaders.put(header.getKey(), header.getValue()); - } - httpExchange.getRequestBody().close(); - httpExchange.sendResponseHeaders(statusCode, body.length() == 0 ? -1 : body.length()); - if (body.length() > 0) { - try (OutputStream out = httpExchange.getResponseBody()) { - out.write(body.toString().getBytes(UTF_8)); - } - } - httpExchange.close(); - } - } - - private RestClient createRestClient(final boolean useAuth, final boolean usePreemptiveAuth, - final boolean enableMetaHeader) { - HttpHost host = new HttpHost(httpServer.getAddress().getHostString(), - httpServer.getAddress().getPort()); - - final RestClientBuilder restClientBuilder = - RestClient.builder(host).setDefaultHeaders(defaultHeaders); - if (pathPrefix.length() > 0) { - restClientBuilder.setPathPrefix(pathPrefix); - } - - restClientBuilder.setMetaHeaderEnabled(enableMetaHeader); - - - if (useAuth) { - // provide the username/password for every request - var creds = Base64.getEncoder().encodeToString("user:pass".getBytes()); - - HttpAsyncClientBuilder httpclientBuilder = HttpAsyncClients.custom(); - - httpclientBuilder.setDefaultHeaders(Arrays.asList(new BasicHeader("Authorization", - "Basic " + creds))); - - if (!usePreemptiveAuth) { - httpclientBuilder - .disableAuthCaching() - .setTargetAuthenticationStrategy(new DefaultAuthenticationStrategy()); - } - restClientBuilder.setCustomRestClient(httpclientBuilder.build()); - } - - return restClientBuilder.build(); - } - - @After - public void stopHttpServers() throws IOException { - restClient.close(); - restClient = null; - httpServer.stop(0); - httpServer = null; - } - - /* - * Tests sending a bunch of async requests works well (e.g. no TimeoutException from the leased pool) - * See https://github.com/elastic/elasticsearch/issues/24069 - */ - - public void testManyAsyncRequests() throws Exception { - int iters = randomIntBetween(500, 1000); - final CountDownLatch latch = new CountDownLatch(iters); - final List exceptions = new CopyOnWriteArrayList<>(); - for (int i = 0; i < iters; i++) { - Request request = new Request("PUT", "/200"); - request.setEntity(new StringEntity("{}", ContentType.APPLICATION_JSON)); - restClient.performRequestAsync(request, new ResponseListener() { - @Override - public void onSuccess(Response response) { - latch.countDown(); - } - - @Override - public void onFailure(Exception exception) { - exceptions.add(exception); - latch.countDown(); - } - }); - } - - assertTrue("timeout waiting for requests to be sent", latch.await(10, TimeUnit.SECONDS)); - if (exceptions.isEmpty() == false) { - AssertionError error = new AssertionError( - "expected no failures but got some. see suppressed for first 10 of [" + exceptions.size() + "] failures" - ); - for (Exception exception : exceptions.subList(0, Math.min(10, exceptions.size()))) { - error.addSuppressed(exception); - } - throw error; - } - } - - public void testCancelAsyncRequest() throws Exception { - Request request = new Request(randomHttpMethod(getRandom()), "/wait"); - CountDownLatch requestLatch = new CountDownLatch(1); - AtomicReference error = new AtomicReference<>(); - Cancellable cancellable = restClient.performRequestAsync(request, new ResponseListener() { - @Override - public void onSuccess(Response response) { - throw new AssertionError("onResponse called unexpectedly"); - } - - @Override - public void onFailure(Exception exception) { - error.set(exception); - requestLatch.countDown(); - } - }); - cancellable.cancel(); - waitForCancelHandler.cancelDone(); - assertTrue(requestLatch.await(5, TimeUnit.SECONDS)); - assertThat(error.get(), instanceOf(CancellationException.class)); - } - - /** - * This test verifies some assumptions that we rely upon around the way the async http client works - * when reusing the same request - * throughout multiple retries, and the use of the - * {@link org.apache.hc.client5.http.classic.methods.HttpUriRequestBase#abort()} method. - * In fact the low-level REST client reuses the same request instance throughout multiple retries, and - * relies on the http client - * to set the future ref to the request properly so that when abort is called, the proper future gets - * cancelled. - */ - public void testRequestResetAndAbort() throws Exception { - try (CloseableHttpAsyncClient client = HttpAsyncClientBuilder.create().build()) { - client.start(); - HttpHost httpHost = new HttpHost(httpServer.getAddress().getHostString(), - httpServer.getAddress().getPort()); - HttpGet httpGet = new HttpGet(httpHost.toURI() + pathPrefix + "/200"); - - // calling abort before the request is sent is a no-op - httpGet.abort(); - assertTrue(httpGet.isAborted()); - - { - httpGet.reset(); - assertFalse(httpGet.isAborted()); - httpGet.abort(); - Future future = client.execute(SimpleHttpRequest.copy(httpGet), null); - httpGet.setDependency((org.apache.hc.core5.concurrent.Cancellable) future); - try { - future.get(); - fail("expected cancellation exception"); - } catch (CancellationException e) { - // expected - } - assertTrue(future.isCancelled()); - } - { - httpGet.reset(); - Future future = client.execute(SimpleHttpRequest.copy(httpGet), null); - httpGet.setDependency((org.apache.hc.core5.concurrent.Cancellable) future); - - assertFalse(httpGet.isAborted()); - httpGet.abort(); - assertTrue(httpGet.isAborted()); - try { - assertTrue(future.isDone()); - future.get(); - } catch (CancellationException e) { - // expected sometimes - if the future was cancelled before executing successfully - } - } - { - httpGet.reset(); - assertFalse(httpGet.isAborted()); - Future future = client.execute(SimpleHttpRequest.copy(httpGet), null); - httpGet.setDependency((org.apache.hc.core5.concurrent.Cancellable) future); - - assertFalse(httpGet.isAborted()); - assertEquals(200, future.get().getCode()); - assertFalse(future.isCancelled()); - } - } - } - - /** - * End to end test for delete with body. We test it explicitly as it is not supported - * out of the box by {@link org.apache.hc.client5.http.impl.async.HttpAsyncClients}. - * Exercises the test http server ability to send back whatever body it received. - */ - public void testDeleteWithBody() throws Exception { - bodyTest("DELETE"); - } - - /** - * End to end test for get with body. We test it explicitly as it is not supported - * out of the box by {@link org.apache.hc.client5.http.impl.async.HttpAsyncClients}. - * Exercises the test http server ability to send back whatever body it received. - */ - public void testGetWithBody() throws Exception { - bodyTest("GET"); - } - - public void testEncodeParams() throws Exception { - { - Request request = new Request("PUT", "/200"); - request.addParameter("routing", "this/is/the/routing"); - Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); - assertEquals(pathPrefix + "/200?routing=this%2Fis%2Fthe%2Frouting", - response.getRequestLine().getUri()); - } - { - Request request = new Request("PUT", "/200"); - request.addParameter("routing", "this|is|the|routing"); - Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); - assertEquals(pathPrefix + "/200?routing=this%7Cis%7Cthe%7Crouting", - response.getRequestLine().getUri()); - } - { - Request request = new Request("PUT", "/200"); - request.addParameter("routing", "routing#1"); - Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); - assertEquals(pathPrefix + "/200?routing=routing%231", response.getRequestLine().getUri()); - } - { - Request request = new Request("PUT", "/200"); - request.addParameter("routing", "中文"); - Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); - assertEquals(pathPrefix + "/200?routing=%E4%B8%AD%E6%96%87", response.getRequestLine().getUri()); - } - { - Request request = new Request("PUT", "/200"); - request.addParameter("routing", "foo bar"); - Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); - assertEquals(pathPrefix + "/200?routing=foo%20bar", response.getRequestLine().getUri()); - } - { - Request request = new Request("PUT", "/200"); - request.addParameter("routing", "foo+bar"); - Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); - assertEquals(pathPrefix + "/200?routing=foo%2Bbar", response.getRequestLine().getUri()); - } - { - Request request = new Request("PUT", "/200"); - request.addParameter("routing", "foo/bar"); - Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); - assertEquals(pathPrefix + "/200?routing=foo%2Fbar", response.getRequestLine().getUri()); - } - { - Request request = new Request("PUT", "/200"); - request.addParameter("routing", "foo^bar"); - Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); - assertEquals(pathPrefix + "/200?routing=foo%5Ebar", response.getRequestLine().getUri()); - } - } - - /** - * Verify that credentials are sent on the first request with preemptive auth enabled (default when - * provided with credentials). - */ - public void testPreemptiveAuthEnabled() throws Exception { - final String[] methods = {"POST", "PUT", "GET", "DELETE"}; - - try (RestClient restClient = createRestClient(true, true, true)) { - for (final String method : methods) { - final Response response = bodyTest(restClient, method); - - assertThat(response.getHeader("Authorization"), startsWith("Basic")); - } - } - } - - private Response bodyTest(final String method) throws Exception { - return bodyTest(restClient, method); - } - - private Response bodyTest(final RestClient client, final String method) throws Exception { - int statusCode = randomStatusCode(getRandom()); - return bodyTest(client, method, statusCode, new Header[0]); - } - - private Response bodyTest(RestClient client, String method, int statusCode, Header[] headers) throws Exception { - String requestBody = "{ \"field\": \"value\" }"; - Request request = new Request(method, "/" + statusCode); - request.setJsonEntity(requestBody); - RequestOptions.Builder options = request.getOptions().toBuilder(); - for (Header header : headers) { - options.addHeader(header.getName(), header.getValue()); - } - request.setOptions(options); - Response esResponse; - try { - esResponse = RestClientSingleHostTests.performRequestSyncOrAsync(client, request); - } catch (ResponseException e) { - esResponse = e.getResponse(); - } - assertEquals(method, esResponse.getRequestLine().getMethod()); - assertEquals(statusCode, esResponse.getStatusCode()); - assertEquals(pathPrefix + "/" + statusCode, esResponse.getRequestLine().getUri()); - assertEquals(requestBody, EntityUtils.toString(esResponse.getEntity())); - - return esResponse; - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientSingleHostTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientSingleHostTests.java deleted file mode 100644 index a67f677b5..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientSingleHostTests.java +++ /dev/null @@ -1,694 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hc.client5.http.ConnectTimeoutException; -import org.apache.hc.client5.http.classic.methods.HttpHead; -import org.apache.hc.client5.http.classic.methods.HttpOptions; -import org.apache.hc.client5.http.classic.methods.HttpPatch; -import org.apache.hc.client5.http.classic.methods.HttpPost; -import org.apache.hc.client5.http.classic.methods.HttpPut; -import org.apache.hc.client5.http.classic.methods.HttpTrace; -import org.apache.hc.client5.http.classic.methods.HttpUriRequest; -import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; -import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.client5.http.protocol.HttpClientContext; -import org.apache.hc.core5.concurrent.FutureCallback; -import org.apache.hc.core5.http.ConnectionClosedException; -import org.apache.hc.core5.http.ContentType; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.HttpEntity; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.HttpRequest; -import org.apache.hc.core5.http.HttpResponse; -import org.apache.hc.core5.http.io.entity.EntityUtils; -import org.apache.hc.core5.http.io.entity.StringEntity; -import org.apache.hc.core5.http.message.BasicClassicHttpRequest; -import org.apache.hc.core5.http.message.BasicClassicHttpResponse; -import org.apache.hc.core5.http.nio.AsyncDataProducer; -import org.apache.hc.core5.http.nio.AsyncRequestProducer; -import org.apache.hc.core5.http.nio.AsyncResponseConsumer; -import org.apache.hc.core5.net.URIBuilder; -import org.elasticsearch.client.HttpDeleteWithEntity; -import org.elasticsearch.client.HttpGetWithEntity; -import org.elasticsearch.client.Request; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.ResponseException; -import org.elasticsearch.client.ResponseListener; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientTestUtil; -import org.elasticsearch.client.WarningFailureException; -import org.elasticsearch.client.WarningsHandler; -import org.elasticsearch.client.node.Node; -import org.elasticsearch.client.node.selector.NodeSelector; -import org.elasticsearch.client.producer.BasicAsyncEntityProducer; -import org.junit.After; -import org.junit.Before; -import org.mockito.ArgumentCaptor; -import org.mockito.stubbing.Answer; - -import javax.net.ssl.SSLHandshakeException; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.lang.reflect.Field; -import java.net.SocketTimeoutException; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicReference; - -import static java.util.Collections.singletonList; -import static org.elasticsearch.client.RestClientTestUtil.canHaveBody; -import static org.elasticsearch.client.RestClientTestUtil.getAllErrorStatusCodes; -import static org.elasticsearch.client.RestClientTestUtil.getHttpMethods; -import static org.elasticsearch.client.RestClientTestUtil.getOkStatusCodes; -import static org.elasticsearch.client.RestClientTestUtil.randomStatusCode; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -/** - * Tests for basic functionality of {@link RestClient} against one single host: tests http requests being - * sent, headers, - * body, different status codes and corresponding responses/exceptions. - * Relies on a mock http client to intercept requests and return desired responses based on request path. - */ -public class RestClientSingleHostTests extends RestClientTestCase { - private static final Log logger = LogFactory.getLog(RestClientSingleHostTests.class); - - private ExecutorService exec = Executors.newFixedThreadPool(1); - private RestClient restClient; - private Header[] defaultHeaders; - private Node node; - private CloseableHttpAsyncClient httpClient; - private HostsTrackingFailureListener failureListener; - private boolean strictDeprecationMode; - - @Before - public void createRestClient() { - httpClient = mockHttpClient(exec); - defaultHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header-default"); - node = new Node(new HttpHost("localhost", 9200)); - failureListener = new HostsTrackingFailureListener(); - strictDeprecationMode = randomBoolean(); - restClient = new RestClient( - this.httpClient, - defaultHeaders, - singletonList(node), - null, - failureListener, - NodeSelector.ANY, - strictDeprecationMode, - false, - false - ); - } - - @SuppressWarnings("unchecked") - static CloseableHttpAsyncClient mockHttpClient(final ExecutorService exec) { - CloseableHttpAsyncClient httpClient = mock(CloseableHttpAsyncClient.class); - when( - httpClient.execute( - any(AsyncRequestProducer.class), - any(AsyncResponseConsumer.class), - any(HttpClientContext.class), - nullable(FutureCallback.class) - ) - ).thenAnswer((Answer>) invocationOnMock -> { - final AsyncRequestProducer requestProducer = - (AsyncRequestProducer) invocationOnMock.getArguments()[0]; - final FutureCallback futureCallback = - (FutureCallback) invocationOnMock.getArguments()[3]; - // Call the callback asynchronous to better simulate how async http client works - return exec.submit(() -> { - if (futureCallback != null) { - try { - HttpResponse httpResponse = responseOrException(requestProducer); - futureCallback.completed(httpResponse); - } catch (Exception e) { - futureCallback.failed(e); - } - return null; - } - return responseOrException(requestProducer); - }); - }); - return httpClient; - } - - private static HttpResponse responseOrException(AsyncDataProducer requestProducer) throws Exception { - // request is private in BasicRequestProducer, need to make it accessible first - Field requestField = requestProducer.getClass().getDeclaredField("request"); - requestField.setAccessible(true); - final HttpRequest request = (HttpRequest) requestField.get(requestProducer); - final HttpHost httpHost = new HttpHost(request.getAuthority().getHostName(), - request.getAuthority().getPort()); - // return the desired status code or exception depending on the path - switch (request.getPath()) { - case "/soe": - throw new SocketTimeoutException(httpHost.toString()); - case "/coe": - throw new ConnectTimeoutException(httpHost.toString()); - case "/ioe": - throw new IOException(httpHost.toString()); - case "/closed": - throw new ConnectionClosedException(); - case "/handshake": - throw new SSLHandshakeException(""); - case "/uri": - throw new URISyntaxException("", ""); - case "/runtime": - throw new RuntimeException(); - default: - int statusCode = Integer.parseInt(request.getPath().substring(1)); - - final BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(statusCode, ""); - Optional entity = retrieveEntity(requestProducer); - - // return the same body that was sent - if (entity.isPresent()) { - assertTrue("the entity is not repeatable, cannot set it to the response directly", - entity.get().isRepeatable()); - httpResponse.setEntity(entity.get()); - } - // return the same headers that were sent - httpResponse.setHeaders(request.getHeaders()); - return httpResponse; - } - } - - private static Optional retrieveEntity(AsyncDataProducer requestProducer) throws NoSuchFieldException, IllegalAccessException { - // entity is in the dataProducer field, both are private - Field dataProducerField = requestProducer.getClass().getDeclaredField("dataProducer"); - dataProducerField.setAccessible(true); - final BasicAsyncEntityProducer dataProducer = - (BasicAsyncEntityProducer) dataProducerField.get(requestProducer); - - if (dataProducer != null) { - Field entityField = dataProducer.getClass().getDeclaredField("entity"); - entityField.setAccessible(true); - return Optional.ofNullable((HttpEntity) entityField.get(dataProducer)); - } - return Optional.empty(); - } - - /** - * Shutdown the executor so we don't leak threads into other test runs. - */ - @After - public void shutdownExec() { - exec.shutdown(); - } - - /** - * Verifies the content of the {@link HttpRequest} that's internally created and passed through to the - * http client - */ - @SuppressWarnings("unchecked") - public void testInternalHttpRequest() throws Exception { - ArgumentCaptor requestArgumentCaptor = ArgumentCaptor.forClass - (AsyncRequestProducer.class); - int times = 0; - for (String httpMethod : getHttpMethods()) { - HttpRequest expectedRequest = performRandomRequest(httpMethod); - verify(httpClient, times(++times)).execute( - requestArgumentCaptor.capture(), - any(AsyncResponseConsumer.class), - any(HttpClientContext.class), - nullable(FutureCallback.class) - ); - AsyncRequestProducer requestProducer = requestArgumentCaptor.getValue(); - Field requestField = requestProducer.getClass().getDeclaredField("request"); - requestField.setAccessible(true); - final HttpRequest actualRequest = (HttpRequest) requestField.get(requestProducer); - assertEquals(expectedRequest.getRequestUri(), actualRequest.getRequestUri()); - assertArrayEquals(expectedRequest.getHeaders(), actualRequest.getHeaders()); - if (canHaveBody(expectedRequest) && expectedRequest instanceof BasicClassicHttpRequest) { - Optional actualEntity = retrieveEntity(requestProducer); - if (actualEntity.isPresent()) { - HttpEntity expectedEntity = ((BasicClassicHttpRequest) expectedRequest).getEntity(); - assertEquals(EntityUtils.toString(expectedEntity), - EntityUtils.toString(actualEntity.get())); - } - } - } - } - - /** - * End to end test for ok status codes - */ - public void testOkStatusCodes() throws Exception { - for (String method : getHttpMethods()) { - for (int okStatusCode : getOkStatusCodes()) { - Response response = performRequestSyncOrAsync(restClient, new Request(method, - "/" + okStatusCode)); - assertThat(response.getStatusCode(), equalTo(okStatusCode)); - } - } - failureListener.assertNotCalled(); - } - - /** - * End to end test for error status codes: they should cause an exception to be thrown - */ - public void testErrorStatusCodes() throws Exception { - for (String method : getHttpMethods()) { - // error status codes should cause an exception to be thrown - for (int errorStatusCode : getAllErrorStatusCodes()) { - try { - Request request = new Request(method, "/" + errorStatusCode); - Response response = restClient.performRequest(request); - fail("request should have failed"); - } catch (ResponseException e) { - assertEquals(errorStatusCode, e.getResponse().getStatusCode()); - assertExceptionStackContainsCallingMethod(e); - } - } - } - } - - public void testPerformRequestIOExceptions() throws Exception { - for (String method : getHttpMethods()) { - // IOExceptions should be let bubble up - try { - restClient.performRequest(new Request(method, "/ioe")); - fail("request should have failed"); - } catch (IOException e) { - // And we do all that so the thrown exception has our method in the stacktrace - assertExceptionStackContainsCallingMethod(e); - } - failureListener.assertCalled(singletonList(node)); - try { - restClient.performRequest(new Request(method, "/coe")); - fail("request should have failed"); - } catch (ConnectTimeoutException e) { - // And we do all that so the thrown exception has our method in the stacktrace - assertExceptionStackContainsCallingMethod(e); - } - failureListener.assertCalled(singletonList(node)); - try { - restClient.performRequest(new Request(method, "/soe")); - fail("request should have failed"); - } catch (SocketTimeoutException e) { - // And we do all that so the thrown exception has our method in the stacktrace - assertExceptionStackContainsCallingMethod(e); - } - failureListener.assertCalled(singletonList(node)); - try { - restClient.performRequest(new Request(method, "/closed")); - fail("request should have failed"); - } catch (ConnectionClosedException e) { - // And we do all that so the thrown exception has our method in the stacktrace - assertExceptionStackContainsCallingMethod(e); - } - failureListener.assertCalled(singletonList(node)); - try { - restClient.performRequest(new Request(method, "/handshake")); - fail("request should have failed"); - } catch (SSLHandshakeException e) { - // And we do all that so the thrown exception has our method in the stacktrace - assertExceptionStackContainsCallingMethod(e); - } - failureListener.assertCalled(singletonList(node)); - } - } - - public void testPerformRequestRuntimeExceptions() throws Exception { - for (String method : getHttpMethods()) { - try { - restClient.performRequest(new Request(method, "/runtime")); - fail("request should have failed"); - } catch (RuntimeException e) { - // And we do all that so the thrown exception has our method in the stacktrace - assertExceptionStackContainsCallingMethod(e); - } - failureListener.assertCalled(singletonList(node)); - } - } - - public void testPerformRequestExceptions() throws Exception { - for (String method : getHttpMethods()) { - try { - restClient.performRequest(new Request(method, "/uri")); - fail("request should have failed"); - } catch (RuntimeException e) { - assertThat(e.getCause(), instanceOf(URISyntaxException.class)); - // And we do all that so the thrown exception has our method in the stacktrace - assertExceptionStackContainsCallingMethod(e); - } - failureListener.assertCalled(singletonList(node)); - } - } - - /** - * End to end test for request and response body. Exercises the mock http client ability to send back - * whatever body it has received. - */ - public void testBody() throws Exception { - String body = "{ \"field\": \"value\" }"; - StringEntity entity = new StringEntity(body, ContentType.APPLICATION_JSON); - for (String method : Arrays.asList("DELETE", "GET", "PATCH", "POST", "PUT")) { - for (int okStatusCode : getOkStatusCodes()) { - Request request = new Request(method, "/" + okStatusCode); - request.setEntity(entity); - Response response = restClient.performRequest(request); - assertThat(response.getStatusCode(), equalTo(okStatusCode)); - assertThat(EntityUtils.toString(response.getEntity()), equalTo(body)); - } - for (int errorStatusCode : getAllErrorStatusCodes()) { - Request request = new Request(method, "/" + errorStatusCode); - request.setEntity(entity); - try { - restClient.performRequest(request); - fail("request should have failed"); - } catch (ResponseException e) { - Response response = e.getResponse(); - assertThat(response.getStatusCode(), equalTo(errorStatusCode)); - assertThat(EntityUtils.toString(response.getEntity()), equalTo(body)); - assertExceptionStackContainsCallingMethod(e); - } - } - } - for (String method : Arrays.asList("HEAD", "OPTIONS", "TRACE")) { - Request request = new Request(method, "/" + randomStatusCode(getRandom())); - request.setEntity(entity); - try { - performRequestSyncOrAsync(restClient, request); - fail("request should have failed"); - } catch (UnsupportedOperationException e) { - assertThat(e.getMessage(), equalTo(method + " with body is not supported")); - } - } - } - - /** - * End to end test for request and response headers. Exercises the mock http client ability to send back - * whatever headers it has received. - */ - public void testHeaders() throws Exception { - for (String method : getHttpMethods()) { - final Header[] requestHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header"); - final int statusCode = randomStatusCode(getRandom()); - Request request = new Request(method, "/" + statusCode); - RequestOptions.Builder options = request.getOptions().toBuilder(); - for (Header requestHeader : requestHeaders) { - options.addHeader(requestHeader.getName(), requestHeader.getValue()); - } - request.setOptions(options); - Response esResponse; - try { - esResponse = performRequestSyncOrAsync(restClient, request); - } catch (ResponseException e) { - esResponse = e.getResponse(); - } - assertThat(esResponse.getStatusCode(), equalTo(statusCode)); - assertHeaders(defaultHeaders, requestHeaders, esResponse.getHeaders(), - Collections.emptySet()); - assertFalse(esResponse.hasWarnings()); - } - } - - public void testDeprecationWarnings() throws Exception { - String chars = randomAsciiAlphanumOfLength(5); - assertDeprecationWarnings(singletonList("poorly formatted " + chars), singletonList("poorly " + - "formatted " + chars)); - assertDeprecationWarnings(singletonList(formatWarningWithoutDate(chars)), singletonList(chars)); - assertDeprecationWarnings(singletonList(formatWarning(chars)), singletonList(chars)); - assertDeprecationWarnings( - Arrays.asList(formatWarning(chars), "another one", "and another"), - Arrays.asList(chars, "another one", "and another") - ); - assertDeprecationWarnings(Arrays.asList("ignorable one", "and another"), Arrays.asList("ignorable " + - "one", "and another")); - assertDeprecationWarnings(singletonList("exact"), singletonList("exact")); - assertDeprecationWarnings(Collections.emptyList(), Collections.emptyList()); - - String proxyWarning = "112 - \"network down\" \"Sat, 25 Aug 2012 23:34:45 GMT\""; - assertDeprecationWarnings(singletonList(proxyWarning), singletonList(proxyWarning)); - } - - private enum DeprecationWarningOption { - PERMISSIVE { - protected WarningsHandler warningsHandler() { - return WarningsHandler.PERMISSIVE; - } - }, - STRICT { - protected WarningsHandler warningsHandler() { - return WarningsHandler.STRICT; - } - }, - FILTERED { - protected WarningsHandler warningsHandler() { - return new WarningsHandler() { - @Override - public boolean warningsShouldFailRequest(List warnings) { - for (String warning : warnings) { - if (false == warning.startsWith("ignorable")) { - return true; - } - } - return false; - } - }; - } - }, - EXACT { - protected WarningsHandler warningsHandler() { - return new WarningsHandler() { - @Override - public boolean warningsShouldFailRequest(List warnings) { - return false == warnings.equals(Arrays.asList("exact")); - } - }; - } - }; - - protected abstract WarningsHandler warningsHandler(); - } - - private void assertDeprecationWarnings(List warningHeaderTexts, List warningBodyTexts) throws Exception { - String method = randomFrom(getHttpMethods()); - Request request = new Request(method, "/200"); - RequestOptions.Builder options = request.getOptions().toBuilder(); - for (String warningHeaderText : warningHeaderTexts) { - options.addHeader("Warning", warningHeaderText); - } - - final boolean expectFailure; - if (randomBoolean()) { - logger.info("checking strictWarningsMode=[" + strictDeprecationMode + "] and warnings=" + warningBodyTexts); - expectFailure = strictDeprecationMode && false == warningBodyTexts.isEmpty(); - } else { - DeprecationWarningOption warningOption = randomFrom(DeprecationWarningOption.values()); - logger.info("checking warningOption=" + warningOption + " and warnings=" + warningBodyTexts); - options.setWarningsHandler(warningOption.warningsHandler()); - expectFailure = warningOption.warningsHandler().warningsShouldFailRequest(warningBodyTexts); - } - request.setOptions(options); - - Response response; - if (expectFailure) { - try { - performRequestSyncOrAsync(restClient, request); - fail("expected WarningFailureException from warnings"); - return; - } catch (WarningFailureException e) { - if (false == warningBodyTexts.isEmpty()) { - assertThat(e.getMessage(), containsString("\nWarnings: " + warningBodyTexts)); - } - response = e.getResponse(); - } - } else { - response = performRequestSyncOrAsync(restClient, request); - } - assertEquals(false == warningBodyTexts.isEmpty(), response.hasWarnings()); - assertEquals(warningBodyTexts, response.getWarnings()); - } - - /** - * Emulates Elasticsearch's HeaderWarningLogger.formatWarning in simple - * cases. We don't have that available because we're testing against 1.7. - */ - private static String formatWarningWithoutDate(String warningBody) { - final String hash = new String(new byte[40], StandardCharsets.UTF_8).replace('\0', 'e'); - return "299 Elasticsearch-1.2.2-SNAPSHOT-" + hash + " \"" + warningBody + "\""; - } - - private static String formatWarning(String warningBody) { - return formatWarningWithoutDate(warningBody) + " \"Mon, 01 Jan 2001 00:00:00 GMT\""; - } - - private HttpUriRequest performRandomRequest(String method) throws Exception { - String uriAsString = "/" + randomStatusCode(getRandom()); - Request request = new Request(method, uriAsString); - URIBuilder uriBuilder = new URIBuilder(uriAsString); - if (randomBoolean()) { - int numParams = randomIntBetween(1, 3); - for (int i = 0; i < numParams; i++) { - String name = "param-" + i; - String value = randomAsciiAlphanumOfLengthBetween(3, 10); - request.addParameter(name, value); - uriBuilder.addParameter(name, value); - } - } - URI uri = uriBuilder.build(); - - HttpUriRequestBase expectedRequest; - switch (method) { - case "DELETE": - expectedRequest = new HttpDeleteWithEntity(uri); - break; - case "GET": - expectedRequest = new HttpGetWithEntity(uri); - break; - case "HEAD": - expectedRequest = new HttpHead(uri); - break; - case "OPTIONS": - expectedRequest = new HttpOptions(uri); - break; - case "PATCH": - expectedRequest = new HttpPatch(uri); - break; - case "POST": - expectedRequest = new HttpPost(uri); - break; - case "PUT": - expectedRequest = new HttpPut(uri); - break; - case "TRACE": - expectedRequest = new HttpTrace(uri); - break; - default: - throw new UnsupportedOperationException("method not supported: " + method); - } - - if (canHaveBody(expectedRequest) && getRandom().nextBoolean()) { - HttpEntity entity = new StringEntity(randomAsciiAlphanumOfLengthBetween(10, 100), - ContentType.APPLICATION_JSON); - (expectedRequest).setEntity(entity); - request.setEntity(entity); - } - - final Set uniqueNames = new HashSet<>(); - if (randomBoolean()) { - Header[] headers = RestClientTestUtil.randomHeaders(getRandom(), "Header"); - RequestOptions.Builder options = request.getOptions().toBuilder(); - for (Header header : headers) { - options.addHeader(header.getName(), header.getValue()); - expectedRequest.addHeader(new RequestOptions.ReqHeader(header.getName(), header.getValue())); - uniqueNames.add(header.getName()); - } - request.setOptions(options); - } - for (Header defaultHeader : defaultHeaders) { - // request level headers override default headers - if (uniqueNames.contains(defaultHeader.getName()) == false) { - expectedRequest.addHeader(defaultHeader); - } - } - try { - performRequestSyncOrAsync(restClient, request); - } catch (Exception e) { - // all good - } - return expectedRequest; - } - - static Response performRequestSyncOrAsync(RestClient restClient, Request request) throws Exception { - // randomize between sync and async methods - if (randomBoolean()) { - return restClient.performRequest(request); - } else { - final AtomicReference exceptionRef = new AtomicReference<>(); - final AtomicReference responseRef = new AtomicReference<>(); - final CountDownLatch latch = new CountDownLatch(1); - restClient.performRequestAsync(request, new ResponseListener() { - @Override - public void onSuccess(Response response) { - responseRef.set(response); - latch.countDown(); - - } - - @Override - public void onFailure(Exception exception) { - exceptionRef.set(exception); - latch.countDown(); - } - }); - latch.await(); - if (exceptionRef.get() != null) { - throw exceptionRef.get(); - } - return responseRef.get(); - } - } - - /** - * Asserts that the provided {@linkplain Exception} contains the method - * that called this somewhere on its stack. This is - * normally the case for synchronous calls but {@link RestClient} performs - * synchronous calls by performing asynchronous calls and blocking the - * current thread until the call returns so it has to take special care - * to make sure that the caller shows up in the exception. We use this - * assertion to make sure that we don't break that "special care". - */ - private static void assertExceptionStackContainsCallingMethod(Throwable t) { - // 0 is getStackTrace - // 1 is this method - // 2 is the caller, what we want - StackTraceElement myMethod = Thread.currentThread().getStackTrace()[2]; - for (StackTraceElement se : t.getStackTrace()) { - if (se.getClassName().equals(myMethod.getClassName()) && se.getMethodName().equals(myMethod.getMethodName())) { - return; - } - } - StringWriter stack = new StringWriter(); - t.printStackTrace(new PrintWriter(stack)); - fail("didn't find the calling method (looks like " + myMethod + ") in:\n" + stack); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTestCase.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTestCase.java deleted file mode 100644 index 507bdfbd0..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTestCase.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import com.carrotsearch.randomizedtesting.JUnit3MethodProvider; -import com.carrotsearch.randomizedtesting.MixWithSuiteName; -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.SeedDecorators; -import com.carrotsearch.randomizedtesting.annotations.TestMethodProviders; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakGroup; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies; -import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite; -import org.apache.hc.core5.http.Header; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -@TestMethodProviders({ JUnit3MethodProvider.class }) -@SeedDecorators({ MixWithSuiteName.class }) // See LUCENE-3995 for rationale. -@ThreadLeakScope(ThreadLeakScope.Scope.SUITE) -@ThreadLeakGroup(ThreadLeakGroup.Group.MAIN) -@ThreadLeakAction({ ThreadLeakAction.Action.WARN, ThreadLeakAction.Action.INTERRUPT }) -@ThreadLeakZombies(ThreadLeakZombies.Consequence.IGNORE_REMAINING_TESTS) -@ThreadLeakLingering(linger = 5000) // 5 sec lingering -@ThreadLeakFilters(filters = { ClientsGraalVMThreadsFilter.class }) -@TimeoutSuite(millis = 2 * 60 * 60 * 1000) -public abstract class RestClientTestCase extends RandomizedTest { - - /** - * Assert that the actual headers are the expected ones given the original default and request headers. Some headers can be ignored, - * for instance in case the http client is adding its own automatically. - * - * @param defaultHeaders the default headers set to the REST client instance - * @param requestHeaders the request headers sent with a particular request - * @param actualHeaders the actual headers as a result of the provided default and request headers - * @param ignoreHeaders header keys to be ignored as they are not part of default nor request headers, yet they - * will be part of the actual ones - */ - protected static void assertHeaders( - final Header[] defaultHeaders, - final Header[] requestHeaders, - final Header[] actualHeaders, - final Set ignoreHeaders - ) { - final Map> expectedHeaders = new HashMap<>(); - final Set requestHeaderKeys = new HashSet<>(); - for (final Header header : requestHeaders) { - final String name = header.getName(); - addValueToListEntry(expectedHeaders, name, header.getValue()); - requestHeaderKeys.add(name); - } - for (final Header defaultHeader : defaultHeaders) { - final String name = defaultHeader.getName(); - if (requestHeaderKeys.contains(name) == false) { - addValueToListEntry(expectedHeaders, name, defaultHeader.getValue()); - } - } - Set actualIgnoredHeaders = new HashSet<>(); - for (Header responseHeader : actualHeaders) { - final String name = responseHeader.getName(); - if (ignoreHeaders.contains(name)) { - expectedHeaders.remove(name); - actualIgnoredHeaders.add(name); - continue; - } - final String value = responseHeader.getValue(); - final List values = expectedHeaders.get(name); - assertNotNull("found response header [" + name + "] that wasn't originally sent: " + value, values); - assertTrue("found incorrect response header [" + name + "]: " + value, values.remove(value)); - if (values.isEmpty()) { - expectedHeaders.remove(name); - } - } - assertEquals("some headers meant to be ignored were not part of the actual headers", ignoreHeaders, actualIgnoredHeaders); - assertTrue("some headers that were sent weren't returned " + expectedHeaders, expectedHeaders.isEmpty()); - } - - private static void addValueToListEntry(final Map> map, final String name, final String value) { - List values = map.get(name); - if (values == null) { - values = new ArrayList<>(); - map.put(name, values); - } - values.add(value); - } - - public static boolean inFipsJvm() { - return Boolean.parseBoolean(System.getProperty("tests.fips.enabled")); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTestUtil.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTestUtil.java deleted file mode 100644 index 91397c67e..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTestUtil.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import com.carrotsearch.randomizedtesting.generators.RandomNumbers; -import com.carrotsearch.randomizedtesting.generators.RandomPicks; -import com.carrotsearch.randomizedtesting.generators.RandomStrings; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.HttpRequest; -import org.apache.hc.core5.http.message.BasicHeader; -import org.elasticsearch.client.HttpDeleteWithEntity; -import org.elasticsearch.client.HttpGetWithEntity; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Random; - -final class RestClientTestUtil { - - private static final String[] HTTP_METHODS = new String[]{"DELETE", "HEAD", "GET", "OPTIONS", "PATCH", - "POST", "PUT", "TRACE"}; - private static final List ALL_STATUS_CODES; - private static final List OK_STATUS_CODES = Arrays.asList(200, 201); - private static final List ALL_ERROR_STATUS_CODES; - private static List ERROR_NO_RETRY_STATUS_CODES = Arrays.asList(500,501); - private static List ERROR_RETRY_STATUS_CODES = Arrays.asList(502, 503, 504); - - static { - ALL_ERROR_STATUS_CODES = new ArrayList<>(ERROR_RETRY_STATUS_CODES); - ALL_ERROR_STATUS_CODES.addAll(ERROR_NO_RETRY_STATUS_CODES); - ALL_STATUS_CODES = new ArrayList<>(ALL_ERROR_STATUS_CODES); - ALL_STATUS_CODES.addAll(OK_STATUS_CODES); - } - - private RestClientTestUtil() { - - } - - static boolean canHaveBody(HttpRequest httpRequest) { - return httpRequest.getMethod().contains("PUT") || httpRequest.getMethod().contains("POST") || - httpRequest.getMethod().contains("PATCH") || - httpRequest instanceof HttpDeleteWithEntity || httpRequest instanceof HttpGetWithEntity; - } - - static String[] getHttpMethods() { - return HTTP_METHODS; - } - - static String randomHttpMethod(Random random) { - return RandomPicks.randomFrom(random, HTTP_METHODS); - } - - static int randomStatusCode(Random random) { - return RandomPicks.randomFrom(random, ALL_STATUS_CODES); - } - - static int randomOkStatusCode(Random random) { - return RandomPicks.randomFrom(random, OK_STATUS_CODES); - } - - static int randomErrorNoRetryStatusCode(Random random) { - return RandomPicks.randomFrom(random, List.of(500,501)); - } - - static int randomErrorRetryStatusCode(Random random) { - return RandomPicks.randomFrom(random, ERROR_RETRY_STATUS_CODES); - } - - static List getOkStatusCodes() { - return OK_STATUS_CODES; - } - - static List getAllErrorStatusCodes() { - return ALL_ERROR_STATUS_CODES; - } - - static List getAllStatusCodes() { - return ALL_STATUS_CODES; - } - - /** - * Create a random number of {@link Header}s. - * Generated header names will either be the {@code baseName} plus its index, or exactly the provided - * {@code baseName} so that the - * we test also support for multiple headers with same key and different values. - */ - static Header[] randomHeaders(Random random, final String baseName) { - int numHeaders = RandomNumbers.randomIntBetween(random, 0, 5); - final Header[] headers = new Header[numHeaders]; - for (int i = 0; i < numHeaders; i++) { - String headerName = baseName; - // randomly exercise the code path that supports multiple headers with same key - if (random.nextBoolean()) { - headerName = headerName + i; - } - headers[i] = new BasicHeader(headerName, RandomStrings.randomAsciiLettersOfLengthBetween(random - , 3, 10)); - } - return headers; - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTests.java deleted file mode 100644 index 9e2a39820..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RestClientTests.java +++ /dev/null @@ -1,456 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - - -import org.apache.hc.client5.http.auth.AuthCache; -import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.client5.http.impl.auth.BasicAuthCache; -import org.apache.hc.client5.http.impl.auth.BasicScheme; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.reactor.IOReactorStatus; -import org.elasticsearch.client.DeadHostState; -import org.elasticsearch.client.Request; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.ResponseListener; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientTestCase; -import org.elasticsearch.client.node.Node; -import org.elasticsearch.client.node.selector.NodeSelector; - -import java.io.IOException; -import java.net.URI; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.function.Supplier; - -import static java.util.Collections.singletonList; -import static org.hamcrest.Matchers.instanceOf; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class RestClientTests extends RestClientTestCase { - - public void testCloseIsIdempotent() throws IOException { - List nodes = singletonList(new Node(new HttpHost("localhost", 9200))); - CloseableHttpAsyncClient closeableHttpAsyncClient = mock(CloseableHttpAsyncClient.class); - RestClient restClient = new RestClient(closeableHttpAsyncClient, new Header[0], nodes, null, null, - null, false, false, false); - restClient.close(); - verify(closeableHttpAsyncClient, times(1)).close(); - restClient.close(); - verify(closeableHttpAsyncClient, times(2)).close(); - restClient.close(); - verify(closeableHttpAsyncClient, times(3)).close(); - } - - public void testPerformAsyncWithUnsupportedMethod() throws Exception { - final CountDownLatch latch = new CountDownLatch(1); - try (RestClient restClient = createRestClient()) { - restClient.performRequestAsync(new Request("unsupported", randomAsciiLettersOfLength(5)), - new ResponseListener() { - @Override - public void onSuccess(Response response) { - throw new UnsupportedOperationException("onSuccess cannot be called when using a mocked" + - " http client"); - } - - @Override - public void onFailure(Exception exception) { - try { - assertThat(exception, instanceOf(UnsupportedOperationException.class)); - assertEquals("http method not supported: unsupported", exception.getMessage()); - } finally { - latch.countDown(); - } - } - }); - assertTrue("time out waiting for request to return", latch.await(1000, TimeUnit.MILLISECONDS)); - } - } - - public void testPerformAsyncWithWrongEndpoint() throws Exception { - final CountDownLatch latch = new CountDownLatch(1); - try (RestClient restClient = createRestClient()) { - restClient.performRequestAsync(new Request("GET", "::http:///"), new ResponseListener() { - @Override - public void onSuccess(Response response) { - throw new UnsupportedOperationException("onSuccess cannot be called when using a mocked" + - " http client"); - } - - @Override - public void onFailure(Exception exception) { - try { - assertThat(exception, instanceOf(IllegalArgumentException.class)); - assertEquals("Expected scheme name at index 0: ::http:///", exception.getMessage()); - } finally { - latch.countDown(); - } - } - }); - assertTrue("time out waiting for request to return", latch.await(1000, TimeUnit.MILLISECONDS)); - } - } - - public void testBuildUriLeavesPathUntouched() { - final Map emptyMap = Collections.emptyMap(); - { - URI uri = RestClient.buildUri("/foo$bar", "/index/type/id", emptyMap); - assertEquals("/foo$bar/index/type/id", uri.getPath()); - } - { - URI uri = RestClient.buildUri("/", "/*", emptyMap); - assertEquals("/*", uri.getPath()); - } - { - URI uri = RestClient.buildUri("/", "*", emptyMap); - assertEquals("/*", uri.getPath()); - } - { - URI uri = RestClient.buildUri(null, "*", emptyMap); - assertEquals("*", uri.getPath()); - } - { - URI uri = RestClient.buildUri("", "*", emptyMap); - assertEquals("*", uri.getPath()); - } - { - URI uri = RestClient.buildUri(null, "/*", emptyMap); - assertEquals("/*", uri.getPath()); - } - { - URI uri = RestClient.buildUri(null, "/foo$bar/ty/pe/i/d", emptyMap); - assertEquals("/foo$bar/ty/pe/i/d", uri.getPath()); - } - { - URI uri = RestClient.buildUri(null, "/index/type/id", Collections.singletonMap("foo$bar", "x/y" + - "/z")); - assertEquals("/index/type/id", uri.getPath()); - assertEquals("foo$bar=x/y/z", uri.getQuery()); - } - } - - public void testSetNodesWrongArguments() throws IOException { - try (RestClient restClient = createRestClient()) { - restClient.setNodes(null); - fail("setNodes should have failed"); - } catch (IllegalArgumentException e) { - assertEquals("node list must not be null or empty", e.getMessage()); - } - try (RestClient restClient = createRestClient()) { - restClient.setNodes(Collections.emptyList()); - fail("setNodes should have failed"); - } catch (IllegalArgumentException e) { - assertEquals("node list must not be null or empty", e.getMessage()); - } - try (RestClient restClient = createRestClient()) { - restClient.setNodes(Collections.singletonList(null)); - fail("setNodes should have failed"); - } catch (NullPointerException e) { - assertEquals("node cannot be null", e.getMessage()); - } - try (RestClient restClient = createRestClient()) { - restClient.setNodes(Arrays.asList(new Node(new HttpHost("localhost", 9200)), null, - new Node(new HttpHost("localhost", 9201)))); - fail("setNodes should have failed"); - } catch (NullPointerException e) { - assertEquals("node cannot be null", e.getMessage()); - } - } - - public void testSetNodesPreservesOrdering() throws Exception { - try (RestClient restClient = createRestClient()) { - List nodes = randomNodes(); - restClient.setNodes(nodes); - assertEquals(nodes, restClient.getNodes()); - } - } - - private static List randomNodes() { - int numNodes = randomIntBetween(1, 10); - List nodes = new ArrayList<>(numNodes); - for (int i = 0; i < numNodes; i++) { - nodes.add(new Node(new HttpHost("host-" + i, 9200))); - } - return nodes; - } - - public void testSetNodesDuplicatedHosts() throws Exception { - try (RestClient restClient = createRestClient()) { - int numNodes = randomIntBetween(1, 10); - List nodes = new ArrayList<>(numNodes); - Node node = new Node(new HttpHost("host", 9200)); - for (int i = 0; i < numNodes; i++) { - nodes.add(node); - } - restClient.setNodes(nodes); - assertEquals(1, restClient.getNodes().size()); - assertEquals(node, restClient.getNodes().get(0)); - } - } - - public void testSelectHosts() throws IOException { - Node n1 = new Node(new HttpHost("1"), null, null, "1", null, null); - Node n2 = new Node(new HttpHost("2"), null, null, "2", null, null); - Node n3 = new Node(new HttpHost("3"), null, null, "3", null, null); - - NodeSelector not1 = new NodeSelector() { - @Override - public void select(Iterable nodes) { - for (Iterator itr = nodes.iterator(); itr.hasNext(); ) { - if ("1".equals(itr.next().getVersion())) { - itr.remove(); - } - } - } - - @Override - public String toString() { - return "NOT 1"; - } - }; - NodeSelector noNodes = new NodeSelector() { - @Override - public void select(Iterable nodes) { - for (Iterator itr = nodes.iterator(); itr.hasNext(); ) { - itr.next(); - itr.remove(); - } - } - - @Override - public String toString() { - return "NONE"; - } - }; - - List nodes = Arrays.asList(n1, n2, n3); - - Map emptyBlacklist = Collections.emptyMap(); - - // Normal cases where the node selector doesn't reject all living nodes - assertSelectLivingHosts(Arrays.asList(n1, n2, n3), nodes, emptyBlacklist, NodeSelector.ANY); - assertSelectLivingHosts(Arrays.asList(n2, n3), nodes, emptyBlacklist, not1); - - /* - * Try a NodeSelector that excludes all nodes. This should - * throw an exception - */ - { - String message = "NodeSelector [NONE] rejected all nodes, living: [" - + "[host=http://1, version=1], [host=http://2, version=2], " - + "[host=http://3, version=3]] and dead: null"; - assertEquals(message, assertSelectAllRejected(nodes, emptyBlacklist, noNodes)); - } - - // Mark all the nodes dead for a few test cases - { - final AtomicLong time = new AtomicLong(0L); - Supplier timeSupplier = time::get; - Map blacklist = new HashMap<>(); - blacklist.put(n1.getHost(), new DeadHostState(timeSupplier)); - blacklist.put(n2.getHost(), new DeadHostState(new DeadHostState(timeSupplier))); - blacklist.put(n3.getHost(), - new DeadHostState(new DeadHostState(new DeadHostState(timeSupplier)))); - - /* - * case when fewer nodes than blacklist, won't result in any IllegalCapacityException - */ - { - List fewerNodeTuple = Arrays.asList(n1, n2); - assertSelectLivingHosts(Arrays.asList(n1), fewerNodeTuple, blacklist, NodeSelector.ANY); - assertSelectLivingHosts(Arrays.asList(n2), fewerNodeTuple, blacklist, not1); - } - - /* - * selectHosts will revive a single host regardless of - * blacklist time. It'll revive the node that is closest - * to being revived that the NodeSelector is ok with. - */ - assertEquals(singletonList(n1), RestClient.selectNodes(nodes, blacklist, new AtomicInteger(), - NodeSelector.ANY)); - assertEquals(singletonList(n2), RestClient.selectNodes(nodes, blacklist, new AtomicInteger(), - not1)); - - /* - * Try a NodeSelector that excludes all nodes. This should - * return a failure, but a different failure than when the - * blacklist is empty so that the caller knows that all of - * their nodes are blacklisted AND blocked. - */ - String message = "NodeSelector [NONE] rejected all nodes, living: [] and dead: [" - + "[host=http://1, version=1], [host=http://2, version=2], " - + "[host=http://3, version=3]]"; - assertEquals(message, assertSelectAllRejected(nodes, blacklist, noNodes)); - - /* - * Now lets wind the clock forward, past the timeout for one of - * the dead nodes. We should return it. - */ - time.set(new DeadHostState(timeSupplier).getDeadUntilNanos()); - assertSelectLivingHosts(Arrays.asList(n1), nodes, blacklist, NodeSelector.ANY); - - /* - * But if the NodeSelector rejects that node then we'll pick the - * first on that the NodeSelector doesn't reject. - */ - assertSelectLivingHosts(Arrays.asList(n2), nodes, blacklist, not1); - - /* - * If we wind the clock way into the future, past any of the - * blacklist timeouts then we function as though the nodes aren't - * in the blacklist at all. - */ - time.addAndGet(DeadHostState.MAX_CONNECTION_TIMEOUT_NANOS); - assertSelectLivingHosts(Arrays.asList(n1, n2, n3), nodes, blacklist, NodeSelector.ANY); - assertSelectLivingHosts(Arrays.asList(n2, n3), nodes, blacklist, not1); - } - } - - private void assertSelectLivingHosts( - List expectedNodes, - List nodes, - Map blacklist, - NodeSelector nodeSelector - ) throws IOException { - int iterations = 1000; - AtomicInteger lastNodeIndex = new AtomicInteger(0); - assertEquals(expectedNodes, RestClient.selectNodes(nodes, blacklist, lastNodeIndex, nodeSelector)); - // Calling it again rotates the set of results - for (int i = 1; i < iterations; i++) { - Collections.rotate(expectedNodes, 1); - assertEquals("iteration " + i, expectedNodes, RestClient.selectNodes(nodes, blacklist, - lastNodeIndex, nodeSelector)); - } - } - - /** - * Assert that {@link RestClient#selectNodes} fails on the provided arguments. - * - * @return the message in the exception thrown by the failure - */ - private static String assertSelectAllRejected( - List nodes, - Map blacklist, - NodeSelector nodeSelector - ) { - try { - RestClient.selectNodes(nodes, blacklist, new AtomicInteger(0), nodeSelector); - throw new AssertionError("expected selectHosts to fail"); - } catch (IOException e) { - return e.getMessage(); - } - } - - private static RestClient createRestClient() { - List nodes = Collections.singletonList(new Node(new HttpHost("localhost", 9200))); - return new RestClient(mock(CloseableHttpAsyncClient.class), new Header[]{}, nodes, null, null, null - , false, false, false); - } - - public void testRoundRobin() throws IOException { - int numNodes = randomIntBetween(2, 10); - AuthCache authCache = new BasicAuthCache(); - List nodes = new ArrayList<>(numNodes); - for (int i = 0; i < numNodes; i++) { - Node node = new Node(new HttpHost("localhost", 9200 + i)); - nodes.add(node); - authCache.put(node.getHost(), new BasicScheme()); - } - - // test the transition from negative to positive values - AtomicInteger lastNodeIndex = new AtomicInteger(-numNodes); - assertNodes(nodes, lastNodeIndex, 50); - assertEquals(-numNodes + 50, lastNodeIndex.get()); - - // test the highest positive values up to MAX_VALUE - lastNodeIndex.set(Integer.MAX_VALUE - numNodes * 10); - assertNodes(nodes, lastNodeIndex, numNodes * 10); - assertEquals(Integer.MAX_VALUE, lastNodeIndex.get()); - - // test the transition from MAX_VALUE to MIN_VALUE - // this is the only time where there is most likely going to be a jump from a node - // to another one that's not necessarily the next one. - assertEquals(Integer.MIN_VALUE, lastNodeIndex.incrementAndGet()); - assertNodes(nodes, lastNodeIndex, 50); - assertEquals(Integer.MIN_VALUE + 50, lastNodeIndex.get()); - } - - public void testIsRunning() { - List nodes = Collections.singletonList(new Node(new HttpHost("localhost", 9200))); - CloseableHttpAsyncClient client = mock(CloseableHttpAsyncClient.class); - RestClient restClient = new RestClient(client, new Header[]{}, nodes, null, null, null, false, - false, false); - - when(client.getStatus()).thenReturn(IOReactorStatus.ACTIVE); - assertTrue(restClient.isRunning()); - - when(client.getStatus()).thenReturn(IOReactorStatus.INACTIVE); - assertFalse(restClient.isRunning()); - } - - private static void assertNodes(List nodes, AtomicInteger lastNodeIndex, int runs) throws IOException { - int distance = lastNodeIndex.get() % nodes.size(); - /* - * Collections.rotate is not super intuitive: distance 1 means that the last element will become - * the first and so on, - * while distance -1 means that the second element will become the first and so on. - */ - int expectedOffset = distance > 0 ? nodes.size() - distance : Math.abs(distance); - for (int i = 0; i < runs; i++) { - Iterable selectedNodes = RestClient.selectNodes( - nodes, - Collections.emptyMap(), - lastNodeIndex, - NodeSelector.ANY - ); - List expectedNodes = nodes; - int index = 0; - for (Node actualNode : selectedNodes) { - Node expectedNode = expectedNodes.get((index + expectedOffset) % expectedNodes.size()); - assertSame(expectedNode, actualNode); - index++; - } - expectedOffset--; - if (expectedOffset < 0) { - expectedOffset += nodes.size(); - } - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/rest_client/MultiBufferEntityTest.java b/java-client/src/test/java/co/elastic/clients/transport5/rest_client/MultiBufferEntityTest.java deleted file mode 100644 index 720a30ded..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/rest_client/MultiBufferEntityTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.rest_client; - -import co.elastic.clients.elasticsearch.core.BulkRequest; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.endpoints.BinaryResponse; -import co.elastic.clients.transport.rest5_client.RestClientTransport; -import com.sun.net.httpserver.HttpServer; -import org.apache.commons.io.IOUtils; -import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.RestClient; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; - -public class MultiBufferEntityTest { - - @Test - public void testBulkRequest() throws IOException { - - HttpServer httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); - - httpServer.createContext("/_bulk", exchange -> { - exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); - byte[] bytes = IOUtils.toByteArray(exchange.getRequestBody()); - exchange.sendResponseHeaders(200, 0); - exchange.getResponseBody().write(bytes); - exchange.close(); - }); - - httpServer.start(); - - RestClient restClient = - RestClient.builder(new HttpHost(httpServer.getAddress().getAddress(), httpServer.getAddress().getPort())).build(); - - BulkRequest req = BulkRequest.of(_0 -> _0 - .operations(_1 -> _1 - .create(_2 -> _2 - .index("foo") - .id("abc") - .document("abc-doc") - )) - .operations(_1 -> _1 - .create(_2 -> _2 - .index("foo") - .id("def") - .document("def-doc") - )) - .operations(_1 -> _1 - .update(_2 -> _2 - .index("foo") - .id("gh") - .action(_3 -> _3 - .docAsUpsert(true) - .doc("gh-doc")) - ) - ) - ); - RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); - - BinaryResponse binaryResponse = transport.performRequest(req, BulkRequest._ENDPOINT.withBinaryResponse(), null); - - String str = IOUtils.toString(binaryResponse.content(), StandardCharsets.UTF_8); - - httpServer.stop(0); - transport.close(); - - Assertions.assertEquals( - "{\"create\":{\"_id\":\"abc\",\"_index\":\"foo\"}}\n" + - "\"abc-doc\"\n" + - "{\"create\":{\"_id\":\"def\",\"_index\":\"foo\"}}\n" + - "\"def-doc\"\n" + - "{\"update\":{\"_id\":\"gh\",\"_index\":\"foo\"}}\n" + - "{\"doc\":\"gh-doc\",\"doc_as_upsert\":true}\n", - str - ); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/rest_client/RestClientOptionsTest.java b/java-client/src/test/java/co/elastic/clients/transport5/rest_client/RestClientOptionsTest.java deleted file mode 100644 index 61b7a6ea6..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/rest_client/RestClientOptionsTest.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.rest_client; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.SimpleJsonpMapper; -import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.Version; -import co.elastic.clients.transport.endpoints.BooleanResponse; -import co.elastic.clients.transport.rest5_client.RestClientOptions; -import co.elastic.clients.transport.rest5_client.RestClientTransport; -import com.sun.net.httpserver.Headers; -import com.sun.net.httpserver.HttpServer; -import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestClient; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; - -class RestClientOptionsTest extends Assertions { - - /** Collected headers by test name */ - private static Map collectedHeaders; - private static final AtomicInteger testCounter = new AtomicInteger(); - private static HttpServer httpServer; - - private static final String MIME_TYPE = "application/vnd.elasticsearch+json; compatible-with=" + Version.VERSION.major(); - - @BeforeAll - public static void setup() throws IOException { - collectedHeaders = new ConcurrentHashMap<>(); - httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); - - // Register a handler on the core.exists("capture-handler/{name}") endpoint that will capture request headers. - httpServer.createContext("/capture-headers/_doc/", exchange -> { - String testName = exchange.getRequestURI().getPath().substring("/capture-headers/_doc/".length()); - System.out.println(exchange.getResponseHeaders()); - System.out.println(); - collectedHeaders.put(testName, exchange.getRequestHeaders()); - - // Reply with an empty 200 response - exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); - exchange.sendResponseHeaders(200, -1); - exchange.close(); - }); - - httpServer.start(); - } - - @AfterAll - public static void cleanup() { - httpServer.stop(0); - httpServer = null; - collectedHeaders = null; - } - - private ElasticsearchTransport newRestClientTransport(RestClient restClient, JsonpMapper mapper) { - return newRestClientTransport(restClient, mapper, null); - } - - private ElasticsearchTransport newRestClientTransport(RestClient restClient, JsonpMapper mapper, RestClientOptions options) { - return new RestClientTransport(restClient, mapper, options); - //return new RestClientMonolithTransport(restClient, mapper, options); - } - - /** - * Make a server call, capture request headers and check their consistency. - * - * @return the name of the entry in collectedHeaders for further inspection. - */ - private String checkHeaders(ElasticsearchClient esClient) throws IOException { - String testName = "test-" + testCounter.incrementAndGet(); - BooleanResponse exists = esClient.exists(r -> r.index("capture-headers").id(testName)); - assertTrue(exists.value()); - - Headers headers = collectedHeaders.get(testName); - assertNotNull(headers, "No headers collected for test " + testName); - - assertNotNull(headers.get("X-elastic-client-meta"), "Missing client meta header"); - assertEquals(RestClientOptions.CLIENT_META_VALUE, headers.get("X-elastic-client-meta").get(0)); - assertNotNull(headers.get("Accept"), "Missing 'Accept' header"); - assertEquals(MIME_TYPE, headers.get("Accept").get(0)); - - for (Map.Entry> entry: headers.entrySet()) { - System.out.println(entry.getKey() + " " + entry.getValue()); - } - - return testName; - } - - private void checkUserAgent(String testName, String value) { - Headers headers = collectedHeaders.get(testName); - assertNotNull(headers, "No headers collected for test " + testName); - assertNotNull(headers.get("User-Agent"), "Missing 'User-Agent' header"); - assertEquals(value, headers.get("User-Agent").get(0)); - } - - @Test - void testNoRequestOptions() throws Exception { - RestClient llrc = RestClient.builder( - new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) - ).build(); - - ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper()); - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - String id = checkHeaders(esClient); - checkUserAgent(id, RestClientOptions.USER_AGENT_VALUE); - } - - @Test - void testTransportRequestOptions() throws Exception { - RestClient llrc = RestClient.builder( - new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) - ).build(); - - ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper(), - new RestClientOptions.Builder(RequestOptions.DEFAULT.toBuilder()).build() - ); - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - String id = checkHeaders(esClient); - checkUserAgent(id, RestClientOptions.USER_AGENT_VALUE); - } - - @Test - void testClientRequestOptions() throws Exception { - RestClient llrc = RestClient.builder( - new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) - ).build(); - - ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper()); - ElasticsearchClient esClient = new ElasticsearchClient(transport).withTransportOptions( - new RestClientOptions.Builder(RequestOptions.DEFAULT.toBuilder()).build() - ); - - String id = checkHeaders(esClient); - checkUserAgent(id, RestClientOptions.USER_AGENT_VALUE); - } - - @Test - void testLambdaOptionsBuilder() throws Exception { - RestClient llrc = RestClient.builder( - new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) - ).build(); - - ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper()); - ElasticsearchClient esClient = new ElasticsearchClient(transport) - .withTransportOptions(o -> o - .addHeader("Foo", "bar") - .addHeader("x-elastic-client-meta", "foo-bar-client") - ); - - String id = checkHeaders(esClient); - checkUserAgent(id, RestClientOptions.USER_AGENT_VALUE); - } - - @Test - void testRequestOptionsOverridingBuiltin() throws Exception { - RequestOptions options = RequestOptions.DEFAULT.toBuilder() - .addHeader("user-agent", "FooBarAgent/1.0") - .addHeader("x-elastic-client-meta", "foo-bar-client") - .build(); - - RestClient llrc = RestClient.builder( - new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) - ).build(); - - ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper(), new RestClientOptions(options,false)); - ElasticsearchClient esClient = new ElasticsearchClient(transport); - // Should not override client meta - String id = checkHeaders(esClient); - // overriding user-agent is ok - checkUserAgent(id, "FooBarAgent/1.0"); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/util/DateTimeTest.java b/java-client/src/test/java/co/elastic/clients/util/DateTimeTest.java deleted file mode 100644 index fb27c1428..000000000 --- a/java-client/src/test/java/co/elastic/clients/util/DateTimeTest.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.util; - -import co.elastic.clients.testkit.ModelTestCase; -import org.junit.jupiter.api.Test; - -import java.time.Instant; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; - -public class DateTimeTest extends ModelTestCase { - - long millis = 1643822172348L; - String millisJson = "1643822172348"; - - String text = "2022-02-02T17:16:12.348Z"; - String textJson = "\"" + text + "\""; - - @Test - public void testMillis() { - DateTime dateTime; - - dateTime = DateTime.ofEpochMilli(millis); - assertEquals(millis, dateTime.toInstant().toEpochMilli()); - - // Millis, no format - dateTime = checkJsonRoundtrip(DateTime.ofEpochMilli(millis), millisJson); - assertEquals(millis, dateTime.toEpochMilli()); - assertNull(dateTime.formatter); - - // Millis, roundtrip through ISO format - dateTime = checkJsonRoundtrip(DateTime.ofEpochMilli(millis, DateTimeFormatter.ISO_INSTANT), textJson); - assertEquals(millis, dateTime.toEpochMilli()); - assertNull(dateTime.formatter); - } - - @Test - public void testText() { - - DateTime dateTime; - - // Millis as string - dateTime = fromJson("\"1643822172348\"", DateTime.class); - assertEquals(millis, dateTime.toEpochMilli()); - assertNull(dateTime.formatter); - - DateTime dateTimeOrig = dateTime; - - // test STRICT_DATE_OPTIONAL_TIME_FORMATTER - dateTime = fromJson(textJson, DateTime.class); - assertEquals(text, dateTime.toString()); - - assertEquals(dateTime, dateTimeOrig); - - dateTime = fromJson("\"2022-02-27\"", DateTime.class); - assertEquals("2022-02-27T00:00:00Z", dateTime.toInstant().toString()); - - dateTime = fromJson("\"2022-02\"", DateTime.class); - assertEquals("2022-02-01T00:00:00Z", dateTime.toInstant().toString()); - - dateTime = fromJson("\"2022\"", DateTime.class); - assertEquals("2022-01-01T00:00:00Z", dateTime.toInstant().toString()); - - assertEquals("\"2022\"", toJson(dateTime)); - - } - - @Test - public void testInvalidString() { - - // Invalid values should be accepted, and an exception thrown - // only when we parse the value. - // This lazy parsing allows application code that doesn't access - // ill-formed data to not fail on deserialization. - DateTime dateTime = fromJson("\"foobar\"", DateTime.class); - assertEquals("foobar", dateTime.getString()); - - assertThrows(DateTimeParseException.class, dateTime::toInstant); - } - - @Test - public void testInstant() { - - DateTime dateTime; - - dateTime = DateTime.of(text, DateTimeFormatter.ISO_INSTANT); - assertEquals(millis, dateTime.toInstant().toEpochMilli()); - - assertEquals(millis, dateTime.toInstant(DateTimeFormatter.ISO_INSTANT).toEpochMilli()); - - Instant inst = Instant.ofEpochMilli(millis); - - dateTime = DateTime.of(inst); - assertEquals(millisJson, toJson(dateTime)); - - dateTime = DateTime.of(inst, DateTimeFormatter.ISO_DATE_TIME); - assertEquals(textJson, toJson(dateTime)); - - } - - @Test - public void testZonedDateTime() { - - DateTime dateTime; - ZonedDateTime zdt; - - // With timezone information - dateTime = fromJson("\"2022-02-02T18:16:12.348+01:00\"", DateTime.class); - assertEquals(millis, dateTime.toEpochMilli()); - - zdt = dateTime.toZonedDateTime(); - assertEquals(3600, zdt.getOffset().getTotalSeconds()); - - zdt = dateTime.toZonedDateTime(DateTimeFormatter.ISO_ZONED_DATE_TIME); - assertEquals(millis, zdt.toInstant().toEpochMilli()); - - assertEquals(millis, DateTime.of(millisJson).toZonedDateTime().toInstant().toEpochMilli()); - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/util/DuplicateResourceFinderTest.java b/java-client/src/test/java/co/elastic/clients/util/DuplicateResourceFinderTest.java deleted file mode 100644 index 3b7f7ef40..000000000 --- a/java-client/src/test/java/co/elastic/clients/util/DuplicateResourceFinderTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.util; - -import com.fasterxml.jackson.databind.ext.CoreXMLSerializers; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -class DuplicateResourceFinderTest extends Assertions { - - @Test - public void testDuplicateCheck() { - - Exception e = assertThrows(RuntimeException.class, () -> { - DuplicateResourceFinder.ensureClassUniqueness(CoreXMLSerializers.class); - }); - assertTrue(e.getMessage().contains("Several versions of")); - - // Disabling the test should not throw an exception - DuplicateResourceFinder.enableCheck(false); - DuplicateResourceFinder.ensureClassUniqueness(CoreXMLSerializers.class); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/util/NamedValueTest.java b/java-client/src/test/java/co/elastic/clients/util/NamedValueTest.java deleted file mode 100644 index ba609e0af..000000000 --- a/java-client/src/test/java/co/elastic/clients/util/NamedValueTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.util; - -import co.elastic.clients.elasticsearch._types.SortOrder; -import co.elastic.clients.elasticsearch._types.aggregations.TermsAggregation; -import co.elastic.clients.testkit.ModelTestCase; -import org.junit.jupiter.api.Test; - -class NamedValueTest extends ModelTestCase { - - @Test - public void testTermAggregation() { - - String json = "{\"order\":[{\"a\":\"asc\"},{\"b\":\"desc\"}]}"; - - TermsAggregation ta = TermsAggregation.of(b -> b - .order(NamedValue.of("a", SortOrder.Asc)) - .order(NamedValue.of("b", SortOrder.Desc) - ) - ); - - ta = checkJsonRoundtrip(ta, json); - - assertEquals(2, ta.order().size()); - - assertEquals("a", ta.order().get(0).name()); - assertEquals(SortOrder.Asc, ta.order().get(0).value()); - assertEquals("b", ta.order().get(1).name()); - assertEquals(SortOrder.Desc, ta.order().get(1).value()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/util/PairTest.java b/java-client/src/test/java/co/elastic/clients/util/PairTest.java deleted file mode 100644 index d3a6f6c8c..000000000 --- a/java-client/src/test/java/co/elastic/clients/util/PairTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.util; - -import co.elastic.clients.elasticsearch._types.FieldValue; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.elasticsearch.watcher.Condition; -import co.elastic.clients.elasticsearch.watcher.ConditionOp; -import org.junit.jupiter.api.Test; - -class PairTest extends ModelTestCase { - - @Test - public void testCondition() { - - String json = "{\"compare\":{\"foo\":{\"eq\":\"bar\"}}}"; - - Condition c = Condition.of(b -> b - .compare(NamedValue.of("foo", Pair.of(ConditionOp.Eq, FieldValue.of("bar")))) - ); - - c = checkJsonRoundtrip(c, json); - - assertEquals("foo", c.compare().name()); - assertEquals(ConditionOp.Eq, c.compare().value().key()); - assertEquals("bar", c.compare().value().value().stringValue()); - } -} diff --git a/java-client/src/test/java/com/fasterxml/jackson/databind/ext/CoreXMLSerializers.java b/java-client/src/test/java/com/fasterxml/jackson/databind/ext/CoreXMLSerializers.java deleted file mode 100644 index bf4a2d62b..000000000 --- a/java-client/src/test/java/com/fasterxml/jackson/databind/ext/CoreXMLSerializers.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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. - */ - -package com.fasterxml.jackson.databind.ext; - -// A "duplicate" of a class that exists in the project's dependencies. -// It's not actually used by the project, so the duplicate won't harm and is used in DuplicateResourceFinderTest -public class CoreXMLSerializers { -} From 6bb2f0af7fccd52443401c06f445136b36148984 Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Tue, 25 Mar 2025 11:22:30 +0100 Subject: [PATCH 07/38] original tests --- .../documentation/DocTestsTransport.java | 114 ++++ .../api_conventions/ApiConventionsTest.java | 366 ++++++++++ .../api_conventions/LoadingJsonTest.java | 193 ++++++ .../getting_started/ConnectingTest.java | 213 ++++++ .../getting_started/MigrateHlrcTest.java | 74 +++ .../troubleshooting/TroubleShootingTests.java | 93 +++ .../documentation/usage/AggregationsTest.java | 107 +++ .../documentation/usage/IndexingBulkTest.java | 213 ++++++ .../documentation/usage/IndexingTest.java | 208 ++++++ .../clients/documentation/usage/Product.java | 57 ++ .../documentation/usage/ReadingTest.java | 97 +++ .../ElasticsearchTestServer.java | 285 ++++++++ .../bulk/BulkIngesterRetryPolicyTest.java | 544 +++++++++++++++ .../_helpers/bulk/BulkIngesterTest.java | 623 ++++++++++++++++++ .../esql/EsqlAdapterEndToEndTest.java | 203 ++++++ .../_helpers/esql/EsqlAdapterTest.java | 119 ++++ .../experiments/ClientTests.java | 108 +++ .../experiments/ParsingTests.java | 76 +++ .../experiments/UnionVariant.java | 31 + .../elasticsearch/experiments/api/Bar.java | 82 +++ .../experiments/api/DateMathTimeUnit.java | 49 ++ .../experiments/api/FooOptRequest.java | 276 ++++++++ .../experiments/api/FooRequest.java | 315 +++++++++ .../experiments/api/FooResponse.java | 27 + .../experiments/api/query2/BoolQuery.java | 173 +++++ .../experiments/api/query2/Query.java | 205 ++++++ .../experiments/api/query2/QueryTest.java | 44 ++ .../experiments/api/query2/TermsQuery.java | 107 +++ .../experiments/api/query2/Union2.java | 154 +++++ .../experiments/base/Client.java | 48 ++ .../experiments/base/PrimitiveUtils.java | 41 ++ .../experiments/base/Variants.java | 155 +++++ .../experiments/containers/SomeUnion.java | 152 +++++ .../experiments/containers/SomeUnionTest.java | 84 +++ .../containers/SomeUnionVariant.java | 25 + .../experiments/containers/UVariantA.java | 82 +++ .../experiments/containers/UVariantB.java | 82 +++ .../experiments/generics/GenericClass.java | 123 ++++ .../inheritance/InheritanceTest.java | 97 +++ .../inheritance/base/BaseClass.java | 77 +++ .../inheritance/child/ChildClass.java | 93 +++ .../inheritance/final_/FinalClass.java | 98 +++ .../experiments/package-info.java | 23 + .../elasticsearch/model/BuiltinTypesTest.java | 273 ++++++++ .../model/ClassStructureTest.java | 361 ++++++++++ .../model/CodeAdditionsTests.java | 49 ++ .../elasticsearch/model/EndpointTest.java | 94 +++ .../clients/elasticsearch/model/EnumTest.java | 61 ++ .../model/RequestEncodingTest.java | 59 ++ .../elasticsearch/model/TypedKeysTest.java | 299 +++++++++ .../elasticsearch/model/VariantsTest.java | 351 ++++++++++ .../elasticsearch/model/package-info.java | 24 + .../co/elastic/clients/json/JsonDataTest.java | 169 +++++ .../json/JsonpDeserializerBaseTest.java | 50 ++ .../clients/json/JsonpDeserializerTest.java | 42 ++ .../elastic/clients/json/JsonpMapperTest.java | 209 ++++++ .../json/JsonpMappingExceptionTest.java | 110 ++++ .../elastic/clients/json/JsonpUtilsTest.java | 331 ++++++++++ .../clients/json/LazyDeserializerTest.java | 68 ++ .../json/ObjectBuilderDeserializerTest.java | 50 ++ .../jackson/JacksonJsonpGeneratorTest.java | 90 +++ .../json/jackson/JacksonJsonpParserTest.java | 193 ++++++ .../json/jackson/JacksonMapperTest.java | 102 +++ .../clients/json/jackson/JsonEnumTest.java | 56 ++ .../json/jackson/JsonValueParserTest.java | 79 +++ .../clients/testkit/MockHttpClient.java | 156 +++++ .../clients/testkit/ModelTestCase.java | 151 +++++ .../clients/transport/RequestOptionsTest.java | 163 +++++ .../clients/transport/TransportTest.java | 155 +++++ .../clients/transport/TransportUtilsTest.java | 122 ++++ .../clients/transport/VersionInfoTest.java | 32 + .../endpoints/BinaryEndpointTest.java | 128 ++++ .../endpoints/BooleanEndpointTest.java | 37 ++ .../transport/endpoints/EndpointBaseTest.java | 68 ++ .../endpoints/SimpleEndpointTest.java | 71 ++ .../clients/transport/http/HeaderMapTest.java | 78 +++ .../OpenTelemetryForElasticsearchTest.java | 275 ++++++++ .../rest_client/MultiBufferEntityTest.java | 99 +++ .../rest_client/RestClientOptionsTest.java | 202 ++++++ .../rest_client/SafeResponseConsumerTest.java | 206 ++++++ .../co/elastic/clients/util/DateTimeTest.java | 139 ++++ .../util/DuplicateResourceFinderTest.java | 40 ++ .../elastic/clients/util/NamedValueTest.java | 49 ++ .../co/elastic/clients/util/PairTest.java | 45 ++ .../databind/ext/CoreXMLSerializers.java | 25 + 85 files changed, 11697 insertions(+) create mode 100644 java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java create mode 100644 java-client/src/test/java/co/elastic/clients/documentation/api_conventions/ApiConventionsTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/documentation/api_conventions/LoadingJsonTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/documentation/getting_started/MigrateHlrcTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/documentation/troubleshooting/TroubleShootingTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/documentation/usage/AggregationsTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/documentation/usage/IndexingBulkTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/documentation/usage/IndexingTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/documentation/usage/Product.java create mode 100644 java-client/src/test/java/co/elastic/clients/documentation/usage/ReadingTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/bulk/BulkIngesterTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/ClientTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/ParsingTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/UnionVariant.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/Bar.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/DateMathTimeUnit.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooOptRequest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooRequest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooResponse.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/BoolQuery.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/Query.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/QueryTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/TermsQuery.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/Union2.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/Client.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/PrimitiveUtils.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/Variants.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnion.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnionTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnionVariant.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/UVariantA.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/UVariantB.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/generics/GenericClass.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/InheritanceTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/base/BaseClass.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/child/ChildClass.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/final_/FinalClass.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/package-info.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/BuiltinTypesTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/ClassStructureTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/CodeAdditionsTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/EndpointTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/EnumTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/RequestEncodingTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/TypedKeysTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/VariantsTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/package-info.java create mode 100644 java-client/src/test/java/co/elastic/clients/json/JsonDataTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/json/JsonpDeserializerBaseTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/json/JsonpDeserializerTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/json/JsonpMapperTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/json/JsonpMappingExceptionTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/json/JsonpUtilsTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/json/LazyDeserializerTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/json/ObjectBuilderDeserializerTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/json/jackson/JacksonJsonpGeneratorTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/json/jackson/JacksonJsonpParserTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/json/jackson/JacksonMapperTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/json/jackson/JsonEnumTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/json/jackson/JsonValueParserTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/testkit/MockHttpClient.java create mode 100644 java-client/src/test/java/co/elastic/clients/testkit/ModelTestCase.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/TransportTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/VersionInfoTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/endpoints/BinaryEndpointTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/endpoints/BooleanEndpointTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/endpoints/EndpointBaseTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/endpoints/SimpleEndpointTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/http/HeaderMapTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/instrumentation/OpenTelemetryForElasticsearchTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest_client/MultiBufferEntityTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest_client/RestClientOptionsTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest_client/SafeResponseConsumerTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/util/DateTimeTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/util/DuplicateResourceFinderTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/util/NamedValueTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/util/PairTest.java create mode 100644 java-client/src/test/java/com/fasterxml/jackson/databind/ext/CoreXMLSerializers.java diff --git a/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java b/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java new file mode 100644 index 000000000..6d1c41eb5 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java @@ -0,0 +1,114 @@ +/* + * 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. + */ + +package co.elastic.clients.documentation; + +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.TransportOptions; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; + +import javax.annotation.Nullable; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; + +/** + * A transport implementation that always returns the same result. Used for doc snippets where we can to check + * compilation and do very simple tests. + */ +public class DocTestsTransport implements ElasticsearchTransport { + + private final JsonpMapper mapper = new JacksonJsonpMapper( + new ObjectMapper().setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE) + ); + + private final ThreadLocal result = new ThreadLocal<>(); + + private final TransportOptions options = new TransportOptions() { + @Override + public Collection> headers() { + return Collections.emptyList(); + } + + @Override + public Map queryParameters() { + return Collections.emptyMap(); + } + + @Override + public Function, Boolean> onWarnings() { + return null; + } + + @Override + public boolean keepResponseBodyOnException() { + return false; + } + + @Override + public Builder toBuilder() { + return null; + } + }; + + public void setResult(Object result) { + this.result.set(result); + } + + @Override + @SuppressWarnings("unchecked") + public ResponseT performRequest( + RequestT request, + Endpoint endpoint, + @Nullable TransportOptions options + ) throws IOException { + return (ResponseT) result.get(); + } + + @Override + @SuppressWarnings("unchecked") + public CompletableFuture performRequestAsync(RequestT request, Endpoint endpoint, @Nullable TransportOptions options) { + CompletableFuture future = new CompletableFuture<>(); + future.complete((ResponseT) result.get()); + return future; + } + + @Override + public JsonpMapper jsonpMapper() { + return mapper; + } + + @Override + public TransportOptions options() { + return options; + } + + @Override + public void close() throws IOException { + } +} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/api_conventions/ApiConventionsTest.java b/java-client/src/test/java/co/elastic/clients/documentation/api_conventions/ApiConventionsTest.java new file mode 100644 index 000000000..17ac641c6 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/documentation/api_conventions/ApiConventionsTest.java @@ -0,0 +1,366 @@ +/* + * 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. + */ + +package co.elastic.clients.documentation.api_conventions; + +import co.elastic.clients.documentation.DocTestsTransport; +import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.NodeStatistics; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.aggregations.Aggregation; +import co.elastic.clients.elasticsearch._types.query_dsl.Query; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.indices.Alias; +import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; +import co.elastic.clients.elasticsearch.indices.CreateIndexResponse; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.util.ApiTypeHelper; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonValue; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.StringReader; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ApiConventionsTest extends Assertions { + + private static class SomeApplicationData {} + + private DocTestsTransport transport = new DocTestsTransport(); + Logger logger = LoggerFactory.getLogger(this.getClass()); + + public void blockingAndAsync() throws Exception { + + //tag::blocking-and-async + // Synchronous blocking client + ElasticsearchClient client = new ElasticsearchClient(transport); + + if (client.exists(b -> b.index("products").id("foo")).value()) { + logger.info("product exists"); + } + + // Asynchronous non-blocking client + ElasticsearchAsyncClient asyncClient = + new ElasticsearchAsyncClient(transport); + + asyncClient + .exists(b -> b.index("products").id("foo")) + .whenComplete((response, exception) -> { + if (exception != null) { + logger.error("Failed to index", exception); + } else { + logger.info("Product exists"); + } + }); + //end::blocking-and-async + + } + + public void builders() throws Exception { + ElasticsearchClient client = new ElasticsearchClient(transport); + + //tag::builders + CreateIndexResponse createResponse = client.indices().create( + new CreateIndexRequest.Builder() + .index("my-index") + .aliases("foo", + new Alias.Builder().isWriteIndex(true).build() + ) + .build() + ); + //end::builders + } + + public void builderLambdas() throws Exception { + ElasticsearchClient client = new ElasticsearchClient(transport); + + //tag::builder-lambdas + CreateIndexResponse createResponse = client.indices() + .create(createIndexBuilder -> createIndexBuilder + .index("my-index") + .aliases("foo", aliasBuilder -> aliasBuilder + .isWriteIndex(true) + ) + ); + //end::builder-lambdas + } + + public void builderLambdasShort() throws Exception { + ElasticsearchClient client = new ElasticsearchClient(transport); + + //tag::builder-lambdas-short + CreateIndexResponse createResponse = client.indices() + .create(c -> c + .index("my-index") + .aliases("foo", a -> a + .isWriteIndex(true) + ) + ); + //end::builder-lambdas-short + } + + public void builderIntervals() throws Exception { + ObjectMapper mapper = new ObjectMapper(); + mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + ElasticsearchClient client = new ElasticsearchClient(transport); + + //tag::builder-intervals + SearchResponse results = client + .search(b0 -> b0 + .query(b1 -> b1 + .intervals(b2 -> b2 + .field("my_text") + .allOf(b3 -> b3 + .ordered(true) + .intervals(b4 -> b4 + .match(b5 -> b5 + .query("my favorite food") + .maxGaps(0) + .ordered(true) + ) + ) + .intervals(b4 -> b4 + .anyOf(b5 -> b5 + .intervals(b6 -> b6 + .match(b7 -> b7 + .query("hot water") + ) + ) + .intervals(b6 -> b6 + .match(b7 -> b7 + .query("cold porridge") + ) + ) + ) + ) + ) + ) + ), + SomeApplicationData.class // <1> + ); + //end::builder-intervals + } + + @Test + public void variantCreation() { + //tag::variant-creation + Query query = new Query.Builder() + .term(t -> t // <1> + .field("name") // <2> + .value(v -> v.stringValue("foo")) + ) + .build(); // <3> + //end::variant-creation + + //tag::variant-navigation + assertEquals("foo", query.term().value().stringValue()); + //end::variant-navigation + + //tag::variant-kind + if (query.isTerm()) { // <1> + doSomething(query.term()); + } + + switch(query._kind()) { // <2> + case Term: + doSomething(query.term()); + break; + case Intervals: + doSomething(query.intervals()); + break; + default: + doSomething(query._kind(), query._get()); // <3> + } + //end::variant-kind + } + + //tag::custom-variant-types + public static class SphereDistanceAggregate { + private final List buckets; + @JsonCreator + public SphereDistanceAggregate( + @JsonProperty("buckets") List buckets + ) { + this.buckets = buckets; + } + public List buckets() { + return buckets; + }; + } + + public static class Bucket { + private final double key; + private final double docCount; + @JsonCreator + public Bucket( + @JsonProperty("key") double key, + @JsonProperty("doc_count") double docCount) { + this.key = key; + this.docCount = docCount; + } + public double key() { + return key; + } + public double docCount() { + return docCount; + } + } + //end::custom-variant-types + + @Test + public void customVariants() throws Exception { + + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0},\n" + + "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]},\n" + + "\"aggregations\":{\"sphere-distance#neighbors\":{\"buckets\":[{\"key\": 1.0,\"doc_count\":1}]}}}"; + + transport.setResult(SearchResponse.of(b -> b.withJson( + transport.jsonpMapper().jsonProvider().createParser(new StringReader(json)), + transport.jsonpMapper()) + )); + + //tag::custom-variant-creation + Map params = new HashMap<>(); // <1> + params.put("interval", 10); + params.put("scale", "log"); + params.put("origin", new Double[]{145.0, 12.5, 1649.0}); + + SearchRequest request = SearchRequest.of(r -> r + .index("stars") + .aggregations("neighbors", agg -> agg + ._custom("sphere-distance", params) // <2> + ) + ); + //end::custom-variant-creation + + { + //tag::custom-variant-navigation-json + SearchResponse response = esClient.search(request, Void.class); // <1> + + JsonData neighbors = response + .aggregations().get("neighbors") + ._custom(); // <2> + + JsonArray buckets = neighbors.toJson() // <3> + .asJsonObject() + .getJsonArray("buckets"); + + for (JsonValue item : buckets) { + JsonObject bucket = item.asJsonObject(); + double key = bucket.getJsonNumber("key").doubleValue(); + double docCount = bucket.getJsonNumber("doc_count").longValue(); + doSomething(key, docCount); + } + //end::custom-variant-navigation-json + } + + { + //tag::custom-variant-navigation-typed + SearchResponse response = esClient.search(request, Void.class); + + SphereDistanceAggregate neighbors = response + .aggregations().get("neighbors") + ._custom() + .to(SphereDistanceAggregate.class); // <1> + + for (Bucket bucket : neighbors.buckets()) { + doSomething(bucket.key(), bucket.docCount()); + } + //end::custom-variant-navigation-typed + } + } + + @Test + public void collections() { + //tag::collections-list + // Prepare a list of index names + List names = Arrays.asList("idx-a", "idx-b", "idx-c"); + + // Prepare cardinality aggregations for fields "foo" and "bar" + Map cardinalities = new HashMap<>(); + cardinalities.put("foo-count", Aggregation.of(a -> a.cardinality(c -> c.field("foo")))); + cardinalities.put("bar-count", Aggregation.of(a -> a.cardinality(c -> c.field("bar")))); + + // Prepare an aggregation that computes the average of the "size" field + final Aggregation avgSize = Aggregation.of(a -> a.avg(v -> v.field("size"))); + + SearchRequest search = SearchRequest.of(r -> r + // Index list: + // - add all elements of a list + .index(names) + // - add a single element + .index("idx-d") + // - add a vararg list of elements + .index("idx-e", "idx-f", "idx-g") + + // Sort order list: add elements defined by builder lambdas + .sort(s -> s.field(f -> f.field("foo").order(SortOrder.Asc))) + .sort(s -> s.field(f -> f.field("bar").order(SortOrder.Desc))) + + // Aggregation map: + // - add all entries of an existing map + .aggregations(cardinalities) + // - add a key/value entry + .aggregations("avg-size", avgSize) + // - add a key/value defined by a builder lambda + .aggregations("price-histogram", + a -> a.histogram(h -> h.field("price"))) + ); + //end::collections-list + + } + + @Test + public void optionalCollections() { + //tag::optional-collections + NodeStatistics stats = NodeStatistics.of(b -> b + .total(1) + .failed(0) + .successful(1) + ); + + // The `failures` list was not provided. + // - it's not null + assertNotNull(stats.failures()); + // - it's empty + assertEquals(0, stats.failures().size()); + // - and if needed we can know it was actually not defined + assertFalse(ApiTypeHelper.isDefined(stats.failures())); + //end::optional-collections + } + + private void doSomething(Object... o) { + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/api_conventions/LoadingJsonTest.java b/java-client/src/test/java/co/elastic/clients/documentation/api_conventions/LoadingJsonTest.java new file mode 100644 index 000000000..f0a579ea6 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/documentation/api_conventions/LoadingJsonTest.java @@ -0,0 +1,193 @@ +/* + * 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. + */ + +package co.elastic.clients.documentation.api_conventions; + +import co.elastic.clients.documentation.DocTestsTransport; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; +import co.elastic.clients.elasticsearch._types.aggregations.CalendarInterval; +import co.elastic.clients.elasticsearch.core.IndexRequest; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; +import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; +import co.elastic.clients.elasticsearch.indices.CreateIndexResponse; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.json.JsonData; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class LoadingJsonTest extends ModelTestCase { + + private final DocTestsTransport transport = new DocTestsTransport(); + private final ElasticsearchClient client = new ElasticsearchClient(transport); + + private static final SearchResponse searchResponse = SearchResponse.of(b -> b + .aggregations(new HashMap<>()) + .took(0) + .timedOut(false) + .hits(h -> h + .total(t -> t.value(0).relation(TotalHitsRelation.Eq)) + .hits(new ArrayList<>()) + ) + .shards(s -> s + .total(1) + .failed(0) + .successful(1) + ) + ); + + @Test + public void loadIndexDefinition() throws IOException { + + transport.setResult(CreateIndexResponse.of(b -> b + .index("some-index") + .shardsAcknowledged(true) + .acknowledged(true) + )); + + //tag::load-index + InputStream input = this.getClass() + .getResourceAsStream("some-index.json"); //<1> + + CreateIndexRequest req = CreateIndexRequest.of(b -> b + .index("some-index") + .withJson(input) //<2> + ); + + boolean created = client.indices().create(req).acknowledged(); + //end::load-index + } + + @Disabled + @Test + public void ingestDocument() throws IOException { + + File dataDir = null; + + //tag::ingest-data + FileReader file = new FileReader(new File(dataDir, "document-1.json")); + + IndexRequest req; //<1> + + req = IndexRequest.of(b -> b + .index("some-index") + .withJson(file) + ); + + client.index(req); + //end::ingest-data + } + + @Test + public void query1() throws IOException { + transport.setResult(searchResponse); + + //tag::query + Reader queryJson = new StringReader( + "{" + + " \"query\": {" + + " \"range\": {" + + " \"@timestamp\": {" + + " \"gt\": \"now-1w\"" + + " }" + + " }" + + " }" + + "}"); + + SearchRequest aggRequest = SearchRequest.of(b -> b + .withJson(queryJson) //<1> + .aggregations("max-cpu", a1 -> a1 //<2> + .dateHistogram(h -> h + .field("@timestamp") + .calendarInterval(CalendarInterval.Hour) + ) + .aggregations("max", a2 -> a2 + .max(m -> m.field("host.cpu.usage")) + ) + ) + .size(0) + ); + + Map aggs = client + .search(aggRequest, Void.class) //<3> + .aggregations(); + //end::query + } + + @Test + public void query2() throws IOException { + transport.setResult(searchResponse); + + //tag::query-and-agg + Reader queryJson = new StringReader( + "{" + + " \"query\": {" + + " \"range\": {" + + " \"@timestamp\": {" + + " \"gt\": \"now-1w\"" + + " }" + + " }" + + " }," + + " \"size\": 100" + //<1> + "}"); + + Reader aggregationJson = new StringReader( + "{" + + " \"size\": 0, " + //<2> + " \"aggregations\": {" + + " \"hours\": {" + + " \"date_histogram\": {" + + " \"field\": \"@timestamp\"," + + " \"interval\": \"hour\"" + + " }," + + " \"aggregations\": {" + + " \"max-cpu\": {" + + " \"max\": {" + + " \"field\": \"host.cpu.usage\"" + + " }" + + " }" + + " }" + + " }" + + " }" + + "}"); + + SearchRequest aggRequest = SearchRequest.of(b -> b + .withJson(queryJson) //<3> + .withJson(aggregationJson) //<4> + .ignoreUnavailable(true) //<5> + ); + + Map aggs = client + .search(aggRequest, Void.class) + .aggregations(); + //end::query-and-agg + } +} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java b/java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java new file mode 100644 index 000000000..a97a2ac8e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java @@ -0,0 +1,213 @@ +/* + * 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. + */ + +package co.elastic.clients.documentation.getting_started; + +import co.elastic.clients.documentation.usage.Product; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.search.Hit; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.TransportUtils; +import co.elastic.clients.transport.instrumentation.OpenTelemetryForElasticsearch; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import org.apache.http.Header; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.message.BasicHeader; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import javax.net.ssl.SSLContext; +import java.io.File; + +public class ConnectingTest { + + @Disabled // we don't have a running ES + @Test + public void createClient() throws Exception { + //tag::create-client + // URL and API key + String serverUrl = "https://localhost:9200"; + String apiKey = "VnVhQ2ZHY0JDZGJrU..."; + + // Create the low-level client + RestClient restClient = RestClient + .builder(HttpHost.create(serverUrl)) + .setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "ApiKey " + apiKey) + }) + .build(); + + // Create the transport with a Jackson mapper + ElasticsearchTransport transport = new RestClientTransport( + restClient, new JacksonJsonpMapper()); + + // And create the API client + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + // Use the client... + + // Close the client, also closing the underlying transport object and network connections. + esClient.close(); + //end::create-client + + //tag::first-request + SearchResponse search = esClient.search(s -> s + .index("products") + .query(q -> q + .term(t -> t + .field("name") + .value(v -> v.stringValue("bicycle")) + )), + Product.class); + + for (Hit hit: search.hits().hits()) { + processProduct(hit.source()); + } + //end::first-request + } + + @Disabled // we don't have a running ES + @Test + public void createClientWithOpenTelemetry() throws Exception { + //tag::create-client-otel + // URL and API key + String serverUrl = "https://localhost:9200"; + String apiKey = "VnVhQ2ZHY0JDZGJrU..."; + + // Create the low-level client + RestClient restClient = RestClient + .builder(HttpHost.create(serverUrl)) + .setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "ApiKey " + apiKey) + }) + .build(); + // Create and configure custom OpenTelemetry instance + OpenTelemetry customOtel = OpenTelemetrySdk.builder().build(); + + // Create Instrumentation instance using the custom OpenTelemetry instance + // Second constructor argument allows to enable/disable search body capturing + OpenTelemetryForElasticsearch esOtelInstrumentation = + new OpenTelemetryForElasticsearch(customOtel, false); + + // Create the transport with the custom Instrumentation instance + ElasticsearchTransport transport = new RestClientTransport( + restClient, new JacksonJsonpMapper(), null, esOtelInstrumentation + ); + + // And create the API client + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + // Use the client... + + // Close the client, also closing the underlying transport object and network connections. + esClient.close(); + //end::create-client-otel + } + + @Disabled // we don't have a running ES + @Test + public void createSecureClientCert() throws Exception { + + // Create the low-level client + String host = "localhost"; + int port = 9200; + String login = "elastic"; + String password = "changeme"; + + //tag::create-secure-client-cert + File certFile = new File("/path/to/http_ca.crt"); + + SSLContext sslContext = TransportUtils + .sslContextFromHttpCaCrt(certFile); // <1> + + BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); // <2> + credsProv.setCredentials( + AuthScope.ANY, new UsernamePasswordCredentials(login, password) + ); + + RestClient restClient = RestClient + .builder(new HttpHost(host, port, "https")) // <3> + .setHttpClientConfigCallback(hc -> hc + .setSSLContext(sslContext) // <4> + .setDefaultCredentialsProvider(credsProv) + ) + .build(); + + // Create the transport and the API client + ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + // Use the client... + + // Close the client, also closing the underlying transport object and network connections. + esClient.close(); + //end::create-secure-client-cert + } + + @Disabled // we don't have a running ES + @Test + public void createSecureClientFingerPrint() throws Exception { + + // Create the low-level client + String host = "localhost"; + int port = 9200; + String login = "elastic"; + String password = "changeme"; + + //tag::create-secure-client-fingerprint + String fingerprint = ""; + + SSLContext sslContext = TransportUtils + .sslContextFromCaFingerprint(fingerprint); // <1> + + BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); // <2> + credsProv.setCredentials( + AuthScope.ANY, new UsernamePasswordCredentials(login, password) + ); + + RestClient restClient = RestClient + .builder(new HttpHost(host, port, "https")) // <3> + .setHttpClientConfigCallback(hc -> hc + .setSSLContext(sslContext) // <4> + .setDefaultCredentialsProvider(credsProv) + ) + .build(); + + // Create the transport and the API client + ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + // Use the client... + + // Close the client, also closing the underlying transport object and network connections. + esClient.close(); + //end::create-secure-client-fingerprint + } + + private void processProduct(Product p) {} + +} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/getting_started/MigrateHlrcTest.java b/java-client/src/test/java/co/elastic/clients/documentation/getting_started/MigrateHlrcTest.java new file mode 100644 index 000000000..e857188b7 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/documentation/getting_started/MigrateHlrcTest.java @@ -0,0 +1,74 @@ +/* + * 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. + */ + +package co.elastic.clients.documentation.getting_started; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import org.apache.http.HttpHost; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.Test; + +public class MigrateHlrcTest { + + // Fake HLRC -- we don't want to import it for just one example + public static class RestHighLevelClient { + } + + public static class RestHighLevelClientBuilder { + + public RestHighLevelClientBuilder(RestClient restClient) { + } + + public RestHighLevelClientBuilder setApiCompatibilityMode(Boolean enabled) { + return this; + } + + public RestHighLevelClient build() { + return new RestHighLevelClient(); + } + } + + @Test + public void migrate() { + //tag::migrate + // Create the low-level client + RestClient httpClient = RestClient.builder( + new HttpHost("localhost", 9200) + ).build(); + + // Create the HLRC + RestHighLevelClient hlrc = new RestHighLevelClientBuilder(httpClient) + .setApiCompatibilityMode(true) // <1> + .build(); + + // Create the Java API Client with the same low level client + ElasticsearchTransport transport = new RestClientTransport( + httpClient, + new JacksonJsonpMapper() + ); + + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + // hlrc and esClient share the same httpClient + //end::migrate + } +} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/troubleshooting/TroubleShootingTests.java b/java-client/src/test/java/co/elastic/clients/documentation/troubleshooting/TroubleShootingTests.java new file mode 100644 index 000000000..7c1478244 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/documentation/troubleshooting/TroubleShootingTests.java @@ -0,0 +1,93 @@ +/* + * 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. + */ + +package co.elastic.clients.documentation.troubleshooting; + +import co.elastic.clients.documentation.DocTestsTransport; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpMapperFeatures; +import jakarta.json.stream.JsonGenerator; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.StringWriter; +import java.util.Collections; + +public class TroubleShootingTests extends Assertions { + + @Test + public void testMapProperty() { + + SearchResponse searchResponse = new SearchResponse.Builder() + .aggregations( + "price", _2 -> _2 + .avg(_3 -> _3.value(3.14)) + ) + // Required properties on a SearchResponse + .took(1) + .shards(_1 -> _1.successful(1).failed(0).total(1)) + .hits(_1 -> _1 + .total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)) + .hits(Collections.emptyList()) + ) + .timedOut(false) + .build(); + + String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + + "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]},\"aggregations\":{\"avg#price\":{\"value\":3.14}}}"; + + DocTestsTransport transport = new DocTestsTransport(); + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + { + //tag::aggregation-typed-keys + JsonpMapper mapper = esClient._jsonpMapper(); + + StringWriter writer = new StringWriter(); + try (JsonGenerator generator = mapper.jsonProvider().createGenerator(writer)) { + mapper.serialize(searchResponse, generator); + } + String result = writer.toString(); + + // The aggregation property provides the "avg" type and "price" name + assertTrue(result.contains("\"aggregations\":{\"avg#price\":{\"value\":3.14}}}")); + //end::aggregation-typed-keys + } + + { + //tag::aggregation-no-typed-keys + // Create a new mapper with the typed_keys feature disabled + JsonpMapper mapper = esClient._jsonpMapper() + .withAttribute(JsonpMapperFeatures.SERIALIZE_TYPED_KEYS, false); + + StringWriter writer = new StringWriter(); + try (JsonGenerator generator = mapper.jsonProvider().createGenerator(writer)) { + mapper.serialize(searchResponse, generator); + } + String result = writer.toString(); + + // The aggregation only provides the "price" name + assertTrue(result.contains("\"aggregations\":{\"price\":{\"value\":3.14}}}")); + //end::aggregation-no-typed-keys + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/usage/AggregationsTest.java b/java-client/src/test/java/co/elastic/clients/documentation/usage/AggregationsTest.java new file mode 100644 index 000000000..c8635f0b4 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/documentation/usage/AggregationsTest.java @@ -0,0 +1,107 @@ +/* + * 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. + */ + +package co.elastic.clients.documentation.usage; + +import co.elastic.clients.documentation.DocTestsTransport; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.aggregations.HistogramBucket; +import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery; +import co.elastic.clients.elasticsearch._types.query_dsl.Query; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.json.JsonData; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +public class AggregationsTest extends ModelTestCase { + + private final DocTestsTransport transport = new DocTestsTransport(); + private final ElasticsearchClient esClient = new ElasticsearchClient(transport); + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private static final SearchResponse searchResponse = SearchResponse.of(b -> b + .aggregations(new HashMap<>()) + .took(0) + .timedOut(false) + .hits(h -> h + .total(t -> t.value(0).relation(TotalHitsRelation.Eq)) + .hits(new ArrayList<>()) + ) + .shards(s -> s + .total(1) + .failed(0) + .successful(1) + ) + .aggregations("price-histogram", a -> a.histogram(h -> h + .buckets(bu -> bu.array(Collections.singletonList(HistogramBucket.of(hb -> hb + .key(50).docCount(1) + )))) + )) + ); + + @Test + public void priceHistogram() throws Exception { + + transport.setResult(searchResponse); + + //tag::price-histo-request + String searchText = "bike"; + + Query query = MatchQuery.of(m -> m + .field("name") + .query(searchText) + )._toQuery(); + + SearchResponse response = esClient.search(b -> b + .index("products") + .size(0) // <1> + .query(query) // <2> + .aggregations("price-histogram", a -> a // <3> + .histogram(h -> h // <4> + .field("price") + .interval(50.0) + ) + ), + Void.class // <5> + ); + //end::price-histo-request + + //tag::price-histo-response + List buckets = response.aggregations() + .get("price-histogram") // <1> + .histogram() // <2> + .buckets().array(); // <3> + + for (HistogramBucket bucket: buckets) { + logger.info("There are " + bucket.docCount() + + " bikes under " + bucket.key()); + } + + //end::price-histo-response + } +} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/usage/IndexingBulkTest.java b/java-client/src/test/java/co/elastic/clients/documentation/usage/IndexingBulkTest.java new file mode 100644 index 000000000..1e6006978 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/documentation/usage/IndexingBulkTest.java @@ -0,0 +1,213 @@ +/* + * 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. + */ + +package co.elastic.clients.documentation.usage; + +import co.elastic.clients.documentation.DocTestsTransport; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._helpers.bulk.BulkIngester; +import co.elastic.clients.elasticsearch._helpers.bulk.BulkListener; +import co.elastic.clients.elasticsearch.core.BulkRequest; +import co.elastic.clients.elasticsearch.core.BulkResponse; +import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.util.BinaryData; +import co.elastic.clients.util.ContentType; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class IndexingBulkTest extends ModelTestCase { + + private final DocTestsTransport transport = new DocTestsTransport(); + private final ElasticsearchClient esClient = new ElasticsearchClient(transport); + + private final Log logger = LogFactory.getLog(this.getClass()); + + BulkResponse result = BulkResponse.of(r -> r + .errors(false) + .items(Collections.emptyList()) + .took(1) + ); + + private List fetchProducts() { + List list = new ArrayList<>(); + list.add(new Product("bk-1", "City Bike", 123.0)); + list.add(new Product("bk-2", "Mountain Bike", 134.0)); + return list; + } + + @Test + public void indexBulk() throws Exception { + transport.setResult(result); + + //tag::bulk-objects + List products = fetchProducts(); + + BulkRequest.Builder br = new BulkRequest.Builder(); + + for (Product product : products) { + br.operations(op -> op //<1> + .index(idx -> idx //<2> + .index("products") //<3> + .id(product.getSku()) + .document(product) + ) + ); + } + + BulkResponse result = esClient.bulk(br.build()); + + // Log errors, if any + if (result.errors()) { + logger.error("Bulk had errors"); + for (BulkResponseItem item: result.items()) { + if (item.error() != null) { + logger.error(item.error().reason()); + } + } + } + //end::bulk-objects + } + + @Test + public void indexBulkJson() throws Exception { + transport.setResult(result); + + File logDir = new File("."); + + //tag::bulk-json + // List json log files in the log directory + File[] logFiles = logDir.listFiles( + file -> file.getName().matches("log-.*\\.json") + ); + + BulkRequest.Builder br = new BulkRequest.Builder(); + + for (File file: logFiles) { + FileInputStream input = new FileInputStream(file); + BinaryData data = BinaryData.of(IOUtils.toByteArray(input), ContentType.APPLICATION_JSON); + + br.operations(op -> op + .index(idx -> idx + .index("logs") + .document(data) + ) + ); + } + //end::bulk-json + } + + @Test + public void useBulkIndexer() throws Exception { + + File logDir = new File("."); + File[] logFiles = logDir.listFiles( + file -> file.getName().matches("log-.*\\.json") + ); + + //tag::bulk-ingester-setup + BulkIngester ingester = BulkIngester.of(b -> b + .client(esClient) // <1> + .maxOperations(100) // <2> + .flushInterval(1, TimeUnit.SECONDS) // <3> + ); + + for (File file: logFiles) { + FileInputStream input = new FileInputStream(file); + BinaryData data = BinaryData.of(IOUtils.toByteArray(input), ContentType.APPLICATION_JSON); + + ingester.add(op -> op // <4> + .index(idx -> idx + .index("logs") + .document(data) + ) + ); + } + + ingester.close(); // <5> + //end::bulk-ingester-setup + + } + + @Test + public void useBulkIndexerWithContext() throws Exception { + + File[] logFiles = new File[]{}; + + //tag::bulk-ingester-context + BulkListener listener = new BulkListener() { // <1> + @Override + public void beforeBulk(long executionId, BulkRequest request, List contexts) { + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, BulkResponse response) { + // The request was accepted, but may contain failed items. + // The "context" list gives the file name for each bulk item. + logger.debug("Bulk request " + executionId + " completed"); + for (int i = 0; i < contexts.size(); i++) { + BulkResponseItem item = response.items().get(i); + if (item.error() != null) { + // Inspect the failure cause + logger.error("Failed to index file " + contexts.get(i) + " - " + item.error().reason()); + } + } + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, Throwable failure) { + // The request could not be sent + logger.debug("Bulk request " + executionId + " failed", failure); + } + }; + + BulkIngester ingester = BulkIngester.of(b -> b + .client(esClient) + .maxOperations(100) + .flushInterval(1, TimeUnit.SECONDS) + .listener(listener) // <2> + ); + + for (File file: logFiles) { + FileInputStream input = new FileInputStream(file); + BinaryData data = BinaryData.of(IOUtils.toByteArray(input), ContentType.APPLICATION_JSON); + + ingester.add(op -> op + .index(idx -> idx + .index("logs") + .document(data) + ), + file.getName() // <3> + ); + } + + ingester.close(); + //end::bulk-ingester-context + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/usage/IndexingTest.java b/java-client/src/test/java/co/elastic/clients/documentation/usage/IndexingTest.java new file mode 100644 index 000000000..8d2573532 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/documentation/usage/IndexingTest.java @@ -0,0 +1,208 @@ +/* + * 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. + */ + +package co.elastic.clients.documentation.usage; + +import co.elastic.clients.documentation.DocTestsTransport; +import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.Result; +import co.elastic.clients.elasticsearch.core.IndexRequest; +import co.elastic.clients.elasticsearch.core.IndexResponse; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.json.JsonData; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.Reader; +import java.io.StringReader; + +public class IndexingTest extends ModelTestCase { + + private final DocTestsTransport transport = new DocTestsTransport(); + private final ElasticsearchClient esClient = new ElasticsearchClient(transport); + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + IndexResponse result = IndexResponse.of(r -> r + .index("product") + .id("bk-1") + .version(1) + .primaryTerm(1L) + .seqNo(1L) + .result(Result.Created) + .shards(s -> s.total(1).successful(1).failed(0)) + ); + + @Test + @Disabled + public void createIndex() throws Exception { + //tag::create-products-index + esClient.indices().create(c -> c + .index("products") + ); + //end::create-products-index + } + + @Test + @Disabled + public void deleteIndex() throws Exception { + //tag::delete-products-index + esClient.indices().delete(d -> d + .index("products") + ); + //end::delete-products-index + } + + @Test + public void singleDocumentDSL() throws Exception { + + // Stub response + transport.setResult(result); + + //tag::single-doc-dsl + Product product = new Product("bk-1", "City bike", 123.0); + + IndexResponse response = esClient.index(i -> i + .index("products") + .id(product.getSku()) + .document(product) + ); + + logger.info("Indexed with version " + response.version()); + //end::single-doc-dsl + } + + @Test + public void singleDocumentDSLwithOf() throws Exception { + + // Stub response + transport.setResult(result); + + //tag::single-doc-dsl-of + Product product = new Product("bk-1", "City bike", 123.0); + + IndexRequest request = IndexRequest.of(i -> i + .index("products") + .id(product.getSku()) + .document(product) + ); + + IndexResponse response = esClient.index(request); + + logger.info("Indexed with version " + response.version()); + //end::single-doc-dsl-of + } + + @Test + public void singleDocumentBuilder() throws Exception { + + // Stub response + transport.setResult(result); + + //tag::single-doc-builder + Product product = new Product("bk-1", "City bike", 123.0); + + IndexRequest.Builder indexReqBuilder = new IndexRequest.Builder<>(); + indexReqBuilder.index("product"); + indexReqBuilder.id(product.getSku()); + indexReqBuilder.document(product); + + IndexResponse response = esClient.index(indexReqBuilder.build()); + + logger.info("Indexed with version " + response.version()); + //end::single-doc-builder + } + + @Test + public void singleDocumentDSLAsync() throws Exception { + + // Stub response + transport.setResult(result); + + //tag::single-doc-dsl-async + ElasticsearchAsyncClient esAsyncClient = new ElasticsearchAsyncClient(transport); + + Product product = new Product("bk-1", "City bike", 123.0); + + esAsyncClient.index(i -> i + .index("products") + .id(product.getSku()) + .document(product) + ).whenComplete((response, exception) -> { + if (exception != null) { + logger.error("Failed to index", exception); + } else { + logger.info("Indexed with version " + response.version()); + } + }); + //end::single-doc-dsl-async + } + + @Test + public void singleDocumentJson() throws Exception { + // Stub response + transport.setResult(result); + + //tag::single-doc-json + Reader input = new StringReader( + "{'@timestamp': '2022-04-08T13:55:32Z', 'level': 'warn', 'message': 'Some log message'}" + .replace('\'', '"')); + + IndexRequest request = IndexRequest.of(i -> i + .index("logs") + .withJson(input) + ); + + IndexResponse response = esClient.index(request); + + logger.info("Indexed with version " + response.version()); + //end::single-doc-json + + assertEquals("warn", request.document().toJson().asJsonObject().getString("level")); + assertEquals( + "{\"@timestamp\":\"2022-04-08T13:55:32Z\",\"level\":\"warn\",\"message\":\"Some log message\"}", + toJson(request) + ); + } + + @Test + public void deleteDocument() throws Exception { + //tag::single-doc-delete + esClient.delete(d -> d.index("products").id("bk-1")); + //end::single-doc-delete + } + + @Test + @Disabled + public void updateDoc() throws Exception { + //tag::single-doc-update + Product product = new Product("bk-1", "City bike", 123.0); + + esClient.update(u -> u + .index("products") + .id("bk-1") + .upsert(product), + Product.class + ); + //end::single-doc-update + } +} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/usage/Product.java b/java-client/src/test/java/co/elastic/clients/documentation/usage/Product.java new file mode 100644 index 000000000..29d4c2310 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/documentation/usage/Product.java @@ -0,0 +1,57 @@ +/* + * 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. + */ + +package co.elastic.clients.documentation.usage; + +public class Product { + private String sku; + private String name; + private double price; + + public Product() {} + public Product(String sku, String name, double price) { + this.sku = sku; + this.name = name; + this.price = price; + } + + public String getSku() { + return sku; + } + + public void setSku(String sku) { + this.sku = sku; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getPrice() { + return this.price; + } + + public void setPrice(double price) { + this.price = price; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/documentation/usage/ReadingTest.java b/java-client/src/test/java/co/elastic/clients/documentation/usage/ReadingTest.java new file mode 100644 index 000000000..15a6c8ba8 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/documentation/usage/ReadingTest.java @@ -0,0 +1,97 @@ +/* + * 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. + */ + +package co.elastic.clients.documentation.usage; + +import co.elastic.clients.documentation.DocTestsTransport; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.core.GetResponse; +import co.elastic.clients.testkit.ModelTestCase; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ReadingTest extends ModelTestCase { + + private final DocTestsTransport transport = new DocTestsTransport(); + private final ElasticsearchClient esClient = new ElasticsearchClient(transport); + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Test + public void getById() throws Exception { + + transport.setResult(GetResponse.of(r -> r + .found(true) + .index("products") + .id("bk-1") + .version(1L) + .seqNo(0L) + .primaryTerm(0L) + .source(new Product("bk-1", "City Bike", 123.0)) + )); + + //tag::get-by-id + GetResponse response = esClient.get(g -> g + .index("products") // <1> + .id("bk-1"), + Product.class // <2> + ); + + if (response.found()) { + Product product = response.source(); + logger.info("Product name " + product.getName()); + } else { + logger.info ("Product not found"); + } + //end::get-by-id + + } + + @Test + public void getByIdJson() throws Exception { + + transport.setResult(GetResponse.of(r -> r + .found(true) + .index("products") + .id("bk-1") + .version(1L) + .seqNo(0L) + .primaryTerm(0L) + .source(fromJson("{\"name\":\"City Bike\"}", ObjectNode.class, transport.jsonpMapper())) + )); + + //tag::get-by-id-json + GetResponse response = esClient.get(g -> g + .index("products") + .id("bk-1"), + ObjectNode.class // <1> + ); + + if (response.found()) { + ObjectNode json = response.source(); + String name = json.get("name").asText(); + logger.info("Product name " + name); + } else { + logger.info("Product not found"); + } + //end::get-by-id-json + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java new file mode 100644 index 000000000..9fca54c03 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java @@ -0,0 +1,285 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.JsonEndpoint; +import co.elastic.clients.transport.Version; +import co.elastic.clients.transport.endpoints.DelegatingJsonEndpoint; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import org.apache.commons.io.FileUtils; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.elasticsearch.client.RestClient; +import org.testcontainers.elasticsearch.ElasticsearchContainer; +import org.testcontainers.images.builder.ImageFromDockerfile; +import org.testcontainers.shaded.org.apache.commons.io.IOUtils; +import org.testcontainers.utility.DockerImageName; + +import javax.net.ssl.SSLContext; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Base64; + +public class ElasticsearchTestServer implements AutoCloseable { + + private final String[] plugins; + private volatile ElasticsearchContainer container; + private final JsonpMapper mapper = new JsonbJsonpMapper(); + private RestClient restClient; + private ElasticsearchTransport transport; + private ElasticsearchClient client; + + private static ElasticsearchTestServer global; + private static final String artifactsApiUrl = "https://artifacts-api.elastic.co/v1/versions/"; + + public static synchronized ElasticsearchTestServer global() { + if (global == null) { + + // Try localhost:9200 + try { + String localUrl = "http://localhost:9200"; + HttpURLConnection connection = (HttpURLConnection) new URL(localUrl).openConnection(); + connection.setRequestProperty("Authorization", "Basic " + + Base64.getEncoder().encodeToString("elastic:changeme".getBytes(StandardCharsets.UTF_8))); + + try (InputStream input = connection.getInputStream()) { + String content = IOUtils.toString(input, StandardCharsets.UTF_8); + if (content.contains("You Know, for Search")) { + System.out.println("Found a running ES server at http://localhost:9200/"); + + global = new ElasticsearchTestServer(); + global.setup(localUrl, null); + } + } + } catch (Exception e) { + // Create container + System.out.println("Starting global ES test server."); + global = new ElasticsearchTestServer(); + global.start(); + } + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + System.out.println("Stopping global ES test server."); + global.close(); + })); + } + return global; + } + + public ElasticsearchTestServer(String... plugins) { + this.plugins = plugins; + } + + protected void setup(String url, SSLContext sslContext) { + BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); + credsProv.setCredentials( + AuthScope.ANY, new UsernamePasswordCredentials("elastic", "changeme") + ); + restClient = RestClient.builder(HttpHost.create(url)) + .setHttpClientConfigCallback(hc -> hc + .setDefaultCredentialsProvider(credsProv) + .setSSLContext(sslContext) + ) + .build(); + transport = new RestClientTransport(restClient, mapper); + client = new ElasticsearchClient(transport); + } + + private Version selectLatestVersion(Version version, String info) { + if (info.contains(version.toString())) { + return version; + } + // if no version X.Y.0 was found, we give up + if (version.maintenance() == 0) { + throw new RuntimeException("Elasticsearch server container version: " + version + " not yet " + + "available"); + } + return selectLatestVersion(new Version(version.major(), version.minor(), version.maintenance() - 1, + false), info); + } + + private String fetchAndWriteVersionInfo(File file) throws IOException { + String versionInfo = IOUtils.toString(new URL(artifactsApiUrl), StandardCharsets.UTF_8); + FileUtils.writeStringToFile(file, versionInfo, StandardCharsets.UTF_8); + return versionInfo; + } + + private Version getLatestAvailableServerVersion(Version version) { + try { + // check if there's cached information + ClassLoader classLoader = getClass().getClassLoader(); + URL location = classLoader.getResource("./co/elastic/clients/version.json"); + + // writing the info on file before returning + if (location == null) { + File file = new File(classLoader.getResource("./co/elastic/clients").getFile() + "/version" + + ".json"); + String versionInfo = fetchAndWriteVersionInfo(file); + return selectLatestVersion(version, versionInfo); + } + + File file = new File(location.getFile()); + + // info file was found, but it's expired + if (Instant.ofEpochMilli(file.lastModified()).isBefore(Instant.now().minus(24, + ChronoUnit.HOURS))) { + String versionInfo = fetchAndWriteVersionInfo(file); + return selectLatestVersion(version, versionInfo); + } + + // info file exists and it has new info + String versionInfo = FileUtils.readFileToString(file, StandardCharsets.UTF_8); + return selectLatestVersion(version, versionInfo); + + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public synchronized ElasticsearchTestServer start() { + if (this.client != null) { + return this; + } + + Version version = getLatestAvailableServerVersion(Version.VERSION); + + // using specific stable version for tests with plugins + if (plugins.length > 0) { + version = Version.VERSION.major() < 8 ? new Version(7, 17, 25, false) : new Version(8, 16, 0, + false); + } + + String esImage = "docker.elastic.co/elasticsearch/elasticsearch:" + version; + + DockerImageName image; + if (plugins.length == 0) { + image = DockerImageName.parse(esImage); + } else { + String esWithPluginsImage = new ImageFromDockerfile() + .withDockerfileFromBuilder(b -> { + b.from(esImage); + for (String plugin : plugins) { + b.run("/usr/share/elasticsearch/bin/elasticsearch-plugin", "install", plugin); + } + } + ).get(); + + image = DockerImageName + .parse(esWithPluginsImage) + .asCompatibleSubstituteFor("docker.elastic.co/elasticsearch/elasticsearch"); + } + + container = new ElasticsearchContainer(image) + .withEnv("ES_JAVA_OPTS", "-Xms256m -Xmx256m") + .withEnv("path.repo", "/tmp") // for snapshots + .withStartupTimeout(Duration.ofSeconds(30)) + .withPassword("changeme"); + container.start(); + + boolean useTLS = version.major() >= 8; + + SSLContext sslContext = useTLS ? container.createSslContextFromCa() : null; + String url = (useTLS ? "https://" : "http://") + container.getHttpHostAddress(); + + setup(url, sslContext); + + return this; + } + + /** + * Send a request to a server and return the response as JSON. Useful to debug response format issues. + */ + public static JsonData getJsonResponse(ElasticsearchClient client, Req request) throws IOException { + + JsonEndpoint endpoint; + + try { + @SuppressWarnings("unchecked") + JsonEndpoint endpoint0 = (JsonEndpoint) request.getClass() + .getDeclaredField("_ENDPOINT").get(null); + endpoint = endpoint0; + } catch (IllegalAccessException | NoSuchFieldException e) { + throw new RuntimeException(e); + } + + DelegatingJsonEndpoint jsonEndpoint = + new DelegatingJsonEndpoint(endpoint) { + @Override + public JsonpDeserializer responseDeserializer() { + return JsonData._DESERIALIZER; + } + }; + + return client._transport().performRequest(request, jsonEndpoint, client._transportOptions()); + } + + @Override + public void close() { + if (this == global) { + // Closed with a shutdown hook + return; + } + + if (container != null) { + container.stop(); + } + container = null; + } + + public ElasticsearchContainer container() { + return this.container; + } + + public RestClient restClient() { + return restClient; + } + + public ElasticsearchTransport transport() { + return transport; + } + + public JsonpMapper mapper() { + return mapper; + } + + public ElasticsearchClient client() { + return client; + } + + public ElasticsearchAsyncClient asyncClient() { + return new ElasticsearchAsyncClient(client._transport(), client._transportOptions()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java new file mode 100644 index 000000000..dede24b9c --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java @@ -0,0 +1,544 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch._helpers.bulk; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.ErrorCause; +import co.elastic.clients.elasticsearch.core.BulkRequest; +import co.elastic.clients.elasticsearch.core.BulkResponse; +import co.elastic.clients.elasticsearch.core.bulk.BulkOperation; +import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; +import co.elastic.clients.elasticsearch.core.bulk.CreateOperation; +import co.elastic.clients.elasticsearch.core.bulk.DeleteOperation; +import co.elastic.clients.elasticsearch.core.bulk.IndexOperation; +import co.elastic.clients.elasticsearch.core.bulk.OperationType; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.SimpleJsonpMapper; +import co.elastic.clients.transport.BackoffPolicy; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.TransportOptions; +import org.jetbrains.annotations.Nullable; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class BulkIngesterRetryPolicyTest { + + protected static ElasticsearchClient client; + protected static TestTransport transport; + protected static CountingListener listener; + + private BulkOperation create = BulkOperation.of(b -> b.create(c -> c.index("foo").id("1").document("1"))); + private BulkOperation index = BulkOperation.of(b -> b.index(c -> c.index("fooo").id("2").document("2"))); + private BulkOperation indexFail = BulkOperation.of(b -> b.index(c -> c.index("fail").id("2").document( + "2"))); + private BulkOperation delete = BulkOperation.of(b -> b.delete(c -> c.index("foooo").id("3"))); + private BulkOperation deleteFail = BulkOperation.of(b -> b.delete(c -> c.index("fail").id("3"))); + + @BeforeEach + public void setup() { + transport = new TestTransport(); + client = new ElasticsearchClient(transport); + listener = new CountingListener(); + } + + @Test + public void retryTestNoScheduledFlushNoContext() throws Exception { + + // First test, partial success, other will succeed after retrying + { + BulkIngester ingester = newBasicBulkIngester(listener); + + ingester.add(create); + ingester.add(index); + ingester.add(index); + + ingester.close(); + + // 1 instant success, 2 retried, but succeeded. can be either 2 or 3 depending on the retries, + // if they get scheduled at the same exact time + assertTrue(listener.requests.get() == 2 || listener.requests.get() == 3); + // eventually all 3 have to succeed + assertTrue(listener.successOperations.get() == 3); + + // 1 for the create and first try for the indexes, 2 + 2 for both index retries, + // which could be scheduled at the same time, so from 3 to 5 + assertTrue(listener.sentRequestsTotal.get() >= 3 && listener.sentRequestsTotal.get() <= 5); + } + + // Second test, all requests will succeed after retrying + { + transport.reset(); + listener.reset(); + + BulkIngester ingester = newBasicBulkIngester(listener); + + ingester.add(index); + ingester.add(index); + ingester.add(index); + ingester.add(index); + + ingester.close(); + + // between 1 and 4, depending on scheduler + assertTrue(listener.requests.get() >= 1 && listener.requests.get() <= 4); + // eventually all 4 have to succeed + assertTrue(listener.successOperations.get() == 4); + // between 3 and 9, depending on scheduler + assertTrue(listener.sentRequestsTotal.get() >= 3 && listener.sentRequestsTotal.get() <= 9); + } + + // Third test, only one retryable (will succeed), other permanent failures + { + transport.reset(); + listener.reset(); + + BulkIngester ingester = newBasicBulkIngester(listener); + + ingester.add(index); + ingester.add(delete); + ingester.add(delete); + + ingester.close(); + + // 2 failed will be handled together, then 1 retry + assertTrue(listener.requests.get() == 2); + + assertTrue(listener.successOperations.get() == 1); + assertTrue(listener.errorOperations.get() == 2); + // 1 initial + 2 retries + assertTrue(listener.sentRequestsTotal.get() == 3); + } + + // Fourth test, all requests will be retried until policy allows, then fail + { + transport.reset(); + listener.reset(); + + BulkIngester ingester = newBasicBulkIngester(listener); + + ingester.add(indexFail); + ingester.add(indexFail); + ingester.add(indexFail); + + ingester.close(); + + // from 1 to 3 depending on scheduling + assertTrue(listener.requests.get() >= 1 && listener.requests.get() <= 3); + + assertTrue(listener.successOperations.get() == 0); + assertTrue(listener.errorOperations.get() == 3); + // between 8 and 24, depending on scheduler + assertTrue(listener.sentRequestsTotal.get() >= 8 && listener.sentRequestsTotal.get() <= 24); + } + + // Fifth test, one exception that will make everything else fail, no retries triggered + { + transport.reset(); + listener.reset(); + + BulkIngester ingester = newBasicBulkIngester(listener); + + ingester.add(index); + ingester.add(create); + ingester.add(deleteFail); + + ingester.close(); + + // just the one + assertTrue(listener.requests.get() == 1); + + assertTrue(listener.successOperations.get() == 0); + assertTrue(listener.errorOperations.get() == 3); + + // just the one + assertTrue(listener.sentRequestsTotal.get() == 1); + } + + // Sixth test, a mix of everything + { + transport.reset(); + listener.reset(); + + BulkIngester ingester = newBasicBulkIngester(listener); + + ingester.add(create); + ingester.add(index); + ingester.add(indexFail); + ingester.add(delete); + ingester.add(create); + ingester.add(index); + ingester.add(indexFail); + ingester.add(delete); + + ingester.close(); + + // from 2 to 4 depending on scheduling + assertTrue(listener.requests.get() >= 1 && listener.successOperations.get() <= 4); + + assertTrue(listener.successOperations.get() == 4); + assertTrue(listener.errorOperations.get() == 4); + + // between 8 and 18, depending on scheduler + assertTrue(listener.sentRequestsTotal.get() >= 8 && listener.sentRequestsTotal.get() <= 18); + } + + transport.close(); + } + + @Test + public void retryTestFlushAndContextExponentialBackoff() throws Exception { + + // One success, other will succeed after retrying, other will fail eventually + { + BulkIngester ingester = newBulkIngesterWithFlushAndContextAndLongExponential(listener); + + ingester.add(create, 1); + ingester.add(indexFail, 2); + ingester.add(index, 3); + + ingester.close(); + + // should be 3 separate requests sent, one instant, one after a few retries, the last one error. + assertTrue(listener.requests.get() == 3); + // 2 will succeed, one will fail + assertTrue(listener.successOperations.get() == 2); + assertTrue(listener.errorOperations.get() == 1); + // between 8 and 10, depending on scheduler (first one + 2 retries for index + 8 retries for + // indexfail) + assertTrue(listener.sentRequestsTotal.get() >= 8 && listener.sentRequestsTotal.get() <= 11); + // checking order of contexts after send confirmed + Iterator iter = listener.sentContexts.iterator(); + // first one being completed is create + assertTrue(iter.next().equals(1)); + // second one is index, which will take only 2 retries + assertTrue(iter.next().equals(3)); + // last one is indexFail, taking 8 retries to fail + assertTrue(iter.next().equals(2)); + } + + transport.close(); + } + + @Test + public void retryTestNoFlushAndContextExponentialBackoff() throws Exception { + + // One success, other will succeed after retrying, other will fail eventually + { + BulkIngester ingester = newBulkIngesterNoFlushAndContextAndLongExponential(listener); + + ingester.add(create, 1); + ingester.add(indexFail, 2); + ingester.add(index, 3); + + ingester.close(); + + // should be 3 separate requests sent, one instant, one after a few retries, the last one error. + assertTrue(listener.requests.get() == 3); + // 2 will succeed, one will fail + assertTrue(listener.successOperations.get() == 2); + assertTrue(listener.errorOperations.get() == 1); + // between 8 and 10, depending on scheduler (first one + 2 retries for index + 8 retries for + // indexfail) + assertTrue(listener.sentRequestsTotal.get() >= 8 && listener.sentRequestsTotal.get() <= 11); + // checking order of contexts after send confirmed + Iterator iter = listener.sentContexts.iterator(); + // first one being completed is create + assertTrue(iter.next().equals(1)); + // second one is index, which will take only 2 retries + assertTrue(iter.next().equals(3)); + // last one is indexFail, taking 8 retries to fail + assertTrue(iter.next().equals(2)); + } + + transport.close(); + } + + @Test + public void retryMultiThreadStressTest() throws InterruptedException, IOException { + + // DISCLAIMER: this configuration is highly inefficient and only used here to showcase an extreme + // situation where the number of adding threads greatly exceeds the number of concurrent requests + // handled by the ingester. It's strongly recommended to always tweak maxConcurrentRequests + // accordingly. + BulkIngester ingester = BulkIngester.of(b -> b + .client(client) + .listener(listener) + .flushInterval(5, TimeUnit.SECONDS) + .backoffPolicy(BackoffPolicy.constantBackoff(50L, 8))); + + ExecutorService executor = Executors.newFixedThreadPool(50); + + // sends create operations, but once every 1000, one index operation will be sent, + // and once every 5000 an indexFail + for (int i = 0; i < 100000; i++) { + int ii = i; + Runnable thread = () -> { + int finalI = ii; + if (ii % 1000 == 0) { + ingester.add(index, ii); + } else if (ii % 5000 == 0) { + ingester.add(indexFail, ii); + } else { + ingester.add(create, ii); + } + }; + executor.submit(thread); + } + + executor.awaitTermination(10, TimeUnit.SECONDS); + ingester.close(); + + // all operations will succeed eventually, so the total has to be 100000 + assertTrue(listener.successOperations.get() == 100000); + assertTrue(listener.sentContexts.size() == 100000); + assertTrue(listener.errorOperations.get() == 0); + // it's difficult to predict how many requests will be sent, but considering they will be sent + // in batches of 1000, without retries it should be exactly 100, considering that 100 out of + // 100000 will be retried 3 times and 20 will be retried 8 times, if they don't get batched together + // with the others it could result in a total of 560, which is highly unlikely. + // more reasonably there will be between 100 and 300 requests sent. + assertTrue(listener.sentRequestsTotal.get() >= 100 && listener.sentRequestsTotal.get() <= 300); + // same reasoning + assertTrue(listener.requests.get() >= 100 && listener.requests.get() <= 300); + + transport.close(); + } + + + private static class TestTransport implements ElasticsearchTransport { + public final AtomicInteger requestsStarted = new AtomicInteger(); + public final AtomicInteger requestsCompleted = new AtomicInteger(); + public final AtomicInteger operations = new AtomicInteger(); + + public ConcurrentHashMap retryFailures = new ConcurrentHashMap<>(); + + + private final ExecutorService executor = Executors.newCachedThreadPool(); + + @Override + public ResponseT performRequest( + RequestT request, + Endpoint endpoint, + @Nullable TransportOptions options + ) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture performRequestAsync(RequestT request, Endpoint endpoint, @Nullable TransportOptions options) { + + BulkRequest bulk = (BulkRequest) request; + requestsStarted.incrementAndGet(); + operations.addAndGet(bulk.operations().size()); + + if (bulk.operations().isEmpty()) { + System.out.println("No operations!"); + } + + // For testing purposes, different result depending on the operation type. + // Create will always succeed + // Index will always return 429 for 2 times, then 200. Index with index name "fail" will only + // return 429. + // Delete will always return 404. Delete with index name "fail" will throw transport exception. + + try { + + List items = new ArrayList<>(); + for (BulkOperation op : bulk.operations()) { + OperationType operationType = OperationType.Create; + ErrorCause error = null; + int status = 200; + String index = null; + switch (op._kind()) { + case Index: + index = ((IndexOperation) op._get()).index(); + operationType = OperationType.Index; + retryFailures.putIfAbsent(op, 0); + boolean isStillRetrying = retryFailures.computeIfPresent(op, (k, v) -> v + 1) > 2; + error = isStillRetrying && !index.equals("fail") ? null : + ErrorCause.of(e -> e.reason("some error")); + status = isStillRetrying && !index.equals("fail") ? 200 : 429; + break; + case Delete: + index = ((DeleteOperation) op._get()).index(); + if (index.equals("fail")) { + throw new RuntimeException("error"); + } + operationType = OperationType.Delete; + error = ErrorCause.of(e -> e.reason("some error")); + status = 404; + break; + default: + index = ((CreateOperation) op._get()).index(); + break; + } + ErrorCause finalError = error; + int finalStatus = status; + OperationType finalOperationType = operationType; + String finalIndex = index; + items.add(BulkResponseItem.of(b -> b + .index(finalIndex) + .operationType(finalOperationType) + .status(finalStatus) + .error(finalError))); + } + + CompletableFuture response = new CompletableFuture<>(); + executor.submit(() -> { + requestsCompleted.incrementAndGet(); + response.complete(BulkResponse.of(r -> r.errors(false).items(items).took(3))); + }); + + @SuppressWarnings("unchecked") + CompletableFuture result = (CompletableFuture) response; + return result; + } catch (RuntimeException e) { + CompletableFuture future = new CompletableFuture<>(); + future.completeExceptionally(e); + executor.submit(() -> { + future.completeExceptionally(e); + }); + return future; + } + } + + @Override + public JsonpMapper jsonpMapper() { + return SimpleJsonpMapper.INSTANCE; + } + + @Override + public TransportOptions options() { + return null; + } + + @Override + public void close() throws IOException { + executor.shutdown(); + try { + executor.awaitTermination(1, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + public void reset() { + requestsStarted.set(0); + requestsCompleted.set(0); + operations.set(0); + retryFailures = new ConcurrentHashMap<>(); + } + } + + private static class CountingListener implements BulkListener { + public final AtomicInteger sentRequestsTotal = new AtomicInteger(); + public final AtomicInteger successOperations = new AtomicInteger(); + public final AtomicInteger errorOperations = new AtomicInteger(); + public final AtomicInteger requests = new AtomicInteger(); + public final ConcurrentLinkedQueue sentContexts = new ConcurrentLinkedQueue<>(); + + @Override + public void beforeBulk(long executionId, BulkRequest request, List contexts) { + sentRequestsTotal.incrementAndGet(); + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, + BulkResponse response) { + for (BulkResponseItem item : response.items()) { + if (item.error() != null) { + errorOperations.incrementAndGet(); + } else { + successOperations.incrementAndGet(); + } + } + if (contexts.stream().anyMatch(Objects::nonNull)) { + sentContexts.addAll(contexts); + } + requests.incrementAndGet(); + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, + Throwable failure) { + failure.printStackTrace(); + errorOperations.addAndGet(request.operations().size()); + if (contexts.stream().anyMatch(Objects::nonNull)) { + sentContexts.addAll(contexts); + } + requests.incrementAndGet(); + } + + public void reset() { + successOperations.set(0); + errorOperations.set(0); + requests.set(0); + sentRequestsTotal.set(0); + } + } + + private BulkIngester newBasicBulkIngester(BulkListener listener) { + return BulkIngester.of(b -> b + .client(client) + .maxOperations(10) + .maxConcurrentRequests(10) + .listener(listener) + .backoffPolicy(BackoffPolicy.constantBackoff(50L, 8)) + ); + } + + private BulkIngester newBulkIngesterWithFlushAndContextAndLongExponential(BulkListener listener) { + return BulkIngester.of(b -> b + .client(client) + .maxOperations(10) + .maxConcurrentRequests(10) + .listener(listener) + .flushInterval(1000, TimeUnit.MILLISECONDS) + .backoffPolicy(BackoffPolicy.exponentialBackoff(100L, 8)) + ); + } + + private BulkIngester newBulkIngesterNoFlushAndContextAndLongExponential(BulkListener listener) { + return BulkIngester.of(b -> b + .client(client) + .maxOperations(10) + .maxConcurrentRequests(10) + .listener(listener) + .backoffPolicy(BackoffPolicy.exponentialBackoff(100L, 8)) + ); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/bulk/BulkIngesterTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/bulk/BulkIngesterTest.java new file mode 100644 index 000000000..76a48b9fa --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/bulk/BulkIngesterTest.java @@ -0,0 +1,623 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch._helpers.bulk; + +import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.ElasticsearchTestServer; +import co.elastic.clients.elasticsearch.core.BulkRequest; +import co.elastic.clients.elasticsearch.core.BulkResponse; +import co.elastic.clients.elasticsearch.core.bulk.BulkOperation; +import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; +import co.elastic.clients.elasticsearch.core.bulk.OperationType; +import co.elastic.clients.elasticsearch.end_to_end.RequestTest; +import co.elastic.clients.elasticsearch.indices.IndicesStatsResponse; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.SimpleJsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.TransportOptions; +import org.jetbrains.annotations.Nullable; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +class BulkIngesterTest extends Assertions { + + private static final BulkResponseItem successItem = BulkResponseItem.of(i -> i + .index("foo") + .status(200) + .operationType(OperationType.Delete) + ); + + private static final BulkOperation operation = BulkOperation.of(op -> op + .delete(d -> d.index("foo").id("bar")) + ); + + private void printStats(BulkIngester ingester) { + System.out.printf("Ingester - operations: %d (%d), requests: %d (%d)%n", + ingester.operationsCount(), ingester.operationContentionsCount(), + ingester.requestCount(), ingester.requestContentionsCount() + ); + } + + private void printStats(CountingListener listener) { + System.out.printf("Listener - operations: %d, requests: %d%n", + listener.operations.get(), + listener.requests.get() + ); + } + + private void printStats(TestTransport transport) { + System.out.printf("Transport - operations: %d, requests: %d (%d completed)%n", + transport.operations.get(), + transport.requestsStarted.get(), + transport.requestsCompleted.get() + ); + } + + @Test + public void basicTestFlush() throws Exception { + // Prime numbers, so that we have leftovers to flush before shutting down + multiThreadTest(7, 3, 5, 101, true); + } + + @Test + public void basicTestFlushWithInternalScheduler() throws Exception { + // Prime numbers, so that we have leftovers to flush before shutting down + multiThreadTest(7, 3, 5, 101, false); + } + + @Test + public void basicTestNoFlush() throws Exception { + // Will have nothing to flush on close. + multiThreadTest(10, 3, 5, 100, true); + } + + @Test + public void basicTestNoFlushWithInternalScheduler() throws Exception { + // Will have nothing to flush on close. + multiThreadTest(10, 3, 5, 100, false); + } + + private void multiThreadTest(int maxOperations, int maxRequests, int numThreads, int numOperations, + boolean externalScheduler) throws Exception { + + CountingListener listener = new CountingListener(); + TestTransport transport = new TestTransport(); + ElasticsearchAsyncClient client = new ElasticsearchAsyncClient(transport); + ScheduledExecutorService scheduler; + if (externalScheduler) { + scheduler = Executors.newSingleThreadScheduledExecutor(r -> { + Thread t = Executors.defaultThreadFactory().newThread(r); + t.setName("my-bulk-ingester-executor#"); + t.setDaemon(true); + return t; + }); + } else { + scheduler = null; + } + + BulkIngester ingester = BulkIngester.of(b -> b + .client(client) + .maxOperations(maxOperations) + .maxConcurrentRequests(maxRequests) + .scheduler(scheduler) + .listener(listener) + ); + + CountDownLatch latch = new CountDownLatch(numThreads); + for (int i = 0; i < numThreads; i++) { + new Thread(() -> { + try { + Thread.sleep((long)(Math.random() * 100)); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + for (int j = 0; j < numOperations; j++) { + ingester.add(operation); + } + + latch.countDown(); + }).start(); + } + + latch.await(); + + ingester.close(); + transport.close(); + if (scheduler != null) scheduler.shutdownNow(); + + printStats(ingester); + printStats(listener); + printStats(transport); + + int expectedOperations = numThreads * numOperations; + assertEquals(expectedOperations, ingester.operationsCount()); + assertEquals(expectedOperations, listener.operations.get()); + assertEquals(expectedOperations, transport.operations.get()); + + int expectedRequests = expectedOperations / maxOperations + ((expectedOperations % maxOperations == 0) ? 0 : 1) ; + + assertEquals(expectedRequests, ingester.requestCount()); + assertEquals(expectedRequests, listener.requests.get()); + assertEquals(expectedRequests, transport.requestsStarted.get()); + } + + @Test + public void multiThreadStressTest() throws InterruptedException, IOException { + + String index = "bulk-ingester-stress-test"; + ElasticsearchClient client = ElasticsearchTestServer.global().client(); + + // DISCLAIMER: this configuration is highly inefficient and only used here to showcase an extreme + // situation where the number of adding threads greatly exceeds the number of concurrent requests + // handled by the ingester. It's strongly recommended to always tweak maxConcurrentRequests accordingly. + BulkIngester ingester = BulkIngester.of(b -> b + .client(client) + .globalSettings(s -> s.index(index)) + .flushInterval(5, TimeUnit.SECONDS) + ); + + RequestTest.AppData appData = new RequestTest.AppData(); + appData.setIntValue(42); + appData.setMsg("Some message"); + + ExecutorService executor = Executors.newFixedThreadPool(50); + + for (int i = 0; i < 100000; i++) { + int ii = i; + Runnable thread = () -> { + int finalI = ii; + ingester.add(_1 -> _1 + .create(_2 -> _2 + .id(String.valueOf(finalI)) + .document(appData) + )); + }; + executor.submit(thread); + } + + executor.awaitTermination(10,TimeUnit.SECONDS); + ingester.close(); + + client.indices().refresh(); + + IndicesStatsResponse indexStats = client.indices().stats(g -> g.index(index)); + + assertTrue(indexStats.indices().get(index).primaries().docs().count()==100000); + } + + @Test + public void sizeLimitTest() throws Exception { + TestTransport transport = new TestTransport(); + + long operationSize = IngesterOperation.of(new RetryableBulkOperation<>(operation, null, null), transport.jsonpMapper()).size(); + + BulkIngester ingester = BulkIngester.of(b -> b + .client(new ElasticsearchAsyncClient(transport)) + // Set size limit just above operation's size, leading to 2 operations per request + .maxSize(operationSize + 1) + ); + + for (int i = 0; i < 10; i++) { + ingester.add(operation); + } + + ingester.close(); + transport.close(); + + assertEquals(10, ingester.operationsCount()); + assertEquals(5, ingester.requestCount()); + } + + @Test + public void periodicFlushTest() throws Exception { + TestTransport transport = new TestTransport(); + + BulkIngester ingester = BulkIngester.of(b -> b + .client(new ElasticsearchAsyncClient(transport)) + // Flush every 50 ms + .flushInterval(50, TimeUnit.MILLISECONDS) + // Disable other flushing limits + .maxSize(-1) + .maxOperations(-1) + .maxConcurrentRequests(Integer.MAX_VALUE-1) + ); + + // Add an operation every 100 ms to give time + // to the flushing timer to kick in. + for (int i = 0; i < 10; i++) { + ingester.add(operation); + Thread.sleep(100); + } + + ingester.close(); + transport.close(); + + // We should have one operation per request + assertEquals(10, ingester.operationsCount()); + assertEquals(10, ingester.requestCount()); + } + + @Test + public void failingListener() throws Exception { + TestTransport transport = new TestTransport(); + AtomicInteger failureCount = new AtomicInteger(); + AtomicReference> lastContexts = new AtomicReference<>(); + AtomicReference lastRequest = new AtomicReference<>(); + + BulkListener listener = new BulkListener() { + @Override + public void beforeBulk(long executionId, BulkRequest request, List contexts) { + // So that we can test that it's non-empty + lastContexts.set(contexts); + lastRequest.set(request); + + if (executionId == 1) { + // Fail before the request is sent + failureCount.incrementAndGet(); + throw new RuntimeException("Before bulk failure"); + } + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, BulkResponse response) { + if (executionId == 2) { + // Fail after the request is sent + failureCount.incrementAndGet(); + throw new RuntimeException("After bulk failure"); + } + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, Throwable failure) { + + } + }; + + BulkIngester ingester = BulkIngester.of(b -> b + .client(new ElasticsearchAsyncClient(transport)) + // Flush every 50 ms + .flushInterval(50, TimeUnit.MILLISECONDS) + // Disable other flushing limits + .maxSize(-1) + .maxOperations(-1) + .maxConcurrentRequests(Integer.MAX_VALUE - 1) + .listener(listener) + ); + + // Add an operation every 100 ms to give time + // to the flushing timer to kick in. + for (int i = 0; i < 10; i++) { + ingester.add(operation); + Thread.sleep(100); + } + + ingester.close(); + transport.close(); + + // We should have one operation per request + assertEquals(10, ingester.operationsCount()); + assertEquals(10, ingester.requestCount()); + // Transport hasn't seen the request where beforeBulk failed + assertEquals(9, transport.requestsStarted.get()); + + assertEquals(2, failureCount.get()); + + // Also test context list when no values were provided + assertTrue(lastRequest.get().operations().size() > 0); + assertEquals(lastRequest.get().operations().size(), lastContexts.get().size()); + } + + @Test + public void withContextValues() throws Exception { + TestTransport transport = new TestTransport(); + List allRequests = Collections.synchronizedList(new ArrayList<>()); + List> allContexts = Collections.synchronizedList(new ArrayList<>()); + + BulkListener listener = new BulkListener() { + @Override + public void beforeBulk(long executionId, BulkRequest request, List contexts) { + allRequests.add(request); + allContexts.add(contexts); + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, BulkResponse response) { + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, Throwable failure) { + } + }; + + BulkIngester ingester = BulkIngester.of(b -> b + .client(new ElasticsearchAsyncClient(transport)) + // Split every 10 operations + .maxOperations(10) + .listener(listener) + ); + + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + // Set a context only after 5, so that we test filling with nulls. + Integer context = j < 5 ? null : i*10 + j; + ingester.add(operation, context); + } + } + + ingester.close(); + transport.close(); + + // We should have 10 operations per request + assertEquals(100, ingester.operationsCount()); + assertEquals(10, ingester.requestCount()); + + for (int i = 0; i < 10; i++) { + List contexts = allContexts.get(i); + for (int j = 0; j < 10; j++) { + if (j < 5) { + assertNull(contexts.get(j)); + } else { + assertEquals(contexts.get(j), i*10 + j); + } + } + } + } + + @Test + public void testGlobalSettings() throws Exception { + AtomicReference storedRequest = new AtomicReference<>(); + + TestTransport transport = new TestTransport(); + CountingListener listener = new CountingListener() { + @Override + public void beforeBulk(long executionId, BulkRequest request, List contexts) { + super.beforeBulk(executionId, request, contexts); + storedRequest.set(request); + } + }; + + BulkIngester ingester = BulkIngester.of(b -> b + .client(new ElasticsearchAsyncClient(transport)) + .listener(listener) + .globalSettings(s -> s + .index("foo") + .routing("bar") + ) + ); + + ingester.add(operation); + + ingester.close(); + transport.close(); + + assertEquals(1, ingester.operationsCount()); + assertEquals(1, ingester.requestCount()); + + assertEquals("foo", storedRequest.get().index()); + assertEquals("bar", storedRequest.get().routing()); + } + + @Test + public void pipelineTest() { + String json = "{\"create\":{\"_id\":\"some_id\",\"_index\":\"some_idx\",\"pipeline\":\"pipe\",\"require_alias\":true}}"; + JsonpMapper mapper = new SimpleJsonpMapper(); + + BulkOperation create = BulkOperation.of(o -> o.create(c -> c + .pipeline("pipe") + .requireAlias(true) + .index("some_idx") + .id("some_id") + .document("Some doc") + )); + + String createStr = JsonpUtils.toJsonString(create, mapper); + assertEquals(json, createStr); + + BulkOperation create1 = IngesterOperation.of(new RetryableBulkOperation<>(create, null, null), mapper) + .repeatableOperation().operation(); + + String create1Str = JsonpUtils.toJsonString(create1, mapper); + assertEquals(json, create1Str); + } + + @Test + public void endToEndTest() throws Exception { + String index = "bulk-ingester-test"; + ElasticsearchClient client = ElasticsearchTestServer.global().client(); + + BulkIngester ingester = BulkIngester.of(b -> b + .client(client) + .globalSettings(s -> s.index(index)) + ); + + RequestTest.AppData appData = new RequestTest.AppData(); + appData.setIntValue(42); + appData.setMsg("Some message"); + + ingester.add(_1 -> _1 + .create(_2 -> _2 + .id("abc") + .document(appData) + )); + + ingester.add(_1 -> _1 + .create(_2 -> _2 + .id("def") + .document(appData) + )); + + ingester.add(_1 -> _1 + .update(_2 -> _2 + .id("gh") + .action(_3 -> _3 + .docAsUpsert(true) + .doc(appData)) + )); + + // Closing waits until all pending requests are completed + ingester.close(); + + for (String id : Arrays.asList("abc", "def", "gh")) { + assertEquals( + 42, + client.get(b -> b + .index(index) + .id(id), + RequestTest.AppData.class + ).source().getIntValue() + ); + } + + client.indices().delete(d -> d.index(index)); + + } + + @Test + public void testConfigValidation() { + + BulkIngester.Builder b = new BulkIngester.Builder<>(); + + assertThrows(IllegalArgumentException.class, () -> { + b.flushInterval(-1, TimeUnit.MILLISECONDS); + }); + + assertThrows(IllegalArgumentException.class, () -> { + b.maxConcurrentRequests(0); + }); + + assertThrows(IllegalArgumentException.class, () -> { + b.maxSize(-2); + }); + + assertThrows(IllegalArgumentException.class, () -> { + b.maxOperations(-2); + }); + + assertThrows(IllegalStateException.class, () -> { + b.maxSize(-1).maxOperations(-1).build(); + }); + } + + //----------------------------------------------------------------------------------------------------------------- + + private static class CountingListener implements BulkListener { + public final AtomicInteger operations = new AtomicInteger(); + public final AtomicInteger requests = new AtomicInteger(); + @Override + public void beforeBulk(long executionId, BulkRequest request, List contexts) { + + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, BulkResponse response) { + operations.addAndGet(request.operations().size()); + requests.incrementAndGet(); + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, Throwable failure) { + failure.printStackTrace(); + operations.addAndGet(request.operations().size()); + requests.incrementAndGet(); + } + } + + private static class TestTransport implements ElasticsearchTransport { + public final AtomicInteger requestsStarted = new AtomicInteger(); + public final AtomicInteger requestsCompleted = new AtomicInteger(); + public final AtomicInteger operations = new AtomicInteger(); + + private final ExecutorService executor = Executors.newCachedThreadPool(); + + @Override + public ResponseT performRequest( + RequestT request, + Endpoint endpoint, + @Nullable TransportOptions options + ) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture performRequestAsync(RequestT request, Endpoint endpoint, @Nullable TransportOptions options) { + + BulkRequest bulk = (BulkRequest) request; + requestsStarted.incrementAndGet(); + operations.addAndGet(bulk.operations().size()); + + if (bulk.operations().size() == 0) { + System.out.println("No operations!"); + } + + List items = new ArrayList<>(); + for (int i = 0; i < bulk.operations().size(); i++) { + items.add(successItem); + } + + CompletableFuture response = new CompletableFuture<>(); + executor.submit(() -> { + requestsCompleted.incrementAndGet(); + response.complete(BulkResponse.of(r -> r.errors(false).items(items).took(3))); + }); + + @SuppressWarnings("unchecked") + CompletableFuture result = (CompletableFuture)response; + return result; + } + + @Override + public JsonpMapper jsonpMapper() { + return SimpleJsonpMapper.INSTANCE; + } + + @Override + public TransportOptions options() { + return null; + } + + @Override + public void close() throws IOException { + executor.shutdown(); + try { + executor.awaitTermination(1, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java new file mode 100644 index 000000000..eaa413e2b --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java @@ -0,0 +1,203 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch._helpers.esql; + +import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.ElasticsearchTestServer; +import co.elastic.clients.elasticsearch._helpers.esql.jdbc.ResultSetEsqlAdapter; +import co.elastic.clients.elasticsearch._helpers.esql.objects.ObjectsEsqlAdapter; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import org.apache.commons.io.IOUtils; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.ContentType; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.InputStream; +import java.sql.ResultSet; +import java.sql.Timestamp; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +public class EsqlAdapterEndToEndTest extends Assertions { + + static ElasticsearchClient esClient; + + @BeforeAll + public static void setup() throws Exception { + ElasticsearchClient global = ElasticsearchTestServer.global().client(); + RestClient restClient = ((RestClientTransport) global._transport()).restClient(); + esClient = new ElasticsearchClient(new RestClientTransport(restClient, new JacksonJsonpMapper())); + + esClient.indices().delete(d -> d.index("employees").ignoreUnavailable(true)); + + Request request = new Request("POST", "/employees/_bulk?refresh=true"); + + InputStream resourceAsStream = EsqlAdapterTest.class.getResourceAsStream("employees.ndjson"); + byte[] bytes = IOUtils.toByteArray(resourceAsStream); + request.setEntity(new ByteArrayEntity(bytes, ContentType.APPLICATION_JSON)); + + restClient.performRequest(request); + } + + @Test + public void resultSetTest() throws Exception { + + ResultSet rs = esClient.esql().query( + ResultSetEsqlAdapter.INSTANCE, + "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | SORT emp_no | LIMIT 300", + // Testing parameters. Note that FROM and LIMIT do not accept parameters + "10042", "10002" + ); + + { + assertTrue(rs.next()); + assertEquals("10002", rs.getString("emp_no")); + + // Single valued fields come back as single value even if other rows have multiple values + @SuppressWarnings("unchecked") + String job = (String) rs.getObject("job_positions"); + assertEquals("Senior Team Lead", job); + } + + { + assertTrue(rs.next()); + assertEquals("10042", rs.getString("emp_no")); + + java.sql.Date hireDate = rs.getDate("hire_date"); + assertEquals("1993-03-21", hireDate.toString()); + + Timestamp hireDate1 = rs.getTimestamp("hire_date"); + assertEquals( + "1993-03-21T00:00:00Z[UTC]", + DateTimeFormatter.ISO_DATE_TIME.format(hireDate1.toInstant().atZone(ZoneId.of("UTC"))) + ); + + @SuppressWarnings("unchecked") + List jobs = (List) rs.getObject("job_positions"); + + assertEquals(4, jobs.size()); + assertEquals("Architect", jobs.get(0)); + } + + assertFalse(rs.next()); + } + + @Test + public void objectsTest() throws Exception { + Iterable result = esClient.esql().query( + ObjectsEsqlAdapter.of(EmpData.class), + "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | SORT emp_no | LIMIT 300", + // Testing parameters. Note that FROM and LIMIT do not accept parameters + "10042", "10002" + ); + + Iterator it = result.iterator(); + + { + EmpData emp = it.next(); + assertEquals("10002", emp.empNo); + List jobPositions = emp.jobPositions; + // In addition to the value, this tests that single strings are correctly deserialized as a list + assertEquals(Arrays.asList("Senior Team Lead"), emp.jobPositions); + } + + { + EmpData emp = it.next(); + assertEquals("10042", emp.empNo); + assertEquals(4, emp.jobPositions.size()); + assertTrue(emp.jobPositions.contains("Architect")); + assertTrue(emp.jobPositions.contains("Business Analyst")); + assertTrue(emp.jobPositions.contains("Internship")); + assertTrue(emp.jobPositions.contains("Junior Developer")); + + assertEquals("1993-03-21T00:00:00Z[UTC]", + DateTimeFormatter.ISO_DATE_TIME.format(emp.hireDate.toInstant().atZone(ZoneId.of("UTC"))) + ); + } + + assertFalse(it.hasNext()); + + } + + @Test + public void asyncObjects() throws Exception { + + ElasticsearchAsyncClient asyncClient = new ElasticsearchAsyncClient(esClient._transport(), esClient._transportOptions()); + + + CompletableFuture> future = asyncClient.esql().query( + ObjectsEsqlAdapter.of(EmpData.class), + "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | SORT emp_no | LIMIT 300", + // Testing parameters. Note that FROM and LIMIT do not accept parameters + "10042", "10002" + ); + + future.thenApply(result -> { + Iterator it = result.iterator(); + + { + EmpData emp = it.next(); + assertEquals("10002", emp.empNo); + List jobPositions = emp.jobPositions; + // In addition to the value, this tests that single strings are correctly deserialized as a list + assertEquals(Arrays.asList("Senior Team Lead"), emp.jobPositions); + } + + { + EmpData emp = it.next(); + assertEquals("10042", emp.empNo); + assertEquals(4, emp.jobPositions.size()); + assertTrue(emp.jobPositions.contains("Architect")); + assertTrue(emp.jobPositions.contains("Business Analyst")); + assertTrue(emp.jobPositions.contains("Internship")); + assertTrue(emp.jobPositions.contains("Junior Developer")); + + assertEquals("1993-03-21T00:00:00Z[UTC]", + DateTimeFormatter.ISO_DATE_TIME.format(emp.hireDate.toInstant().atZone(ZoneId.of("UTC"))) + ); + } + + assertFalse(it.hasNext()); + return null; + } + ).get(); + } + + @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) + @JsonIgnoreProperties(ignoreUnknown = true) + public static class EmpData { + public String empNo; + public java.util.Date hireDate; + public List jobPositions; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterTest.java new file mode 100644 index 000000000..e3afd3ee0 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterTest.java @@ -0,0 +1,119 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch._helpers.esql; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._helpers.esql.jdbc.ResultSetEsqlAdapter; +import co.elastic.clients.elasticsearch._helpers.esql.objects.ObjectsEsqlAdapter; +import co.elastic.clients.elasticsearch.esql.EsqlFormat; +import co.elastic.clients.json.JsonpMappingException; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.testkit.MockHttpClient; +import co.elastic.clients.transport.endpoints.BinaryResponse; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.sql.ResultSet; +import java.sql.Types; + +public class EsqlAdapterTest extends Assertions { + + String json = "{\n" + + " \"took\": 10," + + " \"columns\": [\n" + + "\t{\"name\": \"avg_salary\", \"type\": \"double\"},\n" + + "\t{\"name\": \"lang\", \t\"type\": \"keyword\"}\n" + + " ],\n" + + " \"values\": [\n" + + "\t[43760.0, \"Spanish\"],\n" + + "\t[48644.0, \"French\"],\n" + + "\t[48832.0, \"German\"]\n" + + " ]\n" + + "}\n"; + + ElasticsearchClient esClient = new MockHttpClient() + .add("/_query", "application/json", json) + .client(new JacksonJsonpMapper()); // object deserializer needs a buffering mapper + + public static class Data { + public double avg_salary; + public String lang; + } + + @Test + public void testMissingColumns() throws IOException { + String badJson = "{\n" + + " \"took\": 10," + + " \"values\": [\n" + + "\t[43760.0, \"Spanish\"],\n" + + "\t[48644.0, \"French\"],\n" + + "\t[48832.0, \"German\"]\n" + + " ]\n" + + "}\n"; + + ElasticsearchClient esClient = new MockHttpClient() + .add("/_query", "application/json", badJson) + .client(new JacksonJsonpMapper()); + + JsonpMappingException jsonMappingException = assertThrows(JsonpMappingException.class, () -> { + esClient.esql().query( + ResultSetEsqlAdapter.INSTANCE, + "FROM employees | STATS avg_salary = AVG(salary) by country" + ); + }); + assertTrue(jsonMappingException.getMessage().contains("Expecting a 'columns' property")); + } + + @Test + public void testObjectDeserializer() throws IOException { + + BinaryResponse response = esClient.esql().query(q -> q + .query("FROM foo") + .format(EsqlFormat.Json) + ); + + Iterable data = esClient.esql().query( + new ObjectsEsqlAdapter<>(Data.class), + "FROM employees | STATS avg_salary = AVG(salary) by country" + ); + + for (Data d: data) { + System.out.println(d.lang + " " + d.avg_salary); + } + } + + @Test + public void testResultSetAdapter() throws Exception { + + ResultSet resultSet = esClient.esql().query( + ResultSetEsqlAdapter.INSTANCE, + "FROM employees | STATS avg_salary = AVG(salary) by country" + ); + + assertEquals(2, resultSet.getMetaData().getColumnCount()); + assertEquals(Types.DOUBLE, resultSet.getMetaData().getColumnType(1)); + assertEquals(Types.VARCHAR, resultSet.getMetaData().getColumnType(2)); + + while (resultSet.next()) { + System.out.println(resultSet.getDouble("avg_salary") + " " + resultSet.getString(2)); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/ClientTests.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/ClientTests.java new file mode 100644 index 000000000..2b5d9332a --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/ClientTests.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments; + +import co.elastic.clients.elasticsearch.experiments.api.Bar; +import co.elastic.clients.elasticsearch.experiments.api.FooRequest; +import co.elastic.clients.elasticsearch.experiments.api.FooResponse; +import co.elastic.clients.elasticsearch.experiments.api.query2.Query; +import co.elastic.clients.elasticsearch.experiments.api.query2.TermsQuery; +import co.elastic.clients.elasticsearch.experiments.base.Client; +import co.elastic.clients.transport.Endpoint; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.Collections; + +public class ClientTests { + + @Test + public void testClient() throws Exception { + + Client client = new Client(){ + @Override + protected ResponseT performRequest( + RequestT request, Endpoint endpoint + ) throws IOException { + // don't care for now, we're testing compilation + return null; + } + }; + + client.foo(fb -> fb + .name("z") + .value(1) + .routing("fooo") + .query(q -> q + .bool(b-> b + .add_must(m -> m.terms((TermsQuery) null)) + ) + //.terms(tq -> tq.term("")) + .meta(Collections.emptyMap()) + ) + ); + + // Builders everywhere + FooResponse r1 = client.foo( + FooRequest.builder() + .name("z") + .value(1) + .bar(Bar.builder() + .name("Raise the bar") + .build() + ) + .build() + ); + + // Illustrates creating an object outside of the client call + TermsQuery filter = TermsQuery.builder() + .field("foo") + .term("bar") + .build(); + + Query filter2 = new Query.Builder() + .terms(t -> t + .field("foo") + .term("bar") + ).build(); + + // Fluid lambda-based builders + FooResponse r2 = client.foo(f -> f + .name("z") + .value(1) + .bar(bar -> bar + .name("Raise the bar") + ) + .query(q -> q + .bool(b -> b + .add_must(q1 -> q1.terms(filter)) + .add_must(q1 -> q1 + .terms(t -> t.field("a").term("b")) + ) + .add_must(q1 -> q1 + .terms(t -> t.field("a").term("b")) + ) + .minimumShouldMatch(2) + ) + ) + ); + } +} + diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/ParsingTests.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/ParsingTests.java new file mode 100644 index 000000000..af207e644 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/ParsingTests.java @@ -0,0 +1,76 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments; + +import co.elastic.clients.elasticsearch.experiments.api.FooRequest; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParsingException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; + +public class ParsingTests extends Assertions { + + @Test + public void testFoo() throws Exception { + + try { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + FooRequest foo = FooRequest.builder() + .name("z") + .value(1) + .indices("a", "b", "c") + .bar(b -> b + .name("Raise the bar") + ) + .build(); + + JsonProvider provider = JsonpUtils.provider(); + JsonGenerator generator = provider.createGenerator(baos); + foo.serialize(generator, new JsonbJsonpMapper()); + + generator.close(); + String str = baos.toString(); + + assertEquals("{\"name\":\"z\",\"value\":1,\"indices\":[\"a\",\"b\",\"c\"],\"bar\":{\"name\":\"Raise the bar\"}}", str); + + JsonParser parser = provider.createParser(new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8))); + + FooRequest foo2 = FooRequest.parser().deserialize(parser, new JsonbJsonpMapper()); + + assertEquals(foo.name(), foo2.name()); + assertEquals(foo.value(), foo2.value()); + assertNull(foo2.size()); + assertEquals(foo.indices(), foo2.indices()); + assertEquals("Raise the bar", foo.bar().name()); + } catch (JsonParsingException je) { + throw new JsonParsingException(je.getMessage() + " at " + je.getLocation(), je, je.getLocation()); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/UnionVariant.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/UnionVariant.java new file mode 100644 index 000000000..34090cb9c --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/UnionVariant.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments; + +/** + * An implementation of a variant type. + */ +public interface UnionVariant { + + /** + * Get the type of this object when used as a variant + */ + Tag _variantType(); +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/Bar.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/Bar.java new file mode 100644 index 000000000..9d63ef63c --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/Bar.java @@ -0,0 +1,82 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.api; + +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import javax.annotation.Nullable; + +public class Bar implements JsonpSerializable { + + private final String name; + + @Nullable + public String name() { + return this.name; + } + + public Bar(Builder builder) { + this.name = builder.name; + } + + @Override + public void serialize(JsonGenerator builder, JsonpMapper mapper) { + builder.writeStartObject(); + if (this.name != null) builder.write("name", this.name); + builder.writeEnd(); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder implements ObjectBuilder { + private String name; + + public Builder name(@Nullable String name) { + this.name = name; + return this; + } + + public Bar build() { + return new Bar(this); + } + } + + private static final JsonpDeserializer PARSER; + + public static JsonpDeserializer parser() { + return PARSER; + } + + static { + ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); + + op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); + + PARSER = new ObjectBuilderDeserializer<>(op); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/DateMathTimeUnit.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/DateMathTimeUnit.java new file mode 100644 index 000000000..a03cbe1e2 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/DateMathTimeUnit.java @@ -0,0 +1,49 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.api; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializer; + +public enum DateMathTimeUnit implements JsonEnum { + + Year("Y"), + Month("M"), + Day("D"), + Hour("h"), + Minute("m"), + Second("s"); + + private final String jsonValue; + + DateMathTimeUnit(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonpDeserializer PARSER; + + static { + PARSER = new Deserializer<>(DateMathTimeUnit.values()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooOptRequest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooOptRequest.java new file mode 100644 index 000000000..7a4c4827a --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooOptRequest.java @@ -0,0 +1,276 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.api; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.endpoints.SimpleEndpoint; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.OptionalInt; + +import static java.util.Objects.requireNonNull; + +// Implementing ToXContent is optional, only if there's a request body +public class FooOptRequest implements JsonpSerializable { + + //=========================================== + // Fields and getters + //=========================================== + + //------------------------------------------- + // A required String + + private final String name; + + @Nonnull + public final String name() { + return this.name; + } + + //------------------------------------------- + // An optional String + + private final String routing; + + @Nonnull + public final Optional routing() { + return Optional.ofNullable(this.routing); + } + + //------------------------------------------- + // A required primitive type + + private final int value; + + public int value() { + return this.value; + } + + //------------------------------------------- + // An optional primitive type + private final OptionalInt size; + + /** + * Description for field {@code size} + */ + @Nonnull + public final OptionalInt size() { + return this.size; + } + + //------------------------------------------- + // An optional array + + private final List indices; + + @Nonnull + public final Optional> indices() { + return Optional.ofNullable(this.indices); + } + + //------------------------------------------- + // An optional sub-object + + private final Bar bar; + + @Nonnull + public Optional bar() { + return Optional.ofNullable(this.bar); + } + + public FooOptRequest(Builder builder) { + this.name = builder.name; + this.routing = builder.routing; + this.value = builder.value; + this.size = builder.size == null ? OptionalInt.empty() : OptionalInt.of(builder.size); + this.indices = builder.indices; + this.bar = builder.bar; + } + + //=========================================== + // Serialization + //=========================================== + + + @Override + public void serialize(JsonGenerator builder, JsonpMapper mapper) { + builder.writeStartObject(); + + // Classic approach is to use the deserialization field's preferred name: + // + // if (buckets.isPresent()) builder.field(INT_FIELD.getPreferredName(), buckets.getAsInt()); + // + // In a generated code context we can use the string constant, which also avoids declaring ParseField if we + // only serialize (e.g. requests) + + // required field + builder.write("name", this.name); + + // optional field + if (this.routing != null) builder.write("routing", this.routing); + + // required field + builder.write("value", value); + + // optional field + if (this.size.isPresent()) builder.write("size", this.size.getAsInt()); + + // We could just call this and let the builder will handle it by itself with: + // + // if (this.indices != null) builder.field("indices", this.indices); + // + // But the logic is a bit involved (like checking circular dependencies) so we use a more direct implementation: + if (this.indices != null) { + builder.writeKey("indices").writeStartArray(); + for (String str : this.indices) builder.write(str); + builder.writeEnd(); + } + + if (this.bar != null) { + builder.writeKey("bar"); + this.bar.serialize(builder, mapper); + } + + builder.writeEnd(); + } + + //=========================================== + // Builder + //=========================================== + + public static Builder builder() { + return new Builder(); + } + + // Constructor with required fields + public static Builder builder(String name, int size) { + Builder result = new Builder(); + result.name(name); + result.size(size); + return result; + } + + public static class Builder implements ObjectBuilder { + private String name; + private String routing; + private int value; + private boolean value$isSet = false; + private Integer size; + private List indices; + private Bar bar; + + public final Builder name(@Nonnull String v) { + this.name = requireNonNull(v); + return this; + } + + public final Builder routing(@Nullable String v) { + this.routing = v; + return this; + } + + public final Builder value(int v) { + this.value = v; + this.value$isSet = true; + return this; + } + + public final Builder size(@Nullable Integer v) { + this.size = v; + return this; + } + + public final Builder indices(@Nullable List v) { + indices = v; + return this; + } + + // Convenience variant with varargs + public final Builder indices(String... v) { + indices = Arrays.asList(v); + return this; + } + + public Builder bar(@Nullable Bar v) { + bar = v; + return this; + } + + public Builder bar(@Nullable Bar.Builder v) { + bar = v.build(); + return this; + } + + public FooOptRequest build() { + requireNonNull(this.name, "Name was not set"); + requireTrue(this.value$isSet, "Value was not set"); + return new FooOptRequest(this); + } + } + + //=========================================== + // Deserialization + //=========================================== + +// // Only expose the most general interface to hide implementation details that may change over time. +// public static final ContextParser PARSER; +// +// static { +// ObjectParser op = +// new ObjectParser<>(FooOptRequest.class.getName(), FooOptRequest.Builder::new); +// +// op.declareString(Builder::name, new ParseField("name")); +// op.declareString(Builder::routing, new ParseField("routing")); +// +// op.declareInt(Builder::value, new ParseField("value")); +// op.declareInt(Builder::size, new ParseField("size")); +// +// op.declareStringArray(Builder::indices, new ParseField("indices")); +// op.declareObject(Builder::bar, Bar.PARSER, new ParseField("bar")); +// +// PARSER = new ObjectBuilderParser<>(op); +// } + + public static final Endpoint ENDPOINT = + new SimpleEndpoint( + "foo", + r -> "POST", + r -> "/foo", + SimpleEndpoint.emptyMap(), + SimpleEndpoint.emptyMap(), + SimpleEndpoint.emptyMap(), + true, + FooResponse.PARSER + ) { + }; + + public static void requireTrue(boolean v, String message) { + if (!v) throw new IllegalStateException(message); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooRequest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooRequest.java new file mode 100644 index 000000000..6c802c66a --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooRequest.java @@ -0,0 +1,315 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.api; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch.experiments.api.query2.Query; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.endpoints.SimpleEndpoint; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +import static java.util.Objects.requireNonNull; + +// Implementing ToXContent is optional, only if there's a request body +public class FooRequest implements JsonpSerializable { + + //=========================================== + // Fields and getters + //=========================================== + + //------------------------------------------- + // A required String + + private final String name; + + @Nonnull + public final String name() { + return this.name; + } + + //------------------------------------------- + // An optional String + + private final String routing; + + @Nullable + public final String routing() { + return this.routing; + } + + //------------------------------------------- + // A required primitive type + + private final int value; + + public int value() { + return this.value; + } + + //------------------------------------------- + // An optional primitive type, represented as a nullable boxed value + + private final Integer size; + + /** + * Description for field {@code size} + */ + @Nullable + public final Integer size() { + return this.size; + } + + //------------------------------------------- + // An optional array + + private final List indices; + + /** + * A string[] property + */ + @Nullable + public final List indices() { + return this.indices; + } + + //------------------------------------------- + // An optional sub-object + + private final Bar bar; + + @Nullable + public Bar bar() { + return this.bar; + } + + //------------------------------------------- + // An optional query + + private final Query query; + + @Nullable + public Query query() { + return this.query; + } + + //------------------------------------------- + + public FooRequest(Builder builder) { + this.name = builder.name; + this.routing = builder.routing; + this.value = builder.value; + this.size = builder.size; + this.indices = builder.indices; + this.bar = builder.bar; + this.query = builder.query; + } + + + //=========================================== + // Builder + //=========================================== + + public static class Builder implements ObjectBuilder { + protected String name; + protected String routing; + protected int value; + protected boolean value$isSet = false; + protected Integer size; + protected List indices; + protected Bar bar; + protected Query query; + + public final Builder name(@Nonnull String v) { + this.name = requireNonNull(v); + return this; + } + + public final Builder routing(String v) { + this.routing = v; + return this; + } + + public final Builder value(int v) { + this.value = v; + this.value$isSet = true; + return this; + } + + public final Builder size(@Nullable Integer v) { + this.size = v; + return this; + } + + public final Builder indices(@Nullable List v) { + indices = v; + return this; + } + + // Convenience variant with varargs + public final Builder indices(String... v) { + indices = Arrays.asList(v); + return this; + } + + public Builder bar(@Nullable Bar v) { + bar = v; + return this; + } + + public Builder bar(Function> b) { + return bar(b.apply(new Bar.Builder()).build()); + } + + public Builder query(Query v) { + this.query = v; + return this; + } + + public Builder query(Function> b) { + return query(b.apply(new Query.Builder()).build()); + } + + public FooRequest build() { + requireNonNull(this.name, "'name' was not set"); + requireTrue(this.value$isSet, "'value' was not set"); + return new FooRequest(this); + } + } + + public static Builder builder() { + return new Builder(); + } + + // Constructor with required fields + public static Builder builder(String name, int size) { + Builder result = new Builder(); + result.name(name); + result.size(size); + return result; + } + + //=========================================== + // Serialization + //=========================================== + + @Override + public void serialize(JsonGenerator builder, JsonpMapper mapper) { + builder.writeStartObject(); + + // Classic approach is to use the deserialization field's preferred name: + // + // if (buckets.isPresent()) builder.field(INT_FIELD.getPreferredName(), buckets.getAsInt()); + // + // In a generated code context we can use the string constant, which also avoids declaring ParseField if we + // only serialize (e.g. requests) + + // required field + builder.write("name", this.name); + + // optional field + if (this.routing != null) builder.write("routing", this.routing); + + // required field + builder.write("value", value); + + // optional field + if (this.size != null) builder.write("size", this.size.intValue()); + + // We could just call this and let the builder will handle it by itself with: + // + // if (this.indices != null) builder.field("indices", this.indices); + // + // But the logic is a bit involved (like checking circular dependencies) so we use a more direct implementation: + if (this.indices != null) { + builder.writeKey("indices").writeStartArray(); + for (String str : this.indices) builder.write(str); + builder.writeEnd(); + } + + if (this.bar != null) { + builder.writeKey("bar"); + this.bar.serialize(builder, mapper); + } + + if (this.query != null) { + builder.writeKey("query"); + this.query.serialize(builder, mapper); + } + + builder.writeEnd(); + } + + //=========================================== + // Deserialization + // (formally not needed for requests) + //=========================================== + + private static final JsonpDeserializer PARSER; + + public static JsonpDeserializer parser() { + return PARSER; + } + + static { + ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); + + op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); + op.add(Builder::routing, JsonpDeserializer.stringDeserializer(), "routing"); + op.add(Builder::value, "value"); // primitive type + op.add(Builder::size, "size"); + op.add(Builder::indices, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), "indices"); + op.add(Builder::bar, Bar.parser(), "bar"); + op.add(Builder::query, Query.parser(), "query"); + + PARSER = new ObjectBuilderDeserializer<>(op); + } + + //=========================================== + // Endpoint + //=========================================== + + public static final Endpoint ENDPOINT = + new SimpleEndpoint<>( + "foo", + r -> "POST", + r -> "/foo", + SimpleEndpoint.emptyMap(), + SimpleEndpoint.emptyMap(), + SimpleEndpoint.emptyMap(), + true, + FooResponse.PARSER + ); + + public static void requireTrue(boolean v, String message) { + if (!v) throw new IllegalStateException(message); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooResponse.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooResponse.java new file mode 100644 index 000000000..ffd5369db --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/FooResponse.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.api; + +import co.elastic.clients.json.JsonpDeserializer; + +public class FooResponse { + + public static JsonpDeserializer PARSER = null; +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/BoolQuery.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/BoolQuery.java new file mode 100644 index 000000000..73d47f3b3 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/BoolQuery.java @@ -0,0 +1,173 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.api.query2; + +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.function.Function; + +public class BoolQuery implements Query.Variant, JsonpSerializable { + + private final Collection should; + private final Collection must; + private final Union2 minimumShouldMatch; + + public BoolQuery(Builder builder) { + this.should = builder.should; + this.must = builder.must; + this.minimumShouldMatch = builder.minimumShouldMatch; + } + + @Override + public Query.Kind _variantType() { + return Query.Kind.Bool; + } + + public Collection should() { + return should; + } + + public Collection must() { + return must; + } + + public Union2 minimumShouldMatch() { + return minimumShouldMatch; + } + + @Override + public void serialize(JsonGenerator builder, JsonpMapper mapper) { + builder.writeStartObject(); + + if (should != null) { + builder.writeKey("should"); + builder.writeStartArray(); + for (Query v: should) v.serialize(builder, mapper); + builder.writeEnd(); + } + + if (should != null) { + builder.writeKey("must"); + builder.writeStartArray(); + for (Query v: must) v.serialize(builder, mapper); + builder.writeEnd(); + } + + if (minimumShouldMatch != null) { + builder.writeKey("minimum_should_match"); + // Unions have to be expanded inline as serialization depends on the value type. + this.minimumShouldMatch.serialize(builder, mapper, + (v, b, p) -> builder.write(v), + (v, b, p) -> builder.write(v) + ); + } + + builder.writeEnd(); + } + + public static class Builder implements ObjectBuilder { + + private Collection should; + private Collection must; + private Union2 minimumShouldMatch; + + public Builder should(Collection v) { + this.should = v; + return this; + } + + public Builder add_should(@Nullable Query v) { + if (v == null) return this; + if (this.should == null) this.should = new ArrayList<>(); + this.should.add(v); + return this; + } + + public Builder add_should(Function> v) { + return add_should(v.apply(new Query.Builder()).build()); + } + + public Builder must(Collection v) { + this.must = v; + return this; + } + + public Builder add_must(@Nullable Query v) { + if (v == null) return this; + if (this.must == null) this.must = new ArrayList<>(); + this.must.add(v); + return this; + } + + public Builder add_must(Function> v) { + return add_must(v.apply(new Query.Builder()).build()); + } + + // Expand all union members + // TODO: check unions with nested structures and fluent builders + public Builder minimumShouldMatch(int v) { + return minimumShouldMatch(Union2.ofA(v)); + } + + public Builder minimumShouldMatch(String v) { + return minimumShouldMatch(Union2.ofB(v)); + } + + public Builder minimumShouldMatch(Union2 v) { + this.minimumShouldMatch = v; + return this; + } + + @Override + public BoolQuery build() { + return new BoolQuery(this); + } + } + + private static final JsonpDeserializer PARSER; + + public static JsonpDeserializer parser() { + return PARSER; + } + + static { + ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); + + op.add(Builder::must, JsonpDeserializer.arrayDeserializer(Query.parser()), "must"); + op.add(Builder::should, JsonpDeserializer.arrayDeserializer(Query.parser()), "should"); + + op.add(Builder::minimumShouldMatch, new Union2.JsonpParser<>( + JsonpDeserializer.integerDeserializer(), + JsonpDeserializer.stringDeserializer() + ), "minimum_should_match"); + + PARSER = new ObjectBuilderDeserializer<>(op); + } + +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/Query.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/Query.java new file mode 100644 index 000000000..d1ae929ba --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/Query.java @@ -0,0 +1,205 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.api.query2; + +import co.elastic.clients.elasticsearch.experiments.UnionVariant; +import co.elastic.clients.json.BuildFunctionDeserializer; +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.TaggedUnion; +import co.elastic.clients.util.TaggedUnionUtils; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonGenerator; + +import java.util.Map; +import java.util.function.Function; + +public class Query implements TaggedUnion, JsonpSerializable { + + public interface Variant extends UnionVariant, JsonpSerializable { + default Query _toQuery() { + return new Query(this); + } + } + + public enum Kind implements JsonEnum { + Bool("bool"), + Terms("terms"); + + private final String jsonValue; + + Kind(String jsonValue) { + this.jsonValue = jsonValue; + } + + @Override + public String jsonValue() { + return null; + } + } + + private static final String BOOL = "bool"; + private static final String TERMS = "terms"; + + private final Kind _variantType; + private final Variant _variantValue; + + @Override + public Kind _kind() { + return _variantType; + } + + @Override + public Variant _get() { + return _variantValue; + } + + // A container-level property that lives besides the variant, like "meta" and "aggs" in aggregations + private Map meta; + + public Query(Variant value) { + this._variantType = value._variantType(); + this._variantValue = value; + } + + private Query(Builder builder) { + this._variantType = builder.$tag; + this._variantValue = builder.$variant; + + this.meta = builder.meta; + } + + // Accessors to container properties + public Map meta() { + return this.meta; + } + + public BoolQuery bool() { + return TaggedUnionUtils.get(this, Kind.Bool); + } + + public TermsQuery terms() { + return TaggedUnionUtils.get(this, Kind.Terms); + } + + @Override + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + generator.writeKey(_variantType.jsonValue); + if (_variantValue instanceof JsonpSerializable) { + ((JsonpSerializable) _variantValue).serialize(generator, mapper); + } else { + // Other serialization + } + if (meta != null) { + generator.writeStartObject("meta"); + for (Map.Entry e: meta.entrySet()) { + generator.write(e.getKey(), e.getValue()); + } + generator.writeEnd(); + } + generator.writeEnd(); + } + + public static class Builder { + + private Variant $variant; + private Kind $tag; + private Map meta; + + // Container properties + public Builder meta(Map value) { + this.meta = value; + return this; + } + + // Variants + // + // We return a container builder and not a builder. This is because a union accepts a single variant and we + // don't want to allow choosing more than one yet we still want to be able to set container-level properties + + public ContainerBuilder bool(BoolQuery v) { + this.$variant = v; + this.$tag = Kind.Bool; + return new ContainerBuilder(); + } + + // If we don't have container properties, the container builder is not necessary + public ObjectBuilder foo() { + return this::build; + } + + public ContainerBuilder bool(Function> f) { + return this.bool(f.apply(new BoolQuery.Builder()).build()); + } + + public ContainerBuilder terms(TermsQuery v) { + this.$variant = v; + this.$tag = Kind.Terms; + return new ContainerBuilder(); + } + + public ContainerBuilder terms(Function> f) { + return this.terms(f.apply(new TermsQuery.Builder()).build()); + } + + // Protected, only called by the container + protected Query build() { + return new Query(this); + } + + /** + * A builder that only contains container-level properties. If we don't have such properties, this + * can be replaced with an {@code ObjectBuilder} + */ + public class ContainerBuilder implements ObjectBuilder { + + public ContainerBuilder meta(Map value) { + Builder.this.meta(value); + return this; + } + + public Query build() { + return Builder.this.build(); + } + } + } + + private static volatile JsonpDeserializer PARSER; + + public static JsonpDeserializer parser() { + if (PARSER == null) { + ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); + op.add(Builder::bool, BoolQuery.parser(), "bool"); + op.add(Builder::terms, TermsQuery.parser(), "terms"); + // parser for "meta" (a map) + + PARSER = new BuildFunctionDeserializer<>(op, Builder::build); + } + + return PARSER; + } + + +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/QueryTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/QueryTest.java new file mode 100644 index 000000000..313905268 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/QueryTest.java @@ -0,0 +1,44 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.api.query2; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Collection; + +public class QueryTest extends Assertions { + @Test + public void testQuery() { + BoolQuery bq = new BoolQuery.Builder().build(); + + Query q = new Query(bq); + + assertEquals(Query.Kind.Bool, q._kind()); + + Query.Variant v = q._get(); + assertEquals(Query.Kind.Bool, v._variantType()); + + Query q1 = v._toQuery(); + + Collection must = q.bool().must(); + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/TermsQuery.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/TermsQuery.java new file mode 100644 index 000000000..c7f4afca4 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/TermsQuery.java @@ -0,0 +1,107 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.api.query2; + +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +public class TermsQuery implements JsonpSerializable, Query.Variant { + + private final String field; + private final String term; + + public TermsQuery(Builder builder) { + this.field = builder.field; + this.term = builder.term; + } + + @Override + public Query.Kind _variantType() { + return Query.Kind.Terms; + } + + public String field() { + return this.field; + } + + public String term() { + return this.term; + } + + @Override + public void serialize(JsonGenerator builder, JsonpMapper mapper) { + // We only serialize our content. It's the enclosing class responsibility to output the variant's discriminant. + // This allows using this class in non-variant contexts. + builder.writeStartObject(); + if (this.field != null) { + builder.write("field", this.field); + } + + if (this.term != null) { + builder.write("term", this.term); + } + + builder.writeEnd(); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder implements ObjectBuilder { + + private String field; + private String term; + + public Builder field(String v) { + this.field = v; + return this; + } + + public Builder term(String v) { + this.term = v; + return this; + } + + @Override + public TermsQuery build() { + return new TermsQuery(this); + } + } + + private static final JsonpDeserializer PARSER; + + public static JsonpDeserializer parser() { + return PARSER; + } + + static { + ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); + op.add(Builder::field, JsonpDeserializer.stringDeserializer(), "field"); + op.add(Builder::term, JsonpDeserializer.stringDeserializer(), "term"); + + PARSER = new ObjectBuilderDeserializer<>(op); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/Union2.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/Union2.java new file mode 100644 index 000000000..004c1703a --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/api/query2/Union2.java @@ -0,0 +1,154 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.api.query2; + +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpDeserializerBase; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.util.TriConsumer; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParser.Event; +import jakarta.json.stream.JsonParsingException; + +/** + * A tagged union (also known as variant, sum type or coproduct) with two members. + * + * The union's value is one (and only one) of the possible variants. The variant in use is defined by the + * {@link #tag()}'s value. + * + * @param type of the first variant + * @param type of the second variant + */ + +// Design note: we cannot require A and B, and by extension Union2, to implement JsonpSerializable as they can be builtin types +// like String or Integer + +public class Union2 { + + /** + * The variant tag. + */ + public enum Tag{A, B}; + + private final Tag tag; + private final Object value; + + private Union2(Tag tag, Object value) { + this.tag = tag; + this.value = value; + } + + /** + * Creates a variant {@code A}. + */ + public static Union2 ofA(A value) { + return new Union2<>(Tag.A, value); + } + + /** + * Creates a variant {@code B}. + */ + public static Union2 ofB(B value) { + return new Union2<>(Tag.B, value); + } + + /** + * Get the variant's tag of this union. + * + * @return the variant's tag + */ + public Tag tag() { + return tag; + } + + /** + * Get the variant {@code A} of this union. + * + * @return the variant's value + * @throws IllegalStateException if the union is not holding a variant {@code A} + */ + public A a() { + return getVariant(Tag.A); + } + + /** + * Get the variant {@code B} of this union. + * + * @return the variant's value + * @throws IllegalStateException if the union is not holding a variant {@code B} + */ + public B b() { + return getVariant(Tag.B); + } + + private T getVariant(Tag tag) { + if (this.tag != tag) throw new IllegalStateException("Union holds variant " + tag); + + @SuppressWarnings("unchecked") + T result = (T)value; + + return result; + } + + //----------------------------------------------------------------------------------------------- + // Serialization / deserialization + + public void serialize( + JsonGenerator builder, JsonpMapper params, + TriConsumer a, + TriConsumer b + ) { + switch (this.tag) { + case A: + a.accept(this.a(), builder, params); + case B: + b.accept(this.b(), builder, params); + } + } + + public static class JsonpParser extends JsonpDeserializerBase> { + + private final JsonpDeserializer parserA; + private final JsonpDeserializer parserB; + + public JsonpParser( + JsonpDeserializer parserA, + JsonpDeserializer parserB + ) { + super(allAcceptedEvents(parserA, parserB)); + this.parserA = parserA; + this.parserB = parserB; + } + + @Override + public Union2 deserialize(JsonParser parser, JsonpMapper mapper, Event event) { + if (parserA.accepts(event)) { + return Union2.ofA(parserA.deserialize(parser, mapper, event)); + + } else if (parserB.accepts(event)) { + return Union2.ofB(parserB.deserialize(parser, mapper, event)); + + } else { + throw new JsonParsingException("Unexpected event '" + event + "'", parser.getLocation()); + } + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/Client.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/Client.java new file mode 100644 index 000000000..f67b25981 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/Client.java @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.base; + +import co.elastic.clients.elasticsearch.experiments.api.FooRequest; +import co.elastic.clients.elasticsearch.experiments.api.FooResponse; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.Transport; +import co.elastic.clients.util.ObjectBuilder; + +import java.io.IOException; +import java.util.function.Function; + +public class Client { + + private Transport transport; + + public FooResponse foo(FooRequest request) throws IOException { + return performRequest(request, FooRequest.ENDPOINT); + } + + public FooResponse foo(Function> b) throws IOException { + return foo(b.apply(new FooRequest.Builder()).build()); + } + + protected ResponseT performRequest( + RequestT request, Endpoint endpoint + ) throws IOException { + return transport.performRequest(request, endpoint, null); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/PrimitiveUtils.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/PrimitiveUtils.java new file mode 100644 index 000000000..a9e95d9a3 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/PrimitiveUtils.java @@ -0,0 +1,41 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.base; + +/** + * Support functions for primitive fields in generated classes + */ +public class PrimitiveUtils { + public static int checkedValue(int value, boolean isSet) { + mustBeSet(isSet); + return value; + } + + public static long checkedValue(long value, boolean isSet) { + mustBeSet(isSet); + return value; + } + + private static void mustBeSet(boolean isSet) { + if (!isSet) { + throw new IllegalStateException("Value is not set"); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/Variants.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/Variants.java new file mode 100644 index 000000000..6edd823a9 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/base/Variants.java @@ -0,0 +1,155 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.base; + +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParsingException; + +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + +/** + * Describes the variants of a transport class, providing their name and parsers. It is representation-agnostic. + */ +public class Variants { + + private Function, Builder> builderFunc; + + private Map, String> variantNames; + private Map> parsers; + + /** + * Builds a new {@code Variants} from a builder-creation function. This approach allows the object to be built lazily, + * which is needed for recursive variant data structures (e.g. a query can be a boolean query that itself contains + * other queries). + * + * This is required because cyclic dependencies between static class initialization code can lead to unexpected + * behaviour (a subclass static init may be called while static init of the parent class is not finished). + */ + public Variants(Function, Builder> b) { + this.builderFunc = b; + } + + public Variants(Builder builder) { + this.variantNames = builder.variantNames; + this.parsers = builder.parsers; + } + + public String variantName(Class clazz) { + build(); + return variantNames.get(clazz); + } + + public JsonpDeserializer variantParser(String name) { + build(); + return parsers.get(name); + } + + private void build() { + if (builderFunc != null) { + Builder builder = builderFunc.apply(new Builder<>()); + this.variantNames = builder.variantNames; + this.parsers = builder.parsers; + this.builderFunc = null; + } + } + + //------------------------------------------------------------------------------------------------------------------- + + public static Builder builder() { + return new Builder<>(); + } + + public static class Builder { + private final Map, String> variantNames = new HashMap<>(); + private final Map> parsers = new HashMap<>(); + + public Builder add(String name, Class clazz, JsonpDeserializer parser) { + variantNames.put(clazz, name); + parsers.put(name, parser); + return this; + } + + public Variants build() { + return new Variants<>(this); + } + } + + //------------------------------------------------------------------------------------------------------------------- + + /** + * Variant serializer/deserializer using externally tagged JSON. + *

+ * See Enumerations in Serde.rs that clearly explains the + * various strategies to represent polymorphic values in JSON. + */ + public static class ExternallyTagged { + + /** + * Creates a parser for externally tagged variants + */ + public static JsonpDeserializer pparser(Variants variants) { + return JsonpDeserializer.of(EnumSet.of(JsonParser.Event.START_OBJECT), (parser, params) -> { + JsonpUtils.expectNextEvent(parser, JsonParser.Event.START_OBJECT); + JsonpUtils.expectNextEvent(parser, JsonParser.Event.KEY_NAME); + + String variant = parser.getString(); + JsonpDeserializer variantParser = variants.variantParser(variant); + + if (variantParser == null) { + throw new JsonParsingException("Unknown variant '" + variant + "'", parser.getLocation()); + } + + T result = variantParser.deserialize(parser, params); + + JsonpUtils.expectNextEvent(parser, JsonParser.Event.END_OBJECT); + + return result; + }); + } + + /** + * Serializes an externally tagged variant object + */ + + public static void serialize( + Variants variants, T v, JsonGenerator builder, JsonpMapper mapper + ) { + @SuppressWarnings("unchecked") + String variant = variants.variantName((Class)v.getClass()); + + if (variant == null) { + throw new IllegalArgumentException("No variant name found for " + v.getClass().getName()); + } + + builder.writeStartObject(); + builder.writeKey(variant); + v.serialize(builder, mapper); + builder.writeEnd(); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnion.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnion.java new file mode 100644 index 000000000..9130b960e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnion.java @@ -0,0 +1,152 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.containers; +/* + // @variants internal tag='type' + interface SomeUnion = UnionItemA | UnionItemB; + + interface VariantA { + type: 'variant_a' + variant_a_prop: String + } + + interface VariantB { + type: 'variant_b' + variant_b_prop: String + } +*/ + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.TaggedUnion; +import co.elastic.clients.util.TaggedUnionUtils; +import jakarta.json.stream.JsonGenerator; + +import java.util.function.Function; + +@JsonpDeserializable +public class SomeUnion implements TaggedUnion, JsonpSerializable { + + public enum Kind implements JsonEnum { + VariantA("variant_a"), + VariantB("variant_b"); + + private final String jsonValue; + + Kind(String jsonValue) { + this.jsonValue = jsonValue; + } + + @Override + public String jsonValue() { + return null; + } + } + + private final SomeUnionVariant _value; + private final Kind _type; + + public SomeUnion(Builder builder) { + this._value = builder._value; + this._type = builder._type; + } + + @Override + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + // Delegate to the variant object + if (_value instanceof JsonpSerializable) { + ((JsonpSerializable)_value).serialize(generator, mapper); + } + } + + @Override + public Kind _kind() { + return _type; + } + + @Override + public SomeUnionVariant _get() { + return _value; + } + + public UVariantA variantA() { + return TaggedUnionUtils.get(this, Kind.VariantA); + } + + public UVariantB variantB() { + return TaggedUnionUtils.get(this, Kind.VariantB); + } + + static class Builder { + + private SomeUnionVariant _value; + private Kind _type; + + // This "builder" doesn't allow building objects. It only contains methods to set a variant. + // These methods return a builder class with no other methods. This enforces the choice of one and only one + // variant at the type level (i.e. at compile time). + + // variant_a + + public ObjectBuilder variantA(UVariantA value) { + this._value = value; + this._type = Kind.VariantA; + final SomeUnion result = build(); + return () -> result; + } + + public ObjectBuilder variantA(Function fn) { + return this.variantA(fn.apply(new UVariantA.Builder()).build()); + } + + // variant_b + + public ObjectBuilder variantB(UVariantB value) { + this._value = value; + this._type = Kind.VariantB; + final SomeUnion result = build(); + return () -> result; + } + + public ObjectBuilder variantB(Function fn) { + return this.variantB(fn.apply(new UVariantB.Builder()).build()); + } + + protected SomeUnion build() { + return new SomeUnion(this); + } + } + + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + SomeUnion::setupSomeUnionDeserializer, Builder::build); + + protected static void setupSomeUnionDeserializer(ObjectDeserializer op) { + op.add(Builder::variantA, UVariantA._DESERIALIZER, "variant_a"); + op.add(Builder::variantB, UVariantB._DESERIALIZER, "variant_b"); + + op.setTypeProperty("type", null); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnionTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnionTest.java new file mode 100644 index 000000000..c257b9cc0 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnionTest.java @@ -0,0 +1,84 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.containers; + +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParsingException; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; +import java.io.StringReader; + +public class SomeUnionTest extends ModelTestCase { + + SomeUnion su = new SomeUnion.Builder() + .variantA(a_ -> a_ + .name("a-name") + ).build(); + + String json = "{\"type\":\"variant_a\",\"name\":\"a-name\"}"; + + @Test + public void testContainerBuilder() { + assertEquals("a-name", su.variantA().name()); + } + + @Test + public void testDeserialization() { + SomeUnion u = fromJson(json, SomeUnion.class); + UVariantA uVariantA = u.variantA(); + assertEquals("a-name", uVariantA.name()); + } + + @Test + public void testSerialization() { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonProvider provider = JsonpUtils.provider(); + JsonGenerator generator = provider.createGenerator(baos); + + su.serialize(generator, new JsonbJsonpMapper()); + generator.close(); + + System.out.println(baos.toString()); + + assertEquals(json, baos.toString()); + + } + + @Test + public void testMissingVariantDeserialization() { + String json = "{}"; + + JsonProvider provider = JsonpUtils.provider(); + JsonParser parser = provider.createParser(new StringReader(json)); + + JsonParsingException e = assertThrows(JsonParsingException.class, () -> { + SomeUnion c = SomeUnion._DESERIALIZER.deserialize(parser, new JsonbJsonpMapper()); + }); + + assertTrue(e.getMessage().contains("Property 'type' not found")); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnionVariant.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnionVariant.java new file mode 100644 index 000000000..2bb9ee595 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnionVariant.java @@ -0,0 +1,25 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.containers; + +import co.elastic.clients.elasticsearch.experiments.UnionVariant; + +public interface SomeUnionVariant extends UnionVariant { +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/UVariantA.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/UVariantA.java new file mode 100644 index 000000000..1deb48e08 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/UVariantA.java @@ -0,0 +1,82 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.containers; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import javax.annotation.Nullable; + +@JsonpDeserializable +public class UVariantA implements SomeUnionVariant, JsonpSerializable { + + private final String name; + + @Override + public String _variantType() { + return "variant_a"; + } + + @Nullable + public String name() { + return this.name; + } + + public UVariantA(Builder builder) { + this.name = builder.name; + } + + @Override + public void serialize(JsonGenerator builder, JsonpMapper mapper) { + builder.writeStartObject(); + // Write variant value + builder.write("type", _variantType()); + if (this.name != null) builder.write("name", this.name); + builder.writeEnd(); + } + + public static class Builder implements ObjectBuilder { + private String name; + + public Builder name(@Nullable String name) { + this.name = name; + return this; + } + + public UVariantA build() { + return new UVariantA(this); + } + } + + public static final JsonpDeserializer _DESERIALIZER; + + static { + ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); + op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); + op.ignore("type"); + _DESERIALIZER = new ObjectBuilderDeserializer<>(op); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/UVariantB.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/UVariantB.java new file mode 100644 index 000000000..36b91b092 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/UVariantB.java @@ -0,0 +1,82 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.containers; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import javax.annotation.Nullable; + +@JsonpDeserializable +public class UVariantB implements SomeUnionVariant, JsonpSerializable { + + private final Integer number; + + @Override + public String _variantType() { + return "variant_a"; + } + + @Nullable + public Integer number () { + return this.number; + } + + public UVariantB(Builder builder) { + this.number = builder.number; + } + + @Override + public void serialize(JsonGenerator builder, JsonpMapper mapper) { + builder.writeStartObject(); + // Write variant value + builder.write("type", _variantType()); + if (this.number != null) builder.write("number", this.number); + builder.writeEnd(); + } + + public static class Builder implements ObjectBuilder { + private Integer number; + + public Builder number(@Nullable Integer number) { + this.number = number; + return this; + } + + public UVariantB build() { + return new UVariantB(this); + } + } + + public static final JsonpDeserializer _DESERIALIZER; + + static { + ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); + op.add(Builder::number, JsonpDeserializer.integerDeserializer(), "number"); + op.ignore("type"); + _DESERIALIZER = new ObjectBuilderDeserializer<>(op); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/generics/GenericClass.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/generics/GenericClass.java new file mode 100644 index 000000000..85d4de0c6 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/generics/GenericClass.java @@ -0,0 +1,123 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.generics; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpSerializer; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.endpoints.SimpleEndpoint; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import java.util.function.Supplier; + +public class GenericClass implements JsonpSerializable { + + // Serializers for generic parameters + private final JsonpSerializer genParamSerializer; + + // Properties + private final GenParam genParam; + + protected GenericClass(Builder builder) { + this.genParamSerializer = builder.genParamSerializer; + this.genParam = builder.genParam; + } + + public GenParam genParam() { + return this.genParam; + } + + @Override + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + generator.writeKey("genParam"); + JsonpUtils.serialize(genParam, generator, genParamSerializer, mapper); + generator.writeEnd(); + } + + public static class Builder implements ObjectBuilder> { + private GenParam genParam; + private JsonpSerializer genParamSerializer; + + /** + * Sets the JSON serializer for {@link GenParam} values. If not set, the client will try to find a suitable + * serializer in the {@link JsonpMapper} and will fail if none is found. + */ + // Internal generic parameters always call this method to avoid runtime lookup + public Builder genParamSerializer(JsonpSerializer value) { + this.genParamSerializer = value; + return this; + } + + public Builder genParam(GenParam value) { + this.genParam = value; + return this; + } + + @Override + public GenericClass build() { + return null; + } + } + + public static JsonpDeserializer> parser( + // A deserializer for each generic parameter + JsonpDeserializer getParamDeserializer + ) { + + return ObjectBuilderDeserializer.createForObject( + (Supplier>) Builder::new, + (op) -> GenericClass.setupParser(op, getParamDeserializer) + ); + } + + private static void setupParser(ObjectDeserializer> op, JsonpDeserializer deserializer) { + op.add(Builder::genParam, deserializer, "genParam"); + } + + + public static Endpoint, ErrorResponse> endpoint( + JsonpDeserializer genParamDeserializer + ) { + return new SimpleEndpoint<>( + "genclass", + // Request method + request -> "GET", + // Request path + request -> "/genclass", + // Path parameters + SimpleEndpoint.emptyMap(), + // Request parameters + SimpleEndpoint.emptyMap(), + // Headers + SimpleEndpoint.emptyMap(), + true, + GenericClass.parser(genParamDeserializer) + ); + } + +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/InheritanceTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/InheritanceTest.java new file mode 100644 index 000000000..ddd636af9 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/InheritanceTest.java @@ -0,0 +1,97 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.inheritance; + +import co.elastic.clients.elasticsearch.experiments.inheritance.child.ChildClass; +import co.elastic.clients.elasticsearch.experiments.inheritance.final_.FinalClass; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; +import java.io.StringReader; + +public class InheritanceTest extends Assertions { + + @Test + public void testSerialization() { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonProvider provider = JsonpUtils.provider(); + + FinalClass fc = new FinalClass.Builder() + // Start fields from the top of the hierarchy to test setter return values + .baseField("baseValue") + .childField("childValue") + .finalField("finalValue") + .build(); + + JsonGenerator generator = provider.createGenerator(baos); + fc.serialize(generator, new JsonbJsonpMapper()); + + generator.close(); + String str = baos.toString(); + + assertEquals("{\"baseField\":\"baseValue\",\"childField\":\"childValue\",\"finalField\":\"finalValue\"}", str); + + baos.reset(); + + ChildClass cc = new ChildClass.Builder() + // Start fields from the top of the hierarchy to test setter return values + .baseField("baseValue") + .childField("childValue") + .build(); + + generator = provider.createGenerator(baos); + cc.serialize(generator, new JsonbJsonpMapper()); + + generator.close(); + str = baos.toString(); + + assertEquals("{\"baseField\":\"baseValue\",\"childField\":\"childValue\"}", str); + } + + @Test + public void testDeserialization() { + JsonProvider provider = JsonpUtils.provider(); + + JsonParser parser = provider.createParser(new StringReader( + "{\"baseField\":\"baseValue\",\"childField\":\"childValue\",\"finalField\":\"finalValue\"}")); + + FinalClass fc = FinalClass.JSONP_PARSER.deserialize(parser, new JsonbJsonpMapper()); + + assertEquals("baseValue", fc.baseField()); + assertEquals("childValue", fc.childField()); + assertEquals("finalValue", fc.finalField()); + + + parser = provider.createParser(new StringReader( + "{\"baseField\":\"baseValue\",\"childField\":\"childValue\"}")); + + ChildClass cc = ChildClass.JSONP_PARSER.deserialize(parser, new JsonbJsonpMapper()); + + assertEquals("baseValue", cc.baseField()); + assertEquals("childValue", cc.childField()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/base/BaseClass.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/base/BaseClass.java new file mode 100644 index 000000000..7cb760dbd --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/base/BaseClass.java @@ -0,0 +1,77 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.inheritance.base; + +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectDeserializer; +import jakarta.json.stream.JsonGenerator; + +import java.util.Objects; + +/** + * An abstract transport class + */ +public abstract class BaseClass implements JsonpSerializable { + + private final String baseField; + + public BaseClass(AbstractBuilder builder) { + this.baseField = Objects.requireNonNull(builder.baseField, "baseField"); + } + + public String baseField() { + return this.baseField; + } + + @Override + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + toJsonpInternal(generator, mapper); + generator.writeEnd(); + } + + protected void toJsonpInternal(JsonGenerator generator, JsonpMapper mapper) { + generator.write("baseField", this.baseField); + } + + //--------------------------------------------------------------------------------------------- + + // This is class protected as it's only of interest to subclasses. Yet public members are visible + // from the outside on public subclasses. + protected abstract static class AbstractBuilder> { + + private String baseField; + + public T baseField(String value) { + this.baseField = value; + return self(); + } + + protected abstract T self(); + } + + //--------------------------------------------------------------------------------------------- + + protected static > void setupBaseClassParser(ObjectDeserializer op) { + op.add(AbstractBuilder::baseField, JsonpDeserializer.stringDeserializer(), "baseField"); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/child/ChildClass.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/child/ChildClass.java new file mode 100644 index 000000000..a8d967896 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/child/ChildClass.java @@ -0,0 +1,93 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.inheritance.child; + +import co.elastic.clients.elasticsearch.experiments.inheritance.base.BaseClass; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import java.util.Objects; + +/** + * A concrete class that both inherits a parent class and has child classes + */ +public class ChildClass extends BaseClass implements JsonpSerializable { + + private final String childField; + + public ChildClass(AbstractBuilder builder) { + super(builder); + this.childField = Objects.requireNonNull(builder.childField, "childField"); + } + + public String childField() { + return this.childField; + } + + @Override + protected void toJsonpInternal(JsonGenerator generator, JsonpMapper params) { + super.toJsonpInternal(generator, params); + generator.write("childField", this.childField); + } + + //--------------------------------------------------------------------------------------------- + + protected abstract static class AbstractBuilder> extends BaseClass.AbstractBuilder { + + private String childField; + + public T childField(String value) { + this.childField = value; + return self(); + } + } + + // We cannot use AbstractBuilder directly, as it would cause a signature clash with subclasses on build(). + // And even without it, the generic parameter on AbstractBuilder is an implementation detail of builder + // inheritance that isn't needed nor nice in user applications. + public static class Builder extends AbstractBuilder implements ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + @Override + public ChildClass build() { + return new ChildClass(this); + } + } + + //--------------------------------------------------------------------------------------------- + + protected static > void setupChildClassParser(ObjectDeserializer op) { + BaseClass.setupBaseClassParser(op); + op.add(AbstractBuilder::childField, JsonpDeserializer.stringDeserializer(), "childField"); + } + + public static final JsonpDeserializer JSONP_PARSER = ObjectBuilderDeserializer.createForObject( + Builder::new, ChildClass::setupChildClassParser + ); + +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/final_/FinalClass.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/final_/FinalClass.java new file mode 100644 index 000000000..e944f8346 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/final_/FinalClass.java @@ -0,0 +1,98 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.experiments.inheritance.final_; + +import co.elastic.clients.elasticsearch.experiments.inheritance.child.ChildClass; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import java.util.Objects; + +/** + * A concrete class that inherits a parent class but has no child classes + */ +public final class FinalClass extends ChildClass { + + private final String finalField; + + public FinalClass(Builder builder) { + super(builder); + this.finalField = Objects.requireNonNull(builder.finalField, "finalField"); + } + + public String finalField() { + return this.finalField; + } + + @Override + protected void toJsonpInternal(JsonGenerator generator, JsonpMapper mapper) { + super.toJsonpInternal(generator, mapper); + generator.write("finalField", this.finalField); + } + + //--------------------------------------------------------------------------------------------- + + public static class Builder + extends AbstractBuilder + implements ObjectBuilder { + + private String finalField; + + public Builder finalField(String value) { + this.finalField = value; + return self(); + } + + @Override + protected Builder self() { + return this; + } + + @Override + public FinalClass build() { + return new FinalClass(this); + } + } + + //--------------------------------------------------------------------------------------------- + + private static void setupFinalClassParser(ObjectDeserializer op) { + ChildClass.setupChildClassParser(op); + op.add(Builder::finalField, JsonpDeserializer.stringDeserializer(), "finalField"); + } + + // Static methods cannot hide other static methods with a different return type or the same erased signature. + // Two possible solutions: + // - use different names, but having SomeClass.someClassParser() has some redundancy in the name + // - use a static field, as a static field can hide a static field of a different type in the parent class + // + // Our choice is to use different names for protected/private parser setup methods are they are hidden from + // the user and use a static field for the final parser, so that we can uniformly write SomeClass.PARSER + // (even if users should rarely have to interact directly with the parser). + + public static final JsonpDeserializer JSONP_PARSER = ObjectBuilderDeserializer.createForObject( + Builder::new, FinalClass::setupFinalClassParser + ); + +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/package-info.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/package-info.java new file mode 100644 index 000000000..05c034865 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ + +/** + * Experiments for the design of high-level client classes and usage illustration of the XContent-related classes. + */ +package co.elastic.clients.elasticsearch.experiments; diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/BuiltinTypesTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/BuiltinTypesTest.java new file mode 100644 index 000000000..ed9d57382 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/BuiltinTypesTest.java @@ -0,0 +1,273 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.FieldValue; +import co.elastic.clients.elasticsearch._types.SortOptions; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.aggregations.StatsAggregate; +import co.elastic.clients.elasticsearch._types.aggregations.StringStatsAggregate; +import co.elastic.clients.elasticsearch._types.query_dsl.SpanGapQuery; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.indices.IndexRoutingAllocationDisk; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.testkit.ModelTestCase; +import jakarta.json.stream.JsonParser; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; +import java.util.List; + +public class BuiltinTypesTest extends ModelTestCase { + + @Test + public void testPrimitiveTypes() { + + assertGetterType(Integer.class, SearchRequest.class, "size"); + + // Lenient boolean: 'threshold_enabled'?: boolean | string + assertGetterType(Boolean.class, IndexRoutingAllocationDisk.class, "thresholdEnabled"); + + } + + @Test + public void testLenientArray() { + // index: Indices --> type Indices = IndexName | IndexName[] + assertGetterType(List.class, SearchRequest.class, "index"); + } + + @Test + public void testNullArrayItem() { + // See https://github.com/elastic/elasticsearch-java/issues/66 + + String json = "[\"a\", null, \"c\"]"; + + // Types that don't accept null events should end up as null values in the list + { + JsonpDeserializer stringDeser = JsonpDeserializer.stringDeserializer(); + assertFalse(stringDeser.accepts(JsonParser.Event.VALUE_NULL)); + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + + List stringList = JsonpDeserializer.arrayDeserializer(stringDeser).deserialize(parser, mapper); + assertEquals("a", stringList.get(0)); + assertNull(stringList.get(1)); + assertEquals("c", stringList.get(2)); + } + + // Types that do accept null events should end up as their null representation + { + assertTrue(FieldValue._DESERIALIZER.accepts(JsonParser.Event.VALUE_NULL)); + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + List valueList = JsonpDeserializer.arrayDeserializer(FieldValue._DESERIALIZER).deserialize(parser, mapper); + + assertEquals("a", valueList.get(0)._get()); + assertTrue(valueList.get(1).isNull()); + assertEquals("c", valueList.get(2)._get()); + } + } + + @Test + public void testSpanGapQuery() { + // Hand-written class + SpanGapQuery q = SpanGapQuery.of(b -> b + .field("a-field") + .spanWidth(12) + ); + + q = checkJsonRoundtrip(q, "{\"a-field\":12}"); + + assertEquals("a-field", q.field()); + assertEquals(12, q.spanWidth()); + } + + @Test + public void testSortOptions() { + // Has a custom deserializer + // Examples: see https://www.elastic.co/guide/en/elasticsearch/reference/current/sort-search-results.html + + String json; + SortOptions sort; + + // Arbitrary field + sort = fromJson( + "{ \"post_date\" : {\"order\" : \"asc\", \"format\": \"strict_date_optional_time_nanos\"}}", + SortOptions.class); + + assertEquals("post_date", sort.field().field()); + assertEquals(SortOrder.Asc, sort.field().order()); + + sort = fromJson("{\n" + + " \"offer.price\" : {\n" + + " \"mode\" : \"avg\",\n" + + " \"order\" : \"asc\",\n" + + " \"nested\": {\n" + + " \"path\": \"offer\",\n" + + " \"filter\": {\n" + + " \"term\" : { \"offer.color\" : \"blue\" }\n" + + " }\n" + + " }\n" + + " }\n" + + " }", SortOptions.class); + + assertEquals("blue", sort.field().nested().filter().term().value().stringValue()); + + // Geo distance + sort = fromJson("{\n" + + " \"_geo_distance\" : {\n" + + " \"pin.location\" : {\n" + + " \"lat\" : 40,\n" + + " \"lon\" : -70\n" + + " },\n" + + " \"order\" : \"asc\",\n" + + " \"unit\" : \"km\"\n" + + " }\n" + + " }", SortOptions.class); + + assertEquals(40, sort.geoDistance().location().get(0).latlon().lat(), 0.1); + + // Simple string shortcuts + sort = fromJson("\"user\"", SortOptions.class); + assertEquals("user", sort.field().field()); + + sort = fromJson("\"_doc\"", SortOptions.class); + assertTrue(sort.isDoc()); + + sort = fromJson("\"_score\"", SortOptions.class); + assertTrue(sort.isScore()); + } + + @Test + public void testFieldValue() { + + FieldValue f; + + f = FieldValue.of(b -> b.nullValue()); + f = checkJsonRoundtrip(f, "null"); + assertTrue(f.isNull()); + assertEquals("null", f._toJsonString()); + + f = FieldValue.of(b -> b.doubleValue(1.23)); + f = checkJsonRoundtrip(f, "1.23"); + assertTrue(f.isDouble()); + assertEquals(1.23, f.doubleValue(), 0.01); + assertEquals("1.23", f._toJsonString()); + + f = FieldValue.of(b -> b.longValue(123)); + f = checkJsonRoundtrip(f, "123"); + assertTrue(f.isLong()); + assertEquals(123, f.longValue()); + assertEquals("123", f._toJsonString()); + + f = FieldValue.of(b -> b.booleanValue(true)); + f = checkJsonRoundtrip(f, "true"); + assertTrue(f.isBoolean()); + assertTrue(f.booleanValue()); + assertEquals("true", f._toJsonString()); + + f = FieldValue.of(b -> b.booleanValue(false)); + f = checkJsonRoundtrip(f, "false"); + assertTrue(f.isBoolean()); + assertFalse(f.booleanValue()); + assertEquals("false", f._toJsonString()); + + f = FieldValue.of(b -> b.stringValue("foo")); + f = checkJsonRoundtrip(f, "\"foo\""); + assertTrue(f.isString()); + assertEquals("foo", f.stringValue()); + assertEquals("foo", f._toJsonString()); + + } + + @Test + public void testNullableDouble() { + StatsAggregate stats; + + // Regular values + stats = StatsAggregate.statsAggregateOf(b -> b // Parent classes can't have an overloaded "of" method + .count(10) + .min(1.0) + .avg(1.5) + .max(2.0) + .sum(5.0) + ); + + stats = checkJsonRoundtrip(stats, "{\"count\":10,\"min\":1.0,\"max\":2.0,\"avg\":1.5,\"sum\":5.0}"); + assertEquals(10, stats.count()); + assertEquals(1.0, stats.min(), 0.01); + assertEquals(1.5, stats.avg(), 0.01); + assertEquals(2.0, stats.max(), 0.01); + assertEquals(5.0, stats.sum(), 0.01); + + // Missing values (Java mapping same as json) + String json = "{\"count\":0,\"min\":null,\"max\":null,\"avg\":0.0,\"sum\":0.0}"; + stats = fromJson(json, StatsAggregate.class); + + assertEquals(0, stats.count()); + assertEquals(null, stats.min()); + assertEquals(0.0, stats.avg(), 0.01); + assertEquals(null, stats.max()); + assertEquals(0.0, stats.sum(), 0.01); + + // We don't serialize null + assertEquals("{\"count\":0,\"avg\":0.0,\"sum\":0.0}", toJson(stats)); + } + + @Test + public void testNullableInt() { + StringStatsAggregate stats = StringStatsAggregate.of(b -> b + .count(1) + .minLength(2) + .avgLength(3D) + .maxLength(4) + .entropy(0D) + ); + + stats = checkJsonRoundtrip(stats, "{\"count\":1,\"min_length\":2,\"max_length\":4,\"avg_length\":3.0,\"entropy\":0.0}"); + assertEquals(2, stats.minLength()); + assertEquals(4, stats.maxLength()); + assertEquals(0, stats.entropy()); + + // Missing values + String json = "{\"count\":1,\"min_length\":null,\"max_length\":null,\"avg_length\":null,\"entropy\":null}"; + stats = fromJson(json, StringStatsAggregate.class); + assertEquals(1, stats.count()); + assertEquals(null, stats.minLength()); + assertEquals(null, stats.maxLength()); + assertEquals(null, stats.entropy()); + } + + @Test + public void testVoidDeserialization() { + String json = "{\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + + "\"hits\":{\"hits\":[{\"_index\":\"foo\",\"_id\":\"w\",\"_source\":{\"foo\": \"bar\"}}]}," + + "\"took\":42,\"timed_out\":false" + + "}"; + + SearchResponse response = fromJson(json, SearchResponse.createSearchResponseDeserializer(JsonpDeserializer.of(Void.class))); + + // Void type skips all the JSON and is serialized to null. + assertEquals(1, response.hits().hits().size()); + assertNull(response.hits().hits().get(0).source()); + assertEquals(42, response.took()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/ClassStructureTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/ClassStructureTest.java new file mode 100644 index 000000000..d18faa465 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/ClassStructureTest.java @@ -0,0 +1,361 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.ErrorCause; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; +import co.elastic.clients.elasticsearch._types.aggregations.Aggregation; +import co.elastic.clients.elasticsearch._types.aggregations.Buckets; +import co.elastic.clients.elasticsearch._types.aggregations.CardinalityAggregate; +import co.elastic.clients.elasticsearch._types.aggregations.DateRangeAggregate; +import co.elastic.clients.elasticsearch._types.aggregations.RangeBucket; +import co.elastic.clients.elasticsearch._types.aggregations.TermsAggregation; +import co.elastic.clients.elasticsearch._types.aggregations.ValueCountAggregation; +import co.elastic.clients.elasticsearch._types.query_dsl.FieldAndFormat; +import co.elastic.clients.elasticsearch._types.query_dsl.IntervalsQuery; +import co.elastic.clients.elasticsearch.core.GetRequest; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.elasticsearch.core.search.HitsMetadata; +import co.elastic.clients.elasticsearch.core.search.TotalHits; +import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.MissingRequiredPropertyException; +import co.elastic.clients.util.NamedValue; +import co.elastic.clients.util.ObjectBuilder; +import org.junit.jupiter.api.Test; + +import javax.annotation.Nullable; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Tests that verify common features of generated classes. + */ +public class ClassStructureTest extends ModelTestCase { + + /** + * Tests optional and required primitive types + */ + @Test + public void testPrimitiveTypes() throws Exception { + // Optional primitive should use the boxed type and be @Nullable + { + Method searchSize = SearchRequest.class.getMethod("size"); + assertNotNull(searchSize.getAnnotation(Nullable.class)); + assertEquals(Integer.class, searchSize.getReturnType()); + } + + // Builder setter for optional primitive should use the boxed type and be @Nullable + { + Method searchBuilderSize = SearchRequest.Builder.class.getMethod("size", Integer.class); + assertTrue(Arrays.stream(searchBuilderSize.getParameterAnnotations()[0]) + .anyMatch(a -> a.annotationType() == Nullable.class)); + } + + // Required primitive should use the primitive type and not be @Nullable + { + Method totalHitsValue = TotalHits.class.getMethod("value"); + assertNull(totalHitsValue.getAnnotation(Nullable.class)); + assertEquals(long.class, totalHitsValue.getReturnType()); + } + + // Builder setter for required primitive should use the primitive type and not be @Nullable + { + Method totalHitsBuilderValue = TotalHits.Builder.class.getMethod("value", long.class); + assertFalse(Arrays.stream(totalHitsBuilderValue.getParameterAnnotations()[0]) + .anyMatch(a -> a.annotationType() == Nullable.class)); + } + + // Not setting a required primitive should throw an exception + { + assertThrows(MissingRequiredPropertyException.class, () -> TotalHits.of(b -> b)); + } + } + + /** + * Tests correct initialization of inherited fields through builders and data class inheritance. + */ + @Test + public void testDataClassInheritedFieldAssignment() { + // 1 ancestor + { + CardinalityAggregate card = CardinalityAggregate.of(b -> b + .meta(Collections.singletonMap("foo", JsonData.of("bar"))) + .value(1) + ); + + assertAncestorCount(1, card); + assertEquals("bar", card.meta().get("foo").to(String.class)); + assertEquals("{\"meta\":{\"foo\":\"bar\"},\"value\":1}", toJson(card)); + } + + // 3 ancestors + { + DateRangeAggregate date = DateRangeAggregate.of(_1 -> _1 + .meta(Collections.singletonMap("foo", JsonData.of("bar"))) + .buckets(Buckets.of(b -> b.array(Collections.singletonList(RangeBucket.of(_2 -> _2.docCount(1)))))) + ); + + assertAncestorCount(3, date); + assertEquals("bar", date.meta().get("foo").to(String.class)); + assertEquals("{\"meta\":{\"foo\":\"bar\"},\"buckets\":[{\"doc_count\":1}]}", toJson(date)); + } + } + + /** + * Tests correct initialization of inherited fields for union typed. + */ + @Test + public void testUnionInheritedFieldAssignment() { + IntervalsQuery iq = IntervalsQuery.of(_1 -> _1 + .boost(2.0f) + .field("foo") + .allOf(b -> b.intervals(Collections.emptyList())) + ); + assertAncestorCount(1, iq); + assertEquals(2.0f, iq.boost(), 0.01); + assertEquals("{\"foo\":{\"boost\":2.0,\"all_of\":{\"intervals\":[]}}}", toJson(iq)); + } + + @Test + public void testUndefinedCollections() { + // Not setting a required list should throw an exception + { + MissingRequiredPropertyException ex = assertThrows(MissingRequiredPropertyException.class, + () -> HitsMetadata.of(_1 -> _1.total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)))); + assertTrue(ex.getMessage().contains(".hits")); + } + + // Unset list should be non-null, empty but not serialized + { + SearchRequest search = SearchRequest.of(b -> b); + assertNotNull(search.storedFields()); + assertEquals(0, search.storedFields().size()); + assertFalse(ApiTypeHelper.isDefined(search.storedFields())); + assertEquals("{}", toJson(search)); + } + + // Setting an empty list defines it + { + SearchRequest search = SearchRequest.of(b -> b.storedFields(Collections.emptyList())); + assertNotNull(search.storedFields()); + assertEquals(0, search.storedFields().size()); + assertTrue(ApiTypeHelper.isDefined(search.storedFields())); + assertEquals("{\"stored_fields\":[]}", toJson(search)); + } + + // Unset map should be non-null, empty but not serialized + { + CardinalityAggregate card = CardinalityAggregate.of(b -> b.value(1)); + assertNotNull(card.meta()); + assertEquals(0, card.meta().size()); + assertFalse(ApiTypeHelper.isDefined(card.meta())); + assertEquals("{\"value\":1}", toJson(card)); + } + + // Setting an empty map defines it + { + CardinalityAggregate card = CardinalityAggregate.of(b -> b + .value(1) + .meta(Collections.emptyMap()) + ); + assertNotNull(card.meta()); + assertEquals(0, card.meta().size()); + assertTrue(ApiTypeHelper.isDefined(card.meta())); + assertEquals("{\"meta\":{},\"value\":1}", toJson(card)); + } + } + + @Test + public void testListSetters() { + List fields = Arrays.asList("a", "b"); + + { + // Appending doesn't modify the original collection + SearchRequest search = SearchRequest.of(b -> b + .storedFields(fields) + .storedFields("c") + .storedFields("d", "e", "f") + ); + assertEquals(Arrays.asList("a", "b"), fields); + assertEquals(Arrays.asList("a", "b", "c", "d", "e", "f"), search.storedFields()); + } + + { + // Appending doesn't modify the original collection (appending the same list twice) + SearchRequest search = SearchRequest.of(b -> b + .storedFields(fields) + .storedFields(fields) + ); + assertEquals(Arrays.asList("a", "b"), fields); + assertEquals(Arrays.asList("a", "b", "a", "b"), search.storedFields()); + } + + + { + // List cannot be null + List nullFields = null; + assertThrows(NullPointerException.class, () -> { + SearchRequest.of(b -> b + .storedFields(nullFields) + ); + }); + } + + { + // Combine value and builder + FieldAndFormat fieldA = FieldAndFormat.of(f -> f.field("a")); + SearchRequest search = SearchRequest.of(b -> b + .docvalueFields(fieldA) + .docvalueFields(f -> f.field("b")) + .docvalueFields(f -> f.field("c")) + ); + + assertEquals(Arrays.asList("a", "b", "c"), search.docvalueFields().stream() + .map(FieldAndFormat::field).collect(Collectors.toList())); + } + } + + @Test + public void testMapSetters() { + ValueCountAggregation countA = ValueCountAggregation.of(v -> v.field("a")); + ValueCountAggregation countB = ValueCountAggregation.of(v -> v.field("b")); + ValueCountAggregation countC = ValueCountAggregation.of(v -> v.field("c")); + + Map aggs = new HashMap<>(); + aggs.put("aggA", countA._toAggregation()); + aggs.put("aggB", countB._toAggregation()); + + { + // Appending doesn't modify the original collection + SearchRequest search = SearchRequest.of(b -> b + .aggregations(aggs) + .aggregations("aggC", countC._toAggregation()) + .aggregations("aggD", a -> a.valueCount(c -> c.field("d"))) + ); + + // Original map wasn't modified + assertEquals(2, aggs.size()); + + assertEquals(4, search.aggregations().size()); + assertEquals("a", search.aggregations().get("aggA").valueCount().field()); + assertEquals("b", search.aggregations().get("aggB").valueCount().field()); + assertEquals("c", search.aggregations().get("aggC").valueCount().field()); + assertEquals("d", search.aggregations().get("aggD").valueCount().field()); + } + + { + // Map cannot be null + assertThrows(NullPointerException.class, () -> { + Map nullMap = null; + SearchRequest.of(b -> b.aggregations(nullMap)); + }); + } + } + + @Test + public void testDataClassesSingleBuilderUse() { + // no ancestor + WithJsonBase + ObjectBuilderBase + checkSingleBuilderUse(2, new ErrorCause.Builder().type("foo").reason("bar")); + + // 1 ancestor + WithJsonBase + ObjectBuilderBase + checkSingleBuilderUse(3, new CardinalityAggregate.Builder().value(0)); + + // 3 ancestors + WithJsonBase + ObjectBuilderBase + checkSingleBuilderUse(5, new DateRangeAggregate.Builder().buckets(Buckets.of(b -> b.array(Collections.emptyList())))); + } + + @Test + public void testUnionSingleBuilderUse() { + // no ancestor + ObjectBuilderBase + checkSingleBuilderUse(1, new Aggregate.Builder().cardinality(b -> b.value(0))); + + // 1 ancestor + WithJsonBase + ObjectBuilderBase + checkSingleBuilderUse(3, new IntervalsQuery.Builder().field("foo").allOf(b -> b.intervals(Collections.emptyList()))); + } + + @Test + public void testRequiredProperty() { + // All required properties present + GetRequest r = GetRequest.of(b -> b.index("foo").id("bar")); + + // Missing id property throws an exception + MissingRequiredPropertyException ex = assertThrows(MissingRequiredPropertyException.class, () -> { + GetRequest r1 = GetRequest.of(b -> b.index("foo")); + }); + assertEquals("id", ex.getPropertyName()); + + // Disable checks, missing id property is accepted. + try (ApiTypeHelper.DisabledChecksHandle h = ApiTypeHelper.DANGEROUS_disableRequiredPropertiesCheck(true)) { + GetRequest r1 = GetRequest.of(b -> b.index("foo")); + assertNull(r1.id()); + } + + // Checks are enabled again after the try block + ex = assertThrows(MissingRequiredPropertyException.class, () -> { + GetRequest r1 = GetRequest.of(b -> b.index("foo")); + }); + assertEquals("id", ex.getPropertyName()); + } + + /** + * Tests SingleKeyDictionary fields that are not transformed into a behavior. + */ + @Test + public void testNamedValue() { + TermsAggregation termsAgg = TermsAggregation.of(ta -> ta + .order(NamedValue.of("a", SortOrder.Asc)) + .order(NamedValue.of("b", SortOrder.Desc)) + ); + + checkJsonRoundtrip(termsAgg, "{\"order\":[{\"a\":\"asc\"},{\"b\":\"desc\"}]}"); + } + + private void assertAncestorCount(int count, Object obj) { + Class clazz = obj.getClass(); + while(count-- >= 0) { + clazz = clazz.getSuperclass(); + } + assertEquals(Object.class, clazz); + } + + private void checkSingleBuilderUse(int count, ObjectBuilder builder) { + assertAncestorCount(count, builder); + + // Building once should succeed + builder.build(); + + // Building twice should fail + IllegalStateException ex = assertThrows(IllegalStateException.class, builder::build); + assertEquals("Object builders can only be used once", ex.getMessage()); + + // One more for good measure + ex = assertThrows(IllegalStateException.class, builder::build); + assertEquals("Object builders can only be used once", ex.getMessage()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/CodeAdditionsTests.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/CodeAdditionsTests.java new file mode 100644 index 000000000..e19ea16a0 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/CodeAdditionsTests.java @@ -0,0 +1,49 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery; +import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class CodeAdditionsTests extends Assertions { + + @Test + public void testHasClauses() { + + { + BoolQuery.Builder builder = new BoolQuery.Builder(); + assertFalse(builder.hasClauses()); + + BoolQuery query = builder.build(); + assertFalse(query.hasClauses()); + } + + { + BoolQuery.Builder builder = new BoolQuery.Builder(); + builder.must(QueryBuilders.matchAll(b -> b)); + assertTrue(builder.hasClauses()); + + BoolQuery query = builder.build(); + assertTrue(query.hasClauses()); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/EndpointTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/EndpointTest.java new file mode 100644 index 000000000..1065c2c5f --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/EndpointTest.java @@ -0,0 +1,94 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.ExpandWildcard; +import co.elastic.clients.elasticsearch.core.ExistsRequest; +import co.elastic.clients.elasticsearch.core.InfoRequest; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.elasticsearch.indices.RefreshRequest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class EndpointTest extends Assertions { + + @Test + public void testArrayPathParameter() { + RefreshRequest req; + + req = RefreshRequest.of(b -> b); + assertNotNull(req.index()); + assertEquals("/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); + + req = RefreshRequest.of(b -> b.index("a")); + assertEquals("/a/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); + + req = RefreshRequest.of(b -> b.index("a", "b")); + assertEquals("/a,b/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); + + req = RefreshRequest.of(b -> b.index("a", "b", "c")); + assertEquals("/a,b,c/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); + } + + @Test + public void testPathEncoding() { + RefreshRequest req; + + req = RefreshRequest.of(b -> b.index("a/b")); + assertEquals("/a%2Fb/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); + + req = RefreshRequest.of(b -> b.index("a/b", "c/d")); + assertEquals("/a%2Fb,c%2Fd/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); + + } + + @Test + public void testArrayQueryParameter() { + RefreshRequest req; + + req = RefreshRequest.of(b -> b); + assertNotNull(req.expandWildcards()); // undefined list + assertNull(RefreshRequest._ENDPOINT.queryParameters(req).get("expand_wildcards")); + + req = RefreshRequest.of(b -> b.expandWildcards(ExpandWildcard.All)); + // Also tests query encoding of enums + assertEquals("all", RefreshRequest._ENDPOINT.queryParameters(req).get("expand_wildcards")); + + req = RefreshRequest.of(b -> b.expandWildcards(ExpandWildcard.All, ExpandWildcard.Closed)); + assertEquals("all,closed", RefreshRequest._ENDPOINT.queryParameters(req).get("expand_wildcards")); + } + + @Test + public void testRequestToString() { + // Simple path, no parameters, no body + assertEquals("InfoRequest: GET /", InfoRequest._INSTANCE.toString()); + + // Complex path, parameters, no body + assertEquals( + "ExistsRequest: HEAD /idx/_doc/id1?preference=foo&refresh=true", + ExistsRequest.of(b -> b.index("idx").id("id1").preference("foo").refresh(true)).toString() + ); + + assertEquals( + "SearchRequest: POST /idx/_search?typed_keys=true {\"size\":10}", + SearchRequest.of(s -> s.index("idx").size(10)).toString() + ); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/EnumTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/EnumTest.java new file mode 100644 index 000000000..b36ab6d6e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/EnumTest.java @@ -0,0 +1,61 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.Bytes; +import co.elastic.clients.elasticsearch._types.Refresh; +import co.elastic.clients.elasticsearch._types.mapping.GeoOrientation; +import co.elastic.clients.testkit.ModelTestCase; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +public class EnumTest extends ModelTestCase { + + @Test + public void testSimpleEnum() { + assertNull(Bytes.GigaBytes.aliases()); + assertEquals(Bytes.GigaBytes, Bytes._DESERIALIZER.parse("gb")); + } + + @Test + public void testEnumWithAliases() { + assertEquals("left", GeoOrientation.Left.jsonValue()); + assertNotNull(GeoOrientation.Left.aliases()); + + Arrays.asList("right", "RIGHT", "counterclockwise", "ccw").forEach(alias -> { + assertEquals(GeoOrientation.Right, GeoOrientation._DESERIALIZER.parse(alias)); + }); + } + + @Test + public void testBooleanEnum() { + // Quoted value + assertEquals(Refresh.WaitFor, checkJsonRoundtrip(Refresh.WaitFor, "\"wait_for\"")); + + // Unquoted boolean values + assertEquals(Refresh.True, checkJsonRoundtrip(Refresh.True, "true")); + assertEquals(Refresh.False, checkJsonRoundtrip(Refresh.False, "false")); + + // true/false as strings + assertEquals(Refresh.True, fromJson("\"true\"", Refresh.class)); + assertEquals(Refresh.False, fromJson("\"false\"", Refresh.class)); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/RequestEncodingTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/RequestEncodingTest.java new file mode 100644 index 000000000..83b9f5e84 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/RequestEncodingTest.java @@ -0,0 +1,59 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.model; + +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import co.elastic.clients.testkit.ModelTestCase; +import org.junit.jupiter.api.Test; + +public class RequestEncodingTest extends ModelTestCase { + + @Test + public void testParametersNotInJson() { + + // This checks that path parameters ("q") are not serialized as json + // and variant containers ser/deser + + SearchRequest request = new SearchRequest.Builder() + .q("blah") + .query(b1 -> b1 + .type(b2 -> b2 + .value("foo")) + ) + .aggregations( + "myagg", b2 -> b2 + .avg(b3 -> b3.field("foo")) + ) + .build(); + + JsonbJsonpMapper mapper = new JsonbJsonpMapper(); + String str = toJson(request, mapper); + + assertEquals("{\"aggregations\":{\"myagg\":{\"avg\":{\"field\":\"foo\"}}},\"query\":{\"type\":{\"value\":\"foo\"}}}", str); + + request = fromJson(str, SearchRequest.class, mapper); + + assertTrue(request.query().isType()); + assertEquals("foo", request.query().type().value()); + assertNull(request.q()); + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/TypedKeysTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/TypedKeysTest.java new file mode 100644 index 000000000..609b08822 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/TypedKeysTest.java @@ -0,0 +1,299 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; +import co.elastic.clients.elasticsearch._types.aggregations.AvgAggregate; +import co.elastic.clients.elasticsearch._types.aggregations.StringTermsAggregate; +import co.elastic.clients.elasticsearch._types.aggregations.StringTermsBucket; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpMapperFeatures; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.util.ListBuilder; +import co.elastic.clients.util.MapBuilder; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.JsonGenerator; +import org.junit.jupiter.api.Test; + +import java.io.StringWriter; +import java.util.Collections; + +public class TypedKeysTest extends ModelTestCase { + + @Test + public void testMapProperty() { + + SearchResponse resp = new SearchResponse.Builder() + .aggregations( + "foo", _2 -> _2 + .avg(_3 -> _3.value(3.14)) + ) + // Required properties on a SearchResponse + .took(1) + .shards(_1 -> _1.successful(1).failed(0).total(1)) + .hits(_1 -> _1 + .total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)) + .hits(Collections.emptyList()) + ) + .timedOut(false) + .build(); + + String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + + "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]},\"aggregations\":{\"avg#foo\":{\"value\":3.14}}}"; + + assertEquals(json, toJson(resp)); + + resp = fromJson(json, SearchResponse.createSearchResponseDeserializer(JsonpDeserializer.voidDeserializer())); + + assertEquals(1, resp.took()); + assertEquals(3.14, resp.aggregations().get("foo").avg().value(), 0.001); + + } + + @Test + public void testMapPropertyWithoutTypedKeys() { + + SearchResponse resp = new SearchResponse.Builder() + .aggregations( + "foo", _2 -> _2 + .avg(_3 -> _3.value(3.14)) + ) + // Required properties on a SearchResponse + .took(1) + .shards(_1 -> _1.successful(1).failed(0).total(1)) + .hits(_1 -> _1 + .total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)) + .hits(Collections.emptyList()) + ) + .timedOut(false) + .build(); + + // Note "foo" and not "avg#foo" below + String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + + "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]},\"aggregations\":{\"foo\":{\"value\":3.14}}}"; + + JsonpMapper newMapper = mapper.withAttribute(JsonpMapperFeatures.SERIALIZE_TYPED_KEYS, false); + + assertEquals(json, toJson(resp, newMapper)); + } + + + @Test + public void testAdditionalProperties() { + + Aggregate avg1 = AvgAggregate.of(_1 -> _1.value(1.0))._toAggregate(); + Aggregate avg2 = AvgAggregate.of(_1 -> _1.value(2.0))._toAggregate(); + + Aggregate aggregate = StringTermsAggregate.of(_0 -> _0 + .sumOtherDocCount(1L) + .buckets(b -> b.array( + ListBuilder.of(StringTermsBucket.Builder::new) + .add(_1 -> _1 + .key("key_1") + .docCount(1) + .aggregations(MapBuilder.of("bar", avg1)) + ) + .add(_1 -> _1 + .key("key_2") + .docCount(2) + .aggregations(MapBuilder.of("bar", avg2)) + ) + .build() + )) + ) + ._toAggregate(); + + SearchResponse resp = new SearchResponse.Builder() + .aggregations("foo", aggregate) + // Required properties on a SearchResponse + .took(1) + .shards(_1 -> _1.successful(1).failed(0).total(1)) + .hits(_1 -> _1 + .total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)) + .hits(Collections.emptyList()) + ) + .timedOut(false) + .build(); + + + String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + + "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]}," + + "\"aggregations\":{\"sterms#foo\":{\"buckets\":[" + + "{\"avg#bar\":{\"value\":1.0},\"doc_count\":1,\"key\":\"key_1\"}," + + "{\"avg#bar\":{\"value\":2.0},\"doc_count\":2,\"key\":\"key_2\"}" + + "],\"sum_other_doc_count\":1}}}"; + + assertEquals(json, toJson(resp)); + resp = fromJson(json, SearchResponse.createSearchResponseDeserializer(JsonpDeserializer.voidDeserializer())); + + StringTermsAggregate foo = resp.aggregations().get("foo").sterms(); + assertEquals(1, foo.sumOtherDocCount()); + assertEquals(1, foo.buckets().array().get(0).docCount()); + assertEquals("key_1", foo.buckets().array().get(0).key().stringValue()); + assertEquals(1.0, foo.buckets().array().get(0).aggregations().get("bar").avg().value(), 0.01); + assertEquals("key_2", foo.buckets().array().get(1).key().stringValue()); + assertEquals(2.0, foo.buckets().array().get(1).aggregations().get("bar").avg().value(), 0.01); + } + + // Example taken from + // https://www.elastic.co/guide/en/elasticsearch/reference/8.2/search-aggregations-bucket-reverse-nested-aggregation.html + private static final String nestedJsonWithTypedKeys = "{\n" + + " \"took\": 0," + + " \"timed_out\": false," + + " \"_shards\": {\n" + + " \"successful\": 1,\n" + + " \"failed\": 0,\n" + + " \"skipped\": 0,\n" + + " \"total\": 1\n" + + " },\n" + + " \"hits\": {\n" + + " \"hits\": [],\n" + + " \"total\": {\n" + + " \"relation\": \"eq\",\n" + + " \"value\": 5\n" + + " },\n" + + " \"max_score\": null\n" + + " }," + + " \"aggregations\" : {\n" + + " \"nested#comments\" : {\n" + + " \"doc_count\" : 3,\n" + + " \"sterms#top_usernames\" : {\n" + + " \"doc_count_error_upper_bound\" : 0,\n" + + " \"sum_other_doc_count\" : 0,\n" + + " \"buckets\" : [\n" + + " {\n" + + " \"key\" : \"dan\",\n" + + " \"doc_count\" : 3,\n" + + " \"reverse_nested#comment_to_issue\" : {\n" + + " \"doc_count\" : 1,\n" + + " \"sterms#top_tags_per_comment\" : {\n" + + " \"doc_count_error_upper_bound\" : 0,\n" + + " \"sum_other_doc_count\" : 0,\n" + + " \"buckets\" : [\n" + + " {\n" + + " \"key\" : \"tag1\",\n" + + " \"doc_count\" : 1\n" + + " },\n" + + " {\n" + + " \"key\" : \"tag2\",\n" + + " \"doc_count\" : 1\n" + + " }\n" + + " ]\n" + + " }\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + @Test + public void testSerializeNested() { + + SearchResponse response = fromJson(nestedJsonWithTypedKeys, SearchResponse.class); + + // Check some deeply nested properties + StringTermsBucket bucket = response + .aggregations().get("comments").nested() + .aggregations().get("top_usernames").sterms() + .buckets().array().get(0) + .aggregations().get("comment_to_issue").reverseNested() + .aggregations().get("top_tags_per_comment").sterms() + .buckets().array().get(0); + + assertEquals("tag1", bucket.key().stringValue()); + assertEquals(1, bucket.docCount()); + + // Check that it's typed_keys encoded + String serialized = toJson(response); + assertTrue(serialized.contains("nested#comments")); + assertTrue(serialized.contains("sterms#top_usernames")); + assertTrue(serialized.contains("reverse_nested#comment_to_issue")); + assertTrue(serialized.contains("sterms#top_tags_per_comment")); + + { + // Test direct serialization + JsonProvider jsonProvider = mapper.jsonProvider(); + StringWriter stringWriter = new StringWriter(); + JsonGenerator generator = jsonProvider.createGenerator(stringWriter); + response.serialize(generator, mapper); + generator.close(); + + String directSerialized = stringWriter.toString(); + assertTrue(directSerialized.contains("nested#comments")); + assertTrue(directSerialized.contains("sterms#top_usernames")); + assertTrue(directSerialized.contains("reverse_nested#comment_to_issue")); + assertTrue(directSerialized.contains("sterms#top_tags_per_comment")); + + } + + // Re-parse and re-check + response = fromJson(serialized, SearchResponse.class); + + bucket = response + .aggregations().get("comments").nested() + .aggregations().get("top_usernames").sterms() + .buckets().array().get(0) + .aggregations().get("comment_to_issue").reverseNested() + .aggregations().get("top_tags_per_comment").sterms() + .buckets().array().get(0); + + assertEquals("tag1", bucket.key().stringValue()); + assertEquals(1, bucket.docCount()); + + + JsonProvider jsonProvider = mapper.jsonProvider(); + StringWriter stringWriter = new StringWriter(); + JsonGenerator generator = jsonProvider.createGenerator(stringWriter); + response.serialize(generator, mapper); + generator.close(); + + System.out.println(stringWriter.toString()); + } + + @Test + public void testSerializeNestedWithoutTypedKeys() { + + SearchResponse response = fromJson(nestedJsonWithTypedKeys, SearchResponse.class); + + // Check that it's typed_keys encoded + String serialized = toJson(response); + assertTrue(serialized.contains("nested#comments")); + assertTrue(serialized.contains("sterms#top_usernames")); + assertTrue(serialized.contains("reverse_nested#comment_to_issue")); + assertTrue(serialized.contains("sterms#top_tags_per_comment")); + + // Build the non-typed_keys version (replace 'type#' with 'type#name') + serialized = serialized.replaceAll("\"[^\"]*#", "\""); + assertFalse(serialized.contains("nested#comments")); + assertFalse(serialized.contains("sterms#top_usernames")); + assertFalse(serialized.contains("reverse_nested#comment_to_issue")); + assertFalse(serialized.contains("sterms#top_tags_per_comment")); + + // Serialize without typed keys + JsonpMapper newMapper = mapper.withAttribute(JsonpMapperFeatures.SERIALIZE_TYPED_KEYS, false); + assertEquals(serialized, toJson(response, newMapper)); + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/VariantsTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/VariantsTest.java new file mode 100644 index 000000000..1ffbe6ade --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/VariantsTest.java @@ -0,0 +1,351 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.analysis.Analyzer; +import co.elastic.clients.elasticsearch._types.mapping.Property; +import co.elastic.clients.elasticsearch._types.mapping.TypeMapping; +import co.elastic.clients.elasticsearch._types.query_dsl.FunctionScore; +import co.elastic.clients.elasticsearch._types.query_dsl.Query; +import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.elasticsearch.ilm.ExplainLifecycleResponse; +import co.elastic.clients.elasticsearch.ilm.explain_lifecycle.LifecycleExplainManaged; +import co.elastic.clients.elasticsearch.ilm.explain_lifecycle.LifecycleExplainUnmanaged; +import co.elastic.clients.elasticsearch.indices.GetMappingResponse; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.testkit.ModelTestCase; +import org.junit.jupiter.api.Test; + +import java.util.function.Consumer; + +public class VariantsTest extends ModelTestCase { + + @Test + public void testNested() { + // nested containers: query > intervals > interval + // intervals is a single key dictionary + // query has container properties + + Query q = Query.of(_0 -> _0 + .intervals(_1 -> _1 + .queryName("my-query") + .field("a_field") + .anyOf(_2 -> _2 + .intervals(_3 -> _3 + .match( + _5 -> _5 + .query("match-query") + .analyzer("lowercase") + ) + ) + ) + ) + ); + + assertEquals(Query.Kind.Intervals, q._kind()); + assertNotNull(q.intervals()); + assertEquals("a_field", q.intervals().field()); + assertEquals(1, q.intervals().anyOf().intervals().size()); + assertEquals("lowercase", q.intervals().anyOf().intervals().get(0).match().analyzer()); + + String json = toJson(q); + + assertEquals("{\"intervals\":{\"a_field\":{\"_name\":\"my-query\"," + + "\"any_of\":{\"intervals\":[{\"match\":{\"analyzer\":\"lowercase\",\"query\":\"match-query\"}}]}}}}", json); + + Query q2 = fromJson(json, Query.class); + assertEquals(json, toJson(q2)); + + assertEquals(Query.Kind.Intervals, q2._kind()); + assertNotNull(q2.intervals()); + assertEquals("a_field", q2.intervals().field()); + assertEquals(1, q2.intervals().anyOf().intervals().size()); + assertEquals("lowercase", q2.intervals().anyOf().intervals().get(0).match().analyzer()); + + } + + @Test + public void testInternalTag() { + String expected = "{\"type\":\"ip\",\"fields\":{\"a-field\":{\"type\":\"float\",\"coerce\":true}},\"boost\":1" + + ".0,\"index\":true}"; + + Property p = Property.of(_0 -> _0 + .ip(_1 -> _1 + .index(true) + .boost(1.0) + .fields( + "a-field", _3 -> _3 + .float_(_4 -> _4 + .coerce(true) + ) + ) + ) + ); + + assertEquals(expected, toJson(p)); + + Property property = fromJson(expected, Property.class); + assertTrue(property.ip().index()); + assertEquals(1.0, property.ip().boost().doubleValue(), 0.09); + + assertTrue(property.ip().fields().get("a-field").float_().coerce()); + } + + @Test + public void testDefaultInternalTag() { + + Consumer test = s -> { + Analyzer a = fromJson(s, Analyzer.class); + assertEquals(Analyzer.Kind.Custom, a._kind()); + assertEquals("some-filter", a.custom().filter().get(0)); + assertTrue(a.custom().charFilter().isEmpty()); + assertEquals("some-tokenizer", a.custom().tokenizer()); + }; + + // Explicit type + test.accept("{\"type\":\"custom\",\"filter\":[\"some-filter\"],\"tokenizer\":\"some-tokenizer\"}"); + + // Default type + test.accept("{\"filter\":[\"some-filter\"],\"tokenizer\":\"some-tokenizer\"}"); + } + + @Test + public void testBuilders() { + String json = "{\"exists\":{\"field\":\"foo\"}}"; + Query q; + + q = new Query(QueryBuilders.exists().field("foo").build()); + assertEquals(json, toJson(q)); + + q = QueryBuilders.exists(e -> e.field("foo")); + assertEquals(json, toJson(q)); + } + + + @Test + public void testNestedTaggedUnionWithDefaultTag() { + // https://github.com/elastic/elasticsearch-java/issues/45 + + // Object fields don't really exist in ES and are based on a naming convention where field names + // are dot-separated paths. The hierarchy is rebuilt from these names and ES doesn't send back + // "type": "object" for object properties. + // See https://www.elastic.co/guide/en/elasticsearch/reference/current/object.html + // + // Mappings are therefore a hierarchy of internally-tagged unions based on the "type" property + // with a default "object" tag value if the "type" property is missing. + + String json = + "{\n" + + " \"testindex\" : {\n" + + " \"mappings\" : {\n" + + " \"properties\" : {\n" + + " \"id\" : {\n" + + " \"type\" : \"text\",\n" + + " \"fields\" : {\n" + + " \"keyword\" : {\n" + + " \"type\" : \"keyword\",\n" + + " \"ignore_above\" : 256\n" + + " }\n" + + " }\n" + + " },\n" + + " \"name\" : {\n" + + " \"properties\" : {\n" + + " \"first\" : {\n" + + " \"type\" : \"text\",\n" + + " \"fields\" : {\n" + + " \"keyword\" : {\n" + + " \"type\" : \"keyword\",\n" + + " \"ignore_above\" : 256\n" + + " }\n" + + " }\n" + + " },\n" + + " \"last\" : {\n" + + " \"type\" : \"text\",\n" + + " \"fields\" : {\n" + + " \"keyword\" : {\n" + + " \"type\" : \"keyword\",\n" + + " \"ignore_above\" : 256\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + GetMappingResponse response = fromJson(json, GetMappingResponse.class); + + TypeMapping mappings = response.get("testindex").mappings(); + assertTrue(mappings.properties().get("name").isObject()); + + assertEquals(256, mappings + .properties().get("name").object() + .properties().get("first").text() + .fields().get("keyword").keyword(). + ignoreAbove().longValue() + ); + + assertTrue(mappings.properties().get("id").isText()); + + assertEquals(256, mappings.properties().get("id").text().fields().get("keyword").keyword().ignoreAbove().longValue()); + } + + @Test + public void testEmptyProperty() { + // Edge case where we have a property with no fields and no type + String json = "{}"; + Property property = fromJson(json, Property.class); + assertEquals(Property.Kind.Object, property._kind()); + } + + @Test + public void testNestedVariantsWithContainerProperties() { + + SearchRequest search = SearchRequest.of(s -> s + .aggregations( + "agg1", a -> a + .meta("m1", JsonData.of("m1 value")) + // Here we can choose any aggregation type, but build() isn't accessible + .valueCount(v -> v.field("f")) + // Here we can only set container properties (meta and (sub)aggregations) or build() + .meta("m2", JsonData.of("m2 value")) + ) + ); + + assertEquals("m1 value", search.aggregations().get("agg1").meta().get("m1").to(String.class)); + assertEquals("m2 value", search.aggregations().get("agg1").meta().get("m2").to(String.class)); + } + + @Test + public void testContainerWithOptionalVariants() { + // FunctionScore is the only occurrence of this + + Query q = QueryBuilders.term(t -> t.field("foo").value("bar")); + + // No variant + { + Query fsq = QueryBuilders.functionScore(fs -> fs + .query(q) + .functions(f -> f.weight(1.0)) + ); + + String json = "{\"function_score\":{\"functions\":[{\"weight\":1.0}]," + + "\"query\":{\"term\":{\"foo\":{\"value\":\"bar\"}}}}}"; + assertEquals(json, toJson(fsq)); + + Query fsq2 = checkJsonRoundtrip(fsq, json); + + assertNull(fsq2.functionScore().functions().get(0)._kind()); + assertEquals(1.0, fsq2.functionScore().functions().get(0).weight(), 0.001); + } + + // With a variant + { + Query fsq = QueryBuilders.functionScore(fs -> fs + .query(q) + .functions(f -> f + .weight(1.0) + .linear(l -> l + .numeric(n -> n + .field("foo") + .placement(p -> p.decay(2.0)) + ) + ) + )); + + String json = "{\"function_score\":{\"functions\":[{\"weight\":1.0,\"linear\":{\"foo\":{\"decay\":2.0}}}]," + + "\"query\":{\"term\":{\"foo\":{\"value\":\"bar\"}}}}}"; + assertEquals(json, toJson(fsq)); + + Query fsq2 = checkJsonRoundtrip(fsq, json); + + assertEquals(FunctionScore.Kind.Linear, fsq2.functionScore().functions().get(0)._kind()); + assertEquals(1.0, fsq2.functionScore().functions().get(0).weight(), 0.001); + assertEquals(2.0, fsq2.functionScore().functions().get(0).linear().untyped().placement().decay(), 0.001); + } + } + + @Test + public void testBooleanVariantTag() { + + String jsonT = "{\n" + + " \"indices\": {\n" + + " \"test\": {\n" + + " \"index\": \"test\",\n" + + " \"managed\": true,\n" + + " \"policy\": \"my_policy\",\n" + + " \"index_creation_date_millis\": 1736785235558,\n" + + " \"time_since_index_creation\": \"27.75d\",\n" + + " \"lifecycle_date_millis\": 1736785235558,\n" + + " \"age\": \"27.75d\",\n" + + " \"phase\": \"warm\",\n" + + " \"phase_time_millis\": 1739183166898,\n" + + " \"action\": \"migrate\",\n" + + " \"action_time_millis\": 1739183166898,\n" + + " \"step\": \"check-migration\",\n" + + " \"step_time_millis\": 1739183166898,\n" + + " \"step_info\": {\n" + + " \"message\": \"Waiting for all shard copies to be active\",\n" + + " \"shards_left_to_allocate\": -1,\n" + + " \"all_shards_active\": false,\n" + + " \"number_of_replicas\": 1\n" + + " },\n" + + " \"phase_execution\": {\n" + + " \"policy\": \"my_policy\",\n" + + " \"phase_definition\": {\n" + + " \"min_age\": \"10d\",\n" + + " \"actions\": {\n" + + " \"forcemerge\": {\n" + + " \"max_num_segments\": 1\n" + + " }\n" + + " }\n" + + " },\n" + + " \"version\": 1,\n" + + " \"modified_date_in_millis\": 1739183005443\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + ExplainLifecycleResponse respT = fromJson(jsonT,ExplainLifecycleResponse.class); + + // if managed is "true" then the variant class must be Managed + assertTrue(respT.indices().get("test").isTrue()); + assertTrue(respT.indices().get("test")._get().getClass().equals(LifecycleExplainManaged.class)); + + String jsonF = "{\n" + + " \"indices\": {\n" + + " \"test\": {\n" + + " \"index\": \"test\",\n" + + " \"managed\": false\n" + + " }\n" + + " }\n" + + "}"; + + ExplainLifecycleResponse respF = fromJson(jsonF,ExplainLifecycleResponse.class); + + // if managed is "false" then the variant class must be Unmanaged + assertTrue(respF.indices().get("test").isFalse()); + assertTrue(respF.indices().get("test")._get().getClass().equals(LifecycleExplainUnmanaged.class)); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/package-info.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/package-info.java new file mode 100644 index 000000000..e58c3560b --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/package-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +/** + * Tests that verify correct types and serialization/deserialization of the API specification model using API + * structures that cover the various model features + */ +package co.elastic.clients.elasticsearch.model; diff --git a/java-client/src/test/java/co/elastic/clients/json/JsonDataTest.java b/java-client/src/test/java/co/elastic/clients/json/JsonDataTest.java new file mode 100644 index 000000000..d752a8558 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/json/JsonDataTest.java @@ -0,0 +1,169 @@ +/* + * 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. + */ + +package co.elastic.clients.json; + +import co.elastic.clients.elasticsearch.core.search.Hit; +import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.JsonString; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import org.junit.jupiter.api.Test; + +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; + +public class JsonDataTest extends ModelTestCase { + +// public JsonDataTest() { +// super(JsonImpl.Jackson); +// } + + public static > B withJson(B builder, Reader json, JsonpMapper mapper) { + JsonpDeserializer classDeser = JsonpMapperBase.findDeserializer(builder.getClass().getEnclosingClass()); + + @SuppressWarnings("unchecked") + ObjectDeserializer builderDeser = (ObjectDeserializer)DelegatingDeserializer.unwrap(classDeser); + + JsonParser parser = mapper.jsonProvider().createParser(json); + builderDeser.deserialize(builder, parser, mapper, parser.next()); + return builder; + } + + @Test + public void testBuilderDeserializerHack() { + + CreateIndexRequest.Builder b = new CreateIndexRequest.Builder(); + + // Required request parameter + b.index("foo"); + + // Read body from JSON + withJson(b, new StringReader("{\"aliases\": {\"foo\": {\"is_hidden\": true}}}"), new JacksonJsonpMapper()); + + CreateIndexRequest createIndexRequest = b.build(); + } + + @Test + public void testParsing() { + if (jsonImpl == JsonImpl.Simple) { + return; // Doesn't support user-defined object mapping + } + + String json = "{\"children\":[{\"doubleValue\":3.2,\"intValue\":2}],\"doubleValue\":2.1,\"intValue\":1," + + "\"stringValue\":\"foo\"}"; + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + + JsonData data = JsonData.from(parser, mapper); + checkClass(data); + assertEquals("foo", data.toJson().asJsonObject().getString("stringValue")); + + JsonpMapperTest.SomeClass to = data.to(JsonpMapperTest.SomeClass.class); + assertEquals("foo", to.getStringValue()); + } + + @Test + public void testSerializeObject() { + if (jsonImpl == JsonImpl.Simple) { + return; // Doesn't support user-defined object mapping + } + + String json = "{\"children\":[{\"doubleValue\":3.2,\"intValue\":2}],\"doubleValue\":2.1,\"intValue\":1," + + "\"stringValue\":\"foo\"}"; + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + JsonpMapperTest.SomeClass sc = + mapper.deserialize(parser, JsonpMapperTest.SomeClass.class); + + assertEquals("foo", sc.getStringValue()); + assertEquals(1, sc.getChildren().size()); + assertEquals(2, sc.getChildren().get(0).getIntValue()); + // All good + + JsonData data = JsonData.of(sc); + + StringWriter sw = new StringWriter(); + JsonGenerator generator = mapper.jsonProvider().createGenerator(sw); + + data.serialize(generator, mapper); + generator.close(); + + assertEquals(json, sw.toString()); + } + + @Test + public void testSerializeValueOrBuffer() { + String json = "{\"children\":[{\"doubleValue\":3.2,\"intValue\":2}],\"doubleValue\":2.1,\"intValue\":1," + + "\"stringValue\":\"foo\"}"; + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + + JsonData data = JsonData.from(parser, mapper); + checkClass(data); + + assertEquals(json, toJson(data, mapper)); + } + + @Test + public void testConvert() { + + JsonData json = JsonData.of("foo"); + + final JsonValue value = json.toJson(mapper); + + assertEquals(JsonValue.ValueType.STRING, value.getValueType()); + assertEquals("foo", ((JsonString)value).getString()); + } + + @Test + public void testFieldValues() { + // Specific test for https://github.com/elastic/elasticsearch-java/issues/548 which led to buffered JsonData + + String json = "{\"_index\":\"idx\",\"_id\":\"doc_id\",\"fields\":{\"bar\":\"Bar value\",\"foo\":1}}"; + + Hit hit = fromJson(json, Hit.createHitDeserializer(JsonpDeserializer.voidDeserializer())); + + assertEquals(1, hit.fields().get("foo").to(Integer.class)); + assertEquals("Bar value", hit.fields().get("bar").to(String.class)); + + checkClass(hit.fields().get("foo")); + checkClass(hit.fields().get("bar")); + + assertEquals(json, toJson(hit)); + } + + private void checkClass(JsonData data) { + String name = data.getClass().getName(); + switch (jsonImpl) { + case Jackson: + assertEquals(name, "co.elastic.clients.json.jackson.JacksonJsonBuffer"); + break; + + case Jsonb: + case Simple: + assertEquals(name, "co.elastic.clients.json.JsonDataImpl"); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/json/JsonpDeserializerBaseTest.java b/java-client/src/test/java/co/elastic/clients/json/JsonpDeserializerBaseTest.java new file mode 100644 index 000000000..a25e3830b --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/json/JsonpDeserializerBaseTest.java @@ -0,0 +1,50 @@ +/* + * 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. + */ + +package co.elastic.clients.json; + +import co.elastic.clients.testkit.ModelTestCase; +import jakarta.json.stream.JsonParser; +import org.junit.jupiter.api.Test; + +import java.util.List; + +public class JsonpDeserializerBaseTest extends ModelTestCase { + + @Test + public void testArrayDeserializer() { + + JsonpDeserializer> deser = + JsonpDeserializer.arrayDeserializer(JsonpDeserializer.integerDeserializer()); + + assertFalse(deser.nativeEvents().contains(JsonParser.Event.VALUE_NUMBER)); + assertTrue(deser.acceptedEvents().contains(JsonParser.Event.VALUE_NUMBER)); + + List values = fromJson("[ 42, 43 ]", deser); + assertEquals(2, values.size()); + assertEquals(42, values.get(0)); + assertEquals(43, values.get(1)); + + // Single value representation + values = fromJson("42", deser); + assertEquals(1, values.size()); + assertEquals(42, values.get(0)); + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/json/JsonpDeserializerTest.java b/java-client/src/test/java/co/elastic/clients/json/JsonpDeserializerTest.java new file mode 100644 index 000000000..34c99500f --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/json/JsonpDeserializerTest.java @@ -0,0 +1,42 @@ +/* + * 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. + */ + +package co.elastic.clients.json; + +import co.elastic.clients.testkit.ModelTestCase; +import jakarta.json.stream.JsonParser; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; +import java.util.List; + +public class JsonpDeserializerTest extends ModelTestCase { + + @Test + public void testNullStringInArray() { + JsonpDeserializer> deser = JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()); + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader("[\"a\", null, \"b\"]")); + List list = deser.deserialize(parser, mapper); + + assertEquals("a", list.get(0)); + assertNull(list.get(1)); + assertEquals("b", list.get(2)); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/json/JsonpMapperTest.java b/java-client/src/test/java/co/elastic/clients/json/JsonpMapperTest.java new file mode 100644 index 000000000..37f31249f --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/json/JsonpMapperTest.java @@ -0,0 +1,209 @@ +/* + * 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. + */ + +package co.elastic.clients.json; + +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import jakarta.json.JsonArray; +import jakarta.json.JsonNumber; +import jakarta.json.bind.spi.JsonbProvider; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import org.eclipse.parsson.JsonProviderImpl; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; +import java.io.StringWriter; +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class JsonpMapperTest extends Assertions { + + String json = "{\"children\":[{\"doubleValue\":3.2,\"intValue\":2}],\"doubleValue\":2.1,\"intValue\":1," + + "\"stringValue\":\"foo\"}"; + + @Test + public void testJsonb() { + JsonpMapper mapper = new JsonbJsonpMapper(new JsonProviderImpl(), JsonbProvider.provider()); + testSerialize(mapper, json); + testDeserialize(mapper, json); + testLargeNumber(mapper); + } + + @Test + public void testJackson() { + JacksonJsonpMapper mapper = new JacksonJsonpMapper(); + testSerialize(mapper, json); + testDeserialize(mapper, json); + testLargeNumber(mapper); + } + + @Test + public void testJacksonCustomMapper() { + ObjectMapper jkMapper = new ObjectMapper(); + jkMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + jkMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + + JacksonJsonpMapper mapper = new JacksonJsonpMapper(jkMapper); + + String json = "{\"children\":[{\"double_value\":3.2,\"int_value\":2}],\"double_value\":2.1,\"int_value\":1," + + "\"string_value\":\"foo\"}"; + + testSerialize(mapper, json); + testDeserialize(mapper, json); + } + + @Test + public void testDeserializeWithType() { + + String json = "{\"foo\":{\"int_value\":1,\"double_value\":1.0},\"bar\":{\"int_value\":2,\"double_value\":2.0}}"; + + ObjectMapper jkMapper = new ObjectMapper(); + jkMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + JacksonJsonpMapper mapper = new JacksonJsonpMapper(jkMapper); + + // With type erasure, map values are raw json nodes + { + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + Map map = new HashMap<>(); + map = mapper.deserialize(parser, (Type) map.getClass()); + + Map finalMap = map; + assertThrows(ClassCastException.class, () -> { + assertEquals(1, finalMap.get("foo").intValue); + }); + } + + // Use a j.l.reflect.Type to deserialize map values correctly + { + TypeReference> typeRef = new TypeReference>() {}; + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + Map map = mapper.deserialize(parser, typeRef.getType()); + + System.out.println(map); + assertEquals(1, map.get("foo").intValue); + assertEquals(2, map.get("bar").intValue); + } + } + + private void testSerialize(JsonpMapper mapper, String expected) { + + SomeClass something = new SomeClass(); + something.setIntValue(1); + something.setDoubleValue(2.1); + something.setStringValue("foo"); + + SomeClass other = new SomeClass(); + other.setIntValue(2); + other.setDoubleValue(3.2); + something.setChildren(Collections.singletonList(other)); + + StringWriter strw = new StringWriter(); + JsonGenerator generator = mapper.jsonProvider().createGenerator(strw); + + mapper.serialize(something, generator); + + generator.close(); + + assertEquals(expected, strw.getBuffer().toString()); + } + + private void testDeserialize(JsonpMapper mapper, String json) { + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + SomeClass parsed = mapper.deserialize(parser, SomeClass.class); + + assertEquals(1, parsed.getIntValue()); + assertEquals(2.1, parsed.getDoubleValue(), 0.0); + assertEquals("foo", parsed.getStringValue()); + + List children = parsed.getChildren(); + assertEquals(1, children.size()); + + SomeClass child = children.get(0); + + assertEquals(2, child.getIntValue()); + assertEquals(3.2, child.getDoubleValue(), 0.0); + assertNull(child.getStringValue()); + assertNull(child.getChildren()); + } + + private void testLargeNumber(JsonpMapper mapper) { + String json = "[1e999999]"; + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + parser.next(); + + JsonArray array = parser.getValue().asJsonArray(); + + JsonNumber number = array.getJsonNumber(0); + + assertTrue(Double.isInfinite(number.doubleValue())); + + Assertions.assertThrows(Exception.class, number::bigIntegerValue); + } + + public static class SomeClass { + private List children; + private double doubleValue; + private int intValue; + private String stringValue; + + public int getIntValue() { + return intValue; + } + + public void setIntValue(int intValue) { + this.intValue = intValue; + } + + public String getStringValue() { + return stringValue; + } + + public void setStringValue(String stringValue) { + this.stringValue = stringValue; + } + + public double getDoubleValue() { + return doubleValue; + } + + public void setDoubleValue(double doubleValue) { + this.doubleValue = doubleValue; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/json/JsonpMappingExceptionTest.java b/java-client/src/test/java/co/elastic/clients/json/JsonpMappingExceptionTest.java new file mode 100644 index 000000000..0354e22a1 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/json/JsonpMappingExceptionTest.java @@ -0,0 +1,110 @@ +/* + * 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. + */ + +package co.elastic.clients.json; + +import co.elastic.clients.elasticsearch._types.mapping.TypeMapping; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.testkit.ModelTestCase; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; + +public class JsonpMappingExceptionTest extends ModelTestCase { + + @Test + public void testObjectAndArrayPath() { + + String json = "{" + + " \"took\" : 9," + + " \"timed_out\" : false," + + " \"_shards\" : {" + + " \"total\" : 1," + + " \"successful\" : 1," + + " \"skipped\" : 0," + + " \"failed\" : 0" + + " }," + + " \"hits\" : {" + + " \"total\" : {" + + " \"value\" : 1," + + " \"relation\" : \"eq\"" + + " }," + + " \"max_score\" : 1.0," + + " \"hits\" : [" + + " {" + + " \"_index\" : \"test\"," + + " \"_id\" : \"8aSerXUBs1w7Wkuj31zd\"," + + " \"_score\" : \"1.0\"," + + " \"_source\" : {" + + " \"foo\" : \"bar\"" + + " }" + + " }," + + " {" + + " \"_index\" : \"test\"," + + " \"_id\" : \"8aSerXUBs1w7Wkuj31zd\"," + + " \"_score\" : \"abc\"," + // <====== error here + " \"_source\" : {" + + " \"foo\" : \"bar\"" + + " }" + + " }" + + " ]" + + " }" + + "}"; + + JsonpMappingException e = assertThrows(JsonpMappingException.class, () -> { + // withJson() will read values of the generic parameter type as JsonData + SearchResponse r = SearchResponse.of(b -> b + .withJson(new StringReader(json)) + ); + }); + + assertTrue(e.getMessage().contains("Error deserializing co.elastic.clients.elasticsearch.core.search.Hit")); + assertTrue(e.getMessage().contains("java.lang.NumberFormatException")); + + // Also checks array index in path + assertEquals("hits.hits[1]._score", e.path()); + } + + @Test + public void testLookAhead() { + + String json = + "{" + + " \"properties\": { " + + " \"foo-bar\": {" + + " \"type\": \"text\"," + + " \"baz\": false" + + " }" + + " }" + + "}"; + + // Error deserializing co.elastic.clients.elasticsearch._types.mapping.TextProperty: + // Unknown field 'baz' (JSON path: properties['foo-bar'].baz) (...line no=1, column no=36, offset=35) + + JsonpMappingException e = assertThrows(JsonpMappingException.class, () -> { + fromJson(json, TypeMapping.class, SimpleJsonpMapper.INSTANCE_REJECT_UNKNOWN_FIELDS); + }); + + // Check escaping of non identifier path elements and path from map elements + assertEquals("properties['foo-bar'].baz", e.path()); + + String msg = e.getMessage(); + assertTrue(msg.contains("Unknown field 'baz'")); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/json/JsonpUtilsTest.java b/java-client/src/test/java/co/elastic/clients/json/JsonpUtilsTest.java new file mode 100644 index 000000000..a7f9b7a75 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/json/JsonpUtilsTest.java @@ -0,0 +1,331 @@ +/* + * 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. + */ + +package co.elastic.clients.json; + +import co.elastic.clients.elasticsearch.core.search.Hit; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.elasticsearch.security.IndexPrivilege; +import co.elastic.clients.elasticsearch.security.IndicesPrivileges; +import co.elastic.clients.elasticsearch.security.RoleTemplateScript; +import co.elastic.clients.elasticsearch.security.UserIndicesPrivileges; +import co.elastic.clients.util.AllowForbiddenApis; +import jakarta.json.JsonException; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; +import java.io.StringWriter; +import java.net.URL; +import java.util.Collections; +import java.util.Enumeration; +import java.util.function.Consumer; + +public class JsonpUtilsTest extends ModelTestCase { + + @Test + @AllowForbiddenApis("Testing JsonpUtil.provider()") + public void testProviderLoading() { + // See https://github.com/elastic/elasticsearch-java/issues/163 + + // Create an empty non-delegating classloader and set it as the context classloader. It simulates a + // plugin system that doesn't set the context classloader to the plugins classloader. + ClassLoader emptyLoader = new ClassLoader() { + @Override + public Enumeration getResources(String name) { + return Collections.emptyEnumeration(); + } + }; + + ClassLoader savedLoader = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(emptyLoader); + + assertThrows(JsonException.class, () -> { + assertNotNull(JsonProvider.provider()); + }); + + assertNotNull(JsonpUtils.provider()); + + } finally { + Thread.currentThread().setContextClassLoader(savedLoader); + } + } + + @Test + @AllowForbiddenApis("Testing JsonpUtil.provider()") + public void testProviderCache() { + // A new provider at each call + assertNotSame(JsonpUtils.findProvider(), JsonpUtils.findProvider()); + + // Result is cached + assertSame(JsonpUtils.provider(), JsonpUtils.provider()); + } + + @Test + public void testObjectToString() { + // Test that we call toString() on application classes. + Hit hit = Hit.of(h -> h + .source(new SomeUserData()) + .index("idx") + .id("id1") + ); + assertEquals("Hit: {\"_index\":\"idx\",\"_id\":\"id1\",\"_source\":\"Some user data\"}", hit.toString()); + } + + private static class SomeUserData { + @Override + public String toString() { + return "Some user data"; + } + } + + @Test + public void testLargeObjectToString() { + // Build a large string + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 1001; i++) { + sb.append("0123456789"); + } + + String text = sb.toString(); + assertEquals(10010, text.length()); + + Hit hit = Hit.of(h -> h + .source(text) + .index("idx") + .id("id1") + ); + + String toString = hit.toString(); + + assertEquals(10000 + "Hit: ".length() + "...".length(), toString.length()); + assertTrue(toString.startsWith("Hit: ")); + assertTrue(toString.endsWith("...")); + } + + @Test + public void testSerializeDoubleOrNull() { + // ---- Double values + assertEquals("{\"a\":null}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, Double.NaN, Double.NaN))); + assertEquals("{\"a\":1.0}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, 1.0, Double.NaN))); + + assertEquals("{\"a\":null}", + orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY))); + assertEquals("{\"a\":1.0}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, 1.0, Double.POSITIVE_INFINITY))); + + assertEquals("{\"a\":null}", + orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY))); + assertEquals("{\"a\":1.0}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, 1.0, Double.NEGATIVE_INFINITY))); + + assertEquals("{\"a\":null}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, Double.NaN, 0.0))); + + // Serialize defined default values + assertEquals("{\"a\":0.0}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, 0.0, 0.0))); + + } + + @Test + public void testSerializeIntOrNull() { + assertEquals("{\"a\":null}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, Integer.MAX_VALUE, Integer.MAX_VALUE))); + assertEquals("{\"a\":1}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, 1, Integer.MAX_VALUE))); + assertEquals("{\"a\":1}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, 1, 0))); + + // Integer.MAX_VALUE is valid if not the default value + assertEquals("{\"a\":2147483647}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, Integer.MAX_VALUE, 0))); + assertEquals("{\"a\":2147483647}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, Integer.MAX_VALUE, Integer.MIN_VALUE))); + + // Serialize non infinite default values + assertEquals("{\"a\":0}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, 0, 0))); + } + + @Test + public void testJsonString() { + // Single value + { + IndicesPrivileges priv = IndicesPrivileges.of(i -> i + .names("bar") + .query(q -> q.term(t -> t.field("baz").value(1))) + .privileges(IndexPrivilege.All.jsonValue()) + ); + + String json = "{\"names\":[\"bar\"],\"privileges\":[\"all\"],\"query\":\"{\\\"term\\\":{\\\"baz\\\":{\\\"value\\\":1}}}\"}"; + + assertEquals(json, toJson(priv)); + + priv = fromJson(json, IndicesPrivileges.class); + assertEquals("baz", priv.query().term().field()); + } + + // Single value template + { + IndicesPrivileges priv = IndicesPrivileges.of(i -> i + .names("bar") + .query(q -> q._custom("template", RoleTemplateScript.of(s -> s.id("foo")))) + .privileges(IndexPrivilege.All.jsonValue()) + ); + + String json = "{\"names\":[\"bar\"],\"privileges\":[\"all\"],\"query\":\"{\\\"template\\\":{\\\"id\\\":\\\"foo\\\"}}\"}"; + + assertEquals(json, toJson(priv)); + + priv = fromJson(json, IndicesPrivileges.class); + assertEquals("foo", priv.query()._custom().to(RoleTemplateScript.class).id()); + } + + // Array value + { + UserIndicesPrivileges priv = UserIndicesPrivileges.of(i -> i + .names("bar") + .query(q -> q.term(t -> t.field("baz").value(1))) + .privileges(IndexPrivilege.All.jsonValue()) + .allowRestrictedIndices(false) + ); + + String json = "{\"names\":[\"bar\"],\"privileges\":[\"all\"],\"query\":[\"{\\\"term\\\":{\\\"baz\\\":{\\\"value\\\":1}}}\"]," + + "\"allow_restricted_indices\":false}"; + + assertEquals(json, toJson(priv)); + + priv = fromJson(json, UserIndicesPrivileges.class); + assertEquals("baz", priv.query().get(0).term().field()); + } + } + + @Test + public void testCopy() { + // Tests round-tripping a json document that contains all event types and various kinds of nesting + + String json = "{\n" + + " \"p1\": \"str1\",\n" + + " \"p2\": 42,\n" + + " \"p3\": [\"str31\", \"str32\"],\n" + + " \"p4\": {\n" + + " \"p41\": \"str41\",\n" + + " \"p42\": [\"str421\", \"str422\"],\n" + + " \"p43\": {\n" + + " \"p431\": \"str431\"\n" + + " },\n" + + " \"p44\": true,\n" + + " \"p45\": false,\n" + + " \"p46\": 3.14\n" + + " },\n" + + " \"p5\": [{\n" + + " \"p51\": {\n" + + " \"p511\": \"str511\"\n" + + " }\n" + + " }],\n" + + " \"p6\": null\n" + + "}\n"; + + json = normalizeIndent(json); + + JsonProvider provider = JsonpUtils.provider(); + + JsonParser parser = provider.createParser(new StringReader(json)); + StringWriter sw = new StringWriter(); + JsonGenerator generator = provider.createGenerator(sw); + + JsonpUtils.copy(parser, generator); + parser.close(); + generator.close(); + + assertEquals(json, sw.toString()); + } + + private static String orNullHelper(Consumer c) { + StringWriter sw = new StringWriter(); + JsonGenerator generator = JsonpUtils.provider().createGenerator(sw); + + generator.writeStartObject(); + generator.writeKey("a"); + c.accept(generator); + generator.writeEnd(); + generator.close(); + + return sw.toString(); + } + + /** + * Normalizes the whitespace and indentation of a JSON string by parsing it and copying it to a string generator. + */ + private static String normalizeIndent(String json) { + JsonParser parser = JsonpUtils.provider().createParser(new StringReader(json)); + StringWriter sw = new StringWriter(); + JsonGenerator generator = JsonpUtils.provider().createGenerator(sw); + + copyAll(parser, generator); + + parser.close(); + generator.close(); + return sw.toString(); + } + + private static void copyAll(JsonParser parser, JsonGenerator generator) { + while(parser.hasNext()) { + switch (parser.next()) { + case START_OBJECT: + generator.writeStartObject(); + break; + + case END_OBJECT: + generator.writeEnd(); + break; + + case START_ARRAY: + generator.writeStartArray(); + break; + + case END_ARRAY: + generator.writeEnd(); + break; + + case KEY_NAME: + generator.writeKey(parser.getString()); + break; + + case VALUE_STRING: + generator.write(parser.getString()); + break; + + case VALUE_NULL: + generator.writeNull(); + break; + + case VALUE_TRUE: + generator.write(true); + break; + + case VALUE_FALSE: + generator.write(false); + break; + + case VALUE_NUMBER: + if (parser.isIntegralNumber()) { + generator.write(parser.getLong()); + } else { + generator.write(parser.getBigDecimal()); + } + break; + } + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/json/LazyDeserializerTest.java b/java-client/src/test/java/co/elastic/clients/json/LazyDeserializerTest.java new file mode 100644 index 000000000..fef389daf --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/json/LazyDeserializerTest.java @@ -0,0 +1,68 @@ +/* + * 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. + */ + +package co.elastic.clients.json; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.CompletableFuture; + +public class LazyDeserializerTest extends Assertions { + + @Test + public void testConcurrentInit() throws Exception { + // See https://github.com/elastic/elasticsearch-java/issues/58 + + final LazyDeserializer ld = new LazyDeserializer<>(JsonpDeserializer::stringDeserializer); + + CompletableFuture> fut1; + CompletableFuture> fut2; + + // Lock the mutex and start 2 threads that will compete for it. + synchronized (ld) { + fut1 = futureUnwrap(ld); + fut2 = futureUnwrap(ld); + } + + // We should see the same non-null results everywhere + assertNotNull(fut1.get()); + assertNotNull(fut2.get()); + + final JsonpDeserializer unwrapped = ld.unwrap(); + assertEquals(unwrapped, fut1.get()); + assertEquals(unwrapped, fut2.get()); + + } + + private CompletableFuture> futureUnwrap(LazyDeserializer d) { + + final CompletableFuture> result = new CompletableFuture<>(); + + new Thread(() -> { + try { + result.complete(d.unwrap()); + } catch (Throwable e) { + result.completeExceptionally(e); + } + }).start(); + + return result; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/json/ObjectBuilderDeserializerTest.java b/java-client/src/test/java/co/elastic/clients/json/ObjectBuilderDeserializerTest.java new file mode 100644 index 000000000..98954eea8 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/json/ObjectBuilderDeserializerTest.java @@ -0,0 +1,50 @@ +/* + * 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. + */ + +package co.elastic.clients.json; + +import co.elastic.clients.elasticsearch._types.mapping.TextProperty; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.elasticsearch.transform.UpdateTransformRequest; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; + +public class ObjectBuilderDeserializerTest extends ModelTestCase { + + @Test + public void testNullObjectValue() { + // Should also accept null for optional values + String json = "{ \"index_prefixes\": null }"; + fromJson(json, TextProperty.class); + } + + @Test + public void testNullObjectValueInFunctionBuilder() { + String json = "{\n" + + " \"retention_policy\": null\n" + + " }"; + + UpdateTransformRequest.Builder builder = new UpdateTransformRequest.Builder(); + builder.transformId("foo"); + builder.withJson(new StringReader(json)); + builder.build(); + } + +} diff --git a/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonJsonpGeneratorTest.java b/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonJsonpGeneratorTest.java new file mode 100644 index 000000000..1266f6495 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonJsonpGeneratorTest.java @@ -0,0 +1,90 @@ +/* + * 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. + */ + +package co.elastic.clients.json.jackson; + +import jakarta.json.Json; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonGenerator; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.StringWriter; + +public class JacksonJsonpGeneratorTest extends Assertions { + + @Test + public void testWrite(){ + StringWriter sw = new StringWriter(); + JsonGenerator generator = new JacksonJsonpMapper().jsonProvider().createGenerator(sw); + + generator.writeStartObject(); + + // Boolean + generator.write("bool1", true); + generator.writeKey("bool2"); + generator.write(false); + + // String + generator.write("str1", "foo"); + generator.writeKey("str2"); + generator.write("bar"); + + // Integer + generator.write("int1", 42); + generator.writeKey("int2"); + generator.write(1337); + + // Long + generator.write("long1", 123456789012345L); + generator.writeKey("long2"); + generator.write(123456789012345L); + + generator.write("double1", 0.001); + generator.writeKey("double2"); + generator.write(12345.6789); + + // JsonValue + JsonValue jsonValue = Json.createObjectBuilder() + .add("bool", true) + .add("str", "foo") + .add("int", 42) + .add("long", 123456789012345L) + .add("double", 12345.6789) + .build(); + + generator.write("value", jsonValue); + + generator.close(); + + assertEquals("{" + + "\"bool1\":true," + + "\"bool2\":false," + + "\"str1\":\"foo\"," + + "\"str2\":\"bar\"," + + "\"int1\":42," + + "\"int2\":1337," + + "\"long1\":123456789012345," + + "\"long2\":123456789012345," + + "\"double1\":0.001," + + "\"double2\":12345.6789," + + "\"value\":{\"bool\":true,\"str\":\"foo\",\"int\":42,\"long\":123456789012345,\"double\":12345.6789}" + + "}", sw.toString()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonJsonpParserTest.java b/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonJsonpParserTest.java new file mode 100644 index 000000000..3ac15c3f6 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonJsonpParserTest.java @@ -0,0 +1,193 @@ +/* + * 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. + */ + +package co.elastic.clients.json.jackson; + +import co.elastic.clients.elasticsearch.core.MsearchResponse; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.testkit.ModelTestCase; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParser.Event; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; + +public class JacksonJsonpParserTest extends ModelTestCase { + + private static final String json = + "{ 'foo': 'fooValue', 'bar': { 'baz': 1}, 'quux': [true] }".replace('\'', '"'); + + @Test + public void testEventStream() { + + JacksonJsonProvider provider = new JacksonJsonProvider(); + JsonParser parser = provider.createParser(new StringReader(json)); + + assertEquals(Event.START_OBJECT, parser.next()); + + assertEquals(Event.KEY_NAME, parser.next()); + assertEquals("foo", parser.getString()); + + assertEquals(Event.VALUE_STRING, parser.next()); + assertEquals("fooValue", parser.getString()); + + // test it sometimes, but not always to detect invalid state management + assertTrue(parser.hasNext()); + + assertEquals(Event.KEY_NAME, parser.next()); + assertEquals("bar", parser.getString()); + + assertEquals(Event.START_OBJECT, parser.next()); + + assertEquals(Event.KEY_NAME, parser.next()); + assertEquals("baz", parser.getString()); + + assertTrue(parser.hasNext()); + assertEquals(Event.VALUE_NUMBER, parser.next()); + assertEquals(1, parser.getInt()); + + assertEquals(Event.END_OBJECT, parser.next()); + + assertEquals(Event.KEY_NAME, parser.next()); + assertEquals("quux", parser.getString()); + + assertEquals(Event.START_ARRAY, parser.next()); + + assertEquals(Event.VALUE_TRUE, parser.next()); + + assertEquals(Event.END_ARRAY, parser.next()); + assertEquals(Event.END_OBJECT, parser.next()); + + assertFalse(parser.hasNext()); + } + + @Test + public void testForbidValueGettersAfterHasNext() { + + JacksonJsonProvider provider = new JacksonJsonProvider(); + JsonParser parser = provider.createParser(new StringReader(json)); + + assertEquals(Event.START_OBJECT, parser.next()); + assertEquals(Event.KEY_NAME, parser.next()); + assertEquals(Event.VALUE_STRING, parser.next()); + assertEquals("fooValue", parser.getString()); + + assertTrue(parser.hasNext()); + + try { + assertEquals("fooValue", parser.getString()); + fail(); + } catch (IllegalStateException e) { + // expected + } + } + + @Test + void testMultiSearchResponse() { + String json = + "{\n" + + " \"took\" : 1,\n" + + " \"responses\" : [\n" + + " {\n" + + " \"error\" : {\n" + + " \"root_cause\" : [\n" + + " {\n" + + " \"type\" : \"index_not_found_exception\",\n" + + " \"reason\" : \"no such index [foo_bar]\",\n" + + " \"resource.type\" : \"index_or_alias\",\n" + + " \"resource.id\" : \"foo_bar\",\n" + + " \"index_uuid\" : \"_na_\",\n" + + " \"index\" : \"foo_bar\"\n" + + " }\n" + + " ],\n" + + " \"type\" : \"index_not_found_exception\",\n" + + " \"reason\" : \"no such index [foo_bar]\",\n" + + " \"resource.type\" : \"index_or_alias\",\n" + + " \"resource.id\" : \"foo_bar\",\n" + + " \"index_uuid\" : \"_na_\",\n" + + " \"index\" : \"foo_bar\"\n" + + " },\n" + + " \"status\" : 404\n" + + " },\n" + + " {\n" + + " \"took\" : 1,\n" + + " \"timed_out\" : false,\n" + + " \"_shards\" : {\n" + + " \"total\" : 1,\n" + + " \"successful\" : 1,\n" + + " \"skipped\" : 0,\n" + + " \"failed\" : 0\n" + + " },\n" + + " \"hits\" : {\n" + + " \"total\" : {\n" + + " \"value\" : 5,\n" + + " \"relation\" : \"eq\"\n" + + " },\n" + + " \"max_score\" : 1.0,\n" + + " \"hits\" : [\n" + + " {\n" + + " \"_index\" : \"foo\",\n" + + " \"_id\" : \"Wr0ApoEBa_iiaABtVM57\",\n" + + " \"_score\" : 1.0,\n" + + " \"_source\" : {\n" + + " \"x\" : 1,\n" + + " \"y\" : true\n" + + " }\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"status\" : 200\n" + + " }\n" + + " ]\n" + + "}\n"; + + JsonpMapper mapper = new JacksonJsonpMapper(); + mapper = mapper.withAttribute("co.elastic.clients:Deserializer:_global.msearch.Response.TDocument", + JsonpDeserializer.of(Foo.class)); + @SuppressWarnings("unchecked") + MsearchResponse response = fromJson(json, MsearchResponse.class, mapper); + + assertEquals(2, response.responses().size()); + assertEquals(404, response.responses().get(0).failure().status()); + assertEquals(200, response.responses().get(1).result().status()); + } + + public static class Foo { + private int x; + private boolean y; + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public boolean isY() { + return y; + } + + public void setY(boolean y) { + this.y = y; + } + } + +} diff --git a/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonMapperTest.java b/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonMapperTest.java new file mode 100644 index 000000000..56d42d7ac --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonMapperTest.java @@ -0,0 +1,102 @@ +/* + * 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. + */ + +package co.elastic.clients.json.jackson; + +import co.elastic.clients.elasticsearch.core.search.Hit; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +public class JacksonMapperTest extends ModelTestCase { + + @Test + public void testCustomDeserializer() { + // See https://github.com/elastic/elasticsearch-java/issues/120 + JsonpMapper jsonpMapper = new JacksonJsonpMapper(); + + String json = "{\"_index\":\"foo\",\"_id\":\"1\",\"_source\":{\"model\":\"Foo\",\"age\":42}}"; + + Hit testDataHit = fromJson(json, + Hit.createHitDeserializer(JsonpDeserializer.of(TestData.class)), + jsonpMapper + ); + TestData data = testDataHit.source(); + assertEquals("Foo", data.theModel); + assertEquals(42, data.theAge); + } + + @JsonDeserialize(using = TestData.TestDeserializer.class) + public static class TestData { + public String theModel; + public int theAge; + + public static class TestDeserializer extends JsonDeserializer { + + @Override + public TestData deserialize(JsonParser jp, DeserializationContext ctx) throws IOException { + JsonNode node = jp.getCodec().readTree(jp); + + TestData res = new TestData(); + if (node.has("age")) { + res.theAge = node.get("age").asInt(); + } + if (node.has("model")) { + res.theModel = node.get("model").asText(); + } + return res; + } + } + } + + @Test + public void testSingleValueAsList() { + JsonpMapper jsonpMapper = new JacksonJsonpMapper(); + + String json = "{\"_index\":\"foo\",\"_id\":\"1\",\"_source\":{\"emp_no\":42,\"job_positions\":\"SWE\"}}"; + + Hit testDataHit = fromJson(json, + Hit.createHitDeserializer(JsonpDeserializer.of(EmpData.class)), + jsonpMapper + ); + EmpData data = testDataHit.source(); + assertEquals(42, data.empNo); + assertEquals(Collections.singletonList("SWE"), data.jobPositions); + } + + @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) + @JsonIgnoreProperties(ignoreUnknown = true) + public static class EmpData { + public int empNo; + public List jobPositions; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/json/jackson/JsonEnumTest.java b/java-client/src/test/java/co/elastic/clients/json/jackson/JsonEnumTest.java new file mode 100644 index 000000000..3ae53e2fc --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/json/jackson/JsonEnumTest.java @@ -0,0 +1,56 @@ +/* + * 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. + */ + +package co.elastic.clients.json.jackson; + +import co.elastic.clients.elasticsearch._types.query_dsl.SimpleQueryStringFlag; +import co.elastic.clients.elasticsearch._types.query_dsl.SimpleQueryStringQuery; +import co.elastic.clients.testkit.ModelTestCase; +import org.junit.jupiter.api.Test; + +public class JsonEnumTest extends ModelTestCase { + + @Test + public void testPipeSeparatedEnum() { + { + // Empty flags + String jsonNoFlags = "{\"query\":\"foo\"}"; + SimpleQueryStringQuery q = SimpleQueryStringQuery.of(b -> b + .query("foo") + ); + q = checkJsonRoundtrip(q, jsonNoFlags); + assertEquals("foo", q.query()); + assertTrue(q.flags().isEmpty()); + } + + { + // With flags + String jsonWithFlags = "{\"flags\":\"AND|NEAR\",\"query\":\"foo\"}"; + SimpleQueryStringQuery q = SimpleQueryStringQuery.of(b -> b + .query("foo") + .flags(SimpleQueryStringFlag.And, SimpleQueryStringFlag.Near) + ); + q = checkJsonRoundtrip(q, jsonWithFlags); + assertEquals("foo", q.query()); + assertEquals(2, q.flags().size()); + assertEquals(SimpleQueryStringFlag.And, q.flags().get(0)); + assertEquals(SimpleQueryStringFlag.Near, q.flags().get(1)); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/json/jackson/JsonValueParserTest.java b/java-client/src/test/java/co/elastic/clients/json/jackson/JsonValueParserTest.java new file mode 100644 index 000000000..0f49a6191 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/json/jackson/JsonValueParserTest.java @@ -0,0 +1,79 @@ +/* + * 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. + */ + +package co.elastic.clients.json.jackson; + +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import jakarta.json.JsonObject; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonParser; + +import java.io.StringReader; +import java.util.Map; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class JsonValueParserTest extends Assertions { + + public static class Data { + public Map data; + } + + @Test + public void testFloatsShouldDeserializeAsFloats() throws Exception { + // When using Jackson to target a map of objects, values with a decimal separator + // should deserialize as a double even if they fit in an int or long. + // See https://github.com/elastic/elasticsearch-java/issues/156 + + String json = "{\"data\": {\"value\": 1.4778125E7, \"value2\": 1.4778125E7 }}"; + JsonpMapper mapper = new JacksonJsonpMapper(); + + { + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + Data data = mapper.deserialize(parser, Data.class); + + Double d = (Double)data.data.get("value"); + assertEquals(1.4778125E7, d, 0.001); + } + + { + // Test with buffering used in union resolution + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + parser.next(); + JsonObject object = parser.getObject(); + + // Test equals/hashcode + JsonValue v = object.getJsonObject("data").get("value"); + JsonValue v2 = object.getJsonObject("data").get("value2"); + + assertEquals(v.hashCode(), v2.hashCode()); + assertEquals(v, v2); + + parser = JsonpUtils.jsonValueParser(object, mapper); + Data data = mapper.deserialize(parser, Data.class); + + Double d = (Double)data.data.get("value"); + assertEquals(1.4778125E7, d, 0.001); + } + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/testkit/MockHttpClient.java b/java-client/src/test/java/co/elastic/clients/testkit/MockHttpClient.java new file mode 100644 index 000000000..27b3fba3e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/testkit/MockHttpClient.java @@ -0,0 +1,156 @@ +/* + * 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. + */ + +package co.elastic.clients.testkit; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransportBase; +import co.elastic.clients.transport.TransportException; +import co.elastic.clients.transport.TransportOptions; +import co.elastic.clients.transport.http.TransportHttpClient; +import co.elastic.clients.util.BinaryData; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; + +public class MockHttpClient implements TransportHttpClient { + + private static final Response NotFound = new MockResponse(404, null); + + Map responses = new ConcurrentHashMap<>(); + + public MockHttpClient add(String path, String contentType, byte[] data) { + responses.put(path, new MockResponse(200, BinaryData.of(data, contentType))); + return this; + } + + public MockHttpClient add(String path, String contentType, String text) { + responses.put(path, new MockResponse(200, BinaryData.of(text.getBytes(StandardCharsets.UTF_8), contentType))); + return this; + } + + public ElasticsearchClient client() { + return client(new ModelTestCase() {}.mapper); + } + + public ElasticsearchClient client(JsonpMapper mapper) { + return new ElasticsearchClient(new ElasticsearchTransportBase(this, null, mapper) { + @Override + public void close() throws IOException { + super.close(); + } + }); + } + + + @Override + public Response performRequest( + String endpointId, @Nullable TransportHttpClient.Node node, Request request, TransportOptions option + ) throws IOException { + Response response = responses.get(request.path()); + + if (response == null) { + throw new TransportException(NotFound, "Not found", endpointId); + } + + return response; + } + + @Override + public CompletableFuture performRequestAsync( + String endpointId, @Nullable TransportHttpClient.Node node, Request request, TransportOptions options + ) { + CompletableFuture result = new CompletableFuture<>(); + try { + Response response = performRequest(endpointId, node, request, options); + result.complete(response); + } catch (Exception e) { + result.completeExceptionally(e); + } + return result; + } + + @Override + public void close() throws IOException { + } + + private static class MockResponse implements Response { + + private final int statusCode; + private final BinaryData body; + private final Map headers; + + MockResponse(int statusCode, BinaryData body) { + this.statusCode = statusCode; + this.headers = new HashMap<>(); + this.body = body; + + if (body != null) { + headers.put("content-type", body.contentType()); + } + headers.put("x-elastic-product", "Elasticsearch"); + } + + @Override + public Node node() { + return null; + } + + @Override + public int statusCode() { + return statusCode; + } + + @Nullable + @Override + public String header(String name) { + return headers.get(name.toLowerCase()); + } + + @Override + public List headers(String name) { + String header = header(name); + return header == null ? null : Collections.singletonList(header); + } + + @Nullable + @Override + public BinaryData body() throws IOException { + return body; + } + + @Nullable + @Override + public Object originalResponse() { + return null; + } + + @Override + public void close() throws IOException { + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/testkit/ModelTestCase.java b/java-client/src/test/java/co/elastic/clients/testkit/ModelTestCase.java new file mode 100644 index 000000000..7d6cdbbb2 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/testkit/ModelTestCase.java @@ -0,0 +1,151 @@ +/* + * 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. + */ + +package co.elastic.clients.testkit; + +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.SimpleJsonpMapper; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import org.junit.jupiter.api.Assertions; + +import java.io.StringReader; +import java.io.StringWriter; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.EnumSet; +import java.util.Random; + +/** + * Base class for tests that encode/decode json + */ +public abstract class ModelTestCase extends Assertions { + + protected enum JsonImpl { Jsonb, Jackson, Simple }; + + // Same value for all tests in a test run + private static final int RAND = new Random().nextInt(100); + + protected final JsonImpl jsonImpl; + protected final JsonpMapper mapper; + + private static JsonImpl chooseJsonImpl(EnumSet jsonImplCandidates, int rand) { + // Converting an EnumSet to an array always uses the same order. + return jsonImplCandidates.toArray(new JsonImpl[jsonImplCandidates.size()])[rand % jsonImplCandidates.size()]; + } + + private static JsonpMapper createMapper(JsonImpl jsonImpl, int rand) { + switch(jsonImpl) { + case Jsonb: + System.out.println("Using a JsonB mapper (rand = " + rand + ")."); + return new JsonbJsonpMapper(); + + case Jackson: + System.out.println("Using a Jackson mapper (rand = " + rand + ")."); + return new JacksonJsonpMapper(); + + default: + System.out.println("Using a simple mapper (rand = " + rand + ")."); + return SimpleJsonpMapper.INSTANCE; + } + } + + protected ModelTestCase(EnumSet jsonImplCandidates, int rand) { + jsonImpl = chooseJsonImpl(jsonImplCandidates, rand); + mapper = createMapper(jsonImpl, rand); + } + + protected ModelTestCase(EnumSet jsonImplCandidates) { + this(jsonImplCandidates, RAND); + } + + protected ModelTestCase(JsonImpl jsonImpl) { + this(EnumSet.of(jsonImpl), RAND); + } + + protected ModelTestCase(int rand) { + this(EnumSet.allOf(JsonImpl.class), rand); + } + + protected ModelTestCase() { + this(EnumSet.allOf(JsonImpl.class), RAND); + } + + protected String toJson(T value) { + return toJson(value, mapper); + } + + public static String toJson(T value, JsonpMapper mapper) { + StringWriter sw = new StringWriter(); + JsonProvider provider = mapper.jsonProvider(); + JsonGenerator generator = provider.createGenerator(sw); + mapper.serialize(value, generator); + generator.close(); + return sw.toString(); + } + + public static T fromJson(String json, Class clazz, JsonpMapper mapper) { + return fromJson(json, (Type)clazz, mapper); + } + + public static T fromJson(String json, Type type, JsonpMapper mapper) { + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + return mapper.deserialize(parser, type); + } + + protected T fromJson(String json, Class clazz) { + return fromJson(json, clazz, mapper); + } + + protected T fromJson(String json, Type type) { + return fromJson(json, type, mapper); + } + + @SuppressWarnings("unchecked") + protected T checkJsonRoundtrip(T value, String expectedJson) { + assertEquals(expectedJson, toJson(value)); + return fromJson(expectedJson, (Class)value.getClass()); + } + + protected T fromJson(String json, JsonpDeserializer deserializer) { + return fromJson(json, deserializer, mapper); + } + + protected T fromJson(String json, JsonpDeserializer deserializer, JsonpMapper mapper) { + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + return deserializer.deserialize(parser, mapper); + } + + + public static void assertGetterType(Class expected, Class clazz, String name) { + Method method; + try { + method = clazz.getMethod(name); + } catch (NoSuchMethodException e) { + fail("Getter '" + clazz.getName() + "." + name + "' doesn't exist"); + return; + } + + assertSame(expected, method.getReturnType()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java b/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java new file mode 100644 index 000000000..c7927f980 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java @@ -0,0 +1,163 @@ +/* + * 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. + */ + +package co.elastic.clients.transport; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import com.sun.net.httpserver.HttpServer; +import org.apache.http.HttpHost; +import org.apache.http.NameValuePair; +import org.apache.http.client.utils.URLEncodedUtils; +import org.elasticsearch.client.ResponseException; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; + +public class RequestOptionsTest extends Assertions { + + private static HttpServer httpServer; + private static RestClient restClient; + + @BeforeEach + public void classSetup() throws IOException { + + httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + httpServer.createContext("/", ex -> { + if (ex.getRequestMethod().equals("HEAD")) { + // Call to ping() + ex.sendResponseHeaders(200, -1); + } + + // Call to info() + // Send back all request headers with a 418 that will cause an exception where we can access the LLRC response + ex.getResponseHeaders().putAll(ex.getRequestHeaders()); + ex.sendResponseHeaders(418, 0); + OutputStreamWriter out = new OutputStreamWriter(ex.getResponseBody(), StandardCharsets.UTF_8); + for (Map.Entry> header: ex.getRequestHeaders().entrySet()) { + out.write("header-"); + out.write(header.getKey().toLowerCase(Locale.ROOT)); + out.write("="); + out.write(header.getValue().get(0)); + out.write("\n"); + } + final List params = URLEncodedUtils.parse(ex.getRequestURI(), StandardCharsets.UTF_8); + for (NameValuePair param: params) { + out.write("param-"); + out.write(param.getName()); + out.write("="); + out.write(param.getValue()); + } + out.close(); + }); + + httpServer.start(); + InetSocketAddress address = httpServer.getAddress(); + restClient = RestClient.builder(new HttpHost(address.getHostString(), address.getPort(), "http")) + .build(); + } + + @AfterEach + public void classTearDown() throws IOException { + httpServer.stop(0); + restClient.close(); + } + + private Properties getProps(ElasticsearchClient client) throws IOException { + ResponseException ex = assertThrows(ResponseException.class, client::info); + assertEquals(418, ex.getResponse().getStatusLine().getStatusCode()); + Properties result = new Properties(); + result.load(ex.getResponse().getEntity().getContent()); + return result; + } + + @Test + public void testNonNullClientOptions() { + final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); + final ElasticsearchClient client = new ElasticsearchClient(trsp); + + assertNotNull(client._transportOptions()); + assertSame(trsp.options(), client._transportOptions()); + } + + @Test + public void testDefaultHeaders() throws IOException { + final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); + final ElasticsearchClient client = new ElasticsearchClient(trsp); + + Properties props = getProps(client); + + assertTrue(props.getProperty("header-user-agent").startsWith("elastic-java/" + Version.VERSION.toString())); + assertTrue(props.getProperty("header-x-elastic-client-meta").contains("es=")); + assertTrue(props.getProperty("header-x-elastic-client-meta").contains("hl=2")); + assertEquals( + "application/vnd.elasticsearch+json; compatible-with=" + Version.VERSION.major(), + props.getProperty("header-accept") + ); + } + + @Test + public void testClientHeader() throws IOException { + final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); + final ElasticsearchClient client = new ElasticsearchClient(trsp) + .withTransportOptions(b -> b + .addHeader("X-Foo", "Bar") + .addHeader("uSer-agEnt", "MegaClient/1.2.3") + ); + + Properties props = getProps(client); + assertEquals("Bar", props.getProperty("header-x-foo")); + assertEquals("MegaClient/1.2.3", props.getProperty("header-user-agent")); + } + + @Test + public void testQueryParameter() throws IOException { + final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); + final ElasticsearchClient client = new ElasticsearchClient(trsp) + .withTransportOptions(trsp.options().with( + b -> b.setParameter("format", "pretty") + ) + ); + + Properties props = getProps(client); + assertEquals("pretty", props.getProperty("param-format")); + } + + @Test + public void testMissingProductHeader() { + final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); + final ElasticsearchClient client = new ElasticsearchClient(trsp); + + final TransportException ex = assertThrows(TransportException.class, client::ping); + assertTrue(ex.getMessage().contains("Missing [X-Elastic-Product] header")); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/TransportTest.java b/java-client/src/test/java/co/elastic/clients/transport/TransportTest.java new file mode 100644 index 000000000..d25466bbd --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/TransportTest.java @@ -0,0 +1,155 @@ +/* + * 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. + */ + +package co.elastic.clients.transport; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.http.RepeatableBodyResponse; +import co.elastic.clients.transport.rest_client.RestClientOptions; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.util.BinaryData; +import com.sun.net.httpserver.HttpServer; +import org.apache.http.HttpHost; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.Collections; + +import static co.elastic.clients.util.ContentType.APPLICATION_JSON; + +public class TransportTest extends Assertions { + + @Test + public void testXMLResponse() throws Exception { + HttpServer httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), + 0), 0); + + httpServer.createContext("/_cat/indices", exchange -> { + exchange.sendResponseHeaders(401, 0); + OutputStream out = exchange.getResponseBody(); + out.write( + "Error".getBytes(StandardCharsets.UTF_8) + ); + out.close(); + }); + + httpServer.start(); + InetSocketAddress address = httpServer.getAddress(); + + RestClient restClient = RestClient + .builder(new HttpHost(address.getHostString(), address.getPort(), "http")) + .build(); + + ElasticsearchClient esClient = new ElasticsearchClient(new RestClientTransport(restClient, + new JacksonJsonpMapper())); + + TransportException ex = Assertions.assertThrows( + TransportException.class, + () -> esClient.cat().indices() + ); + + httpServer.stop(0); + + assertEquals(401, ex.statusCode()); + assertEquals("es/cat.indices", ex.endpointId()); + + // Original response is transport-dependent + Response restClientResponse = (Response) ex.response().originalResponse(); + assertEquals(401, restClientResponse.getStatusLine().getStatusCode()); + } + + + @Test + public void testOriginalJsonBodyRetrievalException() throws Exception { + HttpServer httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), + 0), 0); + + httpServer.createContext("/_cat/indices", exchange -> { + exchange.getResponseHeaders().put("Content-Type", Collections.singletonList(APPLICATION_JSON)); + exchange.getResponseHeaders().put("X-Elastic-Product", Collections.singletonList("Elasticsearch" + )); + exchange.sendResponseHeaders(200, 0); + OutputStream out = exchange.getResponseBody(); + out.write( + "definitely not json".getBytes(StandardCharsets.UTF_8) + ); + out.close(); + }); + + httpServer.start(); + InetSocketAddress address = httpServer.getAddress(); + + RestClient restClient = RestClient + .builder(new HttpHost(address.getHostString(), address.getPort(), "http")) + .build(); + + // no transport options, response is not RepeatableBodyResponse, original body cannot be retrieved + ElasticsearchClient esClient = new ElasticsearchClient(new RestClientTransport(restClient, + new JacksonJsonpMapper())); + + TransportException ex = Assertions.assertThrows( + TransportException.class, + () -> esClient.cat().indices() + ); + + assertEquals(200, ex.statusCode()); + assertNotEquals(RepeatableBodyResponse.class, ex.response().getClass()); + + // setting transport option + RestClientOptions options = new RestClientOptions(RequestOptions.DEFAULT, true); + + ElasticsearchTransport transport = new RestClientTransport( + restClient, new JacksonJsonpMapper(), options); + + ElasticsearchClient esClientOptions = new ElasticsearchClient(transport); + + ex = Assertions.assertThrows( + TransportException.class, + () -> esClientOptions.cat().indices() + ); + + httpServer.stop(0); + + assertEquals(200, ex.statusCode()); + assertEquals(RepeatableBodyResponse.class, ex.response().getClass()); + + try (RepeatableBodyResponse repeatableResponse = (RepeatableBodyResponse) ex.response()){ + BinaryData body = repeatableResponse.body(); + StringBuilder sb = new StringBuilder(); + BufferedReader br = new BufferedReader(new InputStreamReader(body.asInputStream())); + String read; + + while ((read = br.readLine()) != null) { + sb.append(read); + } + br.close(); + assertEquals("definitely not json",sb.toString()); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java b/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java new file mode 100644 index 000000000..9b0ee3081 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java @@ -0,0 +1,122 @@ +/* + * 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. + */ + +package co.elastic.clients.transport; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.ElasticsearchTestServer; +import co.elastic.clients.json.SimpleJsonpMapper; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.testcontainers.elasticsearch.ElasticsearchContainer; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; + +public class TransportUtilsTest extends Assertions { + + @Test + public void testNoSslContext() { + assertThrows( + SSLHandshakeException.class, + () -> checkConnection(null) + ); + } + + @Test + public void testCaCertificate() throws Exception { + byte[] cert = ElasticsearchTestServer.global().container().caCertAsBytes().get(); + + checkConnection( + TransportUtils.sslContextFromHttpCaCrt(new ByteArrayInputStream(cert)) + ); + } + + @Test void testCaFingerprint() throws Exception { + byte[] pemCert = ElasticsearchTestServer.global().container().caCertAsBytes().get(); + + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + Certificate x509cert = cf.generateCertificate(new ByteArrayInputStream(pemCert)); + + // Compute SHA-256 fingerprint, which is what ES outputs at start time + String fingerprint = fingerprint(x509cert.getEncoded(), "SHA-256"); + + checkConnection( + TransportUtils.sslContextFromCaFingerprint(fingerprint) + ); + } + + @Test void testInvalidFingerprint() throws Exception { + // Build a dummy SHA-256 signature + String fingerprint = fingerprint("foobar".getBytes(StandardCharsets.UTF_8), "SHA-256"); + + assertThrows( + SSLHandshakeException.class, + () -> checkConnection( + TransportUtils.sslContextFromCaFingerprint(fingerprint) + ) + ); + } + + private void checkConnection(SSLContext sslContext) throws Exception { + ElasticsearchContainer container = ElasticsearchTestServer.global().container(); + + BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); + credsProv.setCredentials( + AuthScope.ANY, new UsernamePasswordCredentials("elastic", "changeme") + ); + + RestClient restClient = RestClient.builder(new HttpHost("localhost", container.getMappedPort(9200), "https")) + .setHttpClientConfigCallback(c -> c + .setSSLContext(sslContext) + .setDefaultCredentialsProvider(credsProv) + ) + .build(); + + RestClientTransport transport = new RestClientTransport(restClient, SimpleJsonpMapper.INSTANCE); + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + assertNotNull(esClient.info()); + } + + private String fingerprint(byte[] bytes, String algorithm) throws Exception { + byte[] fingerprint; + MessageDigest md = MessageDigest.getInstance(algorithm); + md.update(bytes); + fingerprint = md.digest(); + + StringBuilder sb = new StringBuilder(fingerprint.length * 2); + for(byte b: fingerprint) { + sb.append(String.format("%02x", b)); + } + + return sb.toString(); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/VersionInfoTest.java b/java-client/src/test/java/co/elastic/clients/transport/VersionInfoTest.java new file mode 100644 index 000000000..001fcbd41 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/VersionInfoTest.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package co.elastic.clients.transport; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class VersionInfoTest { + + @Test + public void testClientMeta() { + String version = VersionInfo.VERSION; + Assertions.assertTrue(ElasticsearchTransportBase.getClientMeta().startsWith("es=" + version + ",jv=")); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/endpoints/BinaryEndpointTest.java b/java-client/src/test/java/co/elastic/clients/transport/endpoints/BinaryEndpointTest.java new file mode 100644 index 000000000..de4175b3c --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/endpoints/BinaryEndpointTest.java @@ -0,0 +1,128 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.endpoints; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.ElasticsearchTestServer; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.json.SimpleJsonpMapper; +import co.elastic.clients.transport.TransportOptions; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import com.sun.net.httpserver.HttpServer; +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpHost; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; + +public class BinaryEndpointTest extends Assertions { + + /** Collected headers by test name */ + private static HttpServer httpServer; + + @BeforeAll + public static void setup() throws IOException { + httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + + // Register a handler on the core.exists("capture-handler/{name}") endpoint that will capture request headers. + httpServer.createContext("/foo/_mvt/bar/1/0/0", exchange -> { + // Reply with an empty 200 response + exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); + exchange.getResponseHeaders().set("Content-Type", "application/vnd.hello-world"); + exchange.sendResponseHeaders(200, 0); + exchange.getResponseBody().write("Hello world".getBytes(StandardCharsets.UTF_8)); + exchange.close(); + }); + + httpServer.start(); + } + + @AfterAll + public static void cleanup() { + httpServer.stop(0); + httpServer = null; + } + + @Test + public void testMvtSearch() throws IOException { + RestClient llrc = RestClient.builder( + new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort(), "http") + ).build(); + + RestClientTransport transport = new RestClientTransport(llrc, new SimpleJsonpMapper()); + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + BinaryResponse resp = esClient.searchMvt(s -> s + .index("foo") + .field("bar") + .x(0) + .y(0) + .zoom(1) + ); + + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[256]; + + try(InputStream input = resp.content()) { + int len; + while ((len = input.read(buffer)) > 0) { + baos.write(buffer, 0, len); + } + } + + assertEquals("application/vnd.hello-world", resp.contentType()); + assertEquals("Hello world", baos.toString(StandardCharsets.UTF_8.name())); + } + + @Test + public void convertJsonToBinaryEndpoint() throws IOException { + + ElasticsearchClient esClient = ElasticsearchTestServer.global().client(); + + // Create the search request + SearchRequest request = SearchRequest.of(b -> b); + + // Create a binary endpoint from the regular search endpoint. It will not deserialize + // the response and instead will just return the raw response input stream. + BinaryEndpoint binarySearchEndpoint = SearchRequest._ENDPOINT.withBinaryResponse(); + + // Force typed_keys to false, so that aggregations names do not hold type information + TransportOptions options = esClient._transportOptions().toBuilder() + .setParameter("typed_keys", "false") + .build(); + + // Call Elasticsearch by providing the transport the request and endpoint + BinaryResponse binaryResponse = esClient._transport().performRequest(request, binarySearchEndpoint, options); + + // Do something with the response + String response = IOUtils.toString(binaryResponse.content(), StandardCharsets.UTF_8); + assertTrue(response.matches("\\{\"took\":\\d+,\"timed_out\":false.*")); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/endpoints/BooleanEndpointTest.java b/java-client/src/test/java/co/elastic/clients/transport/endpoints/BooleanEndpointTest.java new file mode 100644 index 000000000..1c1b3dfc7 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/endpoints/BooleanEndpointTest.java @@ -0,0 +1,37 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.endpoints; + +import co.elastic.clients.elasticsearch.core.ExistsRequest; +import co.elastic.clients.elasticsearch.security.SamlCompleteLogoutRequest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class BooleanEndpointTest extends Assertions { + + @Test + public void testHasRequestBody() { + ExistsRequest er = ExistsRequest.of(r -> r.index("foo").id("1")); + assertNull(ExistsRequest._ENDPOINT.body(er)); + + SamlCompleteLogoutRequest sclr = SamlCompleteLogoutRequest.of(r -> r.ids("1").realm("r")); + assertNotNull(SamlCompleteLogoutRequest._ENDPOINT.body(sclr)); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/endpoints/EndpointBaseTest.java b/java-client/src/test/java/co/elastic/clients/transport/endpoints/EndpointBaseTest.java new file mode 100644 index 000000000..296bc3b20 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/endpoints/EndpointBaseTest.java @@ -0,0 +1,68 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.endpoints; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch.core.PingRequest; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.transport.Endpoint; +import org.junit.jupiter.api.Test; + +public class EndpointBaseTest extends ModelTestCase { + + @Test + public void testPathEncoding() { + assertEquals("abCD12;-_*", pathEncode("abCD12;-_*")); + assertEquals("XYZ%5B", pathEncode("XYZ[")); + assertEquals("xyz%7B", pathEncode("xyz{")); + assertEquals("foo%2Fbar", pathEncode("foo/bar")); + assertEquals("foo%20bar", pathEncode("foo bar")); + assertEquals("f%C3%AAl%C3%A9", pathEncode("fêlé")); + } + + private String pathEncode(String s) { + StringBuilder sb = new StringBuilder(); + EndpointBase.pathEncode(s, sb); + return sb.toString(); + } + + @Test + public void testErrorDecoding() { + Endpoint endpoint = PingRequest._ENDPOINT; + + { + String json = "{\"error\":\"some error\"}"; + + ErrorResponse response = fromJson(json, endpoint.errorDeserializer(404)); + assertEquals(404, response.status()); + assertEquals("some error", response.error().reason()); + assertEquals("http_status_404", response.error().type()); + } + + { + String json = "{\"status\":401,\"error\":{\"type\":\"the_error_type\",\"reason\":\"some error\"}}"; + + ErrorResponse response = fromJson(json, endpoint.errorDeserializer(404)); + assertEquals(401, response.status()); // value in response body has precedence + assertEquals("some error", response.error().reason()); + assertEquals("the_error_type", response.error().type()); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/endpoints/SimpleEndpointTest.java b/java-client/src/test/java/co/elastic/clients/transport/endpoints/SimpleEndpointTest.java new file mode 100644 index 000000000..263e94ac8 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/endpoints/SimpleEndpointTest.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.endpoints; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.core.CountResponse; +import co.elastic.clients.testkit.MockHttpClient; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.ElasticsearchTransportBase; +import co.elastic.clients.transport.TransportOptions; +import co.elastic.clients.transport.http.TransportHttpClient; +import org.jetbrains.annotations.Nullable; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class SimpleEndpointTest extends ModelTestCase { + + @Test + public void testNoBodyForEmptyObject() throws Exception { + + List requests = new ArrayList<>(); + + MockHttpClient httpClient = new MockHttpClient() { + @Override + public Response performRequest( + String endpointId, @Nullable Node node, Request request, TransportOptions option + ) throws IOException { + requests.add(request); + return super.performRequest(endpointId, node, request, option); + } + }; + + httpClient.add("/_count", "application/json", toJson( + CountResponse.of(c -> c + .count(1) + .shards(s -> s.successful(1).failed(0).total(1)) + ))); + + ElasticsearchTransport transport = new ElasticsearchTransportBase(httpClient, null, mapper) {}; + ElasticsearchClient client = new ElasticsearchClient(transport, null); + + client.count(); + client.count(c -> c.q("foo:bar")); + client.count(c -> c.query(q -> q.term(t -> t.field("foo").value("bar")))); + + assertNull(requests.get(0).body()); + assertNull(requests.get(1).body()); + assertNotNull(requests.get(2).body()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/http/HeaderMapTest.java b/java-client/src/test/java/co/elastic/clients/transport/http/HeaderMapTest.java new file mode 100644 index 000000000..83dee0f8e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/http/HeaderMapTest.java @@ -0,0 +1,78 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.http; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Iterator; +import java.util.Map; + +class HeaderMapTest extends Assertions { + + @Test + public void testCaseSensitivity() { + HeaderMap headers = new HeaderMap(); + + headers.put("Foo", "bar"); + assertEquals("bar", headers.get("Foo")); + assertEquals("bar", headers.get("foo")); + assertEquals("bar", headers.get("fOO")); + + headers.put("foo", "baz"); + assertEquals("baz", headers.get("Foo")); + assertEquals("baz", headers.get("foo")); + assertEquals("baz", headers.get("fOO")); + } + + @Test + public void testLock() { + HeaderMap headers = new HeaderMap(); + + headers.put("foo", "bar"); + + HeaderMap locked = headers.locked(); + assertEquals("bar", headers.get("Foo")); + + assertThrows(UnsupportedOperationException.class, () -> { + locked.put("foo", "baz"); + }); + + assertThrows(UnsupportedOperationException.class, () -> { + Iterator> iterator = locked.entrySet().iterator(); + assertEquals("bar", iterator.next().getValue()); + iterator.remove(); + }); + + headers.put("foo", "baz"); + assertEquals("baz", headers.get("Foo")); + assertEquals("bar", locked.get("Foo")); + } + + @Test + public void testAdd() { + HeaderMap headers = new HeaderMap(); + + headers.add("Foo", "bar"); + headers.add("foo", "baz"); + + assertEquals("bar; baz", headers.get("Foo")); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/instrumentation/OpenTelemetryForElasticsearchTest.java b/java-client/src/test/java/co/elastic/clients/transport/instrumentation/OpenTelemetryForElasticsearchTest.java new file mode 100644 index 000000000..f9435165d --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/instrumentation/OpenTelemetryForElasticsearchTest.java @@ -0,0 +1,275 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.instrumentation; + +import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.query_dsl.Query; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import com.sun.net.httpserver.HttpServer; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import org.apache.http.HttpHost; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class OpenTelemetryForElasticsearchTest { + private static final String INDEX = "test-index"; + private static final String DOC_ID = "1234567"; + private static final String DOC_RESPONSE = "{\n" + + " \"_index\": \"" + INDEX + "\",\n" + + " \"_id\": \"" + DOC_ID + "\",\n" + + " \"_version\": 1,\n" + + " \"_seq_no\": 0,\n" + + " \"_primary_term\": 1,\n" + + " \"found\": true,\n" + + " \"_source\": {\n" + + " \"@timestamp\": \"2099-11-15T14:12:12\",\n" + + " \"message\": \"GET /search HTTP/1.1 200 1070000\"\n" + + " }\n" + + "}"; + private static final String SEARCH_RESPONSE = "{\n" + + " \"took\": 5,\n" + + " \"timed_out\": false,\n" + + " \"_shards\": {\n" + + " \"total\": 1,\n" + + " \"successful\": 1,\n" + + " \"skipped\": 0,\n" + + " \"failed\": 0\n" + + " },\n" + + " \"hits\": {\n" + + " \"total\": {\n" + + " \"value\": 1,\n" + + " \"relation\": \"eq\"\n" + + " },\n" + + " \"max_score\": 1.3862942,\n" + + " \"hits\": [\n" + + " {\n" + + " \"_index\": \"" + INDEX + "\",\n" + + " \"_id\": \"" + DOC_ID + "\",\n" + + " \"_score\": 1.3862942,\n" + + " \"_source\": {\n" + + " \"@timestamp\": \"2099-11-15T14:12:12\",\n" + + " \"message\": \"GET /search HTTP/1.1 200 1070000\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + public static final String DB_OPERATION = "db.operation"; + public static final String URL_FULL = "url.full"; + public static final String SERVER_ADDRESS = "server.address"; + public static final String SERVER_PORT = "server.port"; + // has been renamed in 1.21 from http.method - see https://github.com/open-telemetry/semantic-conventions/blob/main/schemas/1.21.0 + public static final String HTTP_REQUEST_METHOD = "http.request.method"; + private static HttpServer httpServer; + private static MockSpanExporter spanExporter; + private static OpenTelemetry openTelemetry; + private static RestClient restClient; + private static RestClientTransport transport; + private static ElasticsearchClient client; + private static ElasticsearchAsyncClient asyncClient; + + @BeforeAll + public static void setup() throws IOException { + setupOTel(); + setupHttpServer(); + setupClient(); + } + + @AfterAll + public static void cleanUp() throws IOException { + httpServer.stop(0); + transport.close(); + } + + private static void setupClient() { + restClient = + RestClient.builder(new HttpHost(httpServer.getAddress().getAddress(), httpServer.getAddress().getPort())).build(); + + Instrumentation instrumentation = new OpenTelemetryForElasticsearch(openTelemetry, false); + + transport = new RestClientTransport(restClient, new JacksonJsonpMapper(), null, instrumentation); + + client = new ElasticsearchClient(transport); + asyncClient = new ElasticsearchAsyncClient(transport); + } + + private static void setupHttpServer() throws IOException { + httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + + // handler for GetRequest + httpServer.createContext("/" + INDEX + "/_doc/" + DOC_ID, exchange -> { + exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); + exchange.getResponseHeaders().set("Content-Type", "application/json"); + exchange.sendResponseHeaders(200, 0); + exchange.getResponseBody().write(DOC_RESPONSE.getBytes()); + exchange.close(); + }); + + // handler for SearchRequest + httpServer.createContext("/" + INDEX + "/_search", exchange -> { + exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); + exchange.getResponseHeaders().set("Content-Type", "application/json"); + exchange.sendResponseHeaders(200, 0); + exchange.getResponseBody().write(SEARCH_RESPONSE.getBytes()); + exchange.close(); + }); + + httpServer.start(); + } + + private static void setupOTel() { + Resource resource = Resource.getDefault() + .merge(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, "es-api-test"))); + + spanExporter = new MockSpanExporter(); + + SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() + .addSpanProcessor(SimpleSpanProcessor.create(spanExporter)) + .setResource(resource) + .build(); + + openTelemetry = OpenTelemetrySdk.builder() + .setTracerProvider(sdkTracerProvider) + .build(); + } + + @BeforeEach + public void reset() { + spanExporter.reset(); + } + + @Test + public void testGetRequest() throws IOException, InterruptedException { + client.get(r -> r.index(INDEX).id(DOC_ID).refresh(true), Object.class); + Assertions.assertEquals(spanExporter.getSpans().size(), 1); + SpanData span = spanExporter.getSpans().get(0); + Assertions.assertEquals("get", span.getName()); + Assertions.assertEquals("get", span.getAttributes().get(AttributeKey.stringKey(DB_OPERATION))); + Assertions.assertEquals("GET", span.getAttributes().get(AttributeKey.stringKey(HTTP_REQUEST_METHOD))); + Assertions.assertEquals("elasticsearch", span.getAttributes().get(SemanticAttributes.DB_SYSTEM)); + + String url = "http://" + httpServer.getAddress().getHostName() + ":" + httpServer.getAddress().getPort() + + "/" + INDEX + "/_doc/" + DOC_ID + "?refresh=true"; + Assertions.assertEquals(url, span.getAttributes().get(AttributeKey.stringKey(URL_FULL))); + Assertions.assertEquals(httpServer.getAddress().getHostName(), span.getAttributes().get(AttributeKey.stringKey(SERVER_ADDRESS))); + Assertions.assertEquals(httpServer.getAddress().getPort(), span.getAttributes().get(AttributeKey.longKey(SERVER_PORT))); + + // Path parts + Assertions.assertEquals(DOC_ID, span.getAttributes().get(AttributeKey.stringKey("db.elasticsearch.path_parts.id"))); + } + + @Test + public void testSearchRequest() throws IOException, InterruptedException { + // A client that will capture requests + ElasticsearchClient client = new ElasticsearchClient(new RestClientTransport( + restClient, this.client._jsonpMapper(), null, new OpenTelemetryForElasticsearch(openTelemetry, true)) + ); + SearchRequest req = SearchRequest.of(r -> r.index(INDEX).query(q -> q.term(t -> t.field("x").value("y")))); + String queryAsString = JsonpUtils.toJsonString(req, client._jsonpMapper()); + client.search(req, Object.class); + Assertions.assertEquals(spanExporter.getSpans().size(), 1); + SpanData span = spanExporter.getSpans().get(0); + Assertions.assertEquals("search", span.getName()); + Assertions.assertEquals(queryAsString, span.getAttributes().get(SemanticAttributes.DB_STATEMENT)); + } + + @Test + public void testAsyncSearchRequest() throws IOException, InterruptedException, TimeoutException, ExecutionException { + Query query = Query.of(q -> q.term(t -> t.field("x").value("y"))); + Future future = asyncClient.search(r -> r.index(INDEX).query(query), Object.class); + future.get(2, TimeUnit.SECONDS); + spanExporter.awaitNumSpans(1, 2000); + Assertions.assertEquals(spanExporter.getSpans().size(), 1); + SpanData span = spanExporter.getSpans().get(0); + Assertions.assertEquals("search", span.getName()); + + // We're not capturing bodies by default + Assertions.assertNull(span.getAttributes().get(SemanticAttributes.DB_STATEMENT)); + } + + private static class MockSpanExporter implements SpanExporter { + + private final List spans = new ArrayList(); + + @Override + public CompletableResultCode export(Collection spans) { + this.spans.addAll(spans); + synchronized (this) { + notifyAll(); + } + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode flush() { + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode shutdown() { + spans.clear(); + return CompletableResultCode.ofSuccess(); + } + + public List getSpans() { + return spans; + } + + public void reset() { + spans.clear(); + } + + public synchronized void awaitNumSpans(int num, long timeoutMillis) throws InterruptedException { + while(spans.size() < num){ + wait(timeoutMillis); + } + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest_client/MultiBufferEntityTest.java b/java-client/src/test/java/co/elastic/clients/transport/rest_client/MultiBufferEntityTest.java new file mode 100644 index 000000000..b241c1905 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest_client/MultiBufferEntityTest.java @@ -0,0 +1,99 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest_client; + +import co.elastic.clients.elasticsearch.core.BulkRequest; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.endpoints.BinaryResponse; +import com.sun.net.httpserver.HttpServer; +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpHost; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; + +public class MultiBufferEntityTest { + + @Test + public void testBulkRequest() throws IOException { + + HttpServer httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + + httpServer.createContext("/_bulk", exchange -> { + exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); + byte[] bytes = IOUtils.toByteArray(exchange.getRequestBody()); + exchange.sendResponseHeaders(200, 0); + exchange.getResponseBody().write(bytes); + exchange.close(); + }); + + httpServer.start(); + + RestClient restClient = + RestClient.builder(new HttpHost(httpServer.getAddress().getAddress(), httpServer.getAddress().getPort())).build(); + + BulkRequest req = BulkRequest.of(_0 -> _0 + .operations(_1 -> _1 + .create(_2 -> _2 + .index("foo") + .id("abc") + .document("abc-doc") + )) + .operations(_1 -> _1 + .create(_2 -> _2 + .index("foo") + .id("def") + .document("def-doc") + )) + .operations(_1 -> _1 + .update(_2 -> _2 + .index("foo") + .id("gh") + .action(_3 -> _3 + .docAsUpsert(true) + .doc("gh-doc")) + ) + ) + ); + RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); + + BinaryResponse binaryResponse = transport.performRequest(req, BulkRequest._ENDPOINT.withBinaryResponse(), null); + + String str = IOUtils.toString(binaryResponse.content(), StandardCharsets.UTF_8); + + httpServer.stop(0); + transport.close(); + + Assertions.assertEquals( + "{\"create\":{\"_id\":\"abc\",\"_index\":\"foo\"}}\n" + + "\"abc-doc\"\n" + + "{\"create\":{\"_id\":\"def\",\"_index\":\"foo\"}}\n" + + "\"def-doc\"\n" + + "{\"update\":{\"_id\":\"gh\",\"_index\":\"foo\"}}\n" + + "{\"doc\":\"gh-doc\",\"doc_as_upsert\":true}\n", + str + ); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest_client/RestClientOptionsTest.java b/java-client/src/test/java/co/elastic/clients/transport/rest_client/RestClientOptionsTest.java new file mode 100644 index 000000000..cf8995944 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest_client/RestClientOptionsTest.java @@ -0,0 +1,202 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest_client; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.SimpleJsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.Version; +import co.elastic.clients.transport.endpoints.BooleanResponse; +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpServer; +import org.apache.http.HttpHost; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +class RestClientOptionsTest extends Assertions { + + /** Collected headers by test name */ + private static Map collectedHeaders; + private static final AtomicInteger testCounter = new AtomicInteger(); + private static HttpServer httpServer; + + private static final String MIME_TYPE = "application/vnd.elasticsearch+json; compatible-with=" + Version.VERSION.major(); + + @BeforeAll + public static void setup() throws IOException { + collectedHeaders = new ConcurrentHashMap<>(); + httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + + // Register a handler on the core.exists("capture-handler/{name}") endpoint that will capture request headers. + httpServer.createContext("/capture-headers/_doc/", exchange -> { + String testName = exchange.getRequestURI().getPath().substring("/capture-headers/_doc/".length()); + System.out.println(exchange.getResponseHeaders()); + System.out.println(); + collectedHeaders.put(testName, exchange.getRequestHeaders()); + + // Reply with an empty 200 response + exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); + exchange.sendResponseHeaders(200, -1); + exchange.close(); + }); + + httpServer.start(); + } + + @AfterAll + public static void cleanup() { + httpServer.stop(0); + httpServer = null; + collectedHeaders = null; + } + + private ElasticsearchTransport newRestClientTransport(RestClient restClient, JsonpMapper mapper) { + return newRestClientTransport(restClient, mapper, null); + } + + private ElasticsearchTransport newRestClientTransport(RestClient restClient, JsonpMapper mapper, RestClientOptions options) { + return new RestClientTransport(restClient, mapper, options); + //return new RestClientMonolithTransport(restClient, mapper, options); + } + + /** + * Make a server call, capture request headers and check their consistency. + * + * @return the name of the entry in collectedHeaders for further inspection. + */ + private String checkHeaders(ElasticsearchClient esClient) throws IOException { + String testName = "test-" + testCounter.incrementAndGet(); + BooleanResponse exists = esClient.exists(r -> r.index("capture-headers").id(testName)); + assertTrue(exists.value()); + + Headers headers = collectedHeaders.get(testName); + assertNotNull(headers, "No headers collected for test " + testName); + + assertNotNull(headers.get("X-elastic-client-meta"), "Missing client meta header"); + assertEquals(RestClientOptions.CLIENT_META_VALUE, headers.get("X-elastic-client-meta").get(0)); + assertNotNull(headers.get("Accept"), "Missing 'Accept' header"); + assertEquals(MIME_TYPE, headers.get("Accept").get(0)); + + for (Map.Entry> entry: headers.entrySet()) { + System.out.println(entry.getKey() + " " + entry.getValue()); + } + + return testName; + } + + private void checkUserAgent(String testName, String value) { + Headers headers = collectedHeaders.get(testName); + assertNotNull(headers, "No headers collected for test " + testName); + assertNotNull(headers.get("User-Agent"), "Missing 'User-Agent' header"); + assertEquals(value, headers.get("User-Agent").get(0)); + } + + @Test + void testNoRequestOptions() throws Exception { + RestClient llrc = RestClient.builder( + new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort(), "http") + ).build(); + + ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper()); + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + String id = checkHeaders(esClient); + checkUserAgent(id, RestClientOptions.USER_AGENT_VALUE); + } + + @Test + void testTransportRequestOptions() throws Exception { + RestClient llrc = RestClient.builder( + new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort(), "http") + ).build(); + + ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper(), + new RestClientOptions.Builder(RequestOptions.DEFAULT.toBuilder()).build() + ); + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + String id = checkHeaders(esClient); + checkUserAgent(id, RestClientOptions.USER_AGENT_VALUE); + } + + @Test + void testClientRequestOptions() throws Exception { + RestClient llrc = RestClient.builder( + new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort(), "http") + ).build(); + + ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper()); + ElasticsearchClient esClient = new ElasticsearchClient(transport).withTransportOptions( + new RestClientOptions.Builder(RequestOptions.DEFAULT.toBuilder()).build() + ); + + String id = checkHeaders(esClient); + checkUserAgent(id, RestClientOptions.USER_AGENT_VALUE); + } + + @Test + void testLambdaOptionsBuilder() throws Exception { + RestClient llrc = RestClient.builder( + new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort(), "http") + ).build(); + + ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper()); + ElasticsearchClient esClient = new ElasticsearchClient(transport) + .withTransportOptions(o -> o + .addHeader("Foo", "bar") + .addHeader("x-elastic-client-meta", "foo-bar-client") + ); + + String id = checkHeaders(esClient); + checkUserAgent(id, RestClientOptions.USER_AGENT_VALUE); + } + + @Test + void testRequestOptionsOverridingBuiltin() throws Exception { + RequestOptions options = RequestOptions.DEFAULT.toBuilder() + .addHeader("user-agent", "FooBarAgent/1.0") + .addHeader("x-elastic-client-meta", "foo-bar-client") + .build(); + + RestClient llrc = RestClient.builder( + new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort(), "http") + ).build(); + + ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper(), new RestClientOptions(options,false)); + ElasticsearchClient esClient = new ElasticsearchClient(transport); + // Should not override client meta + String id = checkHeaders(esClient); + // overriding user-agent is ok + checkUserAgent(id, "FooBarAgent/1.0"); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest_client/SafeResponseConsumerTest.java b/java-client/src/test/java/co/elastic/clients/transport/rest_client/SafeResponseConsumerTest.java new file mode 100644 index 000000000..2910ed5d5 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest_client/SafeResponseConsumerTest.java @@ -0,0 +1,206 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest_client; + +import com.sun.net.httpserver.HttpServer; +import org.apache.http.HttpEntity; +import org.apache.http.HttpException; +import org.apache.http.HttpHost; +import org.apache.http.HttpResponse; +import org.apache.http.entity.ContentType; +import org.apache.http.nio.ContentDecoder; +import org.apache.http.nio.IOControl; +import org.elasticsearch.client.HeapBufferedAsyncResponseConsumer; +import org.elasticsearch.client.HttpAsyncResponseConsumerFactory; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; + +public class SafeResponseConsumerTest { + + static HttpServer Server; + static HttpHost ESHost; + + // A consumer factory that throws an Error, to simulate the effect of an OOME + static HttpAsyncResponseConsumerFactory FailingConsumerFactory = () -> new HeapBufferedAsyncResponseConsumer(100 * 1024 * 1024) { + @Override + protected void onResponseReceived(HttpResponse httpResponse) throws HttpException, IOException { + super.onResponseReceived(httpResponse); + } + + @Override + protected void onContentReceived(ContentDecoder decoder, IOControl ioctrl) throws IOException { + super.onContentReceived(decoder, ioctrl); + throw new Error("Error in onContentReceived"); + } + + @Override + protected void onEntityEnclosed(HttpEntity entity, ContentType contentType) throws IOException { + super.onEntityEnclosed(entity, contentType); + } + }; + + @BeforeAll + public static void setup() throws Exception { + Server = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + Server.start(); + + Server.createContext("/", exchange -> { + String path = exchange.getRequestURI().getPath(); + exchange.getResponseHeaders().set("Content-Type", "application/json"); + exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); + + if (path.equals("/")) { + byte[] bytes = Info.getBytes(StandardCharsets.UTF_8); + exchange.sendResponseHeaders(200, bytes.length); + exchange.getResponseBody().write(bytes); + exchange.close(); + return; + } + + exchange.sendResponseHeaders(404, -1); + exchange.close(); + }); + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + try { + Server.stop(1); + } catch (Exception e) { + // Ignore + } + })); + + ESHost = new HttpHost(Server.getAddress().getAddress(), Server.getAddress().getPort()); + } + + @AfterAll + public static void tearDown() { + Server.stop(0); + } + + @Test + public void testReactorDeath() throws Exception { + + // Request options that will simulate an OOME and cause the reactor to die + RequestOptions.Builder failingOptionsBuilder = RequestOptions.DEFAULT.toBuilder(); + failingOptionsBuilder.setHttpAsyncResponseConsumerFactory(FailingConsumerFactory); + RequestOptions failingOptions = failingOptionsBuilder.build(); + + RestClient restClient = RestClient.builder(ESHost).build(); + + // First request, to warm things up. + // An "indice exists" request, that has no response body + Request existsReq = new Request("HEAD", "/index-name"); + restClient.performRequest(existsReq); + + try { + Request infoReq = new Request("GET", "/"); + infoReq.setOptions(failingOptions); + + restClient.performRequest(infoReq); + Assertions.fail("First request should not succeed"); + } catch(Exception t) { +// System.err.println("Request 1 error"); +// t.printStackTrace(); + } + + Thread.sleep(1000); + + try { + // 2nd request with no specific options + Request infoReq = new Request("GET", "/"); + restClient.performRequest(infoReq); + Assertions.fail("Second request should not succeed"); + } catch(Exception t) { +// System.err.println("Request 2 error"); +// t.printStackTrace(); + } + + restClient.close(); + } + + @Test + public void testReactorSurvival() throws Exception { + + // Request options that will simulate an OOME and wrapped in the safe consumer that will + // avoid the reactor's death + RequestOptions.Builder protectedFailingOptionsBuilder = RequestOptions.DEFAULT.toBuilder(); + protectedFailingOptionsBuilder.setHttpAsyncResponseConsumerFactory(() -> + new SafeResponseConsumer<>(FailingConsumerFactory.createHttpAsyncResponseConsumer()) + ); + RequestOptions protectedFailingOptions = protectedFailingOptionsBuilder.build(); + + RestClient restClient = RestClient.builder(ESHost).build(); + + // First request, to warm things up. + // An "indice exists" request, that has no response body + Request existsReq = new Request("HEAD", "/index-name"); + restClient.performRequest(existsReq); + + try { + Request infoReq = new Request("GET", "/"); + infoReq.setOptions(protectedFailingOptions); + + restClient.performRequest(infoReq); + Assertions.fail("First request should not succeed"); + } catch(Exception t) { + // System.err.println("Request 1 error"); + // t.printStackTrace(); + } + + { + // 2nd request with no specific options + Request infoReq = new Request("GET", "/"); + + Response resp = restClient.performRequest(infoReq); + Assertions.assertEquals(200, resp.getStatusLine().getStatusCode()); + } + + restClient.close(); + } + + private static final String Info = "{\n" + + " \"cluster_name\": \"foo\",\n" + + " \"cluster_uuid\": \"bar\",\n" + + " \"version\": {\n" + + " \"build_date\": \"2022-01-28T08:36:04.875279988Z\",\n" + + " \"minimum_wire_compatibility_version\": \"6.8.0\",\n" + + " \"build_hash\": \"bee86328705acaa9a6daede7140defd4d9ec56bd\",\n" + + " \"number\": \"7.17.0\",\n" + + " \"lucene_version\": \"8.11.1\",\n" + + " \"minimum_index_compatibility_version\": \"6.0.0-beta1\",\n" + + " \"build_flavor\": \"default\",\n" + + " \"build_snapshot\": false,\n" + + " \"build_type\": \"docker\"\n" + + " },\n" + + " \"name\": \"instance-0000000000\",\n" + + " \"tagline\": \"You Know, for Search\"\n" + + "}"; +} diff --git a/java-client/src/test/java/co/elastic/clients/util/DateTimeTest.java b/java-client/src/test/java/co/elastic/clients/util/DateTimeTest.java new file mode 100644 index 000000000..fb27c1428 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/util/DateTimeTest.java @@ -0,0 +1,139 @@ +/* + * 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. + */ + +package co.elastic.clients.util; + +import co.elastic.clients.testkit.ModelTestCase; +import org.junit.jupiter.api.Test; + +import java.time.Instant; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +public class DateTimeTest extends ModelTestCase { + + long millis = 1643822172348L; + String millisJson = "1643822172348"; + + String text = "2022-02-02T17:16:12.348Z"; + String textJson = "\"" + text + "\""; + + @Test + public void testMillis() { + DateTime dateTime; + + dateTime = DateTime.ofEpochMilli(millis); + assertEquals(millis, dateTime.toInstant().toEpochMilli()); + + // Millis, no format + dateTime = checkJsonRoundtrip(DateTime.ofEpochMilli(millis), millisJson); + assertEquals(millis, dateTime.toEpochMilli()); + assertNull(dateTime.formatter); + + // Millis, roundtrip through ISO format + dateTime = checkJsonRoundtrip(DateTime.ofEpochMilli(millis, DateTimeFormatter.ISO_INSTANT), textJson); + assertEquals(millis, dateTime.toEpochMilli()); + assertNull(dateTime.formatter); + } + + @Test + public void testText() { + + DateTime dateTime; + + // Millis as string + dateTime = fromJson("\"1643822172348\"", DateTime.class); + assertEquals(millis, dateTime.toEpochMilli()); + assertNull(dateTime.formatter); + + DateTime dateTimeOrig = dateTime; + + // test STRICT_DATE_OPTIONAL_TIME_FORMATTER + dateTime = fromJson(textJson, DateTime.class); + assertEquals(text, dateTime.toString()); + + assertEquals(dateTime, dateTimeOrig); + + dateTime = fromJson("\"2022-02-27\"", DateTime.class); + assertEquals("2022-02-27T00:00:00Z", dateTime.toInstant().toString()); + + dateTime = fromJson("\"2022-02\"", DateTime.class); + assertEquals("2022-02-01T00:00:00Z", dateTime.toInstant().toString()); + + dateTime = fromJson("\"2022\"", DateTime.class); + assertEquals("2022-01-01T00:00:00Z", dateTime.toInstant().toString()); + + assertEquals("\"2022\"", toJson(dateTime)); + + } + + @Test + public void testInvalidString() { + + // Invalid values should be accepted, and an exception thrown + // only when we parse the value. + // This lazy parsing allows application code that doesn't access + // ill-formed data to not fail on deserialization. + DateTime dateTime = fromJson("\"foobar\"", DateTime.class); + assertEquals("foobar", dateTime.getString()); + + assertThrows(DateTimeParseException.class, dateTime::toInstant); + } + + @Test + public void testInstant() { + + DateTime dateTime; + + dateTime = DateTime.of(text, DateTimeFormatter.ISO_INSTANT); + assertEquals(millis, dateTime.toInstant().toEpochMilli()); + + assertEquals(millis, dateTime.toInstant(DateTimeFormatter.ISO_INSTANT).toEpochMilli()); + + Instant inst = Instant.ofEpochMilli(millis); + + dateTime = DateTime.of(inst); + assertEquals(millisJson, toJson(dateTime)); + + dateTime = DateTime.of(inst, DateTimeFormatter.ISO_DATE_TIME); + assertEquals(textJson, toJson(dateTime)); + + } + + @Test + public void testZonedDateTime() { + + DateTime dateTime; + ZonedDateTime zdt; + + // With timezone information + dateTime = fromJson("\"2022-02-02T18:16:12.348+01:00\"", DateTime.class); + assertEquals(millis, dateTime.toEpochMilli()); + + zdt = dateTime.toZonedDateTime(); + assertEquals(3600, zdt.getOffset().getTotalSeconds()); + + zdt = dateTime.toZonedDateTime(DateTimeFormatter.ISO_ZONED_DATE_TIME); + assertEquals(millis, zdt.toInstant().toEpochMilli()); + + assertEquals(millis, DateTime.of(millisJson).toZonedDateTime().toInstant().toEpochMilli()); + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/util/DuplicateResourceFinderTest.java b/java-client/src/test/java/co/elastic/clients/util/DuplicateResourceFinderTest.java new file mode 100644 index 000000000..3b7f7ef40 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/util/DuplicateResourceFinderTest.java @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package co.elastic.clients.util; + +import com.fasterxml.jackson.databind.ext.CoreXMLSerializers; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class DuplicateResourceFinderTest extends Assertions { + + @Test + public void testDuplicateCheck() { + + Exception e = assertThrows(RuntimeException.class, () -> { + DuplicateResourceFinder.ensureClassUniqueness(CoreXMLSerializers.class); + }); + assertTrue(e.getMessage().contains("Several versions of")); + + // Disabling the test should not throw an exception + DuplicateResourceFinder.enableCheck(false); + DuplicateResourceFinder.ensureClassUniqueness(CoreXMLSerializers.class); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/util/NamedValueTest.java b/java-client/src/test/java/co/elastic/clients/util/NamedValueTest.java new file mode 100644 index 000000000..ba609e0af --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/util/NamedValueTest.java @@ -0,0 +1,49 @@ +/* + * 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. + */ + +package co.elastic.clients.util; + +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.aggregations.TermsAggregation; +import co.elastic.clients.testkit.ModelTestCase; +import org.junit.jupiter.api.Test; + +class NamedValueTest extends ModelTestCase { + + @Test + public void testTermAggregation() { + + String json = "{\"order\":[{\"a\":\"asc\"},{\"b\":\"desc\"}]}"; + + TermsAggregation ta = TermsAggregation.of(b -> b + .order(NamedValue.of("a", SortOrder.Asc)) + .order(NamedValue.of("b", SortOrder.Desc) + ) + ); + + ta = checkJsonRoundtrip(ta, json); + + assertEquals(2, ta.order().size()); + + assertEquals("a", ta.order().get(0).name()); + assertEquals(SortOrder.Asc, ta.order().get(0).value()); + assertEquals("b", ta.order().get(1).name()); + assertEquals(SortOrder.Desc, ta.order().get(1).value()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/util/PairTest.java b/java-client/src/test/java/co/elastic/clients/util/PairTest.java new file mode 100644 index 000000000..d3a6f6c8c --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/util/PairTest.java @@ -0,0 +1,45 @@ +/* + * 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. + */ + +package co.elastic.clients.util; + +import co.elastic.clients.elasticsearch._types.FieldValue; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.elasticsearch.watcher.Condition; +import co.elastic.clients.elasticsearch.watcher.ConditionOp; +import org.junit.jupiter.api.Test; + +class PairTest extends ModelTestCase { + + @Test + public void testCondition() { + + String json = "{\"compare\":{\"foo\":{\"eq\":\"bar\"}}}"; + + Condition c = Condition.of(b -> b + .compare(NamedValue.of("foo", Pair.of(ConditionOp.Eq, FieldValue.of("bar")))) + ); + + c = checkJsonRoundtrip(c, json); + + assertEquals("foo", c.compare().name()); + assertEquals(ConditionOp.Eq, c.compare().value().key()); + assertEquals("bar", c.compare().value().value().stringValue()); + } +} diff --git a/java-client/src/test/java/com/fasterxml/jackson/databind/ext/CoreXMLSerializers.java b/java-client/src/test/java/com/fasterxml/jackson/databind/ext/CoreXMLSerializers.java new file mode 100644 index 000000000..bf4a2d62b --- /dev/null +++ b/java-client/src/test/java/com/fasterxml/jackson/databind/ext/CoreXMLSerializers.java @@ -0,0 +1,25 @@ +/* + * 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. + */ + +package com.fasterxml.jackson.databind.ext; + +// A "duplicate" of a class that exists in the project's dependencies. +// It's not actually used by the project, so the duplicate won't harm and is used in DuplicateResourceFinderTest +public class CoreXMLSerializers { +} From 7a8e2d2fde4df6b9ab6a0c44ca0d7c24e7dc75ad Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Tue, 25 Mar 2025 11:26:26 +0100 Subject: [PATCH 08/38] new tests --- .../documentation/DocTestsTransport.java | 119 ++++ .../api_conventions/ApiConventionsTest.java | 366 ++++++++++ .../api_conventions/LoadingJsonTest.java | 193 ++++++ .../getting_started/ConnectingTest.java | 191 ++++++ .../troubleshooting/TroubleShootingTests.java | 93 +++ .../documentation/usage/AggregationsTest.java | 107 +++ .../documentation/usage/IndexingBulkTest.java | 214 ++++++ .../documentation/usage/IndexingTest.java | 209 ++++++ .../documentation/usage/Product.java | 57 ++ .../documentation/usage/ReadingTest.java | 98 +++ .../documentation/usage/SearchingTest.java | 198 ++++++ .../ElasticsearchTestServer.java | 294 ++++++++ .../_helpers/builders/ClientBuildersTest.java | 73 ++ .../bulk/BulkIngesterRetryPolicyTest.java | 546 +++++++++++++++ .../_helpers/bulk/BulkIngesterTest.java | 627 ++++++++++++++++++ .../esql/EsqlAdapterEndToEndTest.java | 205 ++++++ .../_helpers/esql/EsqlAdapterTest.java | 119 ++++ .../elasticsearch/end_to_end/RequestTest.java | 494 ++++++++++++++ .../experiments/ClientTests.java | 108 +++ .../experiments/ParsingTests.java | 76 +++ .../experiments/UnionVariant.java | 31 + .../elasticsearch/experiments/api/Bar.java | 82 +++ .../experiments/api/DateMathTimeUnit.java | 49 ++ .../experiments/api/FooOptRequest.java | 278 ++++++++ .../experiments/api/FooRequest.java | 317 +++++++++ .../experiments/api/FooResponse.java | 27 + .../experiments/api/query2/BoolQuery.java | 175 +++++ .../experiments/api/query2/Query.java | 207 ++++++ .../experiments/api/query2/QueryTest.java | 46 ++ .../experiments/api/query2/TermsQuery.java | 108 +++ .../experiments/api/query2/Union2.java | 154 +++++ .../experiments/base/Client.java | 48 ++ .../experiments/base/PrimitiveUtils.java | 41 ++ .../experiments/base/Variants.java | 155 +++++ .../experiments/containers/SomeUnion.java | 155 +++++ .../experiments/containers/SomeUnionTest.java | 86 +++ .../containers/SomeUnionVariant.java | 25 + .../experiments/containers/UVariantA.java | 83 +++ .../experiments/containers/UVariantB.java | 83 +++ .../experiments/generics/GenericClass.java | 123 ++++ .../inheritance/InheritanceTest.java | 97 +++ .../inheritance/base/BaseClass.java | 77 +++ .../inheritance/child/ChildClass.java | 93 +++ .../inheritance/final_/FinalClass.java | 98 +++ .../experiments/package-info.java | 23 + .../elasticsearch/model/BehaviorsTest.java | 306 +++++++++ .../elasticsearch/model/BuiltinTypesTest.java | 273 ++++++++ .../model/ClassStructureTest.java | 361 ++++++++++ .../model/CodeAdditionsTests.java | 49 ++ .../elasticsearch/model/EndpointTest.java | 94 +++ .../elasticsearch/model/EnumTest.java | 61 ++ .../model/RequestEncodingTest.java | 59 ++ .../model/SerializationTest.java | 134 ++++ .../elasticsearch/model/TypedKeysTest.java | 299 +++++++++ .../elasticsearch/model/UnionTests.java | 354 ++++++++++ .../elasticsearch/model/VariantsTest.java | 351 ++++++++++ .../elasticsearch/model/package-info.java | 24 + .../spec_issues/SpecIssuesTest.java | 316 +++++++++ .../rest5_client/json/JsonDataTest.java | 176 +++++ .../json/JsonpDeserializerBaseTest.java | 51 ++ .../json/JsonpDeserializerTest.java | 43 ++ .../rest5_client/json/JsonpMapperTest.java | 210 ++++++ .../json/JsonpMappingExceptionTest.java | 113 ++++ .../rest5_client/json/JsonpUtilsTest.java | 332 ++++++++++ .../json/LazyDeserializerTest.java | 70 ++ .../json/ObjectBuilderDeserializerTest.java | 50 ++ .../rest5_client/json/WithJsonTest.java | 190 ++++++ .../jackson/JacksonJsonpGeneratorTest.java | 91 +++ .../json/jackson/JacksonJsonpParserTest.java | 195 ++++++ .../json/jackson/JacksonMapperTest.java | 103 +++ .../json/jackson/JsonEnumTest.java | 56 ++ .../json/jackson/JsonValueParserTest.java | 79 +++ .../rest5_client/testkit/MockHttpClient.java | 157 +++++ .../rest5_client/testkit/ModelTestCase.java | 151 +++++ .../transport/RequestOptionsTest.java | 164 +++++ .../rest5_client/transport/TransportTest.java | 159 +++++ .../transport/TransportUtilsTest.java | 121 ++++ .../transport/VersionInfoTest.java | 34 + .../endpoints/BinaryEndpointTest.java | 130 ++++ .../endpoints/BooleanEndpointTest.java | 37 ++ .../transport/endpoints/EndpointBaseTest.java | 70 ++ .../endpoints/SimpleEndpointTest.java | 71 ++ .../transport/http/HeaderMapTest.java | 79 +++ .../OpenTelemetryForElasticsearchTest.java | 277 ++++++++ .../rest_client/MultiBufferEntityTest.java | 100 +++ .../rest_client/RestClientOptionsTest.java | 204 ++++++ .../rest5_client/util/DateTimeTest.java | 140 ++++ .../util/DuplicateResourceFinderTest.java | 41 ++ .../rest5_client/util/NamedValueTest.java | 50 ++ .../clients/rest5_client/util/PairTest.java | 47 ++ 90 files changed, 13520 insertions(+) create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/DocTestsTransport.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/ApiConventionsTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/LoadingJsonTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/getting_started/ConnectingTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/troubleshooting/TroubleShootingTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/AggregationsTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingBulkTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/Product.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/ReadingTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/SearchingTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/ElasticsearchTestServer.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/builders/ClientBuildersTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/end_to_end/RequestTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ClientTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ParsingTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/UnionVariant.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/Bar.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/DateMathTimeUnit.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooOptRequest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooRequest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooResponse.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/BoolQuery.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Query.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/QueryTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/TermsQuery.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Union2.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Client.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/PrimitiveUtils.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Variants.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnion.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionVariant.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantA.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantB.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/generics/GenericClass.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/InheritanceTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/base/BaseClass.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/child/ChildClass.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/final_/FinalClass.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/package-info.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BehaviorsTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BuiltinTypesTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/ClassStructureTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/CodeAdditionsTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EndpointTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EnumTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/RequestEncodingTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/SerializationTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/TypedKeysTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/UnionTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/VariantsTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/package-info.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/spec_issues/SpecIssuesTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonDataTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpDeserializerBaseTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpDeserializerTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpMapperTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpMappingExceptionTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpUtilsTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/LazyDeserializerTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/ObjectBuilderDeserializerTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/WithJsonTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonJsonpGeneratorTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonJsonpParserTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonMapperTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JsonEnumTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JsonValueParserTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/testkit/MockHttpClient.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/testkit/ModelTestCase.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/RequestOptionsTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportUtilsTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/VersionInfoTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BinaryEndpointTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BooleanEndpointTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/EndpointBaseTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/SimpleEndpointTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/http/HeaderMapTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/instrumentation/OpenTelemetryForElasticsearchTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/MultiBufferEntityTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/RestClientOptionsTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/util/DateTimeTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/util/DuplicateResourceFinderTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/util/NamedValueTest.java create mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/util/PairTest.java diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/DocTestsTransport.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/DocTestsTransport.java new file mode 100644 index 000000000..2f2cb263e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/DocTestsTransport.java @@ -0,0 +1,119 @@ +/* + * 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. + */ + +package clients.rest5_client.documentation; + +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.TransportOptions; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; + +import javax.annotation.Nullable; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; + +/** + * A transport implementation that always returns the same result. Used for doc snippets where we can to check + * compilation and do very simple tests. + */ +public class DocTestsTransport implements ElasticsearchTransport { + + private final JsonpMapper mapper = new JacksonJsonpMapper( + new ObjectMapper().setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE) + ); + + private final ThreadLocal result = new ThreadLocal<>(); + + private final TransportOptions options = new TransportOptions() { + @Override + public Collection> headers() { + return Collections.emptyList(); + } + + @Override + public Map queryParameters() { + return Collections.emptyMap(); + } + + @Override + public Function, Boolean> onWarnings() { + return null; + } + + @Override + public void updateToken(String token) { + + } + + @Override + public boolean keepResponseBodyOnException() { + return false; + } + + @Override + public Builder toBuilder() { + return null; + } + }; + + public void setResult(Object result) { + this.result.set(result); + } + + @Override + @SuppressWarnings("unchecked") + public ResponseT performRequest( + RequestT request, + Endpoint endpoint, + @Nullable TransportOptions options + ) throws IOException { + return (ResponseT) result.get(); + } + + @Override + @SuppressWarnings("unchecked") + public CompletableFuture performRequestAsync(RequestT request, Endpoint endpoint, @Nullable TransportOptions options) { + CompletableFuture future = new CompletableFuture<>(); + future.complete((ResponseT) result.get()); + return future; + } + + @Override + public JsonpMapper jsonpMapper() { + return mapper; + } + + @Override + public TransportOptions options() { + return options; + } + + @Override + public void close() throws IOException { + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/ApiConventionsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/ApiConventionsTest.java new file mode 100644 index 000000000..90cd160d4 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/ApiConventionsTest.java @@ -0,0 +1,366 @@ +/* + * 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. + */ + +package clients.rest5_client.documentation.api_conventions; + +import co.elastic.clients.documentation.DocTestsTransport; +import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.NodeStatistics; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.aggregations.Aggregation; +import co.elastic.clients.elasticsearch._types.query_dsl.Query; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.indices.Alias; +import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; +import co.elastic.clients.elasticsearch.indices.CreateIndexResponse; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.util.ApiTypeHelper; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonValue; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.StringReader; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ApiConventionsTest extends Assertions { + + private static class SomeApplicationData {} + + private DocTestsTransport transport = new DocTestsTransport(); + Logger logger = LoggerFactory.getLogger(this.getClass()); + + public void blockingAndAsync() throws Exception { + + //tag::blocking-and-async + // Synchronous blocking client + ElasticsearchClient client = new ElasticsearchClient(transport); + + if (client.exists(b -> b.index("products").id("foo")).value()) { + logger.info("product exists"); + } + + // Asynchronous non-blocking client + ElasticsearchAsyncClient asyncClient = + new ElasticsearchAsyncClient(transport); + + asyncClient + .exists(b -> b.index("products").id("foo")) + .whenComplete((response, exception) -> { + if (exception != null) { + logger.error("Failed to index", exception); + } else { + logger.info("Product exists"); + } + }); + //end::blocking-and-async + + } + + public void builders() throws Exception { + ElasticsearchClient client = new ElasticsearchClient(transport); + + //tag::builders + CreateIndexResponse createResponse = client.indices().create( + new CreateIndexRequest.Builder() + .index("my-index") + .aliases("foo", + new Alias.Builder().isWriteIndex(true).build() + ) + .build() + ); + //end::builders + } + + public void builderLambdas() throws Exception { + ElasticsearchClient client = new ElasticsearchClient(transport); + + //tag::builder-lambdas + CreateIndexResponse createResponse = client.indices() + .create(createIndexBuilder -> createIndexBuilder + .index("my-index") + .aliases("foo", aliasBuilder -> aliasBuilder + .isWriteIndex(true) + ) + ); + //end::builder-lambdas + } + + public void builderLambdasShort() throws Exception { + ElasticsearchClient client = new ElasticsearchClient(transport); + + //tag::builder-lambdas-short + CreateIndexResponse createResponse = client.indices() + .create(c -> c + .index("my-index") + .aliases("foo", a -> a + .isWriteIndex(true) + ) + ); + //end::builder-lambdas-short + } + + public void builderIntervals() throws Exception { + ObjectMapper mapper = new ObjectMapper(); + mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + ElasticsearchClient client = new ElasticsearchClient(transport); + + //tag::builder-intervals + SearchResponse results = client + .search(b0 -> b0 + .query(b1 -> b1 + .intervals(b2 -> b2 + .field("my_text") + .allOf(b3 -> b3 + .ordered(true) + .intervals(b4 -> b4 + .match(b5 -> b5 + .query("my favorite food") + .maxGaps(0) + .ordered(true) + ) + ) + .intervals(b4 -> b4 + .anyOf(b5 -> b5 + .intervals(b6 -> b6 + .match(b7 -> b7 + .query("hot water") + ) + ) + .intervals(b6 -> b6 + .match(b7 -> b7 + .query("cold porridge") + ) + ) + ) + ) + ) + ) + ), + SomeApplicationData.class // <1> + ); + //end::builder-intervals + } + + @Test + public void variantCreation() { + //tag::variant-creation + Query query = new Query.Builder() + .term(t -> t // <1> + .field("name") // <2> + .value(v -> v.stringValue("foo")) + ) + .build(); // <3> + //end::variant-creation + + //tag::variant-navigation + assertEquals("foo", query.term().value().stringValue()); + //end::variant-navigation + + //tag::variant-kind + if (query.isTerm()) { // <1> + doSomething(query.term()); + } + + switch(query._kind()) { // <2> + case Term: + doSomething(query.term()); + break; + case Intervals: + doSomething(query.intervals()); + break; + default: + doSomething(query._kind(), query._get()); // <3> + } + //end::variant-kind + } + + //tag::custom-variant-types + public static class SphereDistanceAggregate { + private final List buckets; + @JsonCreator + public SphereDistanceAggregate( + @JsonProperty("buckets") List buckets + ) { + this.buckets = buckets; + } + public List buckets() { + return buckets; + }; + } + + public static class Bucket { + private final double key; + private final double docCount; + @JsonCreator + public Bucket( + @JsonProperty("key") double key, + @JsonProperty("doc_count") double docCount) { + this.key = key; + this.docCount = docCount; + } + public double key() { + return key; + } + public double docCount() { + return docCount; + } + } + //end::custom-variant-types + + @Test + public void customVariants() throws Exception { + + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0},\n" + + "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]},\n" + + "\"aggregations\":{\"sphere-distance#neighbors\":{\"buckets\":[{\"key\": 1.0,\"doc_count\":1}]}}}"; + + transport.setResult(SearchResponse.of(b -> b.withJson( + transport.jsonpMapper().jsonProvider().createParser(new StringReader(json)), + transport.jsonpMapper()) + )); + + //tag::custom-variant-creation + Map params = new HashMap<>(); // <1> + params.put("interval", 10); + params.put("scale", "log"); + params.put("origin", new Double[]{145.0, 12.5, 1649.0}); + + SearchRequest request = SearchRequest.of(r -> r + .index("stars") + .aggregations("neighbors", agg -> agg + ._custom("sphere-distance", params) // <2> + ) + ); + //end::custom-variant-creation + + { + //tag::custom-variant-navigation-json + SearchResponse response = esClient.search(request, Void.class); // <1> + + JsonData neighbors = response + .aggregations().get("neighbors") + ._custom(); // <2> + + JsonArray buckets = neighbors.toJson() // <3> + .asJsonObject() + .getJsonArray("buckets"); + + for (JsonValue item : buckets) { + JsonObject bucket = item.asJsonObject(); + double key = bucket.getJsonNumber("key").doubleValue(); + double docCount = bucket.getJsonNumber("doc_count").longValue(); + doSomething(key, docCount); + } + //end::custom-variant-navigation-json + } + + { + //tag::custom-variant-navigation-typed + SearchResponse response = esClient.search(request, Void.class); + + SphereDistanceAggregate neighbors = response + .aggregations().get("neighbors") + ._custom() + .to(SphereDistanceAggregate.class); // <1> + + for (Bucket bucket : neighbors.buckets()) { + doSomething(bucket.key(), bucket.docCount()); + } + //end::custom-variant-navigation-typed + } + } + + @Test + public void collections() { + //tag::collections-list + // Prepare a list of index names + List names = Arrays.asList("idx-a", "idx-b", "idx-c"); + + // Prepare cardinality aggregations for fields "foo" and "bar" + Map cardinalities = new HashMap<>(); + cardinalities.put("foo-count", Aggregation.of(a -> a.cardinality(c -> c.field("foo")))); + cardinalities.put("bar-count", Aggregation.of(a -> a.cardinality(c -> c.field("bar")))); + + // Prepare an aggregation that computes the average of the "size" field + final Aggregation avgSize = Aggregation.of(a -> a.avg(v -> v.field("size"))); + + SearchRequest search = SearchRequest.of(r -> r + // Index list: + // - add all elements of a list + .index(names) + // - add a single element + .index("idx-d") + // - add a vararg list of elements + .index("idx-e", "idx-f", "idx-g") + + // Sort order list: add elements defined by builder lambdas + .sort(s -> s.field(f -> f.field("foo").order(SortOrder.Asc))) + .sort(s -> s.field(f -> f.field("bar").order(SortOrder.Desc))) + + // Aggregation map: + // - add all entries of an existing map + .aggregations(cardinalities) + // - add a key/value entry + .aggregations("avg-size", avgSize) + // - add a key/value defined by a builder lambda + .aggregations("price-histogram", + a -> a.histogram(h -> h.field("price"))) + ); + //end::collections-list + + } + + @Test + public void optionalCollections() { + //tag::optional-collections + NodeStatistics stats = NodeStatistics.of(b -> b + .total(1) + .failed(0) + .successful(1) + ); + + // The `failures` list was not provided. + // - it's not null + assertNotNull(stats.failures()); + // - it's empty + assertEquals(0, stats.failures().size()); + // - and if needed we can know it was actually not defined + assertFalse(ApiTypeHelper.isDefined(stats.failures())); + //end::optional-collections + } + + private void doSomething(Object... o) { + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/LoadingJsonTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/LoadingJsonTest.java new file mode 100644 index 000000000..3207b4678 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/LoadingJsonTest.java @@ -0,0 +1,193 @@ +/* + * 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. + */ + +package clients.rest5_client.documentation.api_conventions; + +import co.elastic.clients.documentation.DocTestsTransport; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; +import co.elastic.clients.elasticsearch._types.aggregations.CalendarInterval; +import co.elastic.clients.elasticsearch.core.IndexRequest; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; +import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; +import co.elastic.clients.elasticsearch.indices.CreateIndexResponse; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.json.JsonData; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class LoadingJsonTest extends ModelTestCase { + + private final DocTestsTransport transport = new DocTestsTransport(); + private final ElasticsearchClient client = new ElasticsearchClient(transport); + + private static final SearchResponse searchResponse = SearchResponse.of(b -> b + .aggregations(new HashMap<>()) + .took(0) + .timedOut(false) + .hits(h -> h + .total(t -> t.value(0).relation(TotalHitsRelation.Eq)) + .hits(new ArrayList<>()) + ) + .shards(s -> s + .total(1) + .failed(0) + .successful(1) + ) + ); + + @Test + public void loadIndexDefinition() throws IOException { + + transport.setResult(CreateIndexResponse.of(b -> b + .index("some-index") + .shardsAcknowledged(true) + .acknowledged(true) + )); + + //tag::load-index + InputStream input = this.getClass() + .getResourceAsStream("some-index.json"); //<1> + + CreateIndexRequest req = CreateIndexRequest.of(b -> b + .index("some-index") + .withJson(input) //<2> + ); + + boolean created = client.indices().create(req).acknowledged(); + //end::load-index + } + + @Disabled + @Test + public void ingestDocument() throws IOException { + + File dataDir = null; + + //tag::ingest-data + FileReader file = new FileReader(new File(dataDir, "document-1.json")); + + IndexRequest req; //<1> + + req = IndexRequest.of(b -> b + .index("some-index") + .withJson(file) + ); + + client.index(req); + //end::ingest-data + } + + @Test + public void query1() throws IOException { + transport.setResult(searchResponse); + + //tag::query + Reader queryJson = new StringReader( + "{" + + " \"query\": {" + + " \"range\": {" + + " \"@timestamp\": {" + + " \"gt\": \"now-1w\"" + + " }" + + " }" + + " }" + + "}"); + + SearchRequest aggRequest = SearchRequest.of(b -> b + .withJson(queryJson) //<1> + .aggregations("max-cpu", a1 -> a1 //<2> + .dateHistogram(h -> h + .field("@timestamp") + .calendarInterval(CalendarInterval.Hour) + ) + .aggregations("max", a2 -> a2 + .max(m -> m.field("host.cpu.usage")) + ) + ) + .size(0) + ); + + Map aggs = client + .search(aggRequest, Void.class) //<3> + .aggregations(); + //end::query + } + + @Test + public void query2() throws IOException { + transport.setResult(searchResponse); + + //tag::query-and-agg + Reader queryJson = new StringReader( + "{" + + " \"query\": {" + + " \"range\": {" + + " \"@timestamp\": {" + + " \"gt\": \"now-1w\"" + + " }" + + " }" + + " }," + + " \"size\": 100" + //<1> + "}"); + + Reader aggregationJson = new StringReader( + "{" + + " \"size\": 0, " + //<2> + " \"aggregations\": {" + + " \"hours\": {" + + " \"date_histogram\": {" + + " \"field\": \"@timestamp\"," + + " \"interval\": \"hour\"" + + " }," + + " \"aggregations\": {" + + " \"max-cpu\": {" + + " \"max\": {" + + " \"field\": \"host.cpu.usage\"" + + " }" + + " }" + + " }" + + " }" + + " }" + + "}"); + + SearchRequest aggRequest = SearchRequest.of(b -> b + .withJson(queryJson) //<3> + .withJson(aggregationJson) //<4> + .ignoreUnavailable(true) //<5> + ); + + Map aggs = client + .search(aggRequest, Void.class) + .aggregations(); + //end::query-and-agg + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/getting_started/ConnectingTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/getting_started/ConnectingTest.java new file mode 100644 index 000000000..58f3b6803 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/getting_started/ConnectingTest.java @@ -0,0 +1,191 @@ +/* + * 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. + */ + +//TODO rewrite +package clients.rest5_client.documentation.getting_started; + +public class ConnectingTest { + + /*@Disabled // we don't have a running ES + @Test + public void createClient() throws Exception { + //tag::create-client + // URL and API key + String serverUrl = "https://localhost:9200"; + String apiKey = "VnVhQ2ZHY0JDZGJrU..."; + + // Create the low-level client + RestClient restClient = RestClient + .builder(HttpHost.create(serverUrl)) + .setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "ApiKey " + apiKey) + }) + .build(); + + // Create the transport with a Jackson mapper + ElasticsearchTransport transport = new RestClientTransport( + restClient, new JacksonJsonpMapper()); + + // And create the API client + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + // Use the client... + + // Close the client, also closing the underlying transport object and network connections. + esClient.close(); + //end::create-client + + //tag::first-request + SearchResponse search = esClient.search(s -> s + .index("products") + .query(q -> q + .term(t -> t + .field("name") + .value(v -> v.stringValue("bicycle")) + )), + Product.class); + + for (Hit hit: search.hits().hits()) { + processProduct(hit.source()); + } + //end::first-request + } + + @Disabled // we don't have a running ES + @Test + public void createClientWithOpenTelemetry() throws Exception { + //tag::create-client-otel + // URL and API key + String serverUrl = "https://localhost:9200"; + String apiKey = "VnVhQ2ZHY0JDZGJrU..."; + + // Create the low-level client + RestClient restClient = RestClient + .builder(HttpHost.create(serverUrl)) + .setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "ApiKey " + apiKey) + }) + .build(); + // Create and configure custom OpenTelemetry instance + OpenTelemetry customOtel = OpenTelemetrySdk.builder().build(); + + // Create Instrumentation instance using the custom OpenTelemetry instance + // Second constructor argument allows to enable/disable search body capturing + OpenTelemetryForElasticsearch esOtelInstrumentation = + new OpenTelemetryForElasticsearch(customOtel, false); + + // Create the transport with the custom Instrumentation instance + ElasticsearchTransport transport = new RestClientTransport( + restClient, new JacksonJsonpMapper(), null, esOtelInstrumentation + ); + + // And create the API client + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + // Use the client... + + // Close the client, also closing the underlying transport object and network connections. + esClient.close(); + //end::create-client-otel + } + + @Disabled // we don't have a running ES + @Test + public void createSecureClientCert() throws Exception { + + // Create the low-level client + String host = "localhost"; + int port = 9200; + String login = "elastic"; + String password = "changeme"; + + //tag::create-secure-client-cert + File certFile = new File("/path/to/http_ca.crt"); + + SSLContext sslContext = TransportUtils + .sslContextFromHttpCaCrt(certFile); // <1> + + BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); // <2> + credsProv.setCredentials( + AuthScope.ANY, new UsernamePasswordCredentials(login, password) + ); + + RestClient restClient = RestClient + .builder(new HttpHost(host, port, "https")) // <3> + .setHttpClientConfigCallback(hc -> hc + .setSSLContext(sslContext) // <4> + .setDefaultCredentialsProvider(credsProv) + ) + .build(); + + // Create the transport and the API client + ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + // Use the client... + + // Close the client, also closing the underlying transport object and network connections. + esClient.close(); + //end::create-secure-client-cert + } + + @Disabled // we don't have a running ES + @Test + public void createSecureClientFingerPrint() throws Exception { + + // Create the low-level client + String host = "localhost"; + int port = 9200; + String login = "elastic"; + String password = "changeme"; + + //tag::create-secure-client-fingerprint + String fingerprint = ""; + + SSLContext sslContext = TransportUtils + .sslContextFromCaFingerprint(fingerprint); // <1> + + BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); // <2> + credsProv.setCredentials( + AuthScope.ANY, new UsernamePasswordCredentials(login, password) + ); + + RestClient restClient = RestClient + .builder(new HttpHost(host, port, "https")) // <3> + .setHttpClientConfigCallback(hc -> hc + .setSSLContext(sslContext) // <4> + .setDefaultCredentialsProvider(credsProv) + ) + .build(); + + // Create the transport and the API client + ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + // Use the client... + + // Close the client, also closing the underlying transport object and network connections. + esClient.close(); + //end::create-secure-client-fingerprint + } + + private void processProduct(Product p) {}*/ + +} + diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/troubleshooting/TroubleShootingTests.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/troubleshooting/TroubleShootingTests.java new file mode 100644 index 000000000..55d6ee416 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/troubleshooting/TroubleShootingTests.java @@ -0,0 +1,93 @@ +/* + * 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. + */ + +package clients.rest5_client.documentation.troubleshooting; + +import co.elastic.clients.documentation.DocTestsTransport; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpMapperFeatures; +import jakarta.json.stream.JsonGenerator; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.StringWriter; +import java.util.Collections; + +public class TroubleShootingTests extends Assertions { + + @Test + public void testMapProperty() { + + SearchResponse searchResponse = new SearchResponse.Builder() + .aggregations( + "price", _2 -> _2 + .avg(_3 -> _3.value(3.14)) + ) + // Required properties on a SearchResponse + .took(1) + .shards(_1 -> _1.successful(1).failed(0).total(1)) + .hits(_1 -> _1 + .total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)) + .hits(Collections.emptyList()) + ) + .timedOut(false) + .build(); + + String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + + "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]},\"aggregations\":{\"avg#price\":{\"value\":3.14}}}"; + + DocTestsTransport transport = new DocTestsTransport(); + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + { + //tag::aggregation-typed-keys + JsonpMapper mapper = esClient._jsonpMapper(); + + StringWriter writer = new StringWriter(); + try (JsonGenerator generator = mapper.jsonProvider().createGenerator(writer)) { + mapper.serialize(searchResponse, generator); + } + String result = writer.toString(); + + // The aggregation property provides the "avg" type and "price" name + assertTrue(result.contains("\"aggregations\":{\"avg#price\":{\"value\":3.14}}}")); + //end::aggregation-typed-keys + } + + { + //tag::aggregation-no-typed-keys + // Create a new mapper with the typed_keys feature disabled + JsonpMapper mapper = esClient._jsonpMapper() + .withAttribute(JsonpMapperFeatures.SERIALIZE_TYPED_KEYS, false); + + StringWriter writer = new StringWriter(); + try (JsonGenerator generator = mapper.jsonProvider().createGenerator(writer)) { + mapper.serialize(searchResponse, generator); + } + String result = writer.toString(); + + // The aggregation only provides the "price" name + assertTrue(result.contains("\"aggregations\":{\"price\":{\"value\":3.14}}}")); + //end::aggregation-no-typed-keys + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/AggregationsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/AggregationsTest.java new file mode 100644 index 000000000..cde2ff832 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/AggregationsTest.java @@ -0,0 +1,107 @@ +/* + * 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. + */ + +package clients.rest5_client.documentation.usage; + +import co.elastic.clients.documentation.DocTestsTransport; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.aggregations.HistogramBucket; +import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery; +import co.elastic.clients.elasticsearch._types.query_dsl.Query; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.json.JsonData; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +public class AggregationsTest extends ModelTestCase { + + private final DocTestsTransport transport = new DocTestsTransport(); + private final ElasticsearchClient esClient = new ElasticsearchClient(transport); + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private static final SearchResponse searchResponse = SearchResponse.of(b -> b + .aggregations(new HashMap<>()) + .took(0) + .timedOut(false) + .hits(h -> h + .total(t -> t.value(0).relation(TotalHitsRelation.Eq)) + .hits(new ArrayList<>()) + ) + .shards(s -> s + .total(1) + .failed(0) + .successful(1) + ) + .aggregations("price-histogram", a -> a.histogram(h -> h + .buckets(bu -> bu.array(Collections.singletonList(HistogramBucket.of(hb -> hb + .key(50).docCount(1) + )))) + )) + ); + + @Test + public void priceHistogram() throws Exception { + + transport.setResult(searchResponse); + + //tag::price-histo-request + String searchText = "bike"; + + Query query = MatchQuery.of(m -> m + .field("name") + .query(searchText) + )._toQuery(); + + SearchResponse response = esClient.search(b -> b + .index("products") + .size(0) // <1> + .query(query) // <2> + .aggregations("price-histogram", a -> a // <3> + .histogram(h -> h // <4> + .field("price") + .interval(50.0) + ) + ), + Void.class // <5> + ); + //end::price-histo-request + + //tag::price-histo-response + List buckets = response.aggregations() + .get("price-histogram") // <1> + .histogram() // <2> + .buckets().array(); // <3> + + for (HistogramBucket bucket: buckets) { + logger.info("There are " + bucket.docCount() + + " bikes under " + bucket.key()); + } + + //end::price-histo-response + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingBulkTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingBulkTest.java new file mode 100644 index 000000000..2175813be --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingBulkTest.java @@ -0,0 +1,214 @@ +/* + * 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. + */ + +package clients.rest5_client.documentation.usage; + +import co.elastic.clients.documentation.DocTestsTransport; +import co.elastic.clients.documentation.usage.Product; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._helpers.bulk.BulkIngester; +import co.elastic.clients.elasticsearch._helpers.bulk.BulkListener; +import co.elastic.clients.elasticsearch.core.BulkRequest; +import co.elastic.clients.elasticsearch.core.BulkResponse; +import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.util.BinaryData; +import co.elastic.clients.util.ContentType; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class IndexingBulkTest extends ModelTestCase { + + private final DocTestsTransport transport = new DocTestsTransport(); + private final ElasticsearchClient esClient = new ElasticsearchClient(transport); + + private final Log logger = LogFactory.getLog(this.getClass()); + + BulkResponse result = BulkResponse.of(r -> r + .errors(false) + .items(Collections.emptyList()) + .took(1) + ); + + private List fetchProducts() { + List list = new ArrayList<>(); + list.add(new co.elastic.clients.documentation.usage.Product("bk-1", "City Bike", 123.0)); + list.add(new co.elastic.clients.documentation.usage.Product("bk-2", "Mountain Bike", 134.0)); + return list; + } + + @Test + public void indexBulk() throws Exception { + transport.setResult(result); + + //tag::bulk-objects + List products = fetchProducts(); + + BulkRequest.Builder br = new BulkRequest.Builder(); + + for (Product product : products) { + br.operations(op -> op //<1> + .index(idx -> idx //<2> + .index("products") //<3> + .id(product.getSku()) + .document(product) + ) + ); + } + + BulkResponse result = esClient.bulk(br.build()); + + // Log errors, if any + if (result.errors()) { + logger.error("Bulk had errors"); + for (BulkResponseItem item: result.items()) { + if (item.error() != null) { + logger.error(item.error().reason()); + } + } + } + //end::bulk-objects + } + + @Test + public void indexBulkJson() throws Exception { + transport.setResult(result); + + File logDir = new File("."); + + //tag::bulk-json + // List json log files in the log directory + File[] logFiles = logDir.listFiles( + file -> file.getName().matches("log-.*\\.json") + ); + + BulkRequest.Builder br = new BulkRequest.Builder(); + + for (File file: logFiles) { + FileInputStream input = new FileInputStream(file); + BinaryData data = BinaryData.of(IOUtils.toByteArray(input), ContentType.APPLICATION_JSON); + + br.operations(op -> op + .index(idx -> idx + .index("logs") + .document(data) + ) + ); + } + //end::bulk-json + } + + @Test + public void useBulkIndexer() throws Exception { + + File logDir = new File("."); + File[] logFiles = logDir.listFiles( + file -> file.getName().matches("log-.*\\.json") + ); + + //tag::bulk-ingester-setup + BulkIngester ingester = BulkIngester.of(b -> b + .client(esClient) // <1> + .maxOperations(100) // <2> + .flushInterval(1, TimeUnit.SECONDS) // <3> + ); + + for (File file: logFiles) { + FileInputStream input = new FileInputStream(file); + BinaryData data = BinaryData.of(IOUtils.toByteArray(input), ContentType.APPLICATION_JSON); + + ingester.add(op -> op // <4> + .index(idx -> idx + .index("logs") + .document(data) + ) + ); + } + + ingester.close(); // <5> + //end::bulk-ingester-setup + + } + + @Test + public void useBulkIndexerWithContext() throws Exception { + + File[] logFiles = new File[]{}; + + //tag::bulk-ingester-context + BulkListener listener = new BulkListener() { // <1> + @Override + public void beforeBulk(long executionId, BulkRequest request, List contexts) { + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, BulkResponse response) { + // The request was accepted, but may contain failed items. + // The "context" list gives the file name for each bulk item. + logger.debug("Bulk request " + executionId + " completed"); + for (int i = 0; i < contexts.size(); i++) { + BulkResponseItem item = response.items().get(i); + if (item.error() != null) { + // Inspect the failure cause + logger.error("Failed to index file " + contexts.get(i) + " - " + item.error().reason()); + } + } + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, Throwable failure) { + // The request could not be sent + logger.debug("Bulk request " + executionId + " failed", failure); + } + }; + + BulkIngester ingester = BulkIngester.of(b -> b + .client(esClient) + .maxOperations(100) + .flushInterval(1, TimeUnit.SECONDS) + .listener(listener) // <2> + ); + + for (File file: logFiles) { + FileInputStream input = new FileInputStream(file); + BinaryData data = BinaryData.of(IOUtils.toByteArray(input), ContentType.APPLICATION_JSON); + + ingester.add(op -> op + .index(idx -> idx + .index("logs") + .document(data) + ), + file.getName() // <3> + ); + } + + ingester.close(); + //end::bulk-ingester-context + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingTest.java new file mode 100644 index 000000000..7ad0ea9b5 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingTest.java @@ -0,0 +1,209 @@ +/* + * 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. + */ + +package clients.rest5_client.documentation.usage; + +import co.elastic.clients.documentation.DocTestsTransport; +import co.elastic.clients.documentation.usage.Product; +import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.Result; +import co.elastic.clients.elasticsearch.core.IndexRequest; +import co.elastic.clients.elasticsearch.core.IndexResponse; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.json.JsonData; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.Reader; +import java.io.StringReader; + +public class IndexingTest extends ModelTestCase { + + private final DocTestsTransport transport = new DocTestsTransport(); + private final ElasticsearchClient esClient = new ElasticsearchClient(transport); + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + IndexResponse result = IndexResponse.of(r -> r + .index("product") + .id("bk-1") + .version(1) + .primaryTerm(1L) + .seqNo(1L) + .result(Result.Created) + .shards(s -> s.total(1).successful(1).failed(0)) + ); + + @Test + @Disabled + public void createIndex() throws Exception { + //tag::create-products-index + esClient.indices().create(c -> c + .index("products") + ); + //end::create-products-index + } + + @Test + @Disabled + public void deleteIndex() throws Exception { + //tag::delete-products-index + esClient.indices().delete(d -> d + .index("products") + ); + //end::delete-products-index + } + + @Test + public void singleDocumentDSL() throws Exception { + + // Stub response + transport.setResult(result); + + //tag::single-doc-dsl + co.elastic.clients.documentation.usage.Product product = new co.elastic.clients.documentation.usage.Product("bk-1", "City bike", 123.0); + + IndexResponse response = esClient.index(i -> i + .index("products") + .id(product.getSku()) + .document(product) + ); + + logger.info("Indexed with version " + response.version()); + //end::single-doc-dsl + } + + @Test + public void singleDocumentDSLwithOf() throws Exception { + + // Stub response + transport.setResult(result); + + //tag::single-doc-dsl-of + co.elastic.clients.documentation.usage.Product product = new co.elastic.clients.documentation.usage.Product("bk-1", "City bike", 123.0); + + IndexRequest request = IndexRequest.of(i -> i + .index("products") + .id(product.getSku()) + .document(product) + ); + + IndexResponse response = esClient.index(request); + + logger.info("Indexed with version " + response.version()); + //end::single-doc-dsl-of + } + + @Test + public void singleDocumentBuilder() throws Exception { + + // Stub response + transport.setResult(result); + + //tag::single-doc-builder + co.elastic.clients.documentation.usage.Product product = new co.elastic.clients.documentation.usage.Product("bk-1", "City bike", 123.0); + + IndexRequest.Builder indexReqBuilder = new IndexRequest.Builder<>(); + indexReqBuilder.index("product"); + indexReqBuilder.id(product.getSku()); + indexReqBuilder.document(product); + + IndexResponse response = esClient.index(indexReqBuilder.build()); + + logger.info("Indexed with version " + response.version()); + //end::single-doc-builder + } + + @Test + public void singleDocumentDSLAsync() throws Exception { + + // Stub response + transport.setResult(result); + + //tag::single-doc-dsl-async + ElasticsearchAsyncClient esAsyncClient = new ElasticsearchAsyncClient(transport); + + co.elastic.clients.documentation.usage.Product product = new co.elastic.clients.documentation.usage.Product("bk-1", "City bike", 123.0); + + esAsyncClient.index(i -> i + .index("products") + .id(product.getSku()) + .document(product) + ).whenComplete((response, exception) -> { + if (exception != null) { + logger.error("Failed to index", exception); + } else { + logger.info("Indexed with version " + response.version()); + } + }); + //end::single-doc-dsl-async + } + + @Test + public void singleDocumentJson() throws Exception { + // Stub response + transport.setResult(result); + + //tag::single-doc-json + Reader input = new StringReader( + "{'@timestamp': '2022-04-08T13:55:32Z', 'level': 'warn', 'message': 'Some log message'}" + .replace('\'', '"')); + + IndexRequest request = IndexRequest.of(i -> i + .index("logs") + .withJson(input) + ); + + IndexResponse response = esClient.index(request); + + logger.info("Indexed with version " + response.version()); + //end::single-doc-json + + assertEquals("warn", request.document().toJson().asJsonObject().getString("level")); + assertEquals( + "{\"@timestamp\":\"2022-04-08T13:55:32Z\",\"level\":\"warn\",\"message\":\"Some log message\"}", + toJson(request) + ); + } + + @Test + public void deleteDocument() throws Exception { + //tag::single-doc-delete + esClient.delete(d -> d.index("products").id("bk-1")); + //end::single-doc-delete + } + + @Test + @Disabled + public void updateDoc() throws Exception { + //tag::single-doc-update + co.elastic.clients.documentation.usage.Product product = new co.elastic.clients.documentation.usage.Product("bk-1", "City bike", 123.0); + + esClient.update(u -> u + .index("products") + .id("bk-1") + .upsert(product), + Product.class + ); + //end::single-doc-update + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/Product.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/Product.java new file mode 100644 index 000000000..28f31e8b7 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/Product.java @@ -0,0 +1,57 @@ +/* + * 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. + */ + +package clients.rest5_client.documentation.usage; + +public class Product { + private String sku; + private String name; + private double price; + + public Product() {} + public Product(String sku, String name, double price) { + this.sku = sku; + this.name = name; + this.price = price; + } + + public String getSku() { + return sku; + } + + public void setSku(String sku) { + this.sku = sku; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getPrice() { + return this.price; + } + + public void setPrice(double price) { + this.price = price; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/ReadingTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/ReadingTest.java new file mode 100644 index 000000000..9c63b18ae --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/ReadingTest.java @@ -0,0 +1,98 @@ +/* + * 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. + */ + +package clients.rest5_client.documentation.usage; + +import co.elastic.clients.documentation.DocTestsTransport; +import co.elastic.clients.documentation.usage.Product; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.core.GetResponse; +import co.elastic.clients.testkit.ModelTestCase; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ReadingTest extends ModelTestCase { + + private final DocTestsTransport transport = new DocTestsTransport(); + private final ElasticsearchClient esClient = new ElasticsearchClient(transport); + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Test + public void getById() throws Exception { + + transport.setResult(GetResponse.of(r -> r + .found(true) + .index("products") + .id("bk-1") + .version(1L) + .seqNo(0L) + .primaryTerm(0L) + .source(new co.elastic.clients.documentation.usage.Product("bk-1", "City Bike", 123.0)) + )); + + //tag::get-by-id + GetResponse response = esClient.get(g -> g + .index("products") // <1> + .id("bk-1"), + co.elastic.clients.documentation.usage.Product.class // <2> + ); + + if (response.found()) { + Product product = response.source(); + logger.info("Product name " + product.getName()); + } else { + logger.info ("Product not found"); + } + //end::get-by-id + + } + + @Test + public void getByIdJson() throws Exception { + + transport.setResult(GetResponse.of(r -> r + .found(true) + .index("products") + .id("bk-1") + .version(1L) + .seqNo(0L) + .primaryTerm(0L) + .source(fromJson("{\"name\":\"City Bike\"}", ObjectNode.class, transport.jsonpMapper())) + )); + + //tag::get-by-id-json + GetResponse response = esClient.get(g -> g + .index("products") + .id("bk-1"), + ObjectNode.class // <1> + ); + + if (response.found()) { + ObjectNode json = response.source(); + String name = json.get("name").asText(); + logger.info("Product name " + name); + } else { + logger.info("Product not found"); + } + //end::get-by-id-json + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/SearchingTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/SearchingTest.java new file mode 100644 index 000000000..404057902 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/SearchingTest.java @@ -0,0 +1,198 @@ +/* + * 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. + */ + +package clients.rest5_client.documentation.usage; + +import co.elastic.clients.documentation.DocTestsTransport; +import co.elastic.clients.documentation.usage.Product; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery; +import co.elastic.clients.elasticsearch._types.query_dsl.Query; +import co.elastic.clients.elasticsearch._types.query_dsl.RangeQuery; +import co.elastic.clients.elasticsearch.core.PutScriptResponse; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.SearchTemplateResponse; +import co.elastic.clients.elasticsearch.core.search.Hit; +import co.elastic.clients.elasticsearch.core.search.TotalHits; +import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; +import co.elastic.clients.json.JsonData; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class SearchingTest { + + private final DocTestsTransport transport = new DocTestsTransport(); + private final ElasticsearchClient esClient = new ElasticsearchClient(transport); + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private static final SearchResponse searchResponse = SearchResponse.of(b -> b + .aggregations(new HashMap<>()) + .took(0) + .timedOut(false) + .hits(h -> h + .total(t -> t.value(0).relation(TotalHitsRelation.Eq)) + .hits(new ArrayList<>()) + ) + .shards(s -> s + .total(1) + .failed(0) + .successful(1) + ) + ); + + @Test + public void searchSimpleMatch() throws Exception { + transport.setResult(searchResponse); + + //tag::search-getting-started + String searchText = "bike"; + + SearchResponse response = esClient.search(s -> s + .index("products") + .query(q -> q + .match(t -> t + .field("name") + .query(searchText) + ) + ), + co.elastic.clients.documentation.usage.Product.class + ); + //end::search-getting-started + } + @Test + public void searchMatch() throws Exception { + + transport.setResult(searchResponse); + //tag::search-simple + + String searchText = "bike"; + + SearchResponse response = esClient.search(s -> s + .index("products") // <1> + .query(q -> q // <2> + .match(t -> t // <3> + .field("name") // <4> + .query(searchText) + ) + ), + co.elastic.clients.documentation.usage.Product.class // <5> + ); + + TotalHits total = response.hits().total(); + boolean isExactResult = total.relation() == TotalHitsRelation.Eq; + + if (isExactResult) { + logger.info("There are " + total.value() + " results"); + } else { + logger.info("There are more than " + total.value() + " results"); + } + + List> hits = response.hits().hits(); + for (Hit hit: hits) { + co.elastic.clients.documentation.usage.Product product = hit.source(); + logger.info("Found product " + product.getSku() + ", score " + hit.score()); + } + //end::search-simple + } + + @Test + public void searchNested() throws Exception { + transport.setResult(searchResponse); + //tag::search-nested + String searchText = "bike"; + double maxPrice = 200.0; + + // Search by product name + Query byName = MatchQuery.of(m -> m // <1> + .field("name") + .query(searchText) + )._toQuery(); // <2> + + // Search by max price + Query byMaxPrice = RangeQuery.of(r -> r + .number(n -> n + .field("price") + .gte(maxPrice)) // <3> + )._toQuery(); + + // Combine name and price queries to search the product index + SearchResponse response = esClient.search(s -> s + .index("products") + .query(q -> q + .bool(b -> b // <4> + .must(byName) // <5> + .must(byMaxPrice) + ) + ), + co.elastic.clients.documentation.usage.Product.class + ); + + List> hits = response.hits().hits(); + for (Hit hit: hits) { + co.elastic.clients.documentation.usage.Product product = hit.source(); + logger.info("Found product " + product.getSku() + ", score " + hit.score()); + } + //end::search-nested + } + + @Test + public void searchTemplate() throws Exception { + + transport.setResult(PutScriptResponse.of(r -> r.acknowledged(true))); + + //tag::search-template-script + // Create a script + esClient.putScript(r -> r + .id("query-script") // <1> + .script(s -> s + .lang("mustache") + .source("{\"query\":{\"match\":{\"{{field}}\":\"{{value}}\"}}}") + )); + //end::search-template-script + + transport.setResult(SearchTemplateResponse.of(r -> r + .hits(searchResponse.hits()) + .took(searchResponse.took()) + .timedOut(false) + .shards(searchResponse.shards()) + )); + + //tag::search-template-query + SearchTemplateResponse response = esClient.searchTemplate(r -> r + .index("some-index") + .id("query-script") // <1> + .params("field", JsonData.of("some-field")) // <2> + .params("value", JsonData.of("some-data")), + co.elastic.clients.documentation.usage.Product.class + ); + + List> hits = response.hits().hits(); + for (Hit hit: hits) { + Product product = hit.source(); + logger.info("Found product " + product.getSku() + ", score " + hit.score()); + } + //end::search-template-query + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/ElasticsearchTestServer.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/ElasticsearchTestServer.java new file mode 100644 index 000000000..0edaf3ec3 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/ElasticsearchTestServer.java @@ -0,0 +1,294 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch; + +import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.JsonEndpoint; +import co.elastic.clients.transport.Version; +import co.elastic.clients.transport.endpoints.DelegatingJsonEndpoint; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import org.apache.commons.io.FileUtils; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.message.BasicHeader; +import org.elasticsearch.client.RestClient; +import org.testcontainers.elasticsearch.ElasticsearchContainer; +import org.testcontainers.images.builder.ImageFromDockerfile; +import org.testcontainers.shaded.org.apache.commons.io.IOUtils; +import org.testcontainers.utility.DockerImageName; + +import javax.net.ssl.SSLContext; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Base64; +import java.util.Optional; + +public class ElasticsearchTestServer implements AutoCloseable { + + private final String[] plugins; + private volatile ElasticsearchContainer container; + private final JsonpMapper mapper = new JsonbJsonpMapper(); + private RestClient restClient; + private ElasticsearchTransport transport; + private ElasticsearchClient client; + + private static ElasticsearchTestServer global; + + private static final String artifactsApiUrl = "https://artifacts-api.elastic.co/v1/versions/"; + + public static synchronized ElasticsearchTestServer global() { + if (global == null) { + + // Try localhost:9200 + try { + String localUrl = "http://localhost:9200"; + HttpURLConnection connection = (HttpURLConnection) new URL(localUrl).openConnection(); + connection.setRequestProperty("Authorization", "Basic " + + Base64.getEncoder().encodeToString("elastic:changeme".getBytes(StandardCharsets.UTF_8))); + + try (InputStream input = connection.getInputStream()) { + String content = IOUtils.toString(input, StandardCharsets.UTF_8); + if (content.contains("You Know, for Search")) { + System.out.println("Found a running ES server at http://localhost:9200/"); + + global = new ElasticsearchTestServer(); + global.setup(localUrl, null); + } + } + } catch (Exception e) { + // Create container + System.out.println("Starting global ES test server."); + global = new ElasticsearchTestServer(); + global.start(); + } + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + System.out.println("Stopping global ES test server."); + global.close(); + })); + } + return global; + } + + public ElasticsearchTestServer(String... plugins) { + this.plugins = plugins; + } + + protected void setup(String url, SSLContext sslContext) { + try { + HttpHost host = HttpHost.create(url); + + var pwd = Base64.getEncoder().encodeToString("elastic:changeme".getBytes()); + + + restClient = RestClient.builder(HttpHost.create(url)) + .setSslContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())) + .setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Basic " + pwd) + }) + //.setCompressionEnabled(true) + .build(); + } catch (Exception e) { + throw new RuntimeException(e); + } + transport = new RestClientTransport(restClient, mapper); + client = new ElasticsearchClient(transport); + } + + private Version selectLatestVersion(Version version, String info) { + if (info.contains(version.toString())) { + return version; + } + // if no version X.Y.0 was found, we give up + if (version.maintenance() == 0) { + throw new RuntimeException("Elasticsearch server container version: " + version + " not yet " + + "available"); + } + return selectLatestVersion(new Version(version.major(), version.minor(), version.maintenance() - 1, + false), info); + } + + private String fetchAndWriteVersionInfo(File file) throws IOException { + String versionInfo = IOUtils.toString(new URL(artifactsApiUrl), StandardCharsets.UTF_8); + FileUtils.writeStringToFile(file, versionInfo, StandardCharsets.UTF_8); + return versionInfo; + } + + private Version getLatestAvailableServerVersion(Version version) { + try { + // check if there's cached information + ClassLoader classLoader = getClass().getClassLoader(); + URL location = classLoader.getResource("./co/elastic/clients/version.json"); + + // writing the info on file before returning + if (location == null) { + File file = new File(classLoader.getResource("./co/elastic/clients").getFile() + "/version" + + ".json"); + String versionInfo = fetchAndWriteVersionInfo(file); + return selectLatestVersion(version, versionInfo); + } + + File file = new File(location.getFile()); + + // info file was found, but it's expired + if (Instant.ofEpochMilli(file.lastModified()).isBefore(Instant.now().minus(24, + ChronoUnit.HOURS))) { + String versionInfo = fetchAndWriteVersionInfo(file); + return selectLatestVersion(version, versionInfo); + } + + // info file exists and it has new info + String versionInfo = FileUtils.readFileToString(file, StandardCharsets.UTF_8); + return selectLatestVersion(version, versionInfo); + + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public synchronized ElasticsearchTestServer start() { + if (this.client != null) { + return this; + } + + Version version = getLatestAvailableServerVersion(Version.VERSION); + + // using specific stable version for tests with plugins + if (plugins.length > 0) { + version = Version.VERSION.major() < 8 ? new Version(7, 17, 25, false) : new Version(8, 16, 0, + false); + } + + String esImage = "docker.elastic.co/elasticsearch/elasticsearch:" + version; + + DockerImageName image; + if (plugins.length == 0) { + image = DockerImageName.parse(esImage); + } else { + String esWithPluginsImage = new ImageFromDockerfile() + .withDockerfileFromBuilder(b -> { + b.from(esImage); + for (String plugin : plugins) { + b.run("/usr/share/elasticsearch/bin/elasticsearch-plugin", "install", plugin); + } + } + ).get(); + + image = DockerImageName + .parse(esWithPluginsImage) + .asCompatibleSubstituteFor("docker.elastic.co/elasticsearch/elasticsearch"); + } + + container = new ElasticsearchContainer(image) + .withEnv("ES_JAVA_OPTS", "-Xms256m -Xmx256m") + .withEnv("path.repo", "/tmp") // for snapshots + .withStartupTimeout(Duration.ofSeconds(30)) + .withPassword("changeme"); + container.start(); + + boolean useTLS = version.major() >= 8; + + SSLContext sslContext = useTLS ? container.createSslContextFromCa() : null; + String url = (useTLS ? "https://" : "http://") + container.getHttpHostAddress(); + + setup(url, sslContext); + + return this; + } + + /** + * Send a request to a server and return the response as JSON. Useful to debug response format issues. + */ + public static JsonData getJsonResponse(ElasticsearchClient client, Req request) throws IOException { + + JsonEndpoint endpoint; + + try { + @SuppressWarnings("unchecked") + JsonEndpoint endpoint0 = (JsonEndpoint) request.getClass() + .getDeclaredField("_ENDPOINT").get(null); + endpoint = endpoint0; + } catch (IllegalAccessException | NoSuchFieldException e) { + throw new RuntimeException(e); + } + + DelegatingJsonEndpoint jsonEndpoint = + new DelegatingJsonEndpoint(endpoint) { + @Override + public JsonpDeserializer responseDeserializer() { + return JsonData._DESERIALIZER; + } + }; + + return client._transport().performRequest(request, jsonEndpoint, client._transportOptions()); + } + + @Override + public void close() { + if (this == global) { + // Closed with a shutdown hook + return; + } + + if (container != null) { + container.stop(); + } + container = null; + } + + public ElasticsearchContainer container() { + return this.container; + } + + public RestClient restClient() { + return restClient; + } + + public ElasticsearchTransport transport() { + return transport; + } + + public JsonpMapper mapper() { + return mapper; + } + + public ElasticsearchClient client() { + return client; + } + + public ElasticsearchAsyncClient asyncClient() { + return new ElasticsearchAsyncClient(client._transport(), client._transportOptions()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/builders/ClientBuildersTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/builders/ClientBuildersTest.java new file mode 100644 index 000000000..525c98201 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/builders/ClientBuildersTest.java @@ -0,0 +1,73 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch._helpers.builders; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._helpers.builders.ElasticsearchClientBuilder; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.transport.rest_client.RestClientOptions; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import org.elasticsearch.client.RequestOptions; +import org.junit.jupiter.api.Test; + +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.net.URISyntaxException; +import java.security.NoSuchAlgorithmException; + +import static org.junit.Assert.assertTrue; + +public class ClientBuildersTest { + + @Test + public void build() throws IOException, URISyntaxException, NoSuchAlgorithmException { + + // create client with helper + ElasticsearchClient client = new ElasticsearchClientBuilder() + .host("url") + .usernameAndPassword("elastic", "changeme") + .sslContext(SSLContext.getDefault()) + .build(); + + RestClientOptions options = new RestClientOptions(RequestOptions.DEFAULT, true); + + client = client.withTransportOptions(options); + + // checking options correctness + assertTrue(client._transport().getClass().equals(RestClientTransport.class)); + assertTrue(client._transportOptions().keepResponseBodyOnException()); + assertTrue(client._transportOptions().headers().size() == 3); + + //assertTrue(client._transport().options().keepResponseBodyOnException()); TODO ? + + // token update utility + + client._transportOptions().updateToken("token"); + assertTrue(client._transportOptions().headers().size() == 4); + assertTrue(client._transportOptions().headers().stream().anyMatch(h -> h.getKey().equals( + "Authorization"))); + } + + @Test + public void altSearchBuild() { + // Standard search + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java new file mode 100644 index 000000000..c5d86b2b8 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java @@ -0,0 +1,546 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch._helpers.bulk; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._helpers.bulk.BulkIngester; +import co.elastic.clients.elasticsearch._helpers.bulk.BulkListener; +import co.elastic.clients.elasticsearch._types.ErrorCause; +import co.elastic.clients.elasticsearch.core.BulkRequest; +import co.elastic.clients.elasticsearch.core.BulkResponse; +import co.elastic.clients.elasticsearch.core.bulk.BulkOperation; +import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; +import co.elastic.clients.elasticsearch.core.bulk.CreateOperation; +import co.elastic.clients.elasticsearch.core.bulk.DeleteOperation; +import co.elastic.clients.elasticsearch.core.bulk.IndexOperation; +import co.elastic.clients.elasticsearch.core.bulk.OperationType; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.SimpleJsonpMapper; +import co.elastic.clients.transport.BackoffPolicy; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.TransportOptions; +import org.jetbrains.annotations.Nullable; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class BulkIngesterRetryPolicyTest { + + protected static ElasticsearchClient client; + protected static TestTransport transport; + protected static CountingListener listener; + + private BulkOperation create = BulkOperation.of(b -> b.create(c -> c.index("foo").id("1").document("1"))); + private BulkOperation index = BulkOperation.of(b -> b.index(c -> c.index("fooo").id("2").document("2"))); + private BulkOperation indexFail = BulkOperation.of(b -> b.index(c -> c.index("fail").id("2").document( + "2"))); + private BulkOperation delete = BulkOperation.of(b -> b.delete(c -> c.index("foooo").id("3"))); + private BulkOperation deleteFail = BulkOperation.of(b -> b.delete(c -> c.index("fail").id("3"))); + + @BeforeEach + public void setup() { + transport = new TestTransport(); + client = new ElasticsearchClient(transport); + listener = new CountingListener(); + } + + @Test + public void retryTestNoScheduledFlushNoContext() throws Exception { + + // First test, partial success, other will succeed after retrying + { + BulkIngester ingester = newBasicBulkIngester(listener); + + ingester.add(create); + ingester.add(index); + ingester.add(index); + + ingester.close(); + + // 1 instant success, 2 retried, but succeeded. can be either 2 or 3 depending on the retries, + // if they get scheduled at the same exact time + assertTrue(listener.requests.get() == 2 || listener.requests.get() == 3); + // eventually all 3 have to succeed + assertTrue(listener.successOperations.get() == 3); + + // 1 for the create and first try for the indexes, 2 + 2 for both index retries, + // which could be scheduled at the same time, so from 3 to 5 + assertTrue(listener.sentRequestsTotal.get() >= 3 && listener.sentRequestsTotal.get() <= 5); + } + + // Second test, all requests will succeed after retrying + { + transport.reset(); + listener.reset(); + + BulkIngester ingester = newBasicBulkIngester(listener); + + ingester.add(index); + ingester.add(index); + ingester.add(index); + ingester.add(index); + + ingester.close(); + + // between 1 and 4, depending on scheduler + assertTrue(listener.requests.get() >= 1 && listener.requests.get() <= 4); + // eventually all 4 have to succeed + assertTrue(listener.successOperations.get() == 4); + // between 3 and 9, depending on scheduler + assertTrue(listener.sentRequestsTotal.get() >= 3 && listener.sentRequestsTotal.get() <= 9); + } + + // Third test, only one retryable (will succeed), other permanent failures + { + transport.reset(); + listener.reset(); + + BulkIngester ingester = newBasicBulkIngester(listener); + + ingester.add(index); + ingester.add(delete); + ingester.add(delete); + + ingester.close(); + + // 2 failed will be handled together, then 1 retry + assertTrue(listener.requests.get() == 2); + + assertTrue(listener.successOperations.get() == 1); + assertTrue(listener.errorOperations.get() == 2); + // 1 initial + 2 retries + assertTrue(listener.sentRequestsTotal.get() == 3); + } + + // Fourth test, all requests will be retried until policy allows, then fail + { + transport.reset(); + listener.reset(); + + BulkIngester ingester = newBasicBulkIngester(listener); + + ingester.add(indexFail); + ingester.add(indexFail); + ingester.add(indexFail); + + ingester.close(); + + // from 1 to 3 depending on scheduling + assertTrue(listener.requests.get() >= 1 && listener.requests.get() <= 3); + + assertTrue(listener.successOperations.get() == 0); + assertTrue(listener.errorOperations.get() == 3); + // between 8 and 24, depending on scheduler + assertTrue(listener.sentRequestsTotal.get() >= 8 && listener.sentRequestsTotal.get() <= 24); + } + + // Fifth test, one exception that will make everything else fail, no retries triggered + { + transport.reset(); + listener.reset(); + + BulkIngester ingester = newBasicBulkIngester(listener); + + ingester.add(index); + ingester.add(create); + ingester.add(deleteFail); + + ingester.close(); + + // just the one + assertTrue(listener.requests.get() == 1); + + assertTrue(listener.successOperations.get() == 0); + assertTrue(listener.errorOperations.get() == 3); + + // just the one + assertTrue(listener.sentRequestsTotal.get() == 1); + } + + // Sixth test, a mix of everything + { + transport.reset(); + listener.reset(); + + BulkIngester ingester = newBasicBulkIngester(listener); + + ingester.add(create); + ingester.add(index); + ingester.add(indexFail); + ingester.add(delete); + ingester.add(create); + ingester.add(index); + ingester.add(indexFail); + ingester.add(delete); + + ingester.close(); + + // from 2 to 4 depending on scheduling + assertTrue(listener.requests.get() >= 1 && listener.successOperations.get() <= 4); + + assertTrue(listener.successOperations.get() == 4); + assertTrue(listener.errorOperations.get() == 4); + + // between 8 and 18, depending on scheduler + assertTrue(listener.sentRequestsTotal.get() >= 8 && listener.sentRequestsTotal.get() <= 18); + } + + transport.close(); + } + + @Test + public void retryTestFlushAndContextExponentialBackoff() throws Exception { + + // One success, other will succeed after retrying, other will fail eventually + { + BulkIngester ingester = newBulkIngesterWithFlushAndContextAndLongExponential(listener); + + ingester.add(create, 1); + ingester.add(indexFail, 2); + ingester.add(index, 3); + + ingester.close(); + + // should be 3 separate requests sent, one instant, one after a few retries, the last one error. + assertTrue(listener.requests.get() == 3); + // 2 will succeed, one will fail + assertTrue(listener.successOperations.get() == 2); + assertTrue(listener.errorOperations.get() == 1); + // between 8 and 10, depending on scheduler (first one + 2 retries for index + 8 retries for + // indexfail) + assertTrue(listener.sentRequestsTotal.get() >= 8 && listener.sentRequestsTotal.get() <= 11); + // checking order of contexts after send confirmed + Iterator iter = listener.sentContexts.iterator(); + // first one being completed is create + assertTrue(iter.next().equals(1)); + // second one is index, which will take only 2 retries + assertTrue(iter.next().equals(3)); + // last one is indexFail, taking 8 retries to fail + assertTrue(iter.next().equals(2)); + } + + transport.close(); + } + + @Test + public void retryTestNoFlushAndContextExponentialBackoff() throws Exception { + + // One success, other will succeed after retrying, other will fail eventually + { + BulkIngester ingester = newBulkIngesterNoFlushAndContextAndLongExponential(listener); + + ingester.add(create, 1); + ingester.add(indexFail, 2); + ingester.add(index, 3); + + ingester.close(); + + // should be 3 separate requests sent, one instant, one after a few retries, the last one error. + assertTrue(listener.requests.get() == 3); + // 2 will succeed, one will fail + assertTrue(listener.successOperations.get() == 2); + assertTrue(listener.errorOperations.get() == 1); + // between 8 and 10, depending on scheduler (first one + 2 retries for index + 8 retries for + // indexfail) + assertTrue(listener.sentRequestsTotal.get() >= 8 && listener.sentRequestsTotal.get() <= 11); + // checking order of contexts after send confirmed + Iterator iter = listener.sentContexts.iterator(); + // first one being completed is create + assertTrue(iter.next().equals(1)); + // second one is index, which will take only 2 retries + assertTrue(iter.next().equals(3)); + // last one is indexFail, taking 8 retries to fail + assertTrue(iter.next().equals(2)); + } + + transport.close(); + } + + @Test + public void retryMultiThreadStressTest() throws InterruptedException, IOException { + + // DISCLAIMER: this configuration is highly inefficient and only used here to showcase an extreme + // situation where the number of adding threads greatly exceeds the number of concurrent requests + // handled by the ingester. It's strongly recommended to always tweak maxConcurrentRequests + // accordingly. + BulkIngester ingester = BulkIngester.of(b -> b + .client(client) + .listener(listener) + .flushInterval(5, TimeUnit.SECONDS) + .backoffPolicy(BackoffPolicy.constantBackoff(50L, 8))); + + ExecutorService executor = Executors.newFixedThreadPool(50); + + // sends create operations, but once every 1000, one index operation will be sent, + // and once every 5000 an indexFail + for (int i = 0; i < 100000; i++) { + int ii = i; + Runnable thread = () -> { + int finalI = ii; + if (ii % 1000 == 0) { + ingester.add(index, ii); + } else if (ii % 5000 == 0) { + ingester.add(indexFail, ii); + } else { + ingester.add(create, ii); + } + }; + executor.submit(thread); + } + + executor.awaitTermination(10, TimeUnit.SECONDS); + ingester.close(); + + // all operations will succeed eventually, so the total has to be 100000 + assertTrue(listener.successOperations.get() == 100000); + assertTrue(listener.sentContexts.size() == 100000); + assertTrue(listener.errorOperations.get() == 0); + // it's difficult to predict how many requests will be sent, but considering they will be sent + // in batches of 1000, without retries it should be exactly 100, considering that 100 out of + // 100000 will be retried 3 times and 20 will be retried 8 times, if they don't get batched together + // with the others it could result in a total of 560, which is highly unlikely. + // more reasonably there will be between 100 and 300 requests sent. + assertTrue(listener.sentRequestsTotal.get() >= 100 && listener.sentRequestsTotal.get() <= 300); + // same reasoning + assertTrue(listener.requests.get() >= 100 && listener.requests.get() <= 300); + + transport.close(); + } + + + private static class TestTransport implements ElasticsearchTransport { + public final AtomicInteger requestsStarted = new AtomicInteger(); + public final AtomicInteger requestsCompleted = new AtomicInteger(); + public final AtomicInteger operations = new AtomicInteger(); + + public ConcurrentHashMap retryFailures = new ConcurrentHashMap<>(); + + + private final ExecutorService executor = Executors.newCachedThreadPool(); + + @Override + public ResponseT performRequest( + RequestT request, + Endpoint endpoint, + @Nullable TransportOptions options + ) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture performRequestAsync(RequestT request, Endpoint endpoint, @Nullable TransportOptions options) { + + BulkRequest bulk = (BulkRequest) request; + requestsStarted.incrementAndGet(); + operations.addAndGet(bulk.operations().size()); + + if (bulk.operations().isEmpty()) { + System.out.println("No operations!"); + } + + // For testing purposes, different result depending on the operation type. + // Create will always succeed + // Index will always return 429 for 2 times, then 200. Index with index name "fail" will only + // return 429. + // Delete will always return 404. Delete with index name "fail" will throw transport exception. + + try { + + List items = new ArrayList<>(); + for (BulkOperation op : bulk.operations()) { + OperationType operationType = OperationType.Create; + ErrorCause error = null; + int status = 200; + String index = null; + switch (op._kind()) { + case Index: + index = ((IndexOperation) op._get()).index(); + operationType = OperationType.Index; + retryFailures.putIfAbsent(op, 0); + boolean isStillRetrying = retryFailures.computeIfPresent(op, (k, v) -> v + 1) > 2; + error = isStillRetrying && !index.equals("fail") ? null : + ErrorCause.of(e -> e.reason("some error")); + status = isStillRetrying && !index.equals("fail") ? 200 : 429; + break; + case Delete: + index = ((DeleteOperation) op._get()).index(); + if (index.equals("fail")) { + throw new RuntimeException("error"); + } + operationType = OperationType.Delete; + error = ErrorCause.of(e -> e.reason("some error")); + status = 404; + break; + default: + index = ((CreateOperation) op._get()).index(); + break; + } + ErrorCause finalError = error; + int finalStatus = status; + OperationType finalOperationType = operationType; + String finalIndex = index; + items.add(BulkResponseItem.of(b -> b + .index(finalIndex) + .operationType(finalOperationType) + .status(finalStatus) + .error(finalError))); + } + + CompletableFuture response = new CompletableFuture<>(); + executor.submit(() -> { + requestsCompleted.incrementAndGet(); + response.complete(BulkResponse.of(r -> r.errors(false).items(items).took(3))); + }); + + @SuppressWarnings("unchecked") + CompletableFuture result = (CompletableFuture) response; + return result; + } catch (RuntimeException e) { + CompletableFuture future = new CompletableFuture<>(); + future.completeExceptionally(e); + executor.submit(() -> { + future.completeExceptionally(e); + }); + return future; + } + } + + @Override + public JsonpMapper jsonpMapper() { + return SimpleJsonpMapper.INSTANCE; + } + + @Override + public TransportOptions options() { + return null; + } + + @Override + public void close() throws IOException { + executor.shutdown(); + try { + executor.awaitTermination(1, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + public void reset() { + requestsStarted.set(0); + requestsCompleted.set(0); + operations.set(0); + retryFailures = new ConcurrentHashMap<>(); + } + } + + private static class CountingListener implements BulkListener { + public final AtomicInteger sentRequestsTotal = new AtomicInteger(); + public final AtomicInteger successOperations = new AtomicInteger(); + public final AtomicInteger errorOperations = new AtomicInteger(); + public final AtomicInteger requests = new AtomicInteger(); + public final ConcurrentLinkedQueue sentContexts = new ConcurrentLinkedQueue<>(); + + @Override + public void beforeBulk(long executionId, BulkRequest request, List contexts) { + sentRequestsTotal.incrementAndGet(); + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, + BulkResponse response) { + for (BulkResponseItem item : response.items()) { + if (item.error() != null) { + errorOperations.incrementAndGet(); + } else { + successOperations.incrementAndGet(); + } + } + if (contexts.stream().anyMatch(Objects::nonNull)) { + sentContexts.addAll(contexts); + } + requests.incrementAndGet(); + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, + Throwable failure) { + failure.printStackTrace(); + errorOperations.addAndGet(request.operations().size()); + if (contexts.stream().anyMatch(Objects::nonNull)) { + sentContexts.addAll(contexts); + } + requests.incrementAndGet(); + } + + public void reset() { + successOperations.set(0); + errorOperations.set(0); + requests.set(0); + sentRequestsTotal.set(0); + } + } + + private BulkIngester newBasicBulkIngester(BulkListener listener) { + return BulkIngester.of(b -> b + .client(client) + .maxOperations(10) + .maxConcurrentRequests(10) + .listener(listener) + .backoffPolicy(BackoffPolicy.constantBackoff(50L, 8)) + ); + } + + private BulkIngester newBulkIngesterWithFlushAndContextAndLongExponential(BulkListener listener) { + return BulkIngester.of(b -> b + .client(client) + .maxOperations(10) + .maxConcurrentRequests(10) + .listener(listener) + .flushInterval(1000, TimeUnit.MILLISECONDS) + .backoffPolicy(BackoffPolicy.exponentialBackoff(100L, 8)) + ); + } + + private BulkIngester newBulkIngesterNoFlushAndContextAndLongExponential(BulkListener listener) { + return BulkIngester.of(b -> b + .client(client) + .maxOperations(10) + .maxConcurrentRequests(10) + .listener(listener) + .backoffPolicy(BackoffPolicy.exponentialBackoff(100L, 8)) + ); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterTest.java new file mode 100644 index 000000000..207574632 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterTest.java @@ -0,0 +1,627 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch._helpers.bulk; + +import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.ElasticsearchTestServer; +import co.elastic.clients.elasticsearch._helpers.bulk.BulkIngester; +import co.elastic.clients.elasticsearch._helpers.bulk.BulkListener; +import co.elastic.clients.elasticsearch._helpers.bulk.IngesterOperation; +import co.elastic.clients.elasticsearch._helpers.bulk.RetryableBulkOperation; +import co.elastic.clients.elasticsearch.core.BulkRequest; +import co.elastic.clients.elasticsearch.core.BulkResponse; +import co.elastic.clients.elasticsearch.core.bulk.BulkOperation; +import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; +import co.elastic.clients.elasticsearch.core.bulk.OperationType; +import co.elastic.clients.elasticsearch.end_to_end.RequestTest; +import co.elastic.clients.elasticsearch.indices.IndicesStatsResponse; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.SimpleJsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.TransportOptions; +import org.jetbrains.annotations.Nullable; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +class BulkIngesterTest extends Assertions { + + private static final BulkResponseItem successItem = BulkResponseItem.of(i -> i + .index("foo") + .status(200) + .operationType(OperationType.Delete) + ); + + private static final BulkOperation operation = BulkOperation.of(op -> op + .delete(d -> d.index("foo").id("bar")) + ); + + private void printStats(BulkIngester ingester) { + System.out.printf("Ingester - operations: %d (%d), requests: %d (%d)%n", + ingester.operationsCount(), ingester.operationContentionsCount(), + ingester.requestCount(), ingester.requestContentionsCount() + ); + } + + private void printStats(CountingListener listener) { + System.out.printf("Listener - operations: %d, requests: %d%n", + listener.operations.get(), + listener.requests.get() + ); + } + + private void printStats(TestTransport transport) { + System.out.printf("Transport - operations: %d, requests: %d (%d completed)%n", + transport.operations.get(), + transport.requestsStarted.get(), + transport.requestsCompleted.get() + ); + } + + @Test + public void basicTestFlush() throws Exception { + // Prime numbers, so that we have leftovers to flush before shutting down + multiThreadTest(7, 3, 5, 101, true); + } + + @Test + public void basicTestFlushWithInternalScheduler() throws Exception { + // Prime numbers, so that we have leftovers to flush before shutting down + multiThreadTest(7, 3, 5, 101, false); + } + + @Test + public void basicTestNoFlush() throws Exception { + // Will have nothing to flush on close. + multiThreadTest(10, 3, 5, 100, true); + } + + @Test + public void basicTestNoFlushWithInternalScheduler() throws Exception { + // Will have nothing to flush on close. + multiThreadTest(10, 3, 5, 100, false); + } + + private void multiThreadTest(int maxOperations, int maxRequests, int numThreads, int numOperations, + boolean externalScheduler) throws Exception { + + CountingListener listener = new CountingListener(); + TestTransport transport = new TestTransport(); + ElasticsearchAsyncClient client = new ElasticsearchAsyncClient(transport); + ScheduledExecutorService scheduler; + if (externalScheduler) { + scheduler = Executors.newSingleThreadScheduledExecutor(r -> { + Thread t = Executors.defaultThreadFactory().newThread(r); + t.setName("my-bulk-ingester-executor#"); + t.setDaemon(true); + return t; + }); + } else { + scheduler = null; + } + + BulkIngester ingester = BulkIngester.of(b -> b + .client(client) + .maxOperations(maxOperations) + .maxConcurrentRequests(maxRequests) + .scheduler(scheduler) + .listener(listener) + ); + + CountDownLatch latch = new CountDownLatch(numThreads); + for (int i = 0; i < numThreads; i++) { + new Thread(() -> { + try { + Thread.sleep((long)(Math.random() * 100)); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + for (int j = 0; j < numOperations; j++) { + ingester.add(operation); + } + + latch.countDown(); + }).start(); + } + + latch.await(); + + ingester.close(); + transport.close(); + if (scheduler != null) scheduler.shutdownNow(); + + printStats(ingester); + printStats(listener); + printStats(transport); + + int expectedOperations = numThreads * numOperations; + assertEquals(expectedOperations, ingester.operationsCount()); + assertEquals(expectedOperations, listener.operations.get()); + assertEquals(expectedOperations, transport.operations.get()); + + int expectedRequests = expectedOperations / maxOperations + ((expectedOperations % maxOperations == 0) ? 0 : 1) ; + + assertEquals(expectedRequests, ingester.requestCount()); + assertEquals(expectedRequests, listener.requests.get()); + assertEquals(expectedRequests, transport.requestsStarted.get()); + } + + @Test + public void multiThreadStressTest() throws InterruptedException, IOException { + + String index = "bulk-ingester-stress-test"; + ElasticsearchClient client = ElasticsearchTestServer.global().client(); + + // DISCLAIMER: this configuration is highly inefficient and only used here to showcase an extreme + // situation where the number of adding threads greatly exceeds the number of concurrent requests + // handled by the ingester. It's strongly recommended to always tweak maxConcurrentRequests accordingly. + BulkIngester ingester = BulkIngester.of(b -> b + .client(client) + .globalSettings(s -> s.index(index)) + .flushInterval(5, TimeUnit.SECONDS) + ); + + RequestTest.AppData appData = new RequestTest.AppData(); + appData.setIntValue(42); + appData.setMsg("Some message"); + + ExecutorService executor = Executors.newFixedThreadPool(50); + + for (int i = 0; i < 100000; i++) { + int ii = i; + Runnable thread = () -> { + int finalI = ii; + ingester.add(_1 -> _1 + .create(_2 -> _2 + .id(String.valueOf(finalI)) + .document(appData) + )); + }; + executor.submit(thread); + } + + executor.awaitTermination(10,TimeUnit.SECONDS); + ingester.close(); + + client.indices().refresh(); + + IndicesStatsResponse indexStats = client.indices().stats(g -> g.index(index)); + + assertTrue(indexStats.indices().get(index).primaries().docs().count()==100000); + } + + @Test + public void sizeLimitTest() throws Exception { + TestTransport transport = new TestTransport(); + + long operationSize = IngesterOperation.of(new RetryableBulkOperation<>(operation, null, null), transport.jsonpMapper()).size(); + + BulkIngester ingester = BulkIngester.of(b -> b + .client(new ElasticsearchAsyncClient(transport)) + // Set size limit just above operation's size, leading to 2 operations per request + .maxSize(operationSize + 1) + ); + + for (int i = 0; i < 10; i++) { + ingester.add(operation); + } + + ingester.close(); + transport.close(); + + assertEquals(10, ingester.operationsCount()); + assertEquals(5, ingester.requestCount()); + } + + @Test + public void periodicFlushTest() throws Exception { + TestTransport transport = new TestTransport(); + + BulkIngester ingester = BulkIngester.of(b -> b + .client(new ElasticsearchAsyncClient(transport)) + // Flush every 50 ms + .flushInterval(50, TimeUnit.MILLISECONDS) + // Disable other flushing limits + .maxSize(-1) + .maxOperations(-1) + .maxConcurrentRequests(Integer.MAX_VALUE-1) + ); + + // Add an operation every 100 ms to give time + // to the flushing timer to kick in. + for (int i = 0; i < 10; i++) { + ingester.add(operation); + Thread.sleep(100); + } + + ingester.close(); + transport.close(); + + // We should have one operation per request + assertEquals(10, ingester.operationsCount()); + assertEquals(10, ingester.requestCount()); + } + + @Test + public void failingListener() throws Exception { + TestTransport transport = new TestTransport(); + AtomicInteger failureCount = new AtomicInteger(); + AtomicReference> lastContexts = new AtomicReference<>(); + AtomicReference lastRequest = new AtomicReference<>(); + + BulkListener listener = new BulkListener() { + @Override + public void beforeBulk(long executionId, BulkRequest request, List contexts) { + // So that we can test that it's non-empty + lastContexts.set(contexts); + lastRequest.set(request); + + if (executionId == 1) { + // Fail before the request is sent + failureCount.incrementAndGet(); + throw new RuntimeException("Before bulk failure"); + } + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, BulkResponse response) { + if (executionId == 2) { + // Fail after the request is sent + failureCount.incrementAndGet(); + throw new RuntimeException("After bulk failure"); + } + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, Throwable failure) { + + } + }; + + BulkIngester ingester = BulkIngester.of(b -> b + .client(new ElasticsearchAsyncClient(transport)) + // Flush every 50 ms + .flushInterval(50, TimeUnit.MILLISECONDS) + // Disable other flushing limits + .maxSize(-1) + .maxOperations(-1) + .maxConcurrentRequests(Integer.MAX_VALUE - 1) + .listener(listener) + ); + + // Add an operation every 100 ms to give time + // to the flushing timer to kick in. + for (int i = 0; i < 10; i++) { + ingester.add(operation); + Thread.sleep(100); + } + + ingester.close(); + transport.close(); + + // We should have one operation per request + assertEquals(10, ingester.operationsCount()); + assertEquals(10, ingester.requestCount()); + // Transport hasn't seen the request where beforeBulk failed + assertEquals(9, transport.requestsStarted.get()); + + assertEquals(2, failureCount.get()); + + // Also test context list when no values were provided + assertTrue(lastRequest.get().operations().size() > 0); + assertEquals(lastRequest.get().operations().size(), lastContexts.get().size()); + } + + @Test + public void withContextValues() throws Exception { + TestTransport transport = new TestTransport(); + List allRequests = Collections.synchronizedList(new ArrayList<>()); + List> allContexts = Collections.synchronizedList(new ArrayList<>()); + + BulkListener listener = new BulkListener() { + @Override + public void beforeBulk(long executionId, BulkRequest request, List contexts) { + allRequests.add(request); + allContexts.add(contexts); + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, BulkResponse response) { + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, Throwable failure) { + } + }; + + BulkIngester ingester = BulkIngester.of(b -> b + .client(new ElasticsearchAsyncClient(transport)) + // Split every 10 operations + .maxOperations(10) + .listener(listener) + ); + + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + // Set a context only after 5, so that we test filling with nulls. + Integer context = j < 5 ? null : i*10 + j; + ingester.add(operation, context); + } + } + + ingester.close(); + transport.close(); + + // We should have 10 operations per request + assertEquals(100, ingester.operationsCount()); + assertEquals(10, ingester.requestCount()); + + for (int i = 0; i < 10; i++) { + List contexts = allContexts.get(i); + for (int j = 0; j < 10; j++) { + if (j < 5) { + assertNull(contexts.get(j)); + } else { + assertEquals(contexts.get(j), i*10 + j); + } + } + } + } + + @Test + public void testGlobalSettings() throws Exception { + AtomicReference storedRequest = new AtomicReference<>(); + + TestTransport transport = new TestTransport(); + CountingListener listener = new CountingListener() { + @Override + public void beforeBulk(long executionId, BulkRequest request, List contexts) { + super.beforeBulk(executionId, request, contexts); + storedRequest.set(request); + } + }; + + BulkIngester ingester = BulkIngester.of(b -> b + .client(new ElasticsearchAsyncClient(transport)) + .listener(listener) + .globalSettings(s -> s + .index("foo") + .routing("bar") + ) + ); + + ingester.add(operation); + + ingester.close(); + transport.close(); + + assertEquals(1, ingester.operationsCount()); + assertEquals(1, ingester.requestCount()); + + assertEquals("foo", storedRequest.get().index()); + assertEquals("bar", storedRequest.get().routing()); + } + + @Test + public void pipelineTest() { + String json = "{\"create\":{\"_id\":\"some_id\",\"_index\":\"some_idx\",\"pipeline\":\"pipe\",\"require_alias\":true}}"; + JsonpMapper mapper = new SimpleJsonpMapper(); + + BulkOperation create = BulkOperation.of(o -> o.create(c -> c + .pipeline("pipe") + .requireAlias(true) + .index("some_idx") + .id("some_id") + .document("Some doc") + )); + + String createStr = JsonpUtils.toJsonString(create, mapper); + assertEquals(json, createStr); + + BulkOperation create1 = IngesterOperation.of(new RetryableBulkOperation<>(create, null, null), mapper) + .repeatableOperation().operation(); + + String create1Str = JsonpUtils.toJsonString(create1, mapper); + assertEquals(json, create1Str); + } + + @Test + public void endToEndTest() throws Exception { + String index = "bulk-ingester-test"; + ElasticsearchClient client = ElasticsearchTestServer.global().client(); + + BulkIngester ingester = BulkIngester.of(b -> b + .client(client) + .globalSettings(s -> s.index(index)) + ); + + RequestTest.AppData appData = new RequestTest.AppData(); + appData.setIntValue(42); + appData.setMsg("Some message"); + + ingester.add(_1 -> _1 + .create(_2 -> _2 + .id("abc") + .document(appData) + )); + + ingester.add(_1 -> _1 + .create(_2 -> _2 + .id("def") + .document(appData) + )); + + ingester.add(_1 -> _1 + .update(_2 -> _2 + .id("gh") + .action(_3 -> _3 + .docAsUpsert(true) + .doc(appData)) + )); + + // Closing waits until all pending requests are completed + ingester.close(); + + for (String id : Arrays.asList("abc", "def", "gh")) { + assertEquals( + 42, + client.get(b -> b + .index(index) + .id(id), + RequestTest.AppData.class + ).source().getIntValue() + ); + } + + client.indices().delete(d -> d.index(index)); + + } + + @Test + public void testConfigValidation() { + + BulkIngester.Builder b = new BulkIngester.Builder<>(); + + assertThrows(IllegalArgumentException.class, () -> { + b.flushInterval(-1, TimeUnit.MILLISECONDS); + }); + + assertThrows(IllegalArgumentException.class, () -> { + b.maxConcurrentRequests(0); + }); + + assertThrows(IllegalArgumentException.class, () -> { + b.maxSize(-2); + }); + + assertThrows(IllegalArgumentException.class, () -> { + b.maxOperations(-2); + }); + + assertThrows(IllegalStateException.class, () -> { + b.maxSize(-1).maxOperations(-1).build(); + }); + } + + //----------------------------------------------------------------------------------------------------------------- + + private static class CountingListener implements BulkListener { + public final AtomicInteger operations = new AtomicInteger(); + public final AtomicInteger requests = new AtomicInteger(); + @Override + public void beforeBulk(long executionId, BulkRequest request, List contexts) { + + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, BulkResponse response) { + operations.addAndGet(request.operations().size()); + requests.incrementAndGet(); + } + + @Override + public void afterBulk(long executionId, BulkRequest request, List contexts, Throwable failure) { + failure.printStackTrace(); + operations.addAndGet(request.operations().size()); + requests.incrementAndGet(); + } + } + + private static class TestTransport implements ElasticsearchTransport { + public final AtomicInteger requestsStarted = new AtomicInteger(); + public final AtomicInteger requestsCompleted = new AtomicInteger(); + public final AtomicInteger operations = new AtomicInteger(); + + private final ExecutorService executor = Executors.newCachedThreadPool(); + + @Override + public ResponseT performRequest( + RequestT request, + Endpoint endpoint, + @Nullable TransportOptions options + ) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public CompletableFuture performRequestAsync(RequestT request, Endpoint endpoint, @Nullable TransportOptions options) { + + BulkRequest bulk = (BulkRequest) request; + requestsStarted.incrementAndGet(); + operations.addAndGet(bulk.operations().size()); + + if (bulk.operations().size() == 0) { + System.out.println("No operations!"); + } + + List items = new ArrayList<>(); + for (int i = 0; i < bulk.operations().size(); i++) { + items.add(successItem); + } + + CompletableFuture response = new CompletableFuture<>(); + executor.submit(() -> { + requestsCompleted.incrementAndGet(); + response.complete(BulkResponse.of(r -> r.errors(false).items(items).took(3))); + }); + + @SuppressWarnings("unchecked") + CompletableFuture result = (CompletableFuture)response; + return result; + } + + @Override + public JsonpMapper jsonpMapper() { + return SimpleJsonpMapper.INSTANCE; + } + + @Override + public TransportOptions options() { + return null; + } + + @Override + public void close() throws IOException { + executor.shutdown(); + try { + executor.awaitTermination(1, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java new file mode 100644 index 000000000..8ae60957f --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java @@ -0,0 +1,205 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch._helpers.esql; + +import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.ElasticsearchTestServer; +import co.elastic.clients.elasticsearch._helpers.esql.EsqlAdapterTest; +import co.elastic.clients.elasticsearch._helpers.esql.jdbc.ResultSetEsqlAdapter; +import co.elastic.clients.elasticsearch._helpers.esql.objects.ObjectsEsqlAdapter; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.io.entity.ByteArrayEntity; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import org.apache.commons.io.IOUtils; + +import org.elasticsearch.client.Request; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.InputStream; +import java.sql.ResultSet; +import java.sql.Timestamp; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +public class EsqlAdapterEndToEndTest extends Assertions { + + static ElasticsearchClient esClient; + + @BeforeAll + public static void setup() throws Exception { + ElasticsearchClient global = ElasticsearchTestServer.global().client(); + RestClient restClient = ((RestClientTransport) global._transport()).restClient(); + esClient = new ElasticsearchClient(new RestClientTransport(restClient, new JacksonJsonpMapper())); + + esClient.indices().delete(d -> d.index("employees").ignoreUnavailable(true)); + + Request request = new Request("POST", "/employees/_bulk?refresh=true"); + + InputStream resourceAsStream = EsqlAdapterTest.class.getResourceAsStream("employees.ndjson"); + byte[] bytes = IOUtils.toByteArray(resourceAsStream); + request.setEntity(new ByteArrayEntity(bytes, ContentType.APPLICATION_JSON)); + + restClient.performRequest(request); + } + + @Test + public void resultSetTest() throws Exception { + + ResultSet rs = esClient.esql().query( + ResultSetEsqlAdapter.INSTANCE, + "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | SORT emp_no | LIMIT 300", + // Testing parameters. Note that FROM and LIMIT do not accept parameters + "10042", "10002" + ); + + { + assertTrue(rs.next()); + assertEquals("10002", rs.getString("emp_no")); + + // Single valued fields come back as single value even if other rows have multiple values + @SuppressWarnings("unchecked") + String job = (String) rs.getObject("job_positions"); + assertEquals("Senior Team Lead", job); + } + + { + assertTrue(rs.next()); + assertEquals("10042", rs.getString("emp_no")); + + java.sql.Date hireDate = rs.getDate("hire_date"); + assertEquals("1993-03-21", hireDate.toString()); + + Timestamp hireDate1 = rs.getTimestamp("hire_date"); + assertEquals( + "1993-03-21T00:00:00Z[UTC]", + DateTimeFormatter.ISO_DATE_TIME.format(hireDate1.toInstant().atZone(ZoneId.of("UTC"))) + ); + + @SuppressWarnings("unchecked") + List jobs = (List) rs.getObject("job_positions"); + + assertEquals(4, jobs.size()); + assertEquals("Architect", jobs.get(0)); + } + + assertFalse(rs.next()); + } + + @Test + public void objectsTest() throws Exception { + Iterable result = esClient.esql().query( + ObjectsEsqlAdapter.of(EmpData.class), + "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | SORT emp_no | LIMIT 300", + // Testing parameters. Note that FROM and LIMIT do not accept parameters + "10042", "10002" + ); + + Iterator it = result.iterator(); + + { + EmpData emp = it.next(); + assertEquals("10002", emp.empNo); + List jobPositions = emp.jobPositions; + // In addition to the value, this tests that single strings are correctly deserialized as a list + assertEquals(Arrays.asList("Senior Team Lead"), emp.jobPositions); + } + + { + EmpData emp = it.next(); + assertEquals("10042", emp.empNo); + assertEquals(4, emp.jobPositions.size()); + assertTrue(emp.jobPositions.contains("Architect")); + assertTrue(emp.jobPositions.contains("Business Analyst")); + assertTrue(emp.jobPositions.contains("Internship")); + assertTrue(emp.jobPositions.contains("Junior Developer")); + + assertEquals("1993-03-21T00:00:00Z[UTC]", + DateTimeFormatter.ISO_DATE_TIME.format(emp.hireDate.toInstant().atZone(ZoneId.of("UTC"))) + ); + } + + assertFalse(it.hasNext()); + + } + + @Test + public void asyncObjects() throws Exception { + + ElasticsearchAsyncClient asyncClient = new ElasticsearchAsyncClient(esClient._transport(), esClient._transportOptions()); + + + CompletableFuture> future = asyncClient.esql().query( + ObjectsEsqlAdapter.of(EmpData.class), + "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | SORT emp_no | LIMIT 300", + // Testing parameters. Note that FROM and LIMIT do not accept parameters + "10042", "10002" + ); + + future.thenApply(result -> { + Iterator it = result.iterator(); + + { + EmpData emp = it.next(); + assertEquals("10002", emp.empNo); + List jobPositions = emp.jobPositions; + // In addition to the value, this tests that single strings are correctly deserialized as a list + assertEquals(Arrays.asList("Senior Team Lead"), emp.jobPositions); + } + + { + EmpData emp = it.next(); + assertEquals("10042", emp.empNo); + assertEquals(4, emp.jobPositions.size()); + assertTrue(emp.jobPositions.contains("Architect")); + assertTrue(emp.jobPositions.contains("Business Analyst")); + assertTrue(emp.jobPositions.contains("Internship")); + assertTrue(emp.jobPositions.contains("Junior Developer")); + + assertEquals("1993-03-21T00:00:00Z[UTC]", + DateTimeFormatter.ISO_DATE_TIME.format(emp.hireDate.toInstant().atZone(ZoneId.of("UTC"))) + ); + } + + assertFalse(it.hasNext()); + return null; + } + ).get(); + } + + @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) + @JsonIgnoreProperties(ignoreUnknown = true) + public static class EmpData { + public String empNo; + public java.util.Date hireDate; + public List jobPositions; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterTest.java new file mode 100644 index 000000000..863b5f844 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterTest.java @@ -0,0 +1,119 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch._helpers.esql; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._helpers.esql.jdbc.ResultSetEsqlAdapter; +import co.elastic.clients.elasticsearch._helpers.esql.objects.ObjectsEsqlAdapter; +import co.elastic.clients.elasticsearch.esql.EsqlFormat; +import co.elastic.clients.json.JsonpMappingException; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.testkit.MockHttpClient; +import co.elastic.clients.transport.endpoints.BinaryResponse; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.sql.ResultSet; +import java.sql.Types; + +public class EsqlAdapterTest extends Assertions { + + String json = "{\n" + + " \"took\": 10," + + " \"columns\": [\n" + + "\t{\"name\": \"avg_salary\", \"type\": \"double\"},\n" + + "\t{\"name\": \"lang\", \t\"type\": \"keyword\"}\n" + + " ],\n" + + " \"values\": [\n" + + "\t[43760.0, \"Spanish\"],\n" + + "\t[48644.0, \"French\"],\n" + + "\t[48832.0, \"German\"]\n" + + " ]\n" + + "}\n"; + + ElasticsearchClient esClient = new MockHttpClient() + .add("/_query", "application/json", json) + .client(new JacksonJsonpMapper()); // object deserializer needs a buffering mapper + + public static class Data { + public double avg_salary; + public String lang; + } + + @Test + public void testMissingColumns() throws IOException { + String badJson = "{\n" + + " \"took\": 10," + + " \"values\": [\n" + + "\t[43760.0, \"Spanish\"],\n" + + "\t[48644.0, \"French\"],\n" + + "\t[48832.0, \"German\"]\n" + + " ]\n" + + "}\n"; + + ElasticsearchClient esClient = new MockHttpClient() + .add("/_query", "application/json", badJson) + .client(new JacksonJsonpMapper()); + + JsonpMappingException jsonMappingException = assertThrows(JsonpMappingException.class, () -> { + esClient.esql().query( + ResultSetEsqlAdapter.INSTANCE, + "FROM employees | STATS avg_salary = AVG(salary) by country" + ); + }); + assertTrue(jsonMappingException.getMessage().contains("Expecting a 'columns' property")); + } + + @Test + public void testObjectDeserializer() throws IOException { + + BinaryResponse response = esClient.esql().query(q -> q + .query("FROM foo") + .format(EsqlFormat.Json) + ); + + Iterable data = esClient.esql().query( + new ObjectsEsqlAdapter<>(Data.class), + "FROM employees | STATS avg_salary = AVG(salary) by country" + ); + + for (Data d: data) { + System.out.println(d.lang + " " + d.avg_salary); + } + } + + @Test + public void testResultSetAdapter() throws Exception { + + ResultSet resultSet = esClient.esql().query( + ResultSetEsqlAdapter.INSTANCE, + "FROM employees | STATS avg_salary = AVG(salary) by country" + ); + + assertEquals(2, resultSet.getMetaData().getColumnCount()); + assertEquals(Types.DOUBLE, resultSet.getMetaData().getColumnType(1)); + assertEquals(Types.VARCHAR, resultSet.getMetaData().getColumnType(2)); + + while (resultSet.next()) { + System.out.println(resultSet.getDouble("avg_salary") + " " + resultSet.getString(2)); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/end_to_end/RequestTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/end_to_end/RequestTest.java new file mode 100644 index 000000000..31ed61407 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/end_to_end/RequestTest.java @@ -0,0 +1,494 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.end_to_end; + +import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.ElasticsearchTestServer; +import co.elastic.clients.elasticsearch._types.ElasticsearchException; +import co.elastic.clients.elasticsearch._types.Refresh; +import co.elastic.clients.elasticsearch._types.aggregations.HistogramAggregate; +import co.elastic.clients.elasticsearch._types.mapping.Property; +import co.elastic.clients.elasticsearch.cat.NodesResponse; +import co.elastic.clients.elasticsearch.core.BulkResponse; +import co.elastic.clients.elasticsearch.core.ClearScrollResponse; +import co.elastic.clients.elasticsearch.core.ClosePointInTimeResponse; +import co.elastic.clients.elasticsearch.core.GetResponse; +import co.elastic.clients.elasticsearch.core.IndexResponse; +import co.elastic.clients.elasticsearch.core.MsearchResponse; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.bulk.OperationType; +import co.elastic.clients.elasticsearch.core.msearch.RequestItem; +import co.elastic.clients.elasticsearch.indices.CreateIndexResponse; +import co.elastic.clients.elasticsearch.indices.DiskUsageResponse; +import co.elastic.clients.elasticsearch.indices.GetIndexResponse; +import co.elastic.clients.elasticsearch.indices.GetIndicesSettingsResponse; +import co.elastic.clients.elasticsearch.indices.GetMappingResponse; +import co.elastic.clients.elasticsearch.indices.IndexState; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.transport.endpoints.BooleanResponse; +import co.elastic.clients.util.BinaryData; +import co.elastic.clients.util.ContentType; +import co.elastic.clients.util.DateTime; +import com.fasterxml.jackson.core.type.TypeReference; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +public class RequestTest extends Assertions { + + static ElasticsearchClient client; + + @BeforeAll + public static void setup() { + client = ElasticsearchTestServer.global().client(); + } + + @Test + public void testCount() throws Exception { + // Tests that a no-parameter method exists for endpoints that only have optional properties + assertTrue(client.count().count() >= 0); + } + + @Test + public void testBuildTime() throws Exception { + DateTime buildTime = client.info().version().buildDate(); + Instant early2020 = DateTimeFormatter.ISO_INSTANT.parse("2020-01-01T00:00:00Z", Instant::from); + + assertTrue(early2020.isBefore(buildTime.toInstant())); + } + + @Test + public void testIndexCreation() throws Exception { + ElasticsearchAsyncClient asyncClient = new ElasticsearchAsyncClient(client._transport()); + + // Ping the server + assertTrue(client.ping().value()); + + // Create an index... + final CreateIndexResponse createResponse = client.indices().create(b -> b.index("my-index")); + assertTrue(createResponse.acknowledged()); + assertTrue(createResponse.shardsAcknowledged()); + + // Find info about it, using the async client + CompletableFuture futureResponse = asyncClient.indices().get(b -> b.index("my-index")); + GetIndexResponse response = futureResponse.get(10, TimeUnit.SECONDS); + + Map indices = response.result(); + + assertEquals(1, indices.size()); + assertNotNull(indices.get("my-index")); + } + + @Test + public void testDataIngestion() throws Exception { + + String index = "ingest-test"; + + // Create an index + CreateIndexResponse createIndexResponse = client.indices().create(b -> b + .index(index) + ); + + assertEquals(index, createIndexResponse.index()); + + // Check that it actually exists. Example of a boolean response + BooleanResponse existsResponse = client.indices().exists(b -> b.index(index)); + assertTrue(existsResponse.value()); + + // Ingest some data + AppData appData = new AppData(); + appData.setIntValue(1337); + appData.setMsg("foo"); + + String docId = client.index(b -> b + .index(index) + .id("my/Id") // test with url-unsafe string + .document(appData) + .refresh(Refresh.True) // Make it visible for search + ).id(); + + assertEquals("my/Id", docId); + + // Check auto-created mapping + GetMappingResponse mapping = client.indices().getMapping(b -> b.index(index)); + assertEquals( + Property.Kind.Long, + mapping.get("ingest-test").mappings().properties().get("intValue")._kind() + ); + + // Query by id + AppData esData = client.get(b -> b + .index(index) + .id(docId) + , AppData.class + ).source(); + + assertEquals(1337, esData.getIntValue()); + assertEquals("foo", esData.getMsg()); + + // Query by id a non-existing document + final GetResponse notExists = client.get(b -> b + .index(index) + .id("some-random-id") + , AppData.class + ); + + assertFalse(notExists.found()); + assertNull(notExists.source()); + + // Search + SearchResponse search = client.search(b -> b + .index(index) + , AppData.class + ); + + long hits = search.hits().total().value(); + assertEquals(1, hits); + + esData = search.hits().hits().get(0).source(); + assertEquals(1337, esData.getIntValue()); + assertEquals("foo", esData.getMsg()); + + RequestItem item = RequestItem.of(_1 -> _1 + .header(_2 -> _2.index("test")) + .body(_2 -> _2.size(4)) + ); + + // MSearch: 1st search on an existing index, 2nd one on a non-existing index + final MsearchResponse msearch = client.msearch(_0 -> _0 + .searches(_1 -> _1 + .header(_3 -> _3.index(index)) + .body(_3 -> _3.query(_4 -> _4.matchAll(_5 -> _5))) + ).searches(_1 -> _1 + .header(_3 -> _3.index("non-existing")) + .body(_3 -> _3.query(_4 -> _4.matchAll(_5 -> _5))) + ) + , AppData.class); + + assertEquals(2, msearch.responses().size()); + assertTrue(msearch.responses().get(0).isResult()); + assertEquals(1, msearch.responses().get(0).result().hits().hits().size()); + assertTrue(msearch.responses().get(1).isFailure()); + assertEquals(404, msearch.responses().get(1).failure().status()); + } + + @Test + public void testBinaryDataIngestion() throws IOException { + String index = "binary-ingestion-test"; + String id = "foo-bar"; + + BinaryData data = BinaryData.of("{\"foo\":\"bar\"}".getBytes(), ContentType.APPLICATION_JSON); + + client.index(i -> i + .index(index) + .id(id) + .document(data) + .refresh(Refresh.True) + ); + + GetResponse getResponse = client.get(g -> g + .index(index) + .id(id) + , BinaryData.class + ); + + assertEquals(id, getResponse.id()); + assertEquals( + "{\"foo\":\"bar\"}", + new String(getResponse.source().asByteBuffer().array(), StandardCharsets.UTF_8) + ); + } + + @Test + public void testMappingWithType() throws IOException { + String index = "mapping-with-type"; + + // Ingest some data + Map map = new HashMap<>(); + AppData appData = new AppData(); + appData.setIntValue(1); + appData.setMsg("foo"); + map.put("foo", appData); + appData = new AppData(); + appData.setIntValue(2); + appData.setMsg("bar"); + map.put("bar", appData); + + String id = client.index(i -> i.index(index).document(map)).id(); + + TypeReference> typeRef = new TypeReference>() {}; + + Map result = client.>get(g -> g.index(index).id(id), typeRef.getType()).source(); + assertEquals(1, result.get("foo").intValue); + assertEquals(2, result.get("bar").intValue); + + } + + @Test + public void testCatRequest() throws IOException { + // Cat requests should have the "format=json" added by the transport + NodesResponse nodes = client.cat().nodes(_0 -> _0); + System.out.println(ModelTestCase.toJson(nodes, client._transport().jsonpMapper())); + + assertEquals(1, nodes.valueBody().size()); + assertEquals("*", nodes.valueBody().get(0).master()); + } + + @Test + public void testBulkRequest() throws IOException { + AppData appData = new AppData(); + appData.setIntValue(42); + appData.setMsg("Some message"); + + BulkResponse bulk = client.bulk(_0 -> _0 + .operations(_1 -> _1 + .create(_2 -> _2 + .index("foo") + .id("abc") + .document(appData) + )) + .operations(_1 -> _1 + .create(_2 -> _2 + .index("foo") + .id("def") + .document(appData) + )) + .operations(_1 -> _1 + .update(_2 -> _2 + .index("foo") + .id("gh") + .action(_3 -> _3 + .docAsUpsert(true) + .doc(appData)) + ) + ) + ); + + assertFalse(bulk.errors()); + assertEquals(3, bulk.items().size()); + assertEquals(OperationType.Create, bulk.items().get(0).operationType()); + assertEquals("foo", bulk.items().get(0).index()); + assertEquals(1L, bulk.items().get(0).version().longValue()); + assertEquals("foo", bulk.items().get(1).index()); + assertEquals(1L, bulk.items().get(1).version().longValue()); + assertEquals(42, client.get(b -> b.index("foo").id("gh"), AppData.class).source().intValue); + } + + @Test + public void testRefresh() throws IOException { + AppData appData = new AppData(); + appData.setIntValue(42); + appData.setMsg("Some message"); + + IndexResponse ir = client.index(_0 -> _0 + .index("test") + .id("1") + .document(appData) + .refresh(Refresh.WaitFor) + ); + + assertEquals("1", ir.id()); + } + + @Test public void errorResponse() throws Exception { + BooleanResponse exists = client.exists(_0 -> _0.index("doesnotexist").id("reallynot")); + assertFalse(exists.value()); + + ElasticsearchException ex = assertThrows(ElasticsearchException.class, () -> { + GetResponse response = client.get( + _0 -> _0.index("doesnotexist").id("reallynot"), String.class + ); + }); + + assertEquals("es/get", ex.endpointId()); + assertEquals(404, ex.status()); + assertEquals("index_not_found_exception", ex.error().type()); + assertEquals("doesnotexist", ex.error().metadata().get("index").to(String.class)); + + + ExecutionException ee = assertThrows(ExecutionException.class, () -> { + ElasticsearchAsyncClient aClient = new ElasticsearchAsyncClient(client._transport()); + GetResponse response = aClient.get( + _0 -> _0.index("doesnotexist").id("reallynot"), String.class + ).get(); + }); + + ex = ((ElasticsearchException) ee.getCause()); + assertEquals("es/get", ex.endpointId()); + assertEquals(404, ex.status()); + assertEquals("index_not_found_exception", ex.error().type()); + } + + @Test + public void testErrorStatusCodeWithValidResponse() throws IOException { + // https://github.com/elastic/elasticsearch-java/issues/36 + + // Some endpoints return a faulty status code 404 with a valid response. + // Transports should first try to decode an error, and if they fail because of missing properties for + // the error type, then try to decode the regular request. + + final ClearScrollResponse clearResponse = client.clearScroll(b -> b.scrollId( + "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ==") + ); + assertEquals(0, clearResponse.numFreed()); + + final ClosePointInTimeResponse closeResponse = client.closePointInTime(b -> b.id( + "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBY" + + "QADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA==")); + assertEquals(0, closeResponse.numFreed()); + } + + @Test + public void testSearchAggregation() throws IOException { + + client.create(_1 -> _1.index("products").id("A").document(new Product(5)).refresh(Refresh.True)); + client.create(_1 -> _1.index("products").id("B").document(new Product(15)).refresh(Refresh.True)); + client.create(_1 -> _1.index("products").id("C").document(new Product(25)).refresh(Refresh.True)); + + SearchResponse searchResponse = client.search(_1 -> _1 + .index("products") + .size(0) + .aggregations( + "prices", _3 -> _3 + .histogram(_4 -> _4 + .field("price") + .interval(10.0) + ).aggregations( + "average", _5 -> _5 + .avg(_6 -> _6.field("price")) + ) + ) + , Product.class + ); + + HistogramAggregate prices = searchResponse.aggregations().get("prices").histogram(); + assertEquals(3, prices.buckets().array().size()); + assertEquals(1, prices.buckets().array().get(0).docCount()); + assertEquals(5.0, prices.buckets().array().get(0).aggregations().get("average").avg().value(), 0.01); + + // We've set "size" to zero + assertEquals(0, searchResponse.hits().hits().size()); + + } + + @Test + public void testGetMapping() throws Exception { + // See also VariantsTest.testNestedTaggedUnionWithDefaultTag() + // and https://github.com/elastic/elasticsearch-java/issues/45 + String index = "testindex"; + + Map fields = Collections.singletonMap("keyword", Property.of(p -> p.keyword(k -> k.ignoreAbove(256)))); + Property text = Property.of(p -> p.text(t -> t.fields(fields))); + + client.indices().create(c -> c + .index(index) + .mappings(m -> m + .properties("id", text) + .properties("name", p -> p + .object(o -> o + .properties("first", text) + .properties("last", text) + ) + ) + ) + ); + + GetMappingResponse mr = client.indices().getMapping(mrb -> mrb.index(index)); + + assertNotNull(mr.result().get(index)); + assertNotNull(mr.result().get(index).mappings().properties().get("name").object()); + } + + @Test + public void testDefaultIndexSettings() throws IOException { + //https://github.com/elastic/elasticsearch-java/issues/46 + + String index = "index-settings"; + client.index(_1 -> _1.index(index).document(new Product(5)).refresh(Refresh.True)); + + GetIndicesSettingsResponse settings; + settings = client.indices().getSettings(b -> b.index(index).includeDefaults(true)); + assertNotNull(settings.get(index).defaults()); + + settings = client.indices().getSettings(b -> b.index(index)); + assertNull(settings.get(index).defaults()); + } + + @Test + public void testValueBodyResponse() throws Exception { + DiskUsageResponse resp = client.indices().diskUsage(b -> b + .index("*") + .allowNoIndices(true) + .runExpensiveTasks(true) + ); + + assertNotNull(resp.valueBody().toJson().asJsonObject().get("_shards")); + } + + public static class AppData { + private int intValue; + private String msg; + + public int getIntValue() { + return intValue; + } + + public void setIntValue(int intValue) { + this.intValue = intValue; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + } + + public static class Product { + public double price; + + public Product() {} + public Product(double price) { + this.price = price; + } + + public double getPrice() { + return this.price; + } + + public void setPrice(double price) { + this.price = price; + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ClientTests.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ClientTests.java new file mode 100644 index 000000000..1e96ad2e4 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ClientTests.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments; + +import co.elastic.clients.elasticsearch.experiments.api.Bar; +import co.elastic.clients.elasticsearch.experiments.api.FooRequest; +import co.elastic.clients.elasticsearch.experiments.api.FooResponse; +import co.elastic.clients.elasticsearch.experiments.api.query2.Query; +import co.elastic.clients.elasticsearch.experiments.api.query2.TermsQuery; +import co.elastic.clients.elasticsearch.experiments.base.Client; +import co.elastic.clients.transport.Endpoint; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.Collections; + +public class ClientTests { + + @Test + public void testClient() throws Exception { + + Client client = new Client(){ + @Override + protected ResponseT performRequest( + RequestT request, Endpoint endpoint + ) throws IOException { + // don't care for now, we're testing compilation + return null; + } + }; + + client.foo(fb -> fb + .name("z") + .value(1) + .routing("fooo") + .query(q -> q + .bool(b-> b + .add_must(m -> m.terms((TermsQuery) null)) + ) + //.terms(tq -> tq.term("")) + .meta(Collections.emptyMap()) + ) + ); + + // Builders everywhere + FooResponse r1 = client.foo( + FooRequest.builder() + .name("z") + .value(1) + .bar(Bar.builder() + .name("Raise the bar") + .build() + ) + .build() + ); + + // Illustrates creating an object outside of the client call + TermsQuery filter = TermsQuery.builder() + .field("foo") + .term("bar") + .build(); + + Query filter2 = new Query.Builder() + .terms(t -> t + .field("foo") + .term("bar") + ).build(); + + // Fluid lambda-based builders + FooResponse r2 = client.foo(f -> f + .name("z") + .value(1) + .bar(bar -> bar + .name("Raise the bar") + ) + .query(q -> q + .bool(b -> b + .add_must(q1 -> q1.terms(filter)) + .add_must(q1 -> q1 + .terms(t -> t.field("a").term("b")) + ) + .add_must(q1 -> q1 + .terms(t -> t.field("a").term("b")) + ) + .minimumShouldMatch(2) + ) + ) + ); + } +} + diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ParsingTests.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ParsingTests.java new file mode 100644 index 000000000..d461a2e75 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ParsingTests.java @@ -0,0 +1,76 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments; + +import co.elastic.clients.elasticsearch.experiments.api.FooRequest; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParsingException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; + +public class ParsingTests extends Assertions { + + @Test + public void testFoo() throws Exception { + + try { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + FooRequest foo = FooRequest.builder() + .name("z") + .value(1) + .indices("a", "b", "c") + .bar(b -> b + .name("Raise the bar") + ) + .build(); + + JsonProvider provider = JsonpUtils.provider(); + JsonGenerator generator = provider.createGenerator(baos); + foo.serialize(generator, new JsonbJsonpMapper()); + + generator.close(); + String str = baos.toString(); + + assertEquals("{\"name\":\"z\",\"value\":1,\"indices\":[\"a\",\"b\",\"c\"],\"bar\":{\"name\":\"Raise the bar\"}}", str); + + JsonParser parser = provider.createParser(new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8))); + + FooRequest foo2 = FooRequest.parser().deserialize(parser, new JsonbJsonpMapper()); + + assertEquals(foo.name(), foo2.name()); + assertEquals(foo.value(), foo2.value()); + assertNull(foo2.size()); + assertEquals(foo.indices(), foo2.indices()); + assertEquals("Raise the bar", foo.bar().name()); + } catch (JsonParsingException je) { + throw new JsonParsingException(je.getMessage() + " at " + je.getLocation(), je, je.getLocation()); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/UnionVariant.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/UnionVariant.java new file mode 100644 index 000000000..5d869e6f9 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/UnionVariant.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments; + +/** + * An implementation of a variant type. + */ +public interface UnionVariant { + + /** + * Get the type of this object when used as a variant + */ + Tag _variantType(); +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/Bar.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/Bar.java new file mode 100644 index 000000000..fa2e4635a --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/Bar.java @@ -0,0 +1,82 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.api; + +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import javax.annotation.Nullable; + +public class Bar implements JsonpSerializable { + + private final String name; + + @Nullable + public String name() { + return this.name; + } + + public Bar(Builder builder) { + this.name = builder.name; + } + + @Override + public void serialize(JsonGenerator builder, JsonpMapper mapper) { + builder.writeStartObject(); + if (this.name != null) builder.write("name", this.name); + builder.writeEnd(); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder implements ObjectBuilder { + private String name; + + public Builder name(@Nullable String name) { + this.name = name; + return this; + } + + public Bar build() { + return new Bar(this); + } + } + + private static final JsonpDeserializer PARSER; + + public static JsonpDeserializer parser() { + return PARSER; + } + + static { + ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); + + op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); + + PARSER = new ObjectBuilderDeserializer<>(op); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/DateMathTimeUnit.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/DateMathTimeUnit.java new file mode 100644 index 000000000..6dcf252be --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/DateMathTimeUnit.java @@ -0,0 +1,49 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.api; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializer; + +public enum DateMathTimeUnit implements JsonEnum { + + Year("Y"), + Month("M"), + Day("D"), + Hour("h"), + Minute("m"), + Second("s"); + + private final String jsonValue; + + DateMathTimeUnit(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonpDeserializer PARSER; + + static { + PARSER = new Deserializer<>(DateMathTimeUnit.values()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooOptRequest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooOptRequest.java new file mode 100644 index 000000000..509de500e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooOptRequest.java @@ -0,0 +1,278 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.api; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch.experiments.api.Bar; +import co.elastic.clients.elasticsearch.experiments.api.FooResponse; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.endpoints.SimpleEndpoint; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.OptionalInt; + +import static java.util.Objects.requireNonNull; + +// Implementing ToXContent is optional, only if there's a request body +public class FooOptRequest implements JsonpSerializable { + + //=========================================== + // Fields and getters + //=========================================== + + //------------------------------------------- + // A required String + + private final String name; + + @Nonnull + public final String name() { + return this.name; + } + + //------------------------------------------- + // An optional String + + private final String routing; + + @Nonnull + public final Optional routing() { + return Optional.ofNullable(this.routing); + } + + //------------------------------------------- + // A required primitive type + + private final int value; + + public int value() { + return this.value; + } + + //------------------------------------------- + // An optional primitive type + private final OptionalInt size; + + /** + * Description for field {@code size} + */ + @Nonnull + public final OptionalInt size() { + return this.size; + } + + //------------------------------------------- + // An optional array + + private final List indices; + + @Nonnull + public final Optional> indices() { + return Optional.ofNullable(this.indices); + } + + //------------------------------------------- + // An optional sub-object + + private final co.elastic.clients.elasticsearch.experiments.api.Bar bar; + + @Nonnull + public Optional bar() { + return Optional.ofNullable(this.bar); + } + + public FooOptRequest(Builder builder) { + this.name = builder.name; + this.routing = builder.routing; + this.value = builder.value; + this.size = builder.size == null ? OptionalInt.empty() : OptionalInt.of(builder.size); + this.indices = builder.indices; + this.bar = builder.bar; + } + + //=========================================== + // Serialization + //=========================================== + + + @Override + public void serialize(JsonGenerator builder, JsonpMapper mapper) { + builder.writeStartObject(); + + // Classic approach is to use the deserialization field's preferred name: + // + // if (buckets.isPresent()) builder.field(INT_FIELD.getPreferredName(), buckets.getAsInt()); + // + // In a generated code context we can use the string constant, which also avoids declaring ParseField if we + // only serialize (e.g. requests) + + // required field + builder.write("name", this.name); + + // optional field + if (this.routing != null) builder.write("routing", this.routing); + + // required field + builder.write("value", value); + + // optional field + if (this.size.isPresent()) builder.write("size", this.size.getAsInt()); + + // We could just call this and let the builder will handle it by itself with: + // + // if (this.indices != null) builder.field("indices", this.indices); + // + // But the logic is a bit involved (like checking circular dependencies) so we use a more direct implementation: + if (this.indices != null) { + builder.writeKey("indices").writeStartArray(); + for (String str : this.indices) builder.write(str); + builder.writeEnd(); + } + + if (this.bar != null) { + builder.writeKey("bar"); + this.bar.serialize(builder, mapper); + } + + builder.writeEnd(); + } + + //=========================================== + // Builder + //=========================================== + + public static Builder builder() { + return new Builder(); + } + + // Constructor with required fields + public static Builder builder(String name, int size) { + Builder result = new Builder(); + result.name(name); + result.size(size); + return result; + } + + public static class Builder implements ObjectBuilder { + private String name; + private String routing; + private int value; + private boolean value$isSet = false; + private Integer size; + private List indices; + private co.elastic.clients.elasticsearch.experiments.api.Bar bar; + + public final Builder name(@Nonnull String v) { + this.name = requireNonNull(v); + return this; + } + + public final Builder routing(@Nullable String v) { + this.routing = v; + return this; + } + + public final Builder value(int v) { + this.value = v; + this.value$isSet = true; + return this; + } + + public final Builder size(@Nullable Integer v) { + this.size = v; + return this; + } + + public final Builder indices(@Nullable List v) { + indices = v; + return this; + } + + // Convenience variant with varargs + public final Builder indices(String... v) { + indices = Arrays.asList(v); + return this; + } + + public Builder bar(@Nullable co.elastic.clients.elasticsearch.experiments.api.Bar v) { + bar = v; + return this; + } + + public Builder bar(@Nullable Bar.Builder v) { + bar = v.build(); + return this; + } + + public FooOptRequest build() { + requireNonNull(this.name, "Name was not set"); + requireTrue(this.value$isSet, "Value was not set"); + return new FooOptRequest(this); + } + } + + //=========================================== + // Deserialization + //=========================================== + +// // Only expose the most general interface to hide implementation details that may change over time. +// public static final ContextParser PARSER; +// +// static { +// ObjectParser op = +// new ObjectParser<>(FooOptRequest.class.getName(), FooOptRequest.Builder::new); +// +// op.declareString(Builder::name, new ParseField("name")); +// op.declareString(Builder::routing, new ParseField("routing")); +// +// op.declareInt(Builder::value, new ParseField("value")); +// op.declareInt(Builder::size, new ParseField("size")); +// +// op.declareStringArray(Builder::indices, new ParseField("indices")); +// op.declareObject(Builder::bar, Bar.PARSER, new ParseField("bar")); +// +// PARSER = new ObjectBuilderParser<>(op); +// } + + public static final Endpoint ENDPOINT = + new SimpleEndpoint( + "foo", + r -> "POST", + r -> "/foo", + SimpleEndpoint.emptyMap(), + SimpleEndpoint.emptyMap(), + SimpleEndpoint.emptyMap(), + true, + FooResponse.PARSER + ) { + }; + + public static void requireTrue(boolean v, String message) { + if (!v) throw new IllegalStateException(message); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooRequest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooRequest.java new file mode 100644 index 000000000..6330c04c4 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooRequest.java @@ -0,0 +1,317 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.api; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch.experiments.api.Bar; +import co.elastic.clients.elasticsearch.experiments.api.FooResponse; +import co.elastic.clients.elasticsearch.experiments.api.query2.Query; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.endpoints.SimpleEndpoint; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +import static java.util.Objects.requireNonNull; + +// Implementing ToXContent is optional, only if there's a request body +public class FooRequest implements JsonpSerializable { + + //=========================================== + // Fields and getters + //=========================================== + + //------------------------------------------- + // A required String + + private final String name; + + @Nonnull + public final String name() { + return this.name; + } + + //------------------------------------------- + // An optional String + + private final String routing; + + @Nullable + public final String routing() { + return this.routing; + } + + //------------------------------------------- + // A required primitive type + + private final int value; + + public int value() { + return this.value; + } + + //------------------------------------------- + // An optional primitive type, represented as a nullable boxed value + + private final Integer size; + + /** + * Description for field {@code size} + */ + @Nullable + public final Integer size() { + return this.size; + } + + //------------------------------------------- + // An optional array + + private final List indices; + + /** + * A string[] property + */ + @Nullable + public final List indices() { + return this.indices; + } + + //------------------------------------------- + // An optional sub-object + + private final co.elastic.clients.elasticsearch.experiments.api.Bar bar; + + @Nullable + public co.elastic.clients.elasticsearch.experiments.api.Bar bar() { + return this.bar; + } + + //------------------------------------------- + // An optional query + + private final Query query; + + @Nullable + public Query query() { + return this.query; + } + + //------------------------------------------- + + public FooRequest(Builder builder) { + this.name = builder.name; + this.routing = builder.routing; + this.value = builder.value; + this.size = builder.size; + this.indices = builder.indices; + this.bar = builder.bar; + this.query = builder.query; + } + + + //=========================================== + // Builder + //=========================================== + + public static class Builder implements ObjectBuilder { + protected String name; + protected String routing; + protected int value; + protected boolean value$isSet = false; + protected Integer size; + protected List indices; + protected co.elastic.clients.elasticsearch.experiments.api.Bar bar; + protected Query query; + + public final Builder name(@Nonnull String v) { + this.name = requireNonNull(v); + return this; + } + + public final Builder routing(String v) { + this.routing = v; + return this; + } + + public final Builder value(int v) { + this.value = v; + this.value$isSet = true; + return this; + } + + public final Builder size(@Nullable Integer v) { + this.size = v; + return this; + } + + public final Builder indices(@Nullable List v) { + indices = v; + return this; + } + + // Convenience variant with varargs + public final Builder indices(String... v) { + indices = Arrays.asList(v); + return this; + } + + public Builder bar(@Nullable co.elastic.clients.elasticsearch.experiments.api.Bar v) { + bar = v; + return this; + } + + public Builder bar(Function> b) { + return bar(b.apply(new co.elastic.clients.elasticsearch.experiments.api.Bar.Builder()).build()); + } + + public Builder query(Query v) { + this.query = v; + return this; + } + + public Builder query(Function> b) { + return query(b.apply(new Query.Builder()).build()); + } + + public FooRequest build() { + requireNonNull(this.name, "'name' was not set"); + requireTrue(this.value$isSet, "'value' was not set"); + return new FooRequest(this); + } + } + + public static Builder builder() { + return new Builder(); + } + + // Constructor with required fields + public static Builder builder(String name, int size) { + Builder result = new Builder(); + result.name(name); + result.size(size); + return result; + } + + //=========================================== + // Serialization + //=========================================== + + @Override + public void serialize(JsonGenerator builder, JsonpMapper mapper) { + builder.writeStartObject(); + + // Classic approach is to use the deserialization field's preferred name: + // + // if (buckets.isPresent()) builder.field(INT_FIELD.getPreferredName(), buckets.getAsInt()); + // + // In a generated code context we can use the string constant, which also avoids declaring ParseField if we + // only serialize (e.g. requests) + + // required field + builder.write("name", this.name); + + // optional field + if (this.routing != null) builder.write("routing", this.routing); + + // required field + builder.write("value", value); + + // optional field + if (this.size != null) builder.write("size", this.size.intValue()); + + // We could just call this and let the builder will handle it by itself with: + // + // if (this.indices != null) builder.field("indices", this.indices); + // + // But the logic is a bit involved (like checking circular dependencies) so we use a more direct implementation: + if (this.indices != null) { + builder.writeKey("indices").writeStartArray(); + for (String str : this.indices) builder.write(str); + builder.writeEnd(); + } + + if (this.bar != null) { + builder.writeKey("bar"); + this.bar.serialize(builder, mapper); + } + + if (this.query != null) { + builder.writeKey("query"); + this.query.serialize(builder, mapper); + } + + builder.writeEnd(); + } + + //=========================================== + // Deserialization + // (formally not needed for requests) + //=========================================== + + private static final JsonpDeserializer PARSER; + + public static JsonpDeserializer parser() { + return PARSER; + } + + static { + ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); + + op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); + op.add(Builder::routing, JsonpDeserializer.stringDeserializer(), "routing"); + op.add(Builder::value, "value"); // primitive type + op.add(Builder::size, "size"); + op.add(Builder::indices, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), "indices"); + op.add(Builder::bar, Bar.parser(), "bar"); + op.add(Builder::query, Query.parser(), "query"); + + PARSER = new ObjectBuilderDeserializer<>(op); + } + + //=========================================== + // Endpoint + //=========================================== + + public static final Endpoint ENDPOINT = + new SimpleEndpoint<>( + "foo", + r -> "POST", + r -> "/foo", + SimpleEndpoint.emptyMap(), + SimpleEndpoint.emptyMap(), + SimpleEndpoint.emptyMap(), + true, + FooResponse.PARSER + ); + + public static void requireTrue(boolean v, String message) { + if (!v) throw new IllegalStateException(message); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooResponse.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooResponse.java new file mode 100644 index 000000000..c28d9eb54 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooResponse.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.api; + +import co.elastic.clients.json.JsonpDeserializer; + +public class FooResponse { + + public static JsonpDeserializer PARSER = null; +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/BoolQuery.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/BoolQuery.java new file mode 100644 index 000000000..ca3894aae --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/BoolQuery.java @@ -0,0 +1,175 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.api.query2; + +import co.elastic.clients.elasticsearch.experiments.api.query2.Query; +import co.elastic.clients.elasticsearch.experiments.api.query2.Union2; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.function.Function; + +public class BoolQuery implements co.elastic.clients.elasticsearch.experiments.api.query2.Query.Variant, JsonpSerializable { + + private final Collection should; + private final Collection must; + private final co.elastic.clients.elasticsearch.experiments.api.query2.Union2 minimumShouldMatch; + + public BoolQuery(Builder builder) { + this.should = builder.should; + this.must = builder.must; + this.minimumShouldMatch = builder.minimumShouldMatch; + } + + @Override + public co.elastic.clients.elasticsearch.experiments.api.query2.Query.Kind _variantType() { + return co.elastic.clients.elasticsearch.experiments.api.query2.Query.Kind.Bool; + } + + public Collection should() { + return should; + } + + public Collection must() { + return must; + } + + public co.elastic.clients.elasticsearch.experiments.api.query2.Union2 minimumShouldMatch() { + return minimumShouldMatch; + } + + @Override + public void serialize(JsonGenerator builder, JsonpMapper mapper) { + builder.writeStartObject(); + + if (should != null) { + builder.writeKey("should"); + builder.writeStartArray(); + for (co.elastic.clients.elasticsearch.experiments.api.query2.Query v: should) v.serialize(builder, mapper); + builder.writeEnd(); + } + + if (should != null) { + builder.writeKey("must"); + builder.writeStartArray(); + for (co.elastic.clients.elasticsearch.experiments.api.query2.Query v: must) v.serialize(builder, mapper); + builder.writeEnd(); + } + + if (minimumShouldMatch != null) { + builder.writeKey("minimum_should_match"); + // Unions have to be expanded inline as serialization depends on the value type. + this.minimumShouldMatch.serialize(builder, mapper, + (v, b, p) -> builder.write(v), + (v, b, p) -> builder.write(v) + ); + } + + builder.writeEnd(); + } + + public static class Builder implements ObjectBuilder { + + private Collection should; + private Collection must; + private co.elastic.clients.elasticsearch.experiments.api.query2.Union2 minimumShouldMatch; + + public Builder should(Collection v) { + this.should = v; + return this; + } + + public Builder add_should(@Nullable co.elastic.clients.elasticsearch.experiments.api.query2.Query v) { + if (v == null) return this; + if (this.should == null) this.should = new ArrayList<>(); + this.should.add(v); + return this; + } + + public Builder add_should(Function> v) { + return add_should(v.apply(new co.elastic.clients.elasticsearch.experiments.api.query2.Query.Builder()).build()); + } + + public Builder must(Collection v) { + this.must = v; + return this; + } + + public Builder add_must(@Nullable co.elastic.clients.elasticsearch.experiments.api.query2.Query v) { + if (v == null) return this; + if (this.must == null) this.must = new ArrayList<>(); + this.must.add(v); + return this; + } + + public Builder add_must(Function> v) { + return add_must(v.apply(new co.elastic.clients.elasticsearch.experiments.api.query2.Query.Builder()).build()); + } + + // Expand all union members + // TODO: check unions with nested structures and fluent builders + public Builder minimumShouldMatch(int v) { + return minimumShouldMatch(co.elastic.clients.elasticsearch.experiments.api.query2.Union2.ofA(v)); + } + + public Builder minimumShouldMatch(String v) { + return minimumShouldMatch(co.elastic.clients.elasticsearch.experiments.api.query2.Union2.ofB(v)); + } + + public Builder minimumShouldMatch(co.elastic.clients.elasticsearch.experiments.api.query2.Union2 v) { + this.minimumShouldMatch = v; + return this; + } + + @Override + public BoolQuery build() { + return new BoolQuery(this); + } + } + + private static final JsonpDeserializer PARSER; + + public static JsonpDeserializer parser() { + return PARSER; + } + + static { + ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); + + op.add(Builder::must, JsonpDeserializer.arrayDeserializer(co.elastic.clients.elasticsearch.experiments.api.query2.Query.parser()), "must"); + op.add(Builder::should, JsonpDeserializer.arrayDeserializer(Query.parser()), "should"); + + op.add(Builder::minimumShouldMatch, new Union2.JsonpParser<>( + JsonpDeserializer.integerDeserializer(), + JsonpDeserializer.stringDeserializer() + ), "minimum_should_match"); + + PARSER = new ObjectBuilderDeserializer<>(op); + } + +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Query.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Query.java new file mode 100644 index 000000000..6c2f47e2b --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Query.java @@ -0,0 +1,207 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.api.query2; + +import co.elastic.clients.elasticsearch.experiments.UnionVariant; +import co.elastic.clients.elasticsearch.experiments.api.query2.BoolQuery; +import co.elastic.clients.elasticsearch.experiments.api.query2.TermsQuery; +import co.elastic.clients.json.BuildFunctionDeserializer; +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.TaggedUnion; +import co.elastic.clients.util.TaggedUnionUtils; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonGenerator; + +import java.util.Map; +import java.util.function.Function; + +public class Query implements TaggedUnion, JsonpSerializable { + + public interface Variant extends UnionVariant, JsonpSerializable { + default Query _toQuery() { + return new Query(this); + } + } + + public enum Kind implements JsonEnum { + Bool("bool"), + Terms("terms"); + + private final String jsonValue; + + Kind(String jsonValue) { + this.jsonValue = jsonValue; + } + + @Override + public String jsonValue() { + return null; + } + } + + private static final String BOOL = "bool"; + private static final String TERMS = "terms"; + + private final Kind _variantType; + private final Variant _variantValue; + + @Override + public Kind _kind() { + return _variantType; + } + + @Override + public Variant _get() { + return _variantValue; + } + + // A container-level property that lives besides the variant, like "meta" and "aggs" in aggregations + private Map meta; + + public Query(Variant value) { + this._variantType = value._variantType(); + this._variantValue = value; + } + + private Query(Builder builder) { + this._variantType = builder.$tag; + this._variantValue = builder.$variant; + + this.meta = builder.meta; + } + + // Accessors to container properties + public Map meta() { + return this.meta; + } + + public BoolQuery bool() { + return TaggedUnionUtils.get(this, Kind.Bool); + } + + public TermsQuery terms() { + return TaggedUnionUtils.get(this, Kind.Terms); + } + + @Override + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + generator.writeKey(_variantType.jsonValue); + if (_variantValue instanceof JsonpSerializable) { + ((JsonpSerializable) _variantValue).serialize(generator, mapper); + } else { + // Other serialization + } + if (meta != null) { + generator.writeStartObject("meta"); + for (Map.Entry e: meta.entrySet()) { + generator.write(e.getKey(), e.getValue()); + } + generator.writeEnd(); + } + generator.writeEnd(); + } + + public static class Builder { + + private Variant $variant; + private Kind $tag; + private Map meta; + + // Container properties + public Builder meta(Map value) { + this.meta = value; + return this; + } + + // Variants + // + // We return a container builder and not a builder. This is because a union accepts a single variant and we + // don't want to allow choosing more than one yet we still want to be able to set container-level properties + + public ContainerBuilder bool(BoolQuery v) { + this.$variant = v; + this.$tag = Kind.Bool; + return new ContainerBuilder(); + } + + // If we don't have container properties, the container builder is not necessary + public ObjectBuilder foo() { + return this::build; + } + + public ContainerBuilder bool(Function> f) { + return this.bool(f.apply(new BoolQuery.Builder()).build()); + } + + public ContainerBuilder terms(TermsQuery v) { + this.$variant = v; + this.$tag = Kind.Terms; + return new ContainerBuilder(); + } + + public ContainerBuilder terms(Function> f) { + return this.terms(f.apply(new TermsQuery.Builder()).build()); + } + + // Protected, only called by the container + protected Query build() { + return new Query(this); + } + + /** + * A builder that only contains container-level properties. If we don't have such properties, this + * can be replaced with an {@code ObjectBuilder} + */ + public class ContainerBuilder implements ObjectBuilder { + + public ContainerBuilder meta(Map value) { + Builder.this.meta(value); + return this; + } + + public Query build() { + return Builder.this.build(); + } + } + } + + private static volatile JsonpDeserializer PARSER; + + public static JsonpDeserializer parser() { + if (PARSER == null) { + ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); + op.add(Builder::bool, BoolQuery.parser(), "bool"); + op.add(Builder::terms, TermsQuery.parser(), "terms"); + // parser for "meta" (a map) + + PARSER = new BuildFunctionDeserializer<>(op, Builder::build); + } + + return PARSER; + } + + +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/QueryTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/QueryTest.java new file mode 100644 index 000000000..228f15572 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/QueryTest.java @@ -0,0 +1,46 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.api.query2; + +import co.elastic.clients.elasticsearch.experiments.api.query2.BoolQuery; +import co.elastic.clients.elasticsearch.experiments.api.query2.Query; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Collection; + +public class QueryTest extends Assertions { + @Test + public void testQuery() { + co.elastic.clients.elasticsearch.experiments.api.query2.BoolQuery bq = new BoolQuery.Builder().build(); + + co.elastic.clients.elasticsearch.experiments.api.query2.Query q = new co.elastic.clients.elasticsearch.experiments.api.query2.Query(bq); + + assertEquals(co.elastic.clients.elasticsearch.experiments.api.query2.Query.Kind.Bool, q._kind()); + + co.elastic.clients.elasticsearch.experiments.api.query2.Query.Variant v = q._get(); + assertEquals(co.elastic.clients.elasticsearch.experiments.api.query2.Query.Kind.Bool, v._variantType()); + + co.elastic.clients.elasticsearch.experiments.api.query2.Query q1 = v._toQuery(); + + Collection must = q.bool().must(); + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/TermsQuery.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/TermsQuery.java new file mode 100644 index 000000000..e42883171 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/TermsQuery.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.api.query2; + +import co.elastic.clients.elasticsearch.experiments.api.query2.Query; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +public class TermsQuery implements JsonpSerializable, co.elastic.clients.elasticsearch.experiments.api.query2.Query.Variant { + + private final String field; + private final String term; + + public TermsQuery(Builder builder) { + this.field = builder.field; + this.term = builder.term; + } + + @Override + public co.elastic.clients.elasticsearch.experiments.api.query2.Query.Kind _variantType() { + return Query.Kind.Terms; + } + + public String field() { + return this.field; + } + + public String term() { + return this.term; + } + + @Override + public void serialize(JsonGenerator builder, JsonpMapper mapper) { + // We only serialize our content. It's the enclosing class responsibility to output the variant's discriminant. + // This allows using this class in non-variant contexts. + builder.writeStartObject(); + if (this.field != null) { + builder.write("field", this.field); + } + + if (this.term != null) { + builder.write("term", this.term); + } + + builder.writeEnd(); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder implements ObjectBuilder { + + private String field; + private String term; + + public Builder field(String v) { + this.field = v; + return this; + } + + public Builder term(String v) { + this.term = v; + return this; + } + + @Override + public TermsQuery build() { + return new TermsQuery(this); + } + } + + private static final JsonpDeserializer PARSER; + + public static JsonpDeserializer parser() { + return PARSER; + } + + static { + ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); + op.add(Builder::field, JsonpDeserializer.stringDeserializer(), "field"); + op.add(Builder::term, JsonpDeserializer.stringDeserializer(), "term"); + + PARSER = new ObjectBuilderDeserializer<>(op); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Union2.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Union2.java new file mode 100644 index 000000000..55c8e4279 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Union2.java @@ -0,0 +1,154 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.api.query2; + +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpDeserializerBase; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.util.TriConsumer; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParser.Event; +import jakarta.json.stream.JsonParsingException; + +/** + * A tagged union (also known as variant, sum type or coproduct) with two members. + * + * The union's value is one (and only one) of the possible variants. The variant in use is defined by the + * {@link #tag()}'s value. + * + * @param type of the first variant + * @param type of the second variant + */ + +// Design note: we cannot require A and B, and by extension Union2, to implement JsonpSerializable as they can be builtin types +// like String or Integer + +public class Union2 { + + /** + * The variant tag. + */ + public enum Tag{A, B}; + + private final Tag tag; + private final Object value; + + private Union2(Tag tag, Object value) { + this.tag = tag; + this.value = value; + } + + /** + * Creates a variant {@code A}. + */ + public static Union2 ofA(A value) { + return new Union2<>(Tag.A, value); + } + + /** + * Creates a variant {@code B}. + */ + public static Union2 ofB(B value) { + return new Union2<>(Tag.B, value); + } + + /** + * Get the variant's tag of this union. + * + * @return the variant's tag + */ + public Tag tag() { + return tag; + } + + /** + * Get the variant {@code A} of this union. + * + * @return the variant's value + * @throws IllegalStateException if the union is not holding a variant {@code A} + */ + public A a() { + return getVariant(Tag.A); + } + + /** + * Get the variant {@code B} of this union. + * + * @return the variant's value + * @throws IllegalStateException if the union is not holding a variant {@code B} + */ + public B b() { + return getVariant(Tag.B); + } + + private T getVariant(Tag tag) { + if (this.tag != tag) throw new IllegalStateException("Union holds variant " + tag); + + @SuppressWarnings("unchecked") + T result = (T)value; + + return result; + } + + //----------------------------------------------------------------------------------------------- + // Serialization / deserialization + + public void serialize( + JsonGenerator builder, JsonpMapper params, + TriConsumer a, + TriConsumer b + ) { + switch (this.tag) { + case A: + a.accept(this.a(), builder, params); + case B: + b.accept(this.b(), builder, params); + } + } + + public static class JsonpParser extends JsonpDeserializerBase> { + + private final JsonpDeserializer parserA; + private final JsonpDeserializer parserB; + + public JsonpParser( + JsonpDeserializer parserA, + JsonpDeserializer parserB + ) { + super(allAcceptedEvents(parserA, parserB)); + this.parserA = parserA; + this.parserB = parserB; + } + + @Override + public Union2 deserialize(JsonParser parser, JsonpMapper mapper, Event event) { + if (parserA.accepts(event)) { + return Union2.ofA(parserA.deserialize(parser, mapper, event)); + + } else if (parserB.accepts(event)) { + return Union2.ofB(parserB.deserialize(parser, mapper, event)); + + } else { + throw new JsonParsingException("Unexpected event '" + event + "'", parser.getLocation()); + } + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Client.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Client.java new file mode 100644 index 000000000..a2482a298 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Client.java @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.base; + +import co.elastic.clients.elasticsearch.experiments.api.FooRequest; +import co.elastic.clients.elasticsearch.experiments.api.FooResponse; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.Transport; +import co.elastic.clients.util.ObjectBuilder; + +import java.io.IOException; +import java.util.function.Function; + +public class Client { + + private Transport transport; + + public FooResponse foo(FooRequest request) throws IOException { + return performRequest(request, FooRequest.ENDPOINT); + } + + public FooResponse foo(Function> b) throws IOException { + return foo(b.apply(new FooRequest.Builder()).build()); + } + + protected ResponseT performRequest( + RequestT request, Endpoint endpoint + ) throws IOException { + return transport.performRequest(request, endpoint, null); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/PrimitiveUtils.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/PrimitiveUtils.java new file mode 100644 index 000000000..a6122f198 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/PrimitiveUtils.java @@ -0,0 +1,41 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.base; + +/** + * Support functions for primitive fields in generated classes + */ +public class PrimitiveUtils { + public static int checkedValue(int value, boolean isSet) { + mustBeSet(isSet); + return value; + } + + public static long checkedValue(long value, boolean isSet) { + mustBeSet(isSet); + return value; + } + + private static void mustBeSet(boolean isSet) { + if (!isSet) { + throw new IllegalStateException("Value is not set"); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Variants.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Variants.java new file mode 100644 index 000000000..37c09a99b --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Variants.java @@ -0,0 +1,155 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.base; + +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParsingException; + +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + +/** + * Describes the variants of a transport class, providing their name and parsers. It is representation-agnostic. + */ +public class Variants { + + private Function, Builder> builderFunc; + + private Map, String> variantNames; + private Map> parsers; + + /** + * Builds a new {@code Variants} from a builder-creation function. This approach allows the object to be built lazily, + * which is needed for recursive variant data structures (e.g. a query can be a boolean query that itself contains + * other queries). + * + * This is required because cyclic dependencies between static class initialization code can lead to unexpected + * behaviour (a subclass static init may be called while static init of the parent class is not finished). + */ + public Variants(Function, Builder> b) { + this.builderFunc = b; + } + + public Variants(Builder builder) { + this.variantNames = builder.variantNames; + this.parsers = builder.parsers; + } + + public String variantName(Class clazz) { + build(); + return variantNames.get(clazz); + } + + public JsonpDeserializer variantParser(String name) { + build(); + return parsers.get(name); + } + + private void build() { + if (builderFunc != null) { + Builder builder = builderFunc.apply(new Builder<>()); + this.variantNames = builder.variantNames; + this.parsers = builder.parsers; + this.builderFunc = null; + } + } + + //------------------------------------------------------------------------------------------------------------------- + + public static Builder builder() { + return new Builder<>(); + } + + public static class Builder { + private final Map, String> variantNames = new HashMap<>(); + private final Map> parsers = new HashMap<>(); + + public Builder add(String name, Class clazz, JsonpDeserializer parser) { + variantNames.put(clazz, name); + parsers.put(name, parser); + return this; + } + + public Variants build() { + return new Variants<>(this); + } + } + + //------------------------------------------------------------------------------------------------------------------- + + /** + * Variant serializer/deserializer using externally tagged JSON. + *

+ * See Enumerations in Serde.rs that clearly explains the + * various strategies to represent polymorphic values in JSON. + */ + public static class ExternallyTagged { + + /** + * Creates a parser for externally tagged variants + */ + public static JsonpDeserializer pparser(Variants variants) { + return JsonpDeserializer.of(EnumSet.of(JsonParser.Event.START_OBJECT), (parser, params) -> { + JsonpUtils.expectNextEvent(parser, JsonParser.Event.START_OBJECT); + JsonpUtils.expectNextEvent(parser, JsonParser.Event.KEY_NAME); + + String variant = parser.getString(); + JsonpDeserializer variantParser = variants.variantParser(variant); + + if (variantParser == null) { + throw new JsonParsingException("Unknown variant '" + variant + "'", parser.getLocation()); + } + + T result = variantParser.deserialize(parser, params); + + JsonpUtils.expectNextEvent(parser, JsonParser.Event.END_OBJECT); + + return result; + }); + } + + /** + * Serializes an externally tagged variant object + */ + + public static void serialize( + Variants variants, T v, JsonGenerator builder, JsonpMapper mapper + ) { + @SuppressWarnings("unchecked") + String variant = variants.variantName((Class)v.getClass()); + + if (variant == null) { + throw new IllegalArgumentException("No variant name found for " + v.getClass().getName()); + } + + builder.writeStartObject(); + builder.writeKey(variant); + v.serialize(builder, mapper); + builder.writeEnd(); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnion.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnion.java new file mode 100644 index 000000000..7438accbc --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnion.java @@ -0,0 +1,155 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.containers; +/* + // @variants internal tag='type' + interface SomeUnion = UnionItemA | UnionItemB; + + interface VariantA { + type: 'variant_a' + variant_a_prop: String + } + + interface VariantB { + type: 'variant_b' + variant_b_prop: String + } +*/ + +import co.elastic.clients.elasticsearch.experiments.containers.SomeUnionVariant; +import co.elastic.clients.elasticsearch.experiments.containers.UVariantA; +import co.elastic.clients.elasticsearch.experiments.containers.UVariantB; +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.TaggedUnion; +import co.elastic.clients.util.TaggedUnionUtils; +import jakarta.json.stream.JsonGenerator; + +import java.util.function.Function; + +@JsonpDeserializable +public class SomeUnion implements TaggedUnion, JsonpSerializable { + + public enum Kind implements JsonEnum { + VariantA("variant_a"), + VariantB("variant_b"); + + private final String jsonValue; + + Kind(String jsonValue) { + this.jsonValue = jsonValue; + } + + @Override + public String jsonValue() { + return null; + } + } + + private final SomeUnionVariant _value; + private final Kind _type; + + public SomeUnion(Builder builder) { + this._value = builder._value; + this._type = builder._type; + } + + @Override + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + // Delegate to the variant object + if (_value instanceof JsonpSerializable) { + ((JsonpSerializable)_value).serialize(generator, mapper); + } + } + + @Override + public Kind _kind() { + return _type; + } + + @Override + public SomeUnionVariant _get() { + return _value; + } + + public UVariantA variantA() { + return TaggedUnionUtils.get(this, Kind.VariantA); + } + + public UVariantB variantB() { + return TaggedUnionUtils.get(this, Kind.VariantB); + } + + static class Builder { + + private SomeUnionVariant _value; + private Kind _type; + + // This "builder" doesn't allow building objects. It only contains methods to set a variant. + // These methods return a builder class with no other methods. This enforces the choice of one and only one + // variant at the type level (i.e. at compile time). + + // variant_a + + public ObjectBuilder variantA(UVariantA value) { + this._value = value; + this._type = Kind.VariantA; + final SomeUnion result = build(); + return () -> result; + } + + public ObjectBuilder variantA(Function fn) { + return this.variantA(fn.apply(new UVariantA.Builder()).build()); + } + + // variant_b + + public ObjectBuilder variantB(UVariantB value) { + this._value = value; + this._type = Kind.VariantB; + final SomeUnion result = build(); + return () -> result; + } + + public ObjectBuilder variantB(Function fn) { + return this.variantB(fn.apply(new UVariantB.Builder()).build()); + } + + protected SomeUnion build() { + return new SomeUnion(this); + } + } + + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + SomeUnion::setupSomeUnionDeserializer, Builder::build); + + protected static void setupSomeUnionDeserializer(ObjectDeserializer op) { + op.add(Builder::variantA, UVariantA._DESERIALIZER, "variant_a"); + op.add(Builder::variantB, UVariantB._DESERIALIZER, "variant_b"); + + op.setTypeProperty("type", null); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionTest.java new file mode 100644 index 000000000..ee1134298 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionTest.java @@ -0,0 +1,86 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.containers; + +import co.elastic.clients.elasticsearch.experiments.containers.SomeUnion; +import co.elastic.clients.elasticsearch.experiments.containers.UVariantA; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParsingException; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; +import java.io.StringReader; + +public class SomeUnionTest extends ModelTestCase { + + co.elastic.clients.elasticsearch.experiments.containers.SomeUnion su = new co.elastic.clients.elasticsearch.experiments.containers.SomeUnion.Builder() + .variantA(a_ -> a_ + .name("a-name") + ).build(); + + String json = "{\"type\":\"variant_a\",\"name\":\"a-name\"}"; + + @Test + public void testContainerBuilder() { + assertEquals("a-name", su.variantA().name()); + } + + @Test + public void testDeserialization() { + co.elastic.clients.elasticsearch.experiments.containers.SomeUnion u = fromJson(json, co.elastic.clients.elasticsearch.experiments.containers.SomeUnion.class); + UVariantA uVariantA = u.variantA(); + assertEquals("a-name", uVariantA.name()); + } + + @Test + public void testSerialization() { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonProvider provider = JsonpUtils.provider(); + JsonGenerator generator = provider.createGenerator(baos); + + su.serialize(generator, new JsonbJsonpMapper()); + generator.close(); + + System.out.println(baos.toString()); + + assertEquals(json, baos.toString()); + + } + + @Test + public void testMissingVariantDeserialization() { + String json = "{}"; + + JsonProvider provider = JsonpUtils.provider(); + JsonParser parser = provider.createParser(new StringReader(json)); + + JsonParsingException e = assertThrows(JsonParsingException.class, () -> { + co.elastic.clients.elasticsearch.experiments.containers.SomeUnion c = SomeUnion._DESERIALIZER.deserialize(parser, new JsonbJsonpMapper()); + }); + + assertTrue(e.getMessage().contains("Property 'type' not found")); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionVariant.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionVariant.java new file mode 100644 index 000000000..6f17060eb --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionVariant.java @@ -0,0 +1,25 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.containers; + +import co.elastic.clients.elasticsearch.experiments.UnionVariant; + +public interface SomeUnionVariant extends UnionVariant { +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantA.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantA.java new file mode 100644 index 000000000..c921b58db --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantA.java @@ -0,0 +1,83 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.containers; + +import co.elastic.clients.elasticsearch.experiments.containers.SomeUnionVariant; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import javax.annotation.Nullable; + +@JsonpDeserializable +public class UVariantA implements SomeUnionVariant, JsonpSerializable { + + private final String name; + + @Override + public String _variantType() { + return "variant_a"; + } + + @Nullable + public String name() { + return this.name; + } + + public UVariantA(Builder builder) { + this.name = builder.name; + } + + @Override + public void serialize(JsonGenerator builder, JsonpMapper mapper) { + builder.writeStartObject(); + // Write variant value + builder.write("type", _variantType()); + if (this.name != null) builder.write("name", this.name); + builder.writeEnd(); + } + + public static class Builder implements ObjectBuilder { + private String name; + + public Builder name(@Nullable String name) { + this.name = name; + return this; + } + + public UVariantA build() { + return new UVariantA(this); + } + } + + public static final JsonpDeserializer _DESERIALIZER; + + static { + ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); + op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); + op.ignore("type"); + _DESERIALIZER = new ObjectBuilderDeserializer<>(op); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantB.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantB.java new file mode 100644 index 000000000..95ac7be92 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantB.java @@ -0,0 +1,83 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.containers; + +import co.elastic.clients.elasticsearch.experiments.containers.SomeUnionVariant; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import javax.annotation.Nullable; + +@JsonpDeserializable +public class UVariantB implements SomeUnionVariant, JsonpSerializable { + + private final Integer number; + + @Override + public String _variantType() { + return "variant_a"; + } + + @Nullable + public Integer number () { + return this.number; + } + + public UVariantB(Builder builder) { + this.number = builder.number; + } + + @Override + public void serialize(JsonGenerator builder, JsonpMapper mapper) { + builder.writeStartObject(); + // Write variant value + builder.write("type", _variantType()); + if (this.number != null) builder.write("number", this.number); + builder.writeEnd(); + } + + public static class Builder implements ObjectBuilder { + private Integer number; + + public Builder number(@Nullable Integer number) { + this.number = number; + return this; + } + + public UVariantB build() { + return new UVariantB(this); + } + } + + public static final JsonpDeserializer _DESERIALIZER; + + static { + ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); + op.add(Builder::number, JsonpDeserializer.integerDeserializer(), "number"); + op.ignore("type"); + _DESERIALIZER = new ObjectBuilderDeserializer<>(op); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/generics/GenericClass.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/generics/GenericClass.java new file mode 100644 index 000000000..ce97f5ca0 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/generics/GenericClass.java @@ -0,0 +1,123 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.generics; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpSerializer; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.endpoints.SimpleEndpoint; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import java.util.function.Supplier; + +public class GenericClass implements JsonpSerializable { + + // Serializers for generic parameters + private final JsonpSerializer genParamSerializer; + + // Properties + private final GenParam genParam; + + protected GenericClass(Builder builder) { + this.genParamSerializer = builder.genParamSerializer; + this.genParam = builder.genParam; + } + + public GenParam genParam() { + return this.genParam; + } + + @Override + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + generator.writeKey("genParam"); + JsonpUtils.serialize(genParam, generator, genParamSerializer, mapper); + generator.writeEnd(); + } + + public static class Builder implements ObjectBuilder> { + private GenParam genParam; + private JsonpSerializer genParamSerializer; + + /** + * Sets the JSON serializer for {@link GenParam} values. If not set, the client will try to find a suitable + * serializer in the {@link JsonpMapper} and will fail if none is found. + */ + // Internal generic parameters always call this method to avoid runtime lookup + public Builder genParamSerializer(JsonpSerializer value) { + this.genParamSerializer = value; + return this; + } + + public Builder genParam(GenParam value) { + this.genParam = value; + return this; + } + + @Override + public GenericClass build() { + return null; + } + } + + public static JsonpDeserializer> parser( + // A deserializer for each generic parameter + JsonpDeserializer getParamDeserializer + ) { + + return ObjectBuilderDeserializer.createForObject( + (Supplier>) Builder::new, + (op) -> GenericClass.setupParser(op, getParamDeserializer) + ); + } + + private static void setupParser(ObjectDeserializer> op, JsonpDeserializer deserializer) { + op.add(Builder::genParam, deserializer, "genParam"); + } + + + public static Endpoint, ErrorResponse> endpoint( + JsonpDeserializer genParamDeserializer + ) { + return new SimpleEndpoint<>( + "genclass", + // Request method + request -> "GET", + // Request path + request -> "/genclass", + // Path parameters + SimpleEndpoint.emptyMap(), + // Request parameters + SimpleEndpoint.emptyMap(), + // Headers + SimpleEndpoint.emptyMap(), + true, + GenericClass.parser(genParamDeserializer) + ); + } + +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/InheritanceTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/InheritanceTest.java new file mode 100644 index 000000000..b20f24641 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/InheritanceTest.java @@ -0,0 +1,97 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.inheritance; + +import co.elastic.clients.elasticsearch.experiments.inheritance.child.ChildClass; +import co.elastic.clients.elasticsearch.experiments.inheritance.final_.FinalClass; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; +import java.io.StringReader; + +public class InheritanceTest extends Assertions { + + @Test + public void testSerialization() { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonProvider provider = JsonpUtils.provider(); + + FinalClass fc = new FinalClass.Builder() + // Start fields from the top of the hierarchy to test setter return values + .baseField("baseValue") + .childField("childValue") + .finalField("finalValue") + .build(); + + JsonGenerator generator = provider.createGenerator(baos); + fc.serialize(generator, new JsonbJsonpMapper()); + + generator.close(); + String str = baos.toString(); + + assertEquals("{\"baseField\":\"baseValue\",\"childField\":\"childValue\",\"finalField\":\"finalValue\"}", str); + + baos.reset(); + + ChildClass cc = new ChildClass.Builder() + // Start fields from the top of the hierarchy to test setter return values + .baseField("baseValue") + .childField("childValue") + .build(); + + generator = provider.createGenerator(baos); + cc.serialize(generator, new JsonbJsonpMapper()); + + generator.close(); + str = baos.toString(); + + assertEquals("{\"baseField\":\"baseValue\",\"childField\":\"childValue\"}", str); + } + + @Test + public void testDeserialization() { + JsonProvider provider = JsonpUtils.provider(); + + JsonParser parser = provider.createParser(new StringReader( + "{\"baseField\":\"baseValue\",\"childField\":\"childValue\",\"finalField\":\"finalValue\"}")); + + FinalClass fc = FinalClass.JSONP_PARSER.deserialize(parser, new JsonbJsonpMapper()); + + assertEquals("baseValue", fc.baseField()); + assertEquals("childValue", fc.childField()); + assertEquals("finalValue", fc.finalField()); + + + parser = provider.createParser(new StringReader( + "{\"baseField\":\"baseValue\",\"childField\":\"childValue\"}")); + + ChildClass cc = ChildClass.JSONP_PARSER.deserialize(parser, new JsonbJsonpMapper()); + + assertEquals("baseValue", cc.baseField()); + assertEquals("childValue", cc.childField()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/base/BaseClass.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/base/BaseClass.java new file mode 100644 index 000000000..aeba6b6d7 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/base/BaseClass.java @@ -0,0 +1,77 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.inheritance.base; + +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectDeserializer; +import jakarta.json.stream.JsonGenerator; + +import java.util.Objects; + +/** + * An abstract transport class + */ +public abstract class BaseClass implements JsonpSerializable { + + private final String baseField; + + public BaseClass(AbstractBuilder builder) { + this.baseField = Objects.requireNonNull(builder.baseField, "baseField"); + } + + public String baseField() { + return this.baseField; + } + + @Override + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + toJsonpInternal(generator, mapper); + generator.writeEnd(); + } + + protected void toJsonpInternal(JsonGenerator generator, JsonpMapper mapper) { + generator.write("baseField", this.baseField); + } + + //--------------------------------------------------------------------------------------------- + + // This is class protected as it's only of interest to subclasses. Yet public members are visible + // from the outside on public subclasses. + protected abstract static class AbstractBuilder> { + + private String baseField; + + public T baseField(String value) { + this.baseField = value; + return self(); + } + + protected abstract T self(); + } + + //--------------------------------------------------------------------------------------------- + + protected static > void setupBaseClassParser(ObjectDeserializer op) { + op.add(AbstractBuilder::baseField, JsonpDeserializer.stringDeserializer(), "baseField"); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/child/ChildClass.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/child/ChildClass.java new file mode 100644 index 000000000..3b0a1c88d --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/child/ChildClass.java @@ -0,0 +1,93 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.inheritance.child; + +import co.elastic.clients.elasticsearch.experiments.inheritance.base.BaseClass; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import java.util.Objects; + +/** + * A concrete class that both inherits a parent class and has child classes + */ +public class ChildClass extends BaseClass implements JsonpSerializable { + + private final String childField; + + public ChildClass(AbstractBuilder builder) { + super(builder); + this.childField = Objects.requireNonNull(builder.childField, "childField"); + } + + public String childField() { + return this.childField; + } + + @Override + protected void toJsonpInternal(JsonGenerator generator, JsonpMapper params) { + super.toJsonpInternal(generator, params); + generator.write("childField", this.childField); + } + + //--------------------------------------------------------------------------------------------- + + protected abstract static class AbstractBuilder> extends BaseClass.AbstractBuilder { + + private String childField; + + public T childField(String value) { + this.childField = value; + return self(); + } + } + + // We cannot use AbstractBuilder directly, as it would cause a signature clash with subclasses on build(). + // And even without it, the generic parameter on AbstractBuilder is an implementation detail of builder + // inheritance that isn't needed nor nice in user applications. + public static class Builder extends AbstractBuilder implements ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + @Override + public ChildClass build() { + return new ChildClass(this); + } + } + + //--------------------------------------------------------------------------------------------- + + protected static > void setupChildClassParser(ObjectDeserializer op) { + BaseClass.setupBaseClassParser(op); + op.add(AbstractBuilder::childField, JsonpDeserializer.stringDeserializer(), "childField"); + } + + public static final JsonpDeserializer JSONP_PARSER = ObjectBuilderDeserializer.createForObject( + Builder::new, ChildClass::setupChildClassParser + ); + +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/final_/FinalClass.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/final_/FinalClass.java new file mode 100644 index 000000000..72c87d347 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/final_/FinalClass.java @@ -0,0 +1,98 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.experiments.inheritance.final_; + +import co.elastic.clients.elasticsearch.experiments.inheritance.child.ChildClass; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; + +import java.util.Objects; + +/** + * A concrete class that inherits a parent class but has no child classes + */ +public final class FinalClass extends ChildClass { + + private final String finalField; + + public FinalClass(Builder builder) { + super(builder); + this.finalField = Objects.requireNonNull(builder.finalField, "finalField"); + } + + public String finalField() { + return this.finalField; + } + + @Override + protected void toJsonpInternal(JsonGenerator generator, JsonpMapper mapper) { + super.toJsonpInternal(generator, mapper); + generator.write("finalField", this.finalField); + } + + //--------------------------------------------------------------------------------------------- + + public static class Builder + extends AbstractBuilder + implements ObjectBuilder { + + private String finalField; + + public Builder finalField(String value) { + this.finalField = value; + return self(); + } + + @Override + protected Builder self() { + return this; + } + + @Override + public FinalClass build() { + return new FinalClass(this); + } + } + + //--------------------------------------------------------------------------------------------- + + private static void setupFinalClassParser(ObjectDeserializer op) { + ChildClass.setupChildClassParser(op); + op.add(Builder::finalField, JsonpDeserializer.stringDeserializer(), "finalField"); + } + + // Static methods cannot hide other static methods with a different return type or the same erased signature. + // Two possible solutions: + // - use different names, but having SomeClass.someClassParser() has some redundancy in the name + // - use a static field, as a static field can hide a static field of a different type in the parent class + // + // Our choice is to use different names for protected/private parser setup methods are they are hidden from + // the user and use a static field for the final parser, so that we can uniformly write SomeClass.PARSER + // (even if users should rarely have to interact directly with the parser). + + public static final JsonpDeserializer JSONP_PARSER = ObjectBuilderDeserializer.createForObject( + Builder::new, FinalClass::setupFinalClassParser + ); + +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/package-info.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/package-info.java new file mode 100644 index 000000000..b5569000c --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ + +/** + * Experiments for the design of high-level client classes and usage illustration of the XContent-related classes. + */ +package clients.rest5_client.elasticsearch.experiments; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BehaviorsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BehaviorsTest.java new file mode 100644 index 000000000..7a4272bf3 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BehaviorsTest.java @@ -0,0 +1,306 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.ErrorCause; +import co.elastic.clients.elasticsearch._types.FieldSort; +import co.elastic.clients.elasticsearch._types.FieldValue; +import co.elastic.clients.elasticsearch._types.GeoLocation; +import co.elastic.clients.elasticsearch._types.GeoShapeRelation; +import co.elastic.clients.elasticsearch._types.SortOptions; +import co.elastic.clients.elasticsearch._types.SortOptionsBuilders; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.query_dsl.FunctionScoreQuery; +import co.elastic.clients.elasticsearch._types.query_dsl.MultiValueMode; +import co.elastic.clients.elasticsearch._types.query_dsl.Query; +import co.elastic.clients.elasticsearch._types.query_dsl.ShapeQuery; +import co.elastic.clients.elasticsearch._types.query_dsl.TermQuery; +import co.elastic.clients.elasticsearch.connector.UpdateIndexNameRequest; +import co.elastic.clients.elasticsearch.core.rank_eval.RankEvalQuery; +import co.elastic.clients.elasticsearch.core.search.SourceFilter; +import co.elastic.clients.elasticsearch.model.ClassStructureTest; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.json.LazyDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.util.MapBuilder; +import org.junit.jupiter.api.Test; + +public class BehaviorsTest extends ModelTestCase { + + /** + * Test for SingleKeyDictionary transformed to a behavior. For regular fields, see NamedValue tests in {@link ClassStructureTest} + */ + @Test + public void testSingleKeyDictionary() { + TermQuery q = new TermQuery.Builder() + .queryName("query-name") + .field("field-name") + .value(FieldValue.of("some-value")) + .build(); + + q = checkJsonRoundtrip(q, "{\"field-name\":{\"_name\":\"query-name\",\"value\":\"some-value\"}}"); + + assertEquals("query-name", q.queryName()); + assertEquals("field-name", q.field()); + assertEquals("some-value", q.value().stringValue()); + } + + @Test + public void testAdditionalPropertyOnClass() { + ShapeQuery q = new ShapeQuery.Builder() + .queryName("query-name") + .field("field-name") + .shape(_0 -> _0 + .relation(GeoShapeRelation.Disjoint) + ) + .ignoreUnmapped(true) + .build(); + + q = checkJsonRoundtrip(q, + "{\"field-name\":{\"relation\":\"disjoint\"},\"_name\":\"query-name\",\"ignore_unmapped\":true}" + ); + + assertEquals("query-name", q.queryName()); + assertTrue(q.ignoreUnmapped()); + assertEquals(GeoShapeRelation.Disjoint, q.shape().relation()); + } + + @Test + public void testAdditionalPropertyOnContainer() { + // Regular variant + { + SortOptions so = SortOptions.of(_0 -> _0 + .doc(_1 -> _1.order(SortOrder.Asc)) + ); + + so = checkJsonRoundtrip(so, "{\"_doc\":{\"order\":\"asc\"}}"); + assertEquals(SortOptions.Kind.Doc, so._kind()); + assertEquals(SortOrder.Asc, so.doc().order()); + } + + // Regular variant + { + SortOptions so = SortOptionsBuilders.geoDistance() + .field("foo") + .location(GeoLocation.of(_b -> _b.text("someWKT"))) + .build() + ._toSortOptions(); + + so = checkJsonRoundtrip(so, "{\"_geo_distance\":{\"foo\":[\"someWKT\"]}}"); + assertEquals(SortOptions.Kind.GeoDistance, so._kind()); + assertEquals("foo", so.geoDistance().field()); + assertEquals("someWKT", so.geoDistance().location().get(0).text()); + } + + { + SortOptions so = SortOptions.of(_0 -> _0 + .score(_1 -> _1.order(SortOrder.Asc))); + + so = checkJsonRoundtrip(so, "{\"_score\":{\"order\":\"asc\"}}"); + assertEquals(SortOptions.Kind.Score, so._kind()); + assertEquals(SortOrder.Asc, so.score().order()); + } + + { + SortOptions so = SortOptions.of(_0 -> _0 + .script(_1 -> _1.script(_3 -> _3.source("blah"))) + ); + so = checkJsonRoundtrip(so, "{\"_script\":{\"script\":{\"source\":\"blah\"}}}"); + assertEquals("blah", so.script().script().source()); + + } + + // Additional property variant + { + SortOptions so = SortOptions.of(_0 -> _0 + .field(_1 -> _1.field("foo").order(SortOrder.Desc)) + ); + + so = checkJsonRoundtrip(so, "{\"foo\":{\"order\":\"desc\"}}"); + assertEquals(SortOptions.Kind.Field, so._kind()); + assertEquals("foo", so.field().field()); + assertEquals(SortOrder.Desc, so.field().order()); + } + } + + @Test + public void testAdditionalProperties() { + // Check that additional property map is initialized even if not set explicitly + ErrorCause err = new ErrorCause.Builder() + .reason("Foo") + .type("Bar") + .build(); + assertEquals(0, err.metadata().size()); + + err = new ErrorCause.Builder() + .reason("Some failure") + .type("Some type") + .metadata(MapBuilder.of( + "index", JsonData.of("test"), + "retries", JsonData.of(1) + )) + .build(); + + err = checkJsonRoundtrip(err, "{\"index\":\"test\",\"retries\":1,\"type\":\"Some type\",\"reason\":\"Some failure\"}"); + + assertEquals("Some failure", err.reason()); + assertEquals(1, err.metadata().get("retries").to(int.class).intValue()); + assertEquals("test", err.metadata().get("index").to(String.class)); + } + + @Test + public void testPrimitiveShortcutProperty() { + + // All-in-one: a variant, wrapping a single-key dictionary with a shortcut property + String json = "{\"term\":{\"some-field\":\"some-value\"}}"; + Query q = fromJson(json, Query.class); + + assertEquals("some-field", q.term().field()); + assertEquals("some-value", q.term().value().stringValue()); + + } + + @Test + public void testArrayShortcutProperty() { + + // Check that don't look ahead to handle the shortcut + ObjectDeserializer deser = (ObjectDeserializer) LazyDeserializer.unwrap(SourceFilter._DESERIALIZER); + assertEquals("includes", deser.shortcutProperty()); + assertFalse(deser.shortcutIsObject()); + + // Regular form + SourceFilter sf = fromJson("{\"includes\":[\"foo\",\"bar\"]}", SourceFilter.class); + assertEquals(2, sf.includes().size()); + assertEquals("foo", sf.includes().get(0)); + assertEquals("bar", sf.includes().get(1)); + + // Shortcut with an array value + sf = fromJson("[\"foo\",\"bar\"]", SourceFilter.class); + assertEquals(2, sf.includes().size()); + assertEquals("foo", sf.includes().get(0)); + assertEquals("bar", sf.includes().get(1)); + + // Shortcut with a single value (lenient array) + sf = fromJson("\"foo\"]", SourceFilter.class); + assertEquals(1, sf.includes().size()); + assertEquals("foo", sf.includes().get(0)); + } + + @Test + public void testEnumShortcutProperty() { + + // Check that we don't look ahead to handle the shortcut + ObjectDeserializer deser = (ObjectDeserializer) LazyDeserializer.unwrap(FieldSort._DESERIALIZER); + assertEquals("order", deser.shortcutProperty()); + assertFalse(deser.shortcutIsObject()); + + // We have to test on the enclosing SortOption as FieldSort is used as a single-key dict + SortOptions so = fromJson("{\"foo\":{\"order\":\"asc\"}}", SortOptions.class); + + assertEquals("foo", so.field().field()); + assertEquals(SortOrder.Asc, so.field().order()); + + so = fromJson("{\"foo\":\"asc\"}", SortOptions.class); + + assertEquals("foo", so.field().field()); + assertEquals(SortOrder.Asc, so.field().order()); + } + + @Test + public void testObjectShortcutProperty() { + + // Check that we look ahead to handle the shortcut + ObjectDeserializer deser = (ObjectDeserializer) LazyDeserializer.unwrap(RankEvalQuery._DESERIALIZER); + assertEquals("query", deser.shortcutProperty()); + assertTrue(deser.shortcutIsObject()); + + // Standard form + RankEvalQuery req = fromJson("{\"query\":{\"term\":{\"foo\":{\"value\":\"bar\"}}}}", RankEvalQuery.class); + + assertEquals("foo", req.query().term().field()); + assertEquals("bar", req.query().term().value().stringValue()); + + // Shortcut form + req = fromJson("{\"term\":{\"foo\":{\"value\":\"bar\"}}}", RankEvalQuery.class); + + assertEquals("foo", req.query().term().field()); + assertEquals("bar", req.query().term().value().stringValue()); + + // Nested shortcuts + req = fromJson("{\"term\":{\"foo\":\"bar\"}}", RankEvalQuery.class); + + assertEquals("foo", req.query().term().field()); + assertEquals("bar", req.query().term().value().stringValue()); + } + + @Test + public void testFunctionScoreQuery() { + String shortcut = + "{" + + " \"gauss\": {" + + " \"date\": {" + + " \"origin\": \"2013-09-17\", " + + " \"scale\": \"10d\"," + + " \"offset\": \"5d\", " + + " \"decay\": 0.5" + + " }," + + " \"multi_value_mode\": \"avg\"" + + " }" + + "}"; + + String full = + "{" + + " \"functions\": [" + + " {" + + " \"gauss\": {" + + " \"date\": {" + + " \"origin\": \"2013-09-17\"," + + " \"scale\": \"10d\"," + + " \"offset\": \"5d\"," + + " \"decay\": 0.5" + + " }," + + " \"multi_value_mode\": \"avg\"" + + " }" + + " }" + + " ]" + + "}"; + + FunctionScoreQuery fsq; + + fsq = fromJson(full, FunctionScoreQuery.class); + assertEquals(MultiValueMode.Avg, fsq.functions().get(0).gauss().untyped().multiValueMode()); + + fsq = fromJson(shortcut, FunctionScoreQuery.class); + assertEquals(MultiValueMode.Avg, fsq.functions().get(0).gauss().untyped().multiValueMode()); + } + + @Test + public void testWithNull() { + + String jsonValue = "{\"index_name\":\"value\"}"; + String jsonNull = "{\"index_name\":null}"; + UpdateIndexNameRequest updateValue = UpdateIndexNameRequest.of(u -> u.connectorId("connector").indexName("value")); + UpdateIndexNameRequest updateNull = UpdateIndexNameRequest.of(u -> u.connectorId("connector").indexNameWithNull()); + + assertEquals(jsonValue,toJson(updateValue)); + assertEquals(jsonNull,toJson(updateNull)); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BuiltinTypesTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BuiltinTypesTest.java new file mode 100644 index 000000000..dc85a1045 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BuiltinTypesTest.java @@ -0,0 +1,273 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.FieldValue; +import co.elastic.clients.elasticsearch._types.SortOptions; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.aggregations.StatsAggregate; +import co.elastic.clients.elasticsearch._types.aggregations.StringStatsAggregate; +import co.elastic.clients.elasticsearch._types.query_dsl.SpanGapQuery; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.indices.IndexRoutingAllocationDisk; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.testkit.ModelTestCase; +import jakarta.json.stream.JsonParser; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; +import java.util.List; + +public class BuiltinTypesTest extends ModelTestCase { + + @Test + public void testPrimitiveTypes() { + + assertGetterType(Integer.class, SearchRequest.class, "size"); + + // Lenient boolean: 'threshold_enabled'?: boolean | string + assertGetterType(Boolean.class, IndexRoutingAllocationDisk.class, "thresholdEnabled"); + + } + + @Test + public void testLenientArray() { + // index: Indices --> type Indices = IndexName | IndexName[] + assertGetterType(List.class, SearchRequest.class, "index"); + } + + @Test + public void testNullArrayItem() { + // See https://github.com/elastic/elasticsearch-java/issues/66 + + String json = "[\"a\", null, \"c\"]"; + + // Types that don't accept null events should end up as null values in the list + { + JsonpDeserializer stringDeser = JsonpDeserializer.stringDeserializer(); + assertFalse(stringDeser.accepts(JsonParser.Event.VALUE_NULL)); + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + + List stringList = JsonpDeserializer.arrayDeserializer(stringDeser).deserialize(parser, mapper); + assertEquals("a", stringList.get(0)); + assertNull(stringList.get(1)); + assertEquals("c", stringList.get(2)); + } + + // Types that do accept null events should end up as their null representation + { + assertTrue(FieldValue._DESERIALIZER.accepts(JsonParser.Event.VALUE_NULL)); + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + List valueList = JsonpDeserializer.arrayDeserializer(FieldValue._DESERIALIZER).deserialize(parser, mapper); + + assertEquals("a", valueList.get(0)._get()); + assertTrue(valueList.get(1).isNull()); + assertEquals("c", valueList.get(2)._get()); + } + } + + @Test + public void testSpanGapQuery() { + // Hand-written class + SpanGapQuery q = SpanGapQuery.of(b -> b + .field("a-field") + .spanWidth(12) + ); + + q = checkJsonRoundtrip(q, "{\"a-field\":12}"); + + assertEquals("a-field", q.field()); + assertEquals(12, q.spanWidth()); + } + + @Test + public void testSortOptions() { + // Has a custom deserializer + // Examples: see https://www.elastic.co/guide/en/elasticsearch/reference/current/sort-search-results.html + + String json; + SortOptions sort; + + // Arbitrary field + sort = fromJson( + "{ \"post_date\" : {\"order\" : \"asc\", \"format\": \"strict_date_optional_time_nanos\"}}", + SortOptions.class); + + assertEquals("post_date", sort.field().field()); + assertEquals(SortOrder.Asc, sort.field().order()); + + sort = fromJson("{\n" + + " \"offer.price\" : {\n" + + " \"mode\" : \"avg\",\n" + + " \"order\" : \"asc\",\n" + + " \"nested\": {\n" + + " \"path\": \"offer\",\n" + + " \"filter\": {\n" + + " \"term\" : { \"offer.color\" : \"blue\" }\n" + + " }\n" + + " }\n" + + " }\n" + + " }", SortOptions.class); + + assertEquals("blue", sort.field().nested().filter().term().value().stringValue()); + + // Geo distance + sort = fromJson("{\n" + + " \"_geo_distance\" : {\n" + + " \"pin.location\" : {\n" + + " \"lat\" : 40,\n" + + " \"lon\" : -70\n" + + " },\n" + + " \"order\" : \"asc\",\n" + + " \"unit\" : \"km\"\n" + + " }\n" + + " }", SortOptions.class); + + assertEquals(40, sort.geoDistance().location().get(0).latlon().lat(), 0.1); + + // Simple string shortcuts + sort = fromJson("\"user\"", SortOptions.class); + assertEquals("user", sort.field().field()); + + sort = fromJson("\"_doc\"", SortOptions.class); + assertTrue(sort.isDoc()); + + sort = fromJson("\"_score\"", SortOptions.class); + assertTrue(sort.isScore()); + } + + @Test + public void testFieldValue() { + + FieldValue f; + + f = FieldValue.of(b -> b.nullValue()); + f = checkJsonRoundtrip(f, "null"); + assertTrue(f.isNull()); + assertEquals("null", f._toJsonString()); + + f = FieldValue.of(b -> b.doubleValue(1.23)); + f = checkJsonRoundtrip(f, "1.23"); + assertTrue(f.isDouble()); + assertEquals(1.23, f.doubleValue(), 0.01); + assertEquals("1.23", f._toJsonString()); + + f = FieldValue.of(b -> b.longValue(123)); + f = checkJsonRoundtrip(f, "123"); + assertTrue(f.isLong()); + assertEquals(123, f.longValue()); + assertEquals("123", f._toJsonString()); + + f = FieldValue.of(b -> b.booleanValue(true)); + f = checkJsonRoundtrip(f, "true"); + assertTrue(f.isBoolean()); + assertTrue(f.booleanValue()); + assertEquals("true", f._toJsonString()); + + f = FieldValue.of(b -> b.booleanValue(false)); + f = checkJsonRoundtrip(f, "false"); + assertTrue(f.isBoolean()); + assertFalse(f.booleanValue()); + assertEquals("false", f._toJsonString()); + + f = FieldValue.of(b -> b.stringValue("foo")); + f = checkJsonRoundtrip(f, "\"foo\""); + assertTrue(f.isString()); + assertEquals("foo", f.stringValue()); + assertEquals("foo", f._toJsonString()); + + } + + @Test + public void testNullableDouble() { + StatsAggregate stats; + + // Regular values + stats = StatsAggregate.statsAggregateOf(b -> b // Parent classes can't have an overloaded "of" method + .count(10) + .min(1.0) + .avg(1.5) + .max(2.0) + .sum(5.0) + ); + + stats = checkJsonRoundtrip(stats, "{\"count\":10,\"min\":1.0,\"max\":2.0,\"avg\":1.5,\"sum\":5.0}"); + assertEquals(10, stats.count()); + assertEquals(1.0, stats.min(), 0.01); + assertEquals(1.5, stats.avg(), 0.01); + assertEquals(2.0, stats.max(), 0.01); + assertEquals(5.0, stats.sum(), 0.01); + + // Missing values (Java mapping same as json) + String json = "{\"count\":0,\"min\":null,\"max\":null,\"avg\":0.0,\"sum\":0.0}"; + stats = fromJson(json, StatsAggregate.class); + + assertEquals(0, stats.count()); + assertEquals(null, stats.min()); + assertEquals(0.0, stats.avg(), 0.01); + assertEquals(null, stats.max()); + assertEquals(0.0, stats.sum(), 0.01); + + // We don't serialize null + assertEquals("{\"count\":0,\"avg\":0.0,\"sum\":0.0}", toJson(stats)); + } + + @Test + public void testNullableInt() { + StringStatsAggregate stats = StringStatsAggregate.of(b -> b + .count(1) + .minLength(2) + .avgLength(3D) + .maxLength(4) + .entropy(0D) + ); + + stats = checkJsonRoundtrip(stats, "{\"count\":1,\"min_length\":2,\"max_length\":4,\"avg_length\":3.0,\"entropy\":0.0}"); + assertEquals(2, stats.minLength()); + assertEquals(4, stats.maxLength()); + assertEquals(0, stats.entropy()); + + // Missing values + String json = "{\"count\":1,\"min_length\":null,\"max_length\":null,\"avg_length\":null,\"entropy\":null}"; + stats = fromJson(json, StringStatsAggregate.class); + assertEquals(1, stats.count()); + assertEquals(null, stats.minLength()); + assertEquals(null, stats.maxLength()); + assertEquals(null, stats.entropy()); + } + + @Test + public void testVoidDeserialization() { + String json = "{\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + + "\"hits\":{\"hits\":[{\"_index\":\"foo\",\"_id\":\"w\",\"_source\":{\"foo\": \"bar\"}}]}," + + "\"took\":42,\"timed_out\":false" + + "}"; + + SearchResponse response = fromJson(json, SearchResponse.createSearchResponseDeserializer(JsonpDeserializer.of(Void.class))); + + // Void type skips all the JSON and is serialized to null. + assertEquals(1, response.hits().hits().size()); + assertNull(response.hits().hits().get(0).source()); + assertEquals(42, response.took()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/ClassStructureTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/ClassStructureTest.java new file mode 100644 index 000000000..f18287b22 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/ClassStructureTest.java @@ -0,0 +1,361 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.ErrorCause; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; +import co.elastic.clients.elasticsearch._types.aggregations.Aggregation; +import co.elastic.clients.elasticsearch._types.aggregations.Buckets; +import co.elastic.clients.elasticsearch._types.aggregations.CardinalityAggregate; +import co.elastic.clients.elasticsearch._types.aggregations.DateRangeAggregate; +import co.elastic.clients.elasticsearch._types.aggregations.RangeBucket; +import co.elastic.clients.elasticsearch._types.aggregations.TermsAggregation; +import co.elastic.clients.elasticsearch._types.aggregations.ValueCountAggregation; +import co.elastic.clients.elasticsearch._types.query_dsl.FieldAndFormat; +import co.elastic.clients.elasticsearch._types.query_dsl.IntervalsQuery; +import co.elastic.clients.elasticsearch.core.GetRequest; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.elasticsearch.core.search.HitsMetadata; +import co.elastic.clients.elasticsearch.core.search.TotalHits; +import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.MissingRequiredPropertyException; +import co.elastic.clients.util.NamedValue; +import co.elastic.clients.util.ObjectBuilder; +import org.junit.jupiter.api.Test; + +import javax.annotation.Nullable; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Tests that verify common features of generated classes. + */ +public class ClassStructureTest extends ModelTestCase { + + /** + * Tests optional and required primitive types + */ + @Test + public void testPrimitiveTypes() throws Exception { + // Optional primitive should use the boxed type and be @Nullable + { + Method searchSize = SearchRequest.class.getMethod("size"); + assertNotNull(searchSize.getAnnotation(Nullable.class)); + assertEquals(Integer.class, searchSize.getReturnType()); + } + + // Builder setter for optional primitive should use the boxed type and be @Nullable + { + Method searchBuilderSize = SearchRequest.Builder.class.getMethod("size", Integer.class); + assertTrue(Arrays.stream(searchBuilderSize.getParameterAnnotations()[0]) + .anyMatch(a -> a.annotationType() == Nullable.class)); + } + + // Required primitive should use the primitive type and not be @Nullable + { + Method totalHitsValue = TotalHits.class.getMethod("value"); + assertNull(totalHitsValue.getAnnotation(Nullable.class)); + assertEquals(long.class, totalHitsValue.getReturnType()); + } + + // Builder setter for required primitive should use the primitive type and not be @Nullable + { + Method totalHitsBuilderValue = TotalHits.Builder.class.getMethod("value", long.class); + assertFalse(Arrays.stream(totalHitsBuilderValue.getParameterAnnotations()[0]) + .anyMatch(a -> a.annotationType() == Nullable.class)); + } + + // Not setting a required primitive should throw an exception + { + assertThrows(MissingRequiredPropertyException.class, () -> TotalHits.of(b -> b)); + } + } + + /** + * Tests correct initialization of inherited fields through builders and data class inheritance. + */ + @Test + public void testDataClassInheritedFieldAssignment() { + // 1 ancestor + { + CardinalityAggregate card = CardinalityAggregate.of(b -> b + .meta(Collections.singletonMap("foo", JsonData.of("bar"))) + .value(1) + ); + + assertAncestorCount(1, card); + assertEquals("bar", card.meta().get("foo").to(String.class)); + assertEquals("{\"meta\":{\"foo\":\"bar\"},\"value\":1}", toJson(card)); + } + + // 3 ancestors + { + DateRangeAggregate date = DateRangeAggregate.of(_1 -> _1 + .meta(Collections.singletonMap("foo", JsonData.of("bar"))) + .buckets(Buckets.of(b -> b.array(Collections.singletonList(RangeBucket.of(_2 -> _2.docCount(1)))))) + ); + + assertAncestorCount(3, date); + assertEquals("bar", date.meta().get("foo").to(String.class)); + assertEquals("{\"meta\":{\"foo\":\"bar\"},\"buckets\":[{\"doc_count\":1}]}", toJson(date)); + } + } + + /** + * Tests correct initialization of inherited fields for union typed. + */ + @Test + public void testUnionInheritedFieldAssignment() { + IntervalsQuery iq = IntervalsQuery.of(_1 -> _1 + .boost(2.0f) + .field("foo") + .allOf(b -> b.intervals(Collections.emptyList())) + ); + assertAncestorCount(1, iq); + assertEquals(2.0f, iq.boost(), 0.01); + assertEquals("{\"foo\":{\"boost\":2.0,\"all_of\":{\"intervals\":[]}}}", toJson(iq)); + } + + @Test + public void testUndefinedCollections() { + // Not setting a required list should throw an exception + { + MissingRequiredPropertyException ex = assertThrows(MissingRequiredPropertyException.class, + () -> HitsMetadata.of(_1 -> _1.total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)))); + assertTrue(ex.getMessage().contains(".hits")); + } + + // Unset list should be non-null, empty but not serialized + { + SearchRequest search = SearchRequest.of(b -> b); + assertNotNull(search.storedFields()); + assertEquals(0, search.storedFields().size()); + assertFalse(ApiTypeHelper.isDefined(search.storedFields())); + assertEquals("{}", toJson(search)); + } + + // Setting an empty list defines it + { + SearchRequest search = SearchRequest.of(b -> b.storedFields(Collections.emptyList())); + assertNotNull(search.storedFields()); + assertEquals(0, search.storedFields().size()); + assertTrue(ApiTypeHelper.isDefined(search.storedFields())); + assertEquals("{\"stored_fields\":[]}", toJson(search)); + } + + // Unset map should be non-null, empty but not serialized + { + CardinalityAggregate card = CardinalityAggregate.of(b -> b.value(1)); + assertNotNull(card.meta()); + assertEquals(0, card.meta().size()); + assertFalse(ApiTypeHelper.isDefined(card.meta())); + assertEquals("{\"value\":1}", toJson(card)); + } + + // Setting an empty map defines it + { + CardinalityAggregate card = CardinalityAggregate.of(b -> b + .value(1) + .meta(Collections.emptyMap()) + ); + assertNotNull(card.meta()); + assertEquals(0, card.meta().size()); + assertTrue(ApiTypeHelper.isDefined(card.meta())); + assertEquals("{\"meta\":{},\"value\":1}", toJson(card)); + } + } + + @Test + public void testListSetters() { + List fields = Arrays.asList("a", "b"); + + { + // Appending doesn't modify the original collection + SearchRequest search = SearchRequest.of(b -> b + .storedFields(fields) + .storedFields("c") + .storedFields("d", "e", "f") + ); + assertEquals(Arrays.asList("a", "b"), fields); + assertEquals(Arrays.asList("a", "b", "c", "d", "e", "f"), search.storedFields()); + } + + { + // Appending doesn't modify the original collection (appending the same list twice) + SearchRequest search = SearchRequest.of(b -> b + .storedFields(fields) + .storedFields(fields) + ); + assertEquals(Arrays.asList("a", "b"), fields); + assertEquals(Arrays.asList("a", "b", "a", "b"), search.storedFields()); + } + + + { + // List cannot be null + List nullFields = null; + assertThrows(NullPointerException.class, () -> { + SearchRequest.of(b -> b + .storedFields(nullFields) + ); + }); + } + + { + // Combine value and builder + FieldAndFormat fieldA = FieldAndFormat.of(f -> f.field("a")); + SearchRequest search = SearchRequest.of(b -> b + .docvalueFields(fieldA) + .docvalueFields(f -> f.field("b")) + .docvalueFields(f -> f.field("c")) + ); + + assertEquals(Arrays.asList("a", "b", "c"), search.docvalueFields().stream() + .map(FieldAndFormat::field).collect(Collectors.toList())); + } + } + + @Test + public void testMapSetters() { + ValueCountAggregation countA = ValueCountAggregation.of(v -> v.field("a")); + ValueCountAggregation countB = ValueCountAggregation.of(v -> v.field("b")); + ValueCountAggregation countC = ValueCountAggregation.of(v -> v.field("c")); + + Map aggs = new HashMap<>(); + aggs.put("aggA", countA._toAggregation()); + aggs.put("aggB", countB._toAggregation()); + + { + // Appending doesn't modify the original collection + SearchRequest search = SearchRequest.of(b -> b + .aggregations(aggs) + .aggregations("aggC", countC._toAggregation()) + .aggregations("aggD", a -> a.valueCount(c -> c.field("d"))) + ); + + // Original map wasn't modified + assertEquals(2, aggs.size()); + + assertEquals(4, search.aggregations().size()); + assertEquals("a", search.aggregations().get("aggA").valueCount().field()); + assertEquals("b", search.aggregations().get("aggB").valueCount().field()); + assertEquals("c", search.aggregations().get("aggC").valueCount().field()); + assertEquals("d", search.aggregations().get("aggD").valueCount().field()); + } + + { + // Map cannot be null + assertThrows(NullPointerException.class, () -> { + Map nullMap = null; + SearchRequest.of(b -> b.aggregations(nullMap)); + }); + } + } + + @Test + public void testDataClassesSingleBuilderUse() { + // no ancestor + WithJsonBase + ObjectBuilderBase + checkSingleBuilderUse(2, new ErrorCause.Builder().type("foo").reason("bar")); + + // 1 ancestor + WithJsonBase + ObjectBuilderBase + checkSingleBuilderUse(3, new CardinalityAggregate.Builder().value(0)); + + // 3 ancestors + WithJsonBase + ObjectBuilderBase + checkSingleBuilderUse(5, new DateRangeAggregate.Builder().buckets(Buckets.of(b -> b.array(Collections.emptyList())))); + } + + @Test + public void testUnionSingleBuilderUse() { + // no ancestor + ObjectBuilderBase + checkSingleBuilderUse(1, new Aggregate.Builder().cardinality(b -> b.value(0))); + + // 1 ancestor + WithJsonBase + ObjectBuilderBase + checkSingleBuilderUse(3, new IntervalsQuery.Builder().field("foo").allOf(b -> b.intervals(Collections.emptyList()))); + } + + @Test + public void testRequiredProperty() { + // All required properties present + GetRequest r = GetRequest.of(b -> b.index("foo").id("bar")); + + // Missing id property throws an exception + MissingRequiredPropertyException ex = assertThrows(MissingRequiredPropertyException.class, () -> { + GetRequest r1 = GetRequest.of(b -> b.index("foo")); + }); + assertEquals("id", ex.getPropertyName()); + + // Disable checks, missing id property is accepted. + try (ApiTypeHelper.DisabledChecksHandle h = ApiTypeHelper.DANGEROUS_disableRequiredPropertiesCheck(true)) { + GetRequest r1 = GetRequest.of(b -> b.index("foo")); + assertNull(r1.id()); + } + + // Checks are enabled again after the try block + ex = assertThrows(MissingRequiredPropertyException.class, () -> { + GetRequest r1 = GetRequest.of(b -> b.index("foo")); + }); + assertEquals("id", ex.getPropertyName()); + } + + /** + * Tests SingleKeyDictionary fields that are not transformed into a behavior. + */ + @Test + public void testNamedValue() { + TermsAggregation termsAgg = TermsAggregation.of(ta -> ta + .order(NamedValue.of("a", SortOrder.Asc)) + .order(NamedValue.of("b", SortOrder.Desc)) + ); + + checkJsonRoundtrip(termsAgg, "{\"order\":[{\"a\":\"asc\"},{\"b\":\"desc\"}]}"); + } + + private void assertAncestorCount(int count, Object obj) { + Class clazz = obj.getClass(); + while(count-- >= 0) { + clazz = clazz.getSuperclass(); + } + assertEquals(Object.class, clazz); + } + + private void checkSingleBuilderUse(int count, ObjectBuilder builder) { + assertAncestorCount(count, builder); + + // Building once should succeed + builder.build(); + + // Building twice should fail + IllegalStateException ex = assertThrows(IllegalStateException.class, builder::build); + assertEquals("Object builders can only be used once", ex.getMessage()); + + // One more for good measure + ex = assertThrows(IllegalStateException.class, builder::build); + assertEquals("Object builders can only be used once", ex.getMessage()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/CodeAdditionsTests.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/CodeAdditionsTests.java new file mode 100644 index 000000000..4de302087 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/CodeAdditionsTests.java @@ -0,0 +1,49 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery; +import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class CodeAdditionsTests extends Assertions { + + @Test + public void testHasClauses() { + + { + BoolQuery.Builder builder = new BoolQuery.Builder(); + assertFalse(builder.hasClauses()); + + BoolQuery query = builder.build(); + assertFalse(query.hasClauses()); + } + + { + BoolQuery.Builder builder = new BoolQuery.Builder(); + builder.must(QueryBuilders.matchAll(b -> b)); + assertTrue(builder.hasClauses()); + + BoolQuery query = builder.build(); + assertTrue(query.hasClauses()); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EndpointTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EndpointTest.java new file mode 100644 index 000000000..ba3afac8e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EndpointTest.java @@ -0,0 +1,94 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.ExpandWildcard; +import co.elastic.clients.elasticsearch.core.ExistsRequest; +import co.elastic.clients.elasticsearch.core.InfoRequest; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.elasticsearch.indices.RefreshRequest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class EndpointTest extends Assertions { + + @Test + public void testArrayPathParameter() { + RefreshRequest req; + + req = RefreshRequest.of(b -> b); + assertNotNull(req.index()); + assertEquals("/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); + + req = RefreshRequest.of(b -> b.index("a")); + assertEquals("/a/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); + + req = RefreshRequest.of(b -> b.index("a", "b")); + assertEquals("/a,b/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); + + req = RefreshRequest.of(b -> b.index("a", "b", "c")); + assertEquals("/a,b,c/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); + } + + @Test + public void testPathEncoding() { + RefreshRequest req; + + req = RefreshRequest.of(b -> b.index("a/b")); + assertEquals("/a%2Fb/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); + + req = RefreshRequest.of(b -> b.index("a/b", "c/d")); + assertEquals("/a%2Fb,c%2Fd/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); + + } + + @Test + public void testArrayQueryParameter() { + RefreshRequest req; + + req = RefreshRequest.of(b -> b); + assertNotNull(req.expandWildcards()); // undefined list + assertNull(RefreshRequest._ENDPOINT.queryParameters(req).get("expand_wildcards")); + + req = RefreshRequest.of(b -> b.expandWildcards(ExpandWildcard.All)); + // Also tests query encoding of enums + assertEquals("all", RefreshRequest._ENDPOINT.queryParameters(req).get("expand_wildcards")); + + req = RefreshRequest.of(b -> b.expandWildcards(ExpandWildcard.All, ExpandWildcard.Closed)); + assertEquals("all,closed", RefreshRequest._ENDPOINT.queryParameters(req).get("expand_wildcards")); + } + + @Test + public void testRequestToString() { + // Simple path, no parameters, no body + assertEquals("InfoRequest: GET /", InfoRequest._INSTANCE.toString()); + + // Complex path, parameters, no body + assertEquals( + "ExistsRequest: HEAD /idx/_doc/id1?preference=foo&refresh=true", + ExistsRequest.of(b -> b.index("idx").id("id1").preference("foo").refresh(true)).toString() + ); + + assertEquals( + "SearchRequest: POST /idx/_search?typed_keys=true {\"size\":10}", + SearchRequest.of(s -> s.index("idx").size(10)).toString() + ); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EnumTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EnumTest.java new file mode 100644 index 000000000..62adc3577 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EnumTest.java @@ -0,0 +1,61 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.Bytes; +import co.elastic.clients.elasticsearch._types.Refresh; +import co.elastic.clients.elasticsearch._types.mapping.GeoOrientation; +import co.elastic.clients.testkit.ModelTestCase; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +public class EnumTest extends ModelTestCase { + + @Test + public void testSimpleEnum() { + assertNull(Bytes.GigaBytes.aliases()); + assertEquals(Bytes.GigaBytes, Bytes._DESERIALIZER.parse("gb")); + } + + @Test + public void testEnumWithAliases() { + assertEquals("left", GeoOrientation.Left.jsonValue()); + assertNotNull(GeoOrientation.Left.aliases()); + + Arrays.asList("right", "RIGHT", "counterclockwise", "ccw").forEach(alias -> { + assertEquals(GeoOrientation.Right, GeoOrientation._DESERIALIZER.parse(alias)); + }); + } + + @Test + public void testBooleanEnum() { + // Quoted value + assertEquals(Refresh.WaitFor, checkJsonRoundtrip(Refresh.WaitFor, "\"wait_for\"")); + + // Unquoted boolean values + assertEquals(Refresh.True, checkJsonRoundtrip(Refresh.True, "true")); + assertEquals(Refresh.False, checkJsonRoundtrip(Refresh.False, "false")); + + // true/false as strings + assertEquals(Refresh.True, fromJson("\"true\"", Refresh.class)); + assertEquals(Refresh.False, fromJson("\"false\"", Refresh.class)); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/RequestEncodingTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/RequestEncodingTest.java new file mode 100644 index 000000000..9789f2a38 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/RequestEncodingTest.java @@ -0,0 +1,59 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.model; + +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import co.elastic.clients.testkit.ModelTestCase; +import org.junit.jupiter.api.Test; + +public class RequestEncodingTest extends ModelTestCase { + + @Test + public void testParametersNotInJson() { + + // This checks that path parameters ("q") are not serialized as json + // and variant containers ser/deser + + SearchRequest request = new SearchRequest.Builder() + .q("blah") + .query(b1 -> b1 + .type(b2 -> b2 + .value("foo")) + ) + .aggregations( + "myagg", b2 -> b2 + .avg(b3 -> b3.field("foo")) + ) + .build(); + + JsonbJsonpMapper mapper = new JsonbJsonpMapper(); + String str = toJson(request, mapper); + + assertEquals("{\"aggregations\":{\"myagg\":{\"avg\":{\"field\":\"foo\"}}},\"query\":{\"type\":{\"value\":\"foo\"}}}", str); + + request = fromJson(str, SearchRequest.class, mapper); + + assertTrue(request.query().isType()); + assertEquals("foo", request.query().type().value()); + assertNull(request.q()); + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/SerializationTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/SerializationTest.java new file mode 100644 index 000000000..8b3ad9662 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/SerializationTest.java @@ -0,0 +1,134 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.model; + +import co.elastic.clients.elasticsearch.cat.NodesResponse; +import co.elastic.clients.elasticsearch.core.GetSourceResponse; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapperBase; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.testkit.ModelTestCase; +import io.github.classgraph.ClassGraph; +import io.github.classgraph.ClassInfo; +import io.github.classgraph.ClassInfoList; +import io.github.classgraph.ScanResult; +import jakarta.json.Json; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParsingException; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; + +public class SerializationTest extends ModelTestCase { + + @Test + public void loadAllDeserializers() throws Exception { + + ScanResult scan = new ClassGraph() + .acceptPackages("co.elastic.clients") + .enableAnnotationInfo() + .enableFieldInfo() + .scan(); + + ClassInfoList withAnnotation = scan.getClassesWithAnnotation(JsonpDeserializable.class.getName()); + + assertFalse(withAnnotation.isEmpty(), "No JsonpDeserializable classes"); + + for (ClassInfo info: withAnnotation) { + Class clazz = Class.forName(info.getName()); + JsonpDeserializer deserializer = JsonpMapperBase.findDeserializer(clazz); + assertNotNull(deserializer); + + // Deserialize something dummy to resolve lazy deserializers + JsonParser parser = mapper.jsonProvider().createParser(new StringReader("-")); + assertThrows(JsonParsingException.class, () -> deserializer.deserialize(parser, mapper), info.getName()); + } + + // Check that all classes that have a _DESERIALIZER field also have the annotation + ClassInfoList withDeserializer = scan.getAllClasses().filter((c) -> c.hasDeclaredField("_DESERIALIZER")); + assertFalse(withDeserializer.isEmpty(), "No classes with a _DESERIALIZER field"); + +// Disabled for now, empty response classes still need a deserializer object +// e.g. ExistsIndexTemplateResponse, PingResponse, ExistsResponse, ExistsAliasResponse +// +// Set annotationNames = withAnnotation.stream().map(c -> c.getName()).collect(Collectors.toSet()); +// Set withFieldNames = withDeserializer.stream().map(c -> c.getName()).collect(Collectors.toSet()); +// +// withFieldNames.removeAll(annotationNames); +// +// assertFalse( +// withFieldNames.size() + " classes with the field but not the annotation: " + withFieldNames, +// !withFieldNames.isEmpty() +// ); + + } + + @Test + public void testArrayValueBody() { + + NodesResponse nr = NodesResponse.of(_0 -> _0 + .valueBody(_1 -> _1.bulkTotalOperations("1")) + .valueBody(_1 -> _1.bulkTotalOperations("2")) + ); + + checkJsonRoundtrip(nr, "[{\"bulk.total_operations\":\"1\"},{\"bulk.total_operations\":\"2\"}]"); + + assertEquals(2, nr.valueBody().size()); + assertEquals("1", nr.valueBody().get(0).bulkTotalOperations()); + assertEquals("2", nr.valueBody().get(1).bulkTotalOperations()); + } + + @Test + public void testGenericValueBody() { + + GetSourceResponse r = GetSourceResponse.of(_0 -> _0 + .valueBody("The value") + ); + + String json = toJson(r); + assertEquals("\"The value\"", json); + + JsonpDeserializer> deserializer = + GetSourceResponse.createGetSourceResponseDeserializer(JsonpDeserializer.stringDeserializer()); + + r = deserializer.deserialize(mapper.jsonProvider().createParser(new StringReader(json)), mapper); + + assertEquals("The value", r.valueBody()); + + } + + @Test + public void testJsonpValuesToString() { + + assertEquals("foo", JsonpUtils.toString(Json.createValue("foo"))); + assertEquals("42", JsonpUtils.toString(Json.createValue(42))); + assertEquals("42.1337", JsonpUtils.toString(Json.createValue(42.1337))); + assertEquals("true", JsonpUtils.toString(JsonValue.TRUE)); + assertEquals("false", JsonpUtils.toString(JsonValue.FALSE)); + assertEquals("null", JsonpUtils.toString(JsonValue.NULL)); + assertEquals("a,b,c", JsonpUtils.toString(Json.createArrayBuilder().add("a").add("b").add("c").build())); + + assertThrows(IllegalArgumentException.class, () -> { + JsonpUtils.toString(Json.createObjectBuilder().build()); + }); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/TypedKeysTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/TypedKeysTest.java new file mode 100644 index 000000000..605bb5254 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/TypedKeysTest.java @@ -0,0 +1,299 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; +import co.elastic.clients.elasticsearch._types.aggregations.AvgAggregate; +import co.elastic.clients.elasticsearch._types.aggregations.StringTermsAggregate; +import co.elastic.clients.elasticsearch._types.aggregations.StringTermsBucket; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpMapperFeatures; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.util.ListBuilder; +import co.elastic.clients.util.MapBuilder; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.JsonGenerator; +import org.junit.jupiter.api.Test; + +import java.io.StringWriter; +import java.util.Collections; + +public class TypedKeysTest extends ModelTestCase { + + @Test + public void testMapProperty() { + + SearchResponse resp = new SearchResponse.Builder() + .aggregations( + "foo", _2 -> _2 + .avg(_3 -> _3.value(3.14)) + ) + // Required properties on a SearchResponse + .took(1) + .shards(_1 -> _1.successful(1).failed(0).total(1)) + .hits(_1 -> _1 + .total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)) + .hits(Collections.emptyList()) + ) + .timedOut(false) + .build(); + + String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + + "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]},\"aggregations\":{\"avg#foo\":{\"value\":3.14}}}"; + + assertEquals(json, toJson(resp)); + + resp = fromJson(json, SearchResponse.createSearchResponseDeserializer(JsonpDeserializer.voidDeserializer())); + + assertEquals(1, resp.took()); + assertEquals(3.14, resp.aggregations().get("foo").avg().value(), 0.001); + + } + + @Test + public void testMapPropertyWithoutTypedKeys() { + + SearchResponse resp = new SearchResponse.Builder() + .aggregations( + "foo", _2 -> _2 + .avg(_3 -> _3.value(3.14)) + ) + // Required properties on a SearchResponse + .took(1) + .shards(_1 -> _1.successful(1).failed(0).total(1)) + .hits(_1 -> _1 + .total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)) + .hits(Collections.emptyList()) + ) + .timedOut(false) + .build(); + + // Note "foo" and not "avg#foo" below + String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + + "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]},\"aggregations\":{\"foo\":{\"value\":3.14}}}"; + + JsonpMapper newMapper = mapper.withAttribute(JsonpMapperFeatures.SERIALIZE_TYPED_KEYS, false); + + assertEquals(json, toJson(resp, newMapper)); + } + + + @Test + public void testAdditionalProperties() { + + Aggregate avg1 = AvgAggregate.of(_1 -> _1.value(1.0))._toAggregate(); + Aggregate avg2 = AvgAggregate.of(_1 -> _1.value(2.0))._toAggregate(); + + Aggregate aggregate = StringTermsAggregate.of(_0 -> _0 + .sumOtherDocCount(1L) + .buckets(b -> b.array( + ListBuilder.of(StringTermsBucket.Builder::new) + .add(_1 -> _1 + .key("key_1") + .docCount(1) + .aggregations(MapBuilder.of("bar", avg1)) + ) + .add(_1 -> _1 + .key("key_2") + .docCount(2) + .aggregations(MapBuilder.of("bar", avg2)) + ) + .build() + )) + ) + ._toAggregate(); + + SearchResponse resp = new SearchResponse.Builder() + .aggregations("foo", aggregate) + // Required properties on a SearchResponse + .took(1) + .shards(_1 -> _1.successful(1).failed(0).total(1)) + .hits(_1 -> _1 + .total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)) + .hits(Collections.emptyList()) + ) + .timedOut(false) + .build(); + + + String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + + "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]}," + + "\"aggregations\":{\"sterms#foo\":{\"buckets\":[" + + "{\"avg#bar\":{\"value\":1.0},\"doc_count\":1,\"key\":\"key_1\"}," + + "{\"avg#bar\":{\"value\":2.0},\"doc_count\":2,\"key\":\"key_2\"}" + + "],\"sum_other_doc_count\":1}}}"; + + assertEquals(json, toJson(resp)); + resp = fromJson(json, SearchResponse.createSearchResponseDeserializer(JsonpDeserializer.voidDeserializer())); + + StringTermsAggregate foo = resp.aggregations().get("foo").sterms(); + assertEquals(1, foo.sumOtherDocCount()); + assertEquals(1, foo.buckets().array().get(0).docCount()); + assertEquals("key_1", foo.buckets().array().get(0).key().stringValue()); + assertEquals(1.0, foo.buckets().array().get(0).aggregations().get("bar").avg().value(), 0.01); + assertEquals("key_2", foo.buckets().array().get(1).key().stringValue()); + assertEquals(2.0, foo.buckets().array().get(1).aggregations().get("bar").avg().value(), 0.01); + } + + // Example taken from + // https://www.elastic.co/guide/en/elasticsearch/reference/8.2/search-aggregations-bucket-reverse-nested-aggregation.html + private static final String nestedJsonWithTypedKeys = "{\n" + + " \"took\": 0," + + " \"timed_out\": false," + + " \"_shards\": {\n" + + " \"successful\": 1,\n" + + " \"failed\": 0,\n" + + " \"skipped\": 0,\n" + + " \"total\": 1\n" + + " },\n" + + " \"hits\": {\n" + + " \"hits\": [],\n" + + " \"total\": {\n" + + " \"relation\": \"eq\",\n" + + " \"value\": 5\n" + + " },\n" + + " \"max_score\": null\n" + + " }," + + " \"aggregations\" : {\n" + + " \"nested#comments\" : {\n" + + " \"doc_count\" : 3,\n" + + " \"sterms#top_usernames\" : {\n" + + " \"doc_count_error_upper_bound\" : 0,\n" + + " \"sum_other_doc_count\" : 0,\n" + + " \"buckets\" : [\n" + + " {\n" + + " \"key\" : \"dan\",\n" + + " \"doc_count\" : 3,\n" + + " \"reverse_nested#comment_to_issue\" : {\n" + + " \"doc_count\" : 1,\n" + + " \"sterms#top_tags_per_comment\" : {\n" + + " \"doc_count_error_upper_bound\" : 0,\n" + + " \"sum_other_doc_count\" : 0,\n" + + " \"buckets\" : [\n" + + " {\n" + + " \"key\" : \"tag1\",\n" + + " \"doc_count\" : 1\n" + + " },\n" + + " {\n" + + " \"key\" : \"tag2\",\n" + + " \"doc_count\" : 1\n" + + " }\n" + + " ]\n" + + " }\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + @Test + public void testSerializeNested() { + + SearchResponse response = fromJson(nestedJsonWithTypedKeys, SearchResponse.class); + + // Check some deeply nested properties + StringTermsBucket bucket = response + .aggregations().get("comments").nested() + .aggregations().get("top_usernames").sterms() + .buckets().array().get(0) + .aggregations().get("comment_to_issue").reverseNested() + .aggregations().get("top_tags_per_comment").sterms() + .buckets().array().get(0); + + assertEquals("tag1", bucket.key().stringValue()); + assertEquals(1, bucket.docCount()); + + // Check that it's typed_keys encoded + String serialized = toJson(response); + assertTrue(serialized.contains("nested#comments")); + assertTrue(serialized.contains("sterms#top_usernames")); + assertTrue(serialized.contains("reverse_nested#comment_to_issue")); + assertTrue(serialized.contains("sterms#top_tags_per_comment")); + + { + // Test direct serialization + JsonProvider jsonProvider = mapper.jsonProvider(); + StringWriter stringWriter = new StringWriter(); + JsonGenerator generator = jsonProvider.createGenerator(stringWriter); + response.serialize(generator, mapper); + generator.close(); + + String directSerialized = stringWriter.toString(); + assertTrue(directSerialized.contains("nested#comments")); + assertTrue(directSerialized.contains("sterms#top_usernames")); + assertTrue(directSerialized.contains("reverse_nested#comment_to_issue")); + assertTrue(directSerialized.contains("sterms#top_tags_per_comment")); + + } + + // Re-parse and re-check + response = fromJson(serialized, SearchResponse.class); + + bucket = response + .aggregations().get("comments").nested() + .aggregations().get("top_usernames").sterms() + .buckets().array().get(0) + .aggregations().get("comment_to_issue").reverseNested() + .aggregations().get("top_tags_per_comment").sterms() + .buckets().array().get(0); + + assertEquals("tag1", bucket.key().stringValue()); + assertEquals(1, bucket.docCount()); + + + JsonProvider jsonProvider = mapper.jsonProvider(); + StringWriter stringWriter = new StringWriter(); + JsonGenerator generator = jsonProvider.createGenerator(stringWriter); + response.serialize(generator, mapper); + generator.close(); + + System.out.println(stringWriter.toString()); + } + + @Test + public void testSerializeNestedWithoutTypedKeys() { + + SearchResponse response = fromJson(nestedJsonWithTypedKeys, SearchResponse.class); + + // Check that it's typed_keys encoded + String serialized = toJson(response); + assertTrue(serialized.contains("nested#comments")); + assertTrue(serialized.contains("sterms#top_usernames")); + assertTrue(serialized.contains("reverse_nested#comment_to_issue")); + assertTrue(serialized.contains("sterms#top_tags_per_comment")); + + // Build the non-typed_keys version (replace 'type#' with 'type#name') + serialized = serialized.replaceAll("\"[^\"]*#", "\""); + assertFalse(serialized.contains("nested#comments")); + assertFalse(serialized.contains("sterms#top_usernames")); + assertFalse(serialized.contains("reverse_nested#comment_to_issue")); + assertFalse(serialized.contains("sterms#top_tags_per_comment")); + + // Serialize without typed keys + JsonpMapper newMapper = mapper.withAttribute(JsonpMapperFeatures.SERIALIZE_TYPED_KEYS, false); + assertEquals(serialized, toJson(response, newMapper)); + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/UnionTests.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/UnionTests.java new file mode 100644 index 000000000..b0208edf6 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/UnionTests.java @@ -0,0 +1,354 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.GeoLocation; +import co.elastic.clients.elasticsearch._types.LatLonGeoLocation; +import co.elastic.clients.elasticsearch._types.Script; +import co.elastic.clients.elasticsearch._types.Time; +import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; +import co.elastic.clients.elasticsearch._types.mapping.Property; +import co.elastic.clients.elasticsearch._types.query_dsl.DistanceFeatureQuery; +import co.elastic.clients.elasticsearch._types.query_dsl.MultiValueMode; +import co.elastic.clients.elasticsearch._types.query_dsl.Query; +import co.elastic.clients.elasticsearch._types.query_dsl.RangeRelation; +import co.elastic.clients.elasticsearch._types.query_dsl.TermRangeQuery; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.testkit.ModelTestCase; +import jakarta.json.Json; +import jakarta.json.JsonObject; +import jakarta.json.stream.JsonParser; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; + +public class UnionTests extends ModelTestCase { + + @Test + public void testScriptDeserializer() { + // A union discriminated by its field names (source -> inline, id -> stored) + { + Script s = Script.of(_1 -> _1 + .source("a script") + ); + s = checkJsonRoundtrip(s, "{\"source\":\"a script\"}"); + assertEquals("a script", s.source()); + } + + { + Script s = Script.of(_1 -> _1 + .id("script_id") + ); + s = checkJsonRoundtrip(s, "{\"id\":\"script_id\"}"); + assertEquals("script_id", s.id()); + } + + { + // Test shortcut property + Script s = fromJson("\"a script\"", Script.class); + assertEquals("a script", s.source()); + } + } + + @Test + public void testOpenContainer() { + String json = "{\"foo\":{\"bar\":42}}"; + + JsonParser parser = Json.createParser(new StringReader("{ \"bar\": 42 }")); + parser.next(); + JsonObject value = parser.getObject(); + + Query obj = Query.of(b -> b._custom("foo", value)); + assertEquals(json, toJson(obj)); + + obj = checkJsonRoundtrip(obj, json); + + assertEquals(Query.Kind._Custom, obj._kind()); + assertEquals("foo", obj._customKind()); + assertEquals(42, obj._custom().toJson().asJsonObject().getInt("bar")); + } + + @Test + public void testOpenInternalUnion() { + String json = "{\"type\":\"foo\",\"bar\":42}"; + + JsonParser parser = Json.createParser(new StringReader(json)); + parser.next(); + JsonObject value = parser.getObject(); + + Property obj = Property.of(b -> b._custom("foo", value)); + assertEquals(json, toJson(obj)); + + obj = checkJsonRoundtrip(obj, json); + + assertEquals(Property.Kind._Custom, obj._kind()); + assertEquals("foo", obj._customKind()); + assertEquals(42, obj._custom().toJson().asJsonObject().getInt("bar")); + } + + @Test + public void testOpenTypedKeysUnion() { + String requiredFields = + "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + + "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]}}"; + + String customAgg = "{\"bar\":42}"; + + JsonParser parser = Json.createParser(new StringReader(customAgg)); + parser.next(); + JsonObject value = parser.getObject(); + + SearchResponse obj = SearchResponse.of(b -> b + .withJson(new StringReader(requiredFields)) + .aggregations("custom-agg", a -> a._custom("foo", value)) + ); + + String json = toJson(obj); + System.out.println(json); + assertTrue(json.contains("\"aggregations\":{\"foo#custom-agg\":{\"bar\":42}}")); + + @SuppressWarnings("unchecked") + SearchResponse obj2 = fromJson(json, SearchResponse.class); + + Aggregate aggregate = obj2.aggregations().get("custom-agg"); + assertEquals(Aggregate.Kind._Custom, aggregate._kind()); + assertEquals("foo", aggregate._customKind()); + assertEquals(42, aggregate._custom().toJson().asJsonObject().getInt("bar")); + + + } + + @Test + public void testUntaggedUnion() { + // Range queries + Query numberRangeQuery = Query.of(q -> q.range(r -> r + .number(n -> n + .field("age") + .gte(10D) + .lte(20D) + .boost(1.0F) + .relation(RangeRelation.Contains)))); + + String expectedNumberRangeQuery = "{\"range\":{\"age\":{\"boost\":1.0,\"relation\":\"contains\"," + + "\"gte\":10.0,\"lte\":20.0}}}"; + + assertEquals(expectedNumberRangeQuery, toJson(numberRangeQuery)); + + Query dateRangeQuery = Query.of(q -> q.range(r -> r + .date(d -> d + .field("day") + .gte("20-06-24") + .lte("20-07-24") + .boost(1.0F) + .format("some-format") + .relation(RangeRelation.Contains)))); + + String expectedDateRangeQuery = "{\"range\":{\"day\":{\"boost\":1.0,\"relation\":\"contains\"," + + "\"gte\":\"20-06-24\",\"lte\":\"20-07-24\",\"format\":\"some-format\"}}}"; + + assertEquals(expectedDateRangeQuery, toJson(dateRangeQuery)); + + Query termRangeQuery = Query.of(q -> q.range(r -> r + .term(d -> d + .field("word") + .gte("some") + .lte("word") + .boost(1.0F) + .relation(RangeRelation.Contains)))); + + String expectedTermRangeQuery = "{\"range\":{\"word\":{\"boost\":1.0,\"relation\":\"contains\"," + + "\"gte\":\"some\",\"lte\":\"word\"}}}"; + + assertEquals(expectedTermRangeQuery, toJson(termRangeQuery)); + + String jsonNumberRangeQuery = "{\n" + + " \"range\": {\n" + + " \"age\": {\n" + + " \"gte\": 10,\n" + + " \"lte\": 20,\n" + + " \"boost\": 1.0,\n" + + " \"relation\": \"contains\"\n" + + " }\n" + + " }\n" + + " }"; + + Query numberRangeQueryFromJson = Query.of(q -> q.withJson(new StringReader(jsonNumberRangeQuery))); + + assertTrue(numberRangeQueryFromJson.range().isUntyped()); + assertEquals(10, numberRangeQueryFromJson.range().untyped().gte().to(Integer.class)); + assertEquals(20, numberRangeQueryFromJson.range().untyped().lte().to(Integer.class)); + assertEquals(RangeRelation.Contains, numberRangeQueryFromJson.range().untyped().relation()); + + Query converted = + TermRangeQuery.of(trq -> trq.field("a").gte("b").lte("c"))._toRangeQuery()._toQuery(); + assertTrue(converted.isRange()); + + // Distance feature queries + + Query geoDistanceFeatureQuery = Query.of(q -> q.bool(b -> b + .must(m -> m.matchAll(mm -> mm)) + .should(sh -> sh.distanceFeature(df -> df + .geo(g -> g + .field("location") + .pivot("1000m") + .origin(GeoLocation.of(gl -> gl.latlon(LatLonGeoLocation.of(ll -> ll.lon(-71.3).lat(41.15)))))))))); + + String expectedGeoDistFeatQuery = "{\"bool\":{\"must\":[{\"match_all\":{}}]," + + "\"should\":[{\"distance_feature\":{\"origin\":{\"lat\":41.15,\"lon\":-71.3}," + + "\"pivot\":\"1000m\",\"field\":\"location\"}}]}}"; + assertEquals(expectedGeoDistFeatQuery, toJson(geoDistanceFeatureQuery)); + + + Query dateDistanceFeatureQuery = Query.of(q -> q.bool(b -> b + .must(m -> m.matchAll(mm -> mm)) + .should(sh -> sh.distanceFeature(df -> df + .date(d -> d + .field("date") + .pivot(Time.of(t -> t.time("7d"))) + .origin("now")))))); + + String expectedDateDistFeatQuery = "{\"bool\":{\"must\":[{\"match_all\":{}}]," + + "\"should\":[{\"distance_feature\":{\"origin\":\"now\",\"pivot\":\"7d\",\"field\":\"date\"}}]}}"; + assertEquals(expectedDateDistFeatQuery, toJson(dateDistanceFeatureQuery)); + + String distDateQuery = "{\n" + + " \"bool\": {\n" + + " \"must\": {\n" + + " \"match_all\": {}\n" + + " },\n" + + " \"should\": {\n" + + " \"distance_feature\": {\n" + + " \"field\": \"date\",\n" + + " \"pivot\": \"7d\",\n" + + " \"origin\": \"now\"\n" + + " }\n" + + " }\n" + + " }\n" + + " }"; + + Query distDateQueryFromJson = Query.of(q -> q.withJson(new StringReader(distDateQuery))); + assertTrue(distDateQueryFromJson.bool().should().get(0).distanceFeature().isUntyped()); + assertEquals("7d", + distDateQueryFromJson.bool().should().get(0).distanceFeature().untyped().pivot().to(String.class)); + assertEquals("date", + distDateQueryFromJson.bool().should().get(0).distanceFeature().untyped().field().toString()); + + + String distGeoQuery = "{\n" + + " \"bool\": {\n" + + " \"must\": {\n" + + " \"match_all\": {}\n" + + " },\n" + + " \"should\": {\n" + + " \"distance_feature\": {\n" + + " \"field\": \"location\",\n" + + " \"pivot\": \"1000m\",\n" + + " \"origin\": [-71.3, 41.15]\n" + + " }\n" + + " }\n" + + " }\n" + + " }"; + + Query distGeoQueryFromJson = Query.of(q -> q.withJson(new StringReader(distGeoQuery))); + assertTrue(distGeoQueryFromJson.bool().should().get(0).distanceFeature().isUntyped()); + assertEquals("1000m", + distGeoQueryFromJson.bool().should().get(0).distanceFeature().untyped().pivot().to(String.class)); + assertEquals("location", + distGeoQueryFromJson.bool().should().get(0).distanceFeature().untyped().field()); + + + Query convertedDist = DistanceFeatureQuery.of(dfq -> dfq.date(d -> d + .field("date") + .pivot(Time.of(t -> t.time("7d"))) + .origin("now")))._toQuery(); + + assertTrue(convertedDist.isDistanceFeature()); + + //Decay Function / Function Score queries + + Query functionScoreQueryGaussDate = Query.of(q -> q.functionScore(fs -> fs + .functions(fn -> fn + .gauss(g -> g + .date(d -> d.field("date").placement(pl -> pl + .origin("2013-09-17") + .scale(Time.of(t -> t.time("10d"))) + .offset(Time.of(t -> t.time("5d"))) + .decay(0.5D))))))); + + String expectedFunctionScoreQueryGaussDate = "{\"function_score\":{\"functions\":[{\"gauss" + + "\":{\"date\":{\"decay\":0.5,\"offset\":\"5d\",\"scale\":\"10d\",\"origin\":\"2013-09-17\"}}}]}}"; + assertEquals(expectedFunctionScoreQueryGaussDate, toJson(functionScoreQueryGaussDate)); + + Query functionScoreQueryExpGeo = Query.of(q -> q.functionScore(fs -> fs + .functions(fn -> fn + .exp(g -> g + .geo(d -> d.field("location").placement(pl -> pl + .origin(GeoLocation.of(gl -> gl.latlon(LatLonGeoLocation.of(ll -> ll.lon(-71.3).lat(41.15))))) + .scale("1km") + .offset("2km") + .decay(0.5D))))))); + + String expectedFunctionScoreQueryExpGeo = "{\"function_score\":{\"functions\":[{\"exp\":{\"location" + + "\":{\"decay\":0.5,\"offset\":\"2km\",\"scale\":\"1km\",\"origin\":{\"lat\":41.15,\"lon\":-71" + + ".3}}}}]}}"; + assertEquals(expectedFunctionScoreQueryExpGeo, toJson(functionScoreQueryExpGeo)); + + Query functionScoreQueryLinearNumeric = Query.of(q -> q.functionScore(fs -> fs + .functions(fn -> fn + .linear(g -> g + .numeric(d -> d.field("nums").placement(pl -> pl + .origin(2D) + .scale(3D) + .offset(4D) + .decay(0.5D))))))); + + String expectedFunctionScoreQueryLinearNumeric = "{\"function_score\":{\"functions\":[{\"linear" + + "\":{\"nums\":{\"decay\":0.5,\"offset\":4.0,\"scale\":3.0,\"origin\":2.0}}}]}}"; + assertEquals(expectedFunctionScoreQueryLinearNumeric, toJson(functionScoreQueryLinearNumeric)); + + String funScoreQuery = + " {\n" + + "\"function_score\": {\n" + + " \"functions\": [\n" + + "{\n" + + " \"gauss\": {\n" + + "\"date\": {\n" + + " \"origin\": \"2013-09-17\",\n" + + " \"scale\": \"10d\",\n" + + " \"offset\": \"5d\",\n" + + " \"decay\": 0.5\n" + + "},\n" + + "\"multi_value_mode\": \"avg\"\n" + + " }\n" + + "}\n" + + " ]\n" + + "}\n" + + " }"; + + Query funScoreQueryFromJson = Query.of(q -> q.withJson(new StringReader(funScoreQuery))); + assertTrue(funScoreQueryFromJson.functionScore().functions().get(0).gauss().isUntyped()); + assertEquals("2013-09-17", + funScoreQueryFromJson.functionScore().functions().get(0).gauss().untyped().placement().origin().to(String.class)); + assertEquals(MultiValueMode.Avg, + funScoreQueryFromJson.functionScore().functions().get(0).gauss().untyped().multiValueMode()); + + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/VariantsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/VariantsTest.java new file mode 100644 index 000000000..e68d674dd --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/VariantsTest.java @@ -0,0 +1,351 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.analysis.Analyzer; +import co.elastic.clients.elasticsearch._types.mapping.Property; +import co.elastic.clients.elasticsearch._types.mapping.TypeMapping; +import co.elastic.clients.elasticsearch._types.query_dsl.FunctionScore; +import co.elastic.clients.elasticsearch._types.query_dsl.Query; +import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.elasticsearch.ilm.ExplainLifecycleResponse; +import co.elastic.clients.elasticsearch.ilm.explain_lifecycle.LifecycleExplainManaged; +import co.elastic.clients.elasticsearch.ilm.explain_lifecycle.LifecycleExplainUnmanaged; +import co.elastic.clients.elasticsearch.indices.GetMappingResponse; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.testkit.ModelTestCase; +import org.junit.jupiter.api.Test; + +import java.util.function.Consumer; + +public class VariantsTest extends ModelTestCase { + + @Test + public void testNested() { + // nested containers: query > intervals > interval + // intervals is a single key dictionary + // query has container properties + + Query q = Query.of(_0 -> _0 + .intervals(_1 -> _1 + .queryName("my-query") + .field("a_field") + .anyOf(_2 -> _2 + .intervals(_3 -> _3 + .match( + _5 -> _5 + .query("match-query") + .analyzer("lowercase") + ) + ) + ) + ) + ); + + assertEquals(Query.Kind.Intervals, q._kind()); + assertNotNull(q.intervals()); + assertEquals("a_field", q.intervals().field()); + assertEquals(1, q.intervals().anyOf().intervals().size()); + assertEquals("lowercase", q.intervals().anyOf().intervals().get(0).match().analyzer()); + + String json = toJson(q); + + assertEquals("{\"intervals\":{\"a_field\":{\"_name\":\"my-query\"," + + "\"any_of\":{\"intervals\":[{\"match\":{\"analyzer\":\"lowercase\",\"query\":\"match-query\"}}]}}}}", json); + + Query q2 = fromJson(json, Query.class); + assertEquals(json, toJson(q2)); + + assertEquals(Query.Kind.Intervals, q2._kind()); + assertNotNull(q2.intervals()); + assertEquals("a_field", q2.intervals().field()); + assertEquals(1, q2.intervals().anyOf().intervals().size()); + assertEquals("lowercase", q2.intervals().anyOf().intervals().get(0).match().analyzer()); + + } + + @Test + public void testInternalTag() { + String expected = "{\"type\":\"ip\",\"fields\":{\"a-field\":{\"type\":\"float\",\"coerce\":true}},\"boost\":1" + + ".0,\"index\":true}"; + + Property p = Property.of(_0 -> _0 + .ip(_1 -> _1 + .index(true) + .boost(1.0) + .fields( + "a-field", _3 -> _3 + .float_(_4 -> _4 + .coerce(true) + ) + ) + ) + ); + + assertEquals(expected, toJson(p)); + + Property property = fromJson(expected, Property.class); + assertTrue(property.ip().index()); + assertEquals(1.0, property.ip().boost().doubleValue(), 0.09); + + assertTrue(property.ip().fields().get("a-field").float_().coerce()); + } + + @Test + public void testDefaultInternalTag() { + + Consumer test = s -> { + Analyzer a = fromJson(s, Analyzer.class); + assertEquals(Analyzer.Kind.Custom, a._kind()); + assertEquals("some-filter", a.custom().filter().get(0)); + assertTrue(a.custom().charFilter().isEmpty()); + assertEquals("some-tokenizer", a.custom().tokenizer()); + }; + + // Explicit type + test.accept("{\"type\":\"custom\",\"filter\":[\"some-filter\"],\"tokenizer\":\"some-tokenizer\"}"); + + // Default type + test.accept("{\"filter\":[\"some-filter\"],\"tokenizer\":\"some-tokenizer\"}"); + } + + @Test + public void testBuilders() { + String json = "{\"exists\":{\"field\":\"foo\"}}"; + Query q; + + q = new Query(QueryBuilders.exists().field("foo").build()); + assertEquals(json, toJson(q)); + + q = QueryBuilders.exists(e -> e.field("foo")); + assertEquals(json, toJson(q)); + } + + + @Test + public void testNestedTaggedUnionWithDefaultTag() { + // https://github.com/elastic/elasticsearch-java/issues/45 + + // Object fields don't really exist in ES and are based on a naming convention where field names + // are dot-separated paths. The hierarchy is rebuilt from these names and ES doesn't send back + // "type": "object" for object properties. + // See https://www.elastic.co/guide/en/elasticsearch/reference/current/object.html + // + // Mappings are therefore a hierarchy of internally-tagged unions based on the "type" property + // with a default "object" tag value if the "type" property is missing. + + String json = + "{\n" + + " \"testindex\" : {\n" + + " \"mappings\" : {\n" + + " \"properties\" : {\n" + + " \"id\" : {\n" + + " \"type\" : \"text\",\n" + + " \"fields\" : {\n" + + " \"keyword\" : {\n" + + " \"type\" : \"keyword\",\n" + + " \"ignore_above\" : 256\n" + + " }\n" + + " }\n" + + " },\n" + + " \"name\" : {\n" + + " \"properties\" : {\n" + + " \"first\" : {\n" + + " \"type\" : \"text\",\n" + + " \"fields\" : {\n" + + " \"keyword\" : {\n" + + " \"type\" : \"keyword\",\n" + + " \"ignore_above\" : 256\n" + + " }\n" + + " }\n" + + " },\n" + + " \"last\" : {\n" + + " \"type\" : \"text\",\n" + + " \"fields\" : {\n" + + " \"keyword\" : {\n" + + " \"type\" : \"keyword\",\n" + + " \"ignore_above\" : 256\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + GetMappingResponse response = fromJson(json, GetMappingResponse.class); + + TypeMapping mappings = response.get("testindex").mappings(); + assertTrue(mappings.properties().get("name").isObject()); + + assertEquals(256, mappings + .properties().get("name").object() + .properties().get("first").text() + .fields().get("keyword").keyword(). + ignoreAbove().longValue() + ); + + assertTrue(mappings.properties().get("id").isText()); + + assertEquals(256, mappings.properties().get("id").text().fields().get("keyword").keyword().ignoreAbove().longValue()); + } + + @Test + public void testEmptyProperty() { + // Edge case where we have a property with no fields and no type + String json = "{}"; + Property property = fromJson(json, Property.class); + assertEquals(Property.Kind.Object, property._kind()); + } + + @Test + public void testNestedVariantsWithContainerProperties() { + + SearchRequest search = SearchRequest.of(s -> s + .aggregations( + "agg1", a -> a + .meta("m1", JsonData.of("m1 value")) + // Here we can choose any aggregation type, but build() isn't accessible + .valueCount(v -> v.field("f")) + // Here we can only set container properties (meta and (sub)aggregations) or build() + .meta("m2", JsonData.of("m2 value")) + ) + ); + + assertEquals("m1 value", search.aggregations().get("agg1").meta().get("m1").to(String.class)); + assertEquals("m2 value", search.aggregations().get("agg1").meta().get("m2").to(String.class)); + } + + @Test + public void testContainerWithOptionalVariants() { + // FunctionScore is the only occurrence of this + + Query q = QueryBuilders.term(t -> t.field("foo").value("bar")); + + // No variant + { + Query fsq = QueryBuilders.functionScore(fs -> fs + .query(q) + .functions(f -> f.weight(1.0)) + ); + + String json = "{\"function_score\":{\"functions\":[{\"weight\":1.0}]," + + "\"query\":{\"term\":{\"foo\":{\"value\":\"bar\"}}}}}"; + assertEquals(json, toJson(fsq)); + + Query fsq2 = checkJsonRoundtrip(fsq, json); + + assertNull(fsq2.functionScore().functions().get(0)._kind()); + assertEquals(1.0, fsq2.functionScore().functions().get(0).weight(), 0.001); + } + + // With a variant + { + Query fsq = QueryBuilders.functionScore(fs -> fs + .query(q) + .functions(f -> f + .weight(1.0) + .linear(l -> l + .numeric(n -> n + .field("foo") + .placement(p -> p.decay(2.0)) + ) + ) + )); + + String json = "{\"function_score\":{\"functions\":[{\"weight\":1.0,\"linear\":{\"foo\":{\"decay\":2.0}}}]," + + "\"query\":{\"term\":{\"foo\":{\"value\":\"bar\"}}}}}"; + assertEquals(json, toJson(fsq)); + + Query fsq2 = checkJsonRoundtrip(fsq, json); + + assertEquals(FunctionScore.Kind.Linear, fsq2.functionScore().functions().get(0)._kind()); + assertEquals(1.0, fsq2.functionScore().functions().get(0).weight(), 0.001); + assertEquals(2.0, fsq2.functionScore().functions().get(0).linear().untyped().placement().decay(), 0.001); + } + } + + @Test + public void testBooleanVariantTag() { + + String jsonT = "{\n" + + " \"indices\": {\n" + + " \"test\": {\n" + + " \"index\": \"test\",\n" + + " \"managed\": true,\n" + + " \"policy\": \"my_policy\",\n" + + " \"index_creation_date_millis\": 1736785235558,\n" + + " \"time_since_index_creation\": \"27.75d\",\n" + + " \"lifecycle_date_millis\": 1736785235558,\n" + + " \"age\": \"27.75d\",\n" + + " \"phase\": \"warm\",\n" + + " \"phase_time_millis\": 1739183166898,\n" + + " \"action\": \"migrate\",\n" + + " \"action_time_millis\": 1739183166898,\n" + + " \"step\": \"check-migration\",\n" + + " \"step_time_millis\": 1739183166898,\n" + + " \"step_info\": {\n" + + " \"message\": \"Waiting for all shard copies to be active\",\n" + + " \"shards_left_to_allocate\": -1,\n" + + " \"all_shards_active\": false,\n" + + " \"number_of_replicas\": 1\n" + + " },\n" + + " \"phase_execution\": {\n" + + " \"policy\": \"my_policy\",\n" + + " \"phase_definition\": {\n" + + " \"min_age\": \"10d\",\n" + + " \"actions\": {\n" + + " \"forcemerge\": {\n" + + " \"max_num_segments\": 1\n" + + " }\n" + + " }\n" + + " },\n" + + " \"version\": 1,\n" + + " \"modified_date_in_millis\": 1739183005443\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + ExplainLifecycleResponse respT = fromJson(jsonT,ExplainLifecycleResponse.class); + + // if managed is "true" then the variant class must be Managed + assertTrue(respT.indices().get("test").isTrue()); + assertTrue(respT.indices().get("test")._get().getClass().equals(LifecycleExplainManaged.class)); + + String jsonF = "{\n" + + " \"indices\": {\n" + + " \"test\": {\n" + + " \"index\": \"test\",\n" + + " \"managed\": false\n" + + " }\n" + + " }\n" + + "}"; + + ExplainLifecycleResponse respF = fromJson(jsonF,ExplainLifecycleResponse.class); + + // if managed is "false" then the variant class must be Unmanaged + assertTrue(respF.indices().get("test").isFalse()); + assertTrue(respF.indices().get("test")._get().getClass().equals(LifecycleExplainUnmanaged.class)); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/package-info.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/package-info.java new file mode 100644 index 000000000..11503ca8b --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/package-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +/** + * Tests that verify correct types and serialization/deserialization of the API specification model using API + * structures that cover the various model features + */ +package clients.rest5_client.elasticsearch.model; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/spec_issues/SpecIssuesTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/spec_issues/SpecIssuesTest.java new file mode 100644 index 000000000..e5117ffcd --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/spec_issues/SpecIssuesTest.java @@ -0,0 +1,316 @@ +/* + * 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. + */ + +package clients.rest5_client.elasticsearch.spec_issues; + +import co.elastic.clients.documentation.usage.Product; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.ElasticsearchTestServer; +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch._types.Script; +import co.elastic.clients.elasticsearch._types.analysis.LimitTokenCountTokenFilter; +import co.elastic.clients.elasticsearch._types.mapping.Property; +import co.elastic.clients.elasticsearch._types.mapping.RuntimeField; +import co.elastic.clients.elasticsearch._types.mapping.RuntimeFieldType; +import co.elastic.clients.elasticsearch.cluster.ClusterStatsResponse; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.search.Suggester; +import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; +import co.elastic.clients.elasticsearch.indices.GetFieldMappingRequest; +import co.elastic.clients.elasticsearch.indices.GetFieldMappingResponse; +import co.elastic.clients.elasticsearch.indices.IndexSettings; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.elasticsearch.snapshot.RestoreResponse; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.json.JsonpDeserializer; +import jakarta.json.stream.JsonParser; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.io.InputStream; +import java.io.StringReader; + +/** + * Test issues related to the API specifications. + * + * Depending on the feedback provided, this may involve either loading a JSON file or sending requests to an ES server. + */ +public class SpecIssuesTest extends ModelTestCase { + + @Test + public void i0328_charFilter() throws Exception { + // Both mappings and mappings_path are optional + String json = + "{\n" + + " \"analysis\": { \n" + + " \"char_filter\": {\n" + + " \"multi_char_filter\": {\n" + + " \"type\": \"mapping\",\n" + +// " \"mappings\": [\n" + +// " \"xyz => xyz\"\n" + +// " ],\n" + + " \"mappings_path\": \"analysis/multi-char-replacement.txt\"\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + IndexSettings.of(b -> b.withJson(new StringReader(json))); + } + + @Disabled("Not fixed yet") + @Test + public void i0201_restoreResponse() throws Exception { + RestoreResponse restoreResponse = fromJson("{\"acknowledged\":true}", RestoreResponse.class); + } + + @Test + public void i0298_runtimeMappings() throws Exception { + ElasticsearchClient client = ElasticsearchTestServer.global().client(); + + String index = "i0298"; + + Product p = new Product("p1", "p2", 42.0); + + client.index(ir -> ir + .index(index) + .document(p)); + + client.indices().flush(f -> f.index(index)); + + RuntimeField runtimeField = RuntimeField.of(rf -> rf + .type(RuntimeFieldType.Double) + .script(Script.of(s -> s + .source("emit(doc['price'].value * 1.19)") + )) + ); + + client.search(sr -> sr + .index(index) + .runtimeMappings("priceWithTax", runtimeField), // NOTE: the builder accepts only lists here + Product.class); + } + + @Test + public void i0297_mappingSettings() { + + CreateIndexRequest request = CreateIndexRequest.of(r -> r + .index("i0297") + .settings(s -> s + // This is "mapping" and not "mappings" + .mapping(m -> m.totalFields(totalFields -> totalFields.limit("1001"))) + .otherSettings("foo", JsonData.of("bar")) + ) + ); + + assertEquals("{\"settings\":{\"foo\":\"bar\",\"mapping\":{\"total_fields\":{\"limit\":\"1001\"}}}}", toJson(request)); + } + + @Test + public void i0295_mappingSettings() { + String json = "{\n" + + " \"mappings\": {\n" + + " \"properties\": {\n" + + " \"myfield\": {\n" + + " \"type\": \"text\"\n" + + " }\n" + + " }\n" + + " },\n" + + " \"settings\": {\n" + + " \"index\": {\n" + + " \"max_result_window\": 1000000,\n" + + " \"mapping\": {\n" + + " \"nested_objects\": {\n" + + " \"limit\": 10000\n" + + " }\n" + + " },\n" + + " \"requests\": {\n" + + " \"cache\": {\n" + + " \"enable\": true\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + CreateIndexRequest request = CreateIndexRequest.of(r -> r + .index("i0295") + .withJson(new StringReader(json)) + ); + } + + @Test + public void i0254_suggesterTest() throws Exception { + new Suggester.Builder().suggesters("song-suggest", s -> s.completion(c->c.field("suggest"))).build(); + } + + @Disabled("Stable version 9 not yet available") + @Test + // update: icu_collation_keyword has been released and added to the spec + public void i0249_variantKind() throws Exception { + try (ElasticsearchTestServer server = new ElasticsearchTestServer("analysis-icu").start()) { + + ElasticsearchClient esClient = server.client(); + + esClient.indices().create(r -> r + .index("i0249") + .withJson(new StringReader("{\n" + + " \"mappings\": {\n" + + " \"properties\": {\n" + + " \"name\": { \n" + + " \"type\": \"text\",\n" + + " \"fields\": {\n" + + " \"sort\": { \n" + + " \"type\": \"icu_collation_keyword\",\n" + + " \"index\": false,\n" + + " \"language\": \"de\",\n" + + " \"country\": \"DE\",\n" + + " \"variant\": \"@collation=phonebook\"\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + "}\n")) + ); + + GetFieldMappingResponse fm = esClient.indices().getFieldMapping(b -> b + .index("i0249") + .fields("*") + ); + + Property property = fm.get("i0249").mappings().get("name").mapping().get("name").text().fields().get("sort"); + + assertFalse(property._isCustom()); + assertEquals(Property.Kind.IcuCollationKeyword, property._kind()); + } + } + + @Test + public void i0199_consumeAllTokensOptional() { + // https://github.com/elastic/elasticsearch-java/issues/199 + // Most filter properties are optional + LimitTokenCountTokenFilter filter = LimitTokenCountTokenFilter.of(b -> b); + } + + @Test + public void i0166_multiFieldMapping() throws Exception { + // https://github.com/elastic/elasticsearch-java/issues/166 + ElasticsearchClient client = ElasticsearchTestServer.global().client(); + + String indexName = "i0166_multi_field_mapping"; + + client.index(r -> r + .index(indexName) + .withJson(new StringReader("{\"a\":1,\"b\":2}")) + ); + + GetFieldMappingRequest gfmRequest = GetFieldMappingRequest.of (b -> b + .index(indexName) + .fields("a", "b") + ); + + GetFieldMappingResponse gfmResponse = client.indices().getFieldMapping(gfmRequest); + + assertEquals(2, gfmResponse.get(indexName).mappings().size()); + assertEquals("a", gfmResponse.get(indexName).mappings().get("a").fullName()); + assertEquals("b", gfmResponse.get(indexName).mappings().get("b").fullName()); + } + + @Test + public void i0107_rangeBucketKey() { + // https://github.com/elastic/elasticsearch-java/issues/107 + loadRsrc("issue-0107-response.json", SearchResponse.createSearchResponseDeserializer(JsonData._DESERIALIZER)); + } + + @Test + public void i0088_clusterStats() { + // https://github.com/elastic/elasticsearch-java/issues/88 + loadRsrc("issue-0088-response.json", ClusterStatsResponse._DESERIALIZER); + } + + @Test + public void i0087_filterAggSubAggregation() { + // https://github.com/elastic/elasticsearch-java/issues/87 + SearchResponse resp = loadRsrc("issue-0087-response.json", + SearchResponse.createSearchResponseDeserializer(JsonData._DESERIALIZER)); + + assertEquals( + "cnn.com", + resp.aggregations().get("login_filter").filter() + .aggregations().get("to_domain").sterms() + .buckets().array().get(0).key().stringValue()); + } + + @Test + public void i0080_simpleError() { + // https://github.com/elastic/elasticsearch-java/issues/80 + // When requesting a missing index, the error response in compact format. + // Fixed by adding ErrorCause.reason as a shortcut property + String json = "{\"error\":\"alias [not-existing-alias] missing\",\"status\":404}"; + ErrorResponse err = fromJson(json, ErrorResponse.class); + + assertEquals("alias [not-existing-alias] missing", err.error().reason()); + } + + @Test + public void i0078_deserializeSearchRequest() { + // https://github.com/elastic/elasticsearch-java/issues/78 + loadRsrc("issue-0078.json", SearchRequest._DESERIALIZER); + } + + @Test + public void i0057_suggestDeserialization() { + // https://github.com/elastic/elasticsearch-java/issues/57 + // Note: the _type properties have been removed so that the test works in 8.x too. + SearchResponse resp = loadRsrc("issue-0057-response.json", + SearchResponse.createSearchResponseDeserializer(JsonData._DESERIALIZER)); + + assertEquals(1, resp.suggest().get("completion:completion1").size()); + assertEquals("hash", resp.suggest().get("completion:completion1").get(0).completion().text()); + assertEquals("HashMap-Complete1", resp.suggest().get("completion:completion1").get(0).completion().options().get(0).text()); + } + + @Test + public void i0056_hitsMetadataTotal() throws Exception { + // https://github.com/elastic/elasticsearch-java/issues/56 + SearchResponse res = ElasticsearchTestServer.global().client() + .search(srb -> srb + .trackTotalHits(thb -> thb.enabled(false)), JsonData.class); + } + + @Test + public void gettingVersionFromNodes() throws Exception { + ElasticsearchTestServer.global().client() + .nodes().info().nodes().entrySet().forEach(node -> + assertNotNull(node.getValue().version())); + } + + private T loadRsrc(String res, JsonpDeserializer deser) { + InputStream is = this.getClass().getResourceAsStream(res); + assertNotNull(is, "Resource not found: " + res); + JsonParser parser = mapper.jsonProvider().createParser(is); + return deser.deserialize(parser, mapper); + } + + private T loadRsrc(String res, Class clazz) { + return loadRsrc(res, JsonpDeserializer.of(clazz)); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonDataTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonDataTest.java new file mode 100644 index 000000000..ea1a4ac70 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonDataTest.java @@ -0,0 +1,176 @@ +/* + * 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. + */ + +package clients.rest5_client.json; + +import co.elastic.clients.elasticsearch.core.search.Hit; +import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; +import co.elastic.clients.json.DelegatingDeserializer; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpMapperBase; +import co.elastic.clients.json.JsonpMapperTest; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.JsonString; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import org.junit.jupiter.api.Test; + +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; + +public class JsonDataTest extends ModelTestCase { + +// public JsonDataTest() { +// super(JsonImpl.Jackson); +// } + + public static > B withJson(B builder, Reader json, JsonpMapper mapper) { + JsonpDeserializer classDeser = JsonpMapperBase.findDeserializer(builder.getClass().getEnclosingClass()); + + @SuppressWarnings("unchecked") + ObjectDeserializer builderDeser = (ObjectDeserializer) DelegatingDeserializer.unwrap(classDeser); + + JsonParser parser = mapper.jsonProvider().createParser(json); + builderDeser.deserialize(builder, parser, mapper, parser.next()); + return builder; + } + + @Test + public void testBuilderDeserializerHack() { + + CreateIndexRequest.Builder b = new CreateIndexRequest.Builder(); + + // Required request parameter + b.index("foo"); + + // Read body from JSON + withJson(b, new StringReader("{\"aliases\": {\"foo\": {\"is_hidden\": true}}}"), new JacksonJsonpMapper()); + + CreateIndexRequest createIndexRequest = b.build(); + } + + @Test + public void testParsing() { + if (jsonImpl == JsonImpl.Simple) { + return; // Doesn't support user-defined object mapping + } + + String json = "{\"children\":[{\"doubleValue\":3.2,\"intValue\":2}],\"doubleValue\":2.1,\"intValue\":1," + + "\"stringValue\":\"foo\"}"; + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + + JsonData data = JsonData.from(parser, mapper); + checkClass(data); + assertEquals("foo", data.toJson().asJsonObject().getString("stringValue")); + + JsonpMapperTest.SomeClass to = data.to(JsonpMapperTest.SomeClass.class); + assertEquals("foo", to.getStringValue()); + } + + @Test + public void testSerializeObject() { + if (jsonImpl == JsonImpl.Simple) { + return; // Doesn't support user-defined object mapping + } + + String json = "{\"children\":[{\"doubleValue\":3.2,\"intValue\":2}],\"doubleValue\":2.1,\"intValue\":1," + + "\"stringValue\":\"foo\"}"; + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + JsonpMapperTest.SomeClass sc = + mapper.deserialize(parser, JsonpMapperTest.SomeClass.class); + + assertEquals("foo", sc.getStringValue()); + assertEquals(1, sc.getChildren().size()); + assertEquals(2, sc.getChildren().get(0).getIntValue()); + // All good + + JsonData data = JsonData.of(sc); + + StringWriter sw = new StringWriter(); + JsonGenerator generator = mapper.jsonProvider().createGenerator(sw); + + data.serialize(generator, mapper); + generator.close(); + + assertEquals(json, sw.toString()); + } + + @Test + public void testSerializeValueOrBuffer() { + String json = "{\"children\":[{\"doubleValue\":3.2,\"intValue\":2}],\"doubleValue\":2.1,\"intValue\":1," + + "\"stringValue\":\"foo\"}"; + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + + JsonData data = JsonData.from(parser, mapper); + checkClass(data); + + assertEquals(json, toJson(data, mapper)); + } + + @Test + public void testConvert() { + + JsonData json = JsonData.of("foo"); + + final JsonValue value = json.toJson(mapper); + + assertEquals(JsonValue.ValueType.STRING, value.getValueType()); + assertEquals("foo", ((JsonString)value).getString()); + } + + @Test + public void testFieldValues() { + // Specific test for https://github.com/elastic/elasticsearch-java/issues/548 which led to buffered JsonData + + String json = "{\"_index\":\"idx\",\"_id\":\"doc_id\",\"fields\":{\"bar\":\"Bar value\",\"foo\":1}}"; + + Hit hit = fromJson(json, Hit.createHitDeserializer(JsonpDeserializer.voidDeserializer())); + + assertEquals(1, hit.fields().get("foo").to(Integer.class)); + assertEquals("Bar value", hit.fields().get("bar").to(String.class)); + + checkClass(hit.fields().get("foo")); + checkClass(hit.fields().get("bar")); + + assertEquals(json, toJson(hit)); + } + + private void checkClass(JsonData data) { + String name = data.getClass().getName(); + switch (jsonImpl) { + case Jackson: + assertEquals(name, "co.elastic.clients.json.jackson.JacksonJsonBuffer"); + break; + + case Jsonb: + case Simple: + assertEquals(name, "co.elastic.clients.json.JsonDataImpl"); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpDeserializerBaseTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpDeserializerBaseTest.java new file mode 100644 index 000000000..982b0811a --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpDeserializerBaseTest.java @@ -0,0 +1,51 @@ +/* + * 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. + */ + +package clients.rest5_client.json; + +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.testkit.ModelTestCase; +import jakarta.json.stream.JsonParser; +import org.junit.jupiter.api.Test; + +import java.util.List; + +public class JsonpDeserializerBaseTest extends ModelTestCase { + + @Test + public void testArrayDeserializer() { + + JsonpDeserializer> deser = + JsonpDeserializer.arrayDeserializer(JsonpDeserializer.integerDeserializer()); + + assertFalse(deser.nativeEvents().contains(JsonParser.Event.VALUE_NUMBER)); + assertTrue(deser.acceptedEvents().contains(JsonParser.Event.VALUE_NUMBER)); + + List values = fromJson("[ 42, 43 ]", deser); + assertEquals(2, values.size()); + assertEquals(42, values.get(0)); + assertEquals(43, values.get(1)); + + // Single value representation + values = fromJson("42", deser); + assertEquals(1, values.size()); + assertEquals(42, values.get(0)); + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpDeserializerTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpDeserializerTest.java new file mode 100644 index 000000000..f0e854e9b --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpDeserializerTest.java @@ -0,0 +1,43 @@ +/* + * 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. + */ + +package clients.rest5_client.json; + +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.testkit.ModelTestCase; +import jakarta.json.stream.JsonParser; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; +import java.util.List; + +public class JsonpDeserializerTest extends ModelTestCase { + + @Test + public void testNullStringInArray() { + JsonpDeserializer> deser = JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()); + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader("[\"a\", null, \"b\"]")); + List list = deser.deserialize(parser, mapper); + + assertEquals("a", list.get(0)); + assertNull(list.get(1)); + assertEquals("b", list.get(2)); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpMapperTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpMapperTest.java new file mode 100644 index 000000000..2866abc23 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpMapperTest.java @@ -0,0 +1,210 @@ +/* + * 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. + */ + +package clients.rest5_client.json; + +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import jakarta.json.JsonArray; +import jakarta.json.JsonNumber; +import jakarta.json.bind.spi.JsonbProvider; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import org.eclipse.parsson.JsonProviderImpl; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; +import java.io.StringWriter; +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class JsonpMapperTest extends Assertions { + + String json = "{\"children\":[{\"doubleValue\":3.2,\"intValue\":2}],\"doubleValue\":2.1,\"intValue\":1," + + "\"stringValue\":\"foo\"}"; + + @Test + public void testJsonb() { + JsonpMapper mapper = new JsonbJsonpMapper(new JsonProviderImpl(), JsonbProvider.provider()); + testSerialize(mapper, json); + testDeserialize(mapper, json); + testLargeNumber(mapper); + } + + @Test + public void testJackson() { + JacksonJsonpMapper mapper = new JacksonJsonpMapper(); + testSerialize(mapper, json); + testDeserialize(mapper, json); + testLargeNumber(mapper); + } + + @Test + public void testJacksonCustomMapper() { + ObjectMapper jkMapper = new ObjectMapper(); + jkMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + jkMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + + JacksonJsonpMapper mapper = new JacksonJsonpMapper(jkMapper); + + String json = "{\"children\":[{\"double_value\":3.2,\"int_value\":2}],\"double_value\":2.1,\"int_value\":1," + + "\"string_value\":\"foo\"}"; + + testSerialize(mapper, json); + testDeserialize(mapper, json); + } + + @Test + public void testDeserializeWithType() { + + String json = "{\"foo\":{\"int_value\":1,\"double_value\":1.0},\"bar\":{\"int_value\":2,\"double_value\":2.0}}"; + + ObjectMapper jkMapper = new ObjectMapper(); + jkMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + JacksonJsonpMapper mapper = new JacksonJsonpMapper(jkMapper); + + // With type erasure, map values are raw json nodes + { + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + Map map = new HashMap<>(); + map = mapper.deserialize(parser, (Type) map.getClass()); + + Map finalMap = map; + assertThrows(ClassCastException.class, () -> { + assertEquals(1, finalMap.get("foo").intValue); + }); + } + + // Use a j.l.reflect.Type to deserialize map values correctly + { + TypeReference> typeRef = new TypeReference>() {}; + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + Map map = mapper.deserialize(parser, typeRef.getType()); + + System.out.println(map); + assertEquals(1, map.get("foo").intValue); + assertEquals(2, map.get("bar").intValue); + } + } + + private void testSerialize(JsonpMapper mapper, String expected) { + + SomeClass something = new SomeClass(); + something.setIntValue(1); + something.setDoubleValue(2.1); + something.setStringValue("foo"); + + SomeClass other = new SomeClass(); + other.setIntValue(2); + other.setDoubleValue(3.2); + something.setChildren(Collections.singletonList(other)); + + StringWriter strw = new StringWriter(); + JsonGenerator generator = mapper.jsonProvider().createGenerator(strw); + + mapper.serialize(something, generator); + + generator.close(); + + assertEquals(expected, strw.getBuffer().toString()); + } + + private void testDeserialize(JsonpMapper mapper, String json) { + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + SomeClass parsed = mapper.deserialize(parser, SomeClass.class); + + assertEquals(1, parsed.getIntValue()); + assertEquals(2.1, parsed.getDoubleValue(), 0.0); + assertEquals("foo", parsed.getStringValue()); + + List children = parsed.getChildren(); + assertEquals(1, children.size()); + + SomeClass child = children.get(0); + + assertEquals(2, child.getIntValue()); + assertEquals(3.2, child.getDoubleValue(), 0.0); + assertNull(child.getStringValue()); + assertNull(child.getChildren()); + } + + private void testLargeNumber(JsonpMapper mapper) { + String json = "[1e999999]"; + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + parser.next(); + + JsonArray array = parser.getValue().asJsonArray(); + + JsonNumber number = array.getJsonNumber(0); + + assertTrue(Double.isInfinite(number.doubleValue())); + + Assertions.assertThrows(Exception.class, number::bigIntegerValue); + } + + public static class SomeClass { + private List children; + private double doubleValue; + private int intValue; + private String stringValue; + + public int getIntValue() { + return intValue; + } + + public void setIntValue(int intValue) { + this.intValue = intValue; + } + + public String getStringValue() { + return stringValue; + } + + public void setStringValue(String stringValue) { + this.stringValue = stringValue; + } + + public double getDoubleValue() { + return doubleValue; + } + + public void setDoubleValue(double doubleValue) { + this.doubleValue = doubleValue; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpMappingExceptionTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpMappingExceptionTest.java new file mode 100644 index 000000000..260df72ed --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpMappingExceptionTest.java @@ -0,0 +1,113 @@ +/* + * 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. + */ + +package clients.rest5_client.json; + +import co.elastic.clients.elasticsearch._types.mapping.TypeMapping; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.json.JsonpMappingException; +import co.elastic.clients.json.SimpleJsonpMapper; +import co.elastic.clients.testkit.ModelTestCase; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; + +public class JsonpMappingExceptionTest extends ModelTestCase { + + @Test + public void testObjectAndArrayPath() { + + String json = "{" + + " \"took\" : 9," + + " \"timed_out\" : false," + + " \"_shards\" : {" + + " \"total\" : 1," + + " \"successful\" : 1," + + " \"skipped\" : 0," + + " \"failed\" : 0" + + " }," + + " \"hits\" : {" + + " \"total\" : {" + + " \"value\" : 1," + + " \"relation\" : \"eq\"" + + " }," + + " \"max_score\" : 1.0," + + " \"hits\" : [" + + " {" + + " \"_index\" : \"test\"," + + " \"_id\" : \"8aSerXUBs1w7Wkuj31zd\"," + + " \"_score\" : \"1.0\"," + + " \"_source\" : {" + + " \"foo\" : \"bar\"" + + " }" + + " }," + + " {" + + " \"_index\" : \"test\"," + + " \"_id\" : \"8aSerXUBs1w7Wkuj31zd\"," + + " \"_score\" : \"abc\"," + // <====== error here + " \"_source\" : {" + + " \"foo\" : \"bar\"" + + " }" + + " }" + + " ]" + + " }" + + "}"; + + JsonpMappingException e = assertThrows(JsonpMappingException.class, () -> { + // withJson() will read values of the generic parameter type as JsonData + SearchResponse r = SearchResponse.of(b -> b + .withJson(new StringReader(json)) + ); + }); + + assertTrue(e.getMessage().contains("Error deserializing co.elastic.clients.elasticsearch.core.search.Hit")); + assertTrue(e.getMessage().contains("java.lang.NumberFormatException")); + + // Also checks array index in path + assertEquals("hits.hits[1]._score", e.path()); + } + + @Test + public void testLookAhead() { + + String json = + "{" + + " \"properties\": { " + + " \"foo-bar\": {" + + " \"type\": \"text\"," + + " \"baz\": false" + + " }" + + " }" + + "}"; + + // Error deserializing co.elastic.clients.elasticsearch._types.mapping.TextProperty: + // Unknown field 'baz' (JSON path: properties['foo-bar'].baz) (...line no=1, column no=36, offset=35) + + JsonpMappingException e = assertThrows(JsonpMappingException.class, () -> { + fromJson(json, TypeMapping.class, SimpleJsonpMapper.INSTANCE_REJECT_UNKNOWN_FIELDS); + }); + + // Check escaping of non identifier path elements and path from map elements + assertEquals("properties['foo-bar'].baz", e.path()); + + String msg = e.getMessage(); + assertTrue(msg.contains("Unknown field 'baz'")); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpUtilsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpUtilsTest.java new file mode 100644 index 000000000..ad87eba18 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpUtilsTest.java @@ -0,0 +1,332 @@ +/* + * 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. + */ + +package clients.rest5_client.json; + +import co.elastic.clients.elasticsearch.core.search.Hit; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.elasticsearch.security.IndexPrivilege; +import co.elastic.clients.elasticsearch.security.IndicesPrivileges; +import co.elastic.clients.elasticsearch.security.RoleTemplateScript; +import co.elastic.clients.elasticsearch.security.UserIndicesPrivileges; +import co.elastic.clients.util.AllowForbiddenApis; +import jakarta.json.JsonException; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; +import java.io.StringWriter; +import java.net.URL; +import java.util.Collections; +import java.util.Enumeration; +import java.util.function.Consumer; + +public class JsonpUtilsTest extends ModelTestCase { + + @Test + @AllowForbiddenApis("Testing JsonpUtil.provider()") + public void testProviderLoading() { + // See https://github.com/elastic/elasticsearch-java/issues/163 + + // Create an empty non-delegating classloader and set it as the context classloader. It simulates a + // plugin system that doesn't set the context classloader to the plugins classloader. + ClassLoader emptyLoader = new ClassLoader() { + @Override + public Enumeration getResources(String name) { + return Collections.emptyEnumeration(); + } + }; + + ClassLoader savedLoader = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(emptyLoader); + + assertThrows(JsonException.class, () -> { + assertNotNull(JsonProvider.provider()); + }); + + assertNotNull(JsonpUtils.provider()); + + } finally { + Thread.currentThread().setContextClassLoader(savedLoader); + } + } + + @Test + @AllowForbiddenApis("Testing JsonpUtil.provider()") + public void testProviderCache() { + // A new provider at each call + assertNotSame(JsonpUtils.findProvider(), JsonpUtils.findProvider()); + + // Result is cached + assertSame(JsonpUtils.provider(), JsonpUtils.provider()); + } + + @Test + public void testObjectToString() { + // Test that we call toString() on application classes. + Hit hit = Hit.of(h -> h + .source(new SomeUserData()) + .index("idx") + .id("id1") + ); + assertEquals("Hit: {\"_index\":\"idx\",\"_id\":\"id1\",\"_source\":\"Some user data\"}", hit.toString()); + } + + private static class SomeUserData { + @Override + public String toString() { + return "Some user data"; + } + } + + @Test + public void testLargeObjectToString() { + // Build a large string + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 1001; i++) { + sb.append("0123456789"); + } + + String text = sb.toString(); + assertEquals(10010, text.length()); + + Hit hit = Hit.of(h -> h + .source(text) + .index("idx") + .id("id1") + ); + + String toString = hit.toString(); + + assertEquals(10000 + "Hit: ".length() + "...".length(), toString.length()); + assertTrue(toString.startsWith("Hit: ")); + assertTrue(toString.endsWith("...")); + } + + @Test + public void testSerializeDoubleOrNull() { + // ---- Double values + assertEquals("{\"a\":null}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, Double.NaN, Double.NaN))); + assertEquals("{\"a\":1.0}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, 1.0, Double.NaN))); + + assertEquals("{\"a\":null}", + orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY))); + assertEquals("{\"a\":1.0}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, 1.0, Double.POSITIVE_INFINITY))); + + assertEquals("{\"a\":null}", + orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY))); + assertEquals("{\"a\":1.0}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, 1.0, Double.NEGATIVE_INFINITY))); + + assertEquals("{\"a\":null}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, Double.NaN, 0.0))); + + // Serialize defined default values + assertEquals("{\"a\":0.0}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, 0.0, 0.0))); + + } + + @Test + public void testSerializeIntOrNull() { + assertEquals("{\"a\":null}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, Integer.MAX_VALUE, Integer.MAX_VALUE))); + assertEquals("{\"a\":1}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, 1, Integer.MAX_VALUE))); + assertEquals("{\"a\":1}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, 1, 0))); + + // Integer.MAX_VALUE is valid if not the default value + assertEquals("{\"a\":2147483647}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, Integer.MAX_VALUE, 0))); + assertEquals("{\"a\":2147483647}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, Integer.MAX_VALUE, Integer.MIN_VALUE))); + + // Serialize non infinite default values + assertEquals("{\"a\":0}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, 0, 0))); + } + + @Test + public void testJsonString() { + // Single value + { + IndicesPrivileges priv = IndicesPrivileges.of(i -> i + .names("bar") + .query(q -> q.term(t -> t.field("baz").value(1))) + .privileges(IndexPrivilege.All.jsonValue()) + ); + + String json = "{\"names\":[\"bar\"],\"privileges\":[\"all\"],\"query\":\"{\\\"term\\\":{\\\"baz\\\":{\\\"value\\\":1}}}\"}"; + + assertEquals(json, toJson(priv)); + + priv = fromJson(json, IndicesPrivileges.class); + assertEquals("baz", priv.query().term().field()); + } + + // Single value template + { + IndicesPrivileges priv = IndicesPrivileges.of(i -> i + .names("bar") + .query(q -> q._custom("template", RoleTemplateScript.of(s -> s.id("foo")))) + .privileges(IndexPrivilege.All.jsonValue()) + ); + + String json = "{\"names\":[\"bar\"],\"privileges\":[\"all\"],\"query\":\"{\\\"template\\\":{\\\"id\\\":\\\"foo\\\"}}\"}"; + + assertEquals(json, toJson(priv)); + + priv = fromJson(json, IndicesPrivileges.class); + assertEquals("foo", priv.query()._custom().to(RoleTemplateScript.class).id()); + } + + // Array value + { + UserIndicesPrivileges priv = UserIndicesPrivileges.of(i -> i + .names("bar") + .query(q -> q.term(t -> t.field("baz").value(1))) + .privileges(IndexPrivilege.All.jsonValue()) + .allowRestrictedIndices(false) + ); + + String json = "{\"names\":[\"bar\"],\"privileges\":[\"all\"],\"query\":[\"{\\\"term\\\":{\\\"baz\\\":{\\\"value\\\":1}}}\"]," + + "\"allow_restricted_indices\":false}"; + + assertEquals(json, toJson(priv)); + + priv = fromJson(json, UserIndicesPrivileges.class); + assertEquals("baz", priv.query().get(0).term().field()); + } + } + + @Test + public void testCopy() { + // Tests round-tripping a json document that contains all event types and various kinds of nesting + + String json = "{\n" + + " \"p1\": \"str1\",\n" + + " \"p2\": 42,\n" + + " \"p3\": [\"str31\", \"str32\"],\n" + + " \"p4\": {\n" + + " \"p41\": \"str41\",\n" + + " \"p42\": [\"str421\", \"str422\"],\n" + + " \"p43\": {\n" + + " \"p431\": \"str431\"\n" + + " },\n" + + " \"p44\": true,\n" + + " \"p45\": false,\n" + + " \"p46\": 3.14\n" + + " },\n" + + " \"p5\": [{\n" + + " \"p51\": {\n" + + " \"p511\": \"str511\"\n" + + " }\n" + + " }],\n" + + " \"p6\": null\n" + + "}\n"; + + json = normalizeIndent(json); + + JsonProvider provider = JsonpUtils.provider(); + + JsonParser parser = provider.createParser(new StringReader(json)); + StringWriter sw = new StringWriter(); + JsonGenerator generator = provider.createGenerator(sw); + + JsonpUtils.copy(parser, generator); + parser.close(); + generator.close(); + + assertEquals(json, sw.toString()); + } + + private static String orNullHelper(Consumer c) { + StringWriter sw = new StringWriter(); + JsonGenerator generator = JsonpUtils.provider().createGenerator(sw); + + generator.writeStartObject(); + generator.writeKey("a"); + c.accept(generator); + generator.writeEnd(); + generator.close(); + + return sw.toString(); + } + + /** + * Normalizes the whitespace and indentation of a JSON string by parsing it and copying it to a string generator. + */ + private static String normalizeIndent(String json) { + JsonParser parser = JsonpUtils.provider().createParser(new StringReader(json)); + StringWriter sw = new StringWriter(); + JsonGenerator generator = JsonpUtils.provider().createGenerator(sw); + + copyAll(parser, generator); + + parser.close(); + generator.close(); + return sw.toString(); + } + + private static void copyAll(JsonParser parser, JsonGenerator generator) { + while(parser.hasNext()) { + switch (parser.next()) { + case START_OBJECT: + generator.writeStartObject(); + break; + + case END_OBJECT: + generator.writeEnd(); + break; + + case START_ARRAY: + generator.writeStartArray(); + break; + + case END_ARRAY: + generator.writeEnd(); + break; + + case KEY_NAME: + generator.writeKey(parser.getString()); + break; + + case VALUE_STRING: + generator.write(parser.getString()); + break; + + case VALUE_NULL: + generator.writeNull(); + break; + + case VALUE_TRUE: + generator.write(true); + break; + + case VALUE_FALSE: + generator.write(false); + break; + + case VALUE_NUMBER: + if (parser.isIntegralNumber()) { + generator.write(parser.getLong()); + } else { + generator.write(parser.getBigDecimal()); + } + break; + } + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/LazyDeserializerTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/LazyDeserializerTest.java new file mode 100644 index 000000000..b8c3199ef --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/json/LazyDeserializerTest.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package clients.rest5_client.json; + +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.LazyDeserializer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.CompletableFuture; + +public class LazyDeserializerTest extends Assertions { + + @Test + public void testConcurrentInit() throws Exception { + // See https://github.com/elastic/elasticsearch-java/issues/58 + + final LazyDeserializer ld = new LazyDeserializer<>(JsonpDeserializer::stringDeserializer); + + CompletableFuture> fut1; + CompletableFuture> fut2; + + // Lock the mutex and start 2 threads that will compete for it. + synchronized (ld) { + fut1 = futureUnwrap(ld); + fut2 = futureUnwrap(ld); + } + + // We should see the same non-null results everywhere + assertNotNull(fut1.get()); + assertNotNull(fut2.get()); + + final JsonpDeserializer unwrapped = ld.unwrap(); + assertEquals(unwrapped, fut1.get()); + assertEquals(unwrapped, fut2.get()); + + } + + private CompletableFuture> futureUnwrap(LazyDeserializer d) { + + final CompletableFuture> result = new CompletableFuture<>(); + + new Thread(() -> { + try { + result.complete(d.unwrap()); + } catch (Throwable e) { + result.completeExceptionally(e); + } + }).start(); + + return result; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/ObjectBuilderDeserializerTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/ObjectBuilderDeserializerTest.java new file mode 100644 index 000000000..0cbf19ab2 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/json/ObjectBuilderDeserializerTest.java @@ -0,0 +1,50 @@ +/* + * 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. + */ + +package clients.rest5_client.json; + +import co.elastic.clients.elasticsearch._types.mapping.TextProperty; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.elasticsearch.transform.UpdateTransformRequest; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; + +public class ObjectBuilderDeserializerTest extends ModelTestCase { + + @Test + public void testNullObjectValue() { + // Should also accept null for optional values + String json = "{ \"index_prefixes\": null }"; + fromJson(json, TextProperty.class); + } + + @Test + public void testNullObjectValueInFunctionBuilder() { + String json = "{\n" + + " \"retention_policy\": null\n" + + " }"; + + UpdateTransformRequest.Builder builder = new UpdateTransformRequest.Builder(); + builder.transformId("foo"); + builder.withJson(new StringReader(json)); + builder.build(); + } + +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/WithJsonTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/WithJsonTest.java new file mode 100644 index 000000000..87558d1bc --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/json/WithJsonTest.java @@ -0,0 +1,190 @@ +/* + * 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. + */ + +package clients.rest5_client.json; + +import co.elastic.clients.elasticsearch._types.Script; +import co.elastic.clients.elasticsearch._types.SlicedScroll; +import co.elastic.clients.elasticsearch._types.mapping.Property; +import co.elastic.clients.elasticsearch._types.mapping.TextProperty; +import co.elastic.clients.elasticsearch._types.query_dsl.Query; +import co.elastic.clients.elasticsearch._types.query_dsl.TermQuery; +import co.elastic.clients.elasticsearch.core.IndexRequest; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.indices.PutIndicesSettingsRequest; +import co.elastic.clients.elasticsearch.security.RoleTemplateScript; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.testkit.ModelTestCase; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; + +public class WithJsonTest extends ModelTestCase { + + @Test + public void testRequestWithGenericValueBody() { + String json = "{\"foo\": \"bar\", \"baz\": 1}"; + + IndexRequest req = IndexRequest.of(b -> b + .index("index") // required path parameter (cannot be expressed in json) + .withJson(new StringReader(json)) + ); + + assertEquals("index", req.index()); + assertEquals("bar", req.document().toJson().asJsonObject().getString("foo")); + assertEquals(1, req.document().toJson().asJsonObject().getInt("baz")); + } + + @Test + public void testRequestWithValueBody() { + String json = "{" + + "\"analyze\": {" + + " \"max_token_count\": 12" + + " }" + + "}"; + + PutIndicesSettingsRequest req = PutIndicesSettingsRequest.of(b -> b + .withJson(new StringReader(json)) + ); + + assertEquals(12, req.settings().analyze().maxTokenCount().intValue()); + } + + @Test + public void testRegularObject() { + String json = "{\"field\": \"foo\", \"id\": 12}"; + + SlicedScroll s = SlicedScroll.of(b -> b + .withJson(new StringReader(json)) + .max(34) // required property not present in the json + ); + + assertEquals("foo", s.field()); + assertEquals("12", s.id()); + assertEquals(34, s.max()); + } + + @Test + public void testObjectWithGenericParam() { + + String json = "{" + + " \"took\" : 9," + + " \"timed_out\" : false," + + " \"_shards\" : {" + + " \"total\" : 1," + + " \"successful\" : 1," + + " \"skipped\" : 0," + + " \"failed\" : 0" + + " }," + + " \"hits\" : {" + + " \"total\" : {" + + " \"value\" : 1," + + " \"relation\" : \"eq\"" + + " }," + + " \"max_score\" : 1.0," + + " \"hits\" : [" + + " {" + + " \"_index\" : \"test\"," + + " \"_id\" : \"8aSerXUBs1w7Wkuj31zd\"," + + " \"_score\" : 1.0," + + " \"_source\" : {" + + " \"foo\" : \"bar\"" + + " }" + + " }" + + " ]" + + " }" + + "}"; + + // withJson() will read values of the generic parameter type as JsonData + SearchResponse r = SearchResponse.of(b -> b + .withJson(new StringReader(json)) + ); + + assertEquals(1, r.hits().total().value()); + assertEquals("bar", r.hits().hits().get(0).source().toJson().asJsonObject().getString("foo")); + } + + @Test + public void testTypeWithParent() { + + String json = "{\"source\": \"return doc;\"}"; + + Script is = Script.of(b -> b + .withJson(new StringReader(json)) + ); + + assertEquals("return doc;", is.source()); + } + + @Test + public void testContainerTaggedUnion() { + String json = "{" + + " \"term\": {" + + " \"user.id\": {" + + " \"value\": \"kimchy\"," + + " \"boost\": 1.0" + + " }" + + " }" + + " }"; + + Query q = Query.of(b -> b + .withJson(new StringReader(json)) + ); + + TermQuery tq = q.term(); + assertEquals("user.id", tq.field()); + assertEquals("kimchy", tq.value().stringValue()); + assertEquals(1.0, tq.boost(), 0.001); + } + + @Test + public void testInternallyTaggedUnion() { + String json = "{ " + + " \"type\": \"text\"," + + " \"fields\": {" + + " \"some_field\": { " + + " \"type\": \"keyword\"," + + " \"normalizer\": \"lowercase\"" + + " }" + + " }" + + " }"; + + Property p = Property.of(b -> b + .withJson(new StringReader(json)) + ); + + TextProperty tp = p.text(); + assertEquals("lowercase", tp.fields().get("some_field").keyword().normalizer()); + } + + @Test + public void testExternalTaggedUnion() { + + RoleTemplateScript withSource = RoleTemplateScript.of(j -> j + .withJson(new StringReader("{\"source\": {\"match\": {\"category\": \"click\"}}}"))); + assertTrue(withSource.source().isQueryObject()); + RoleTemplateScript withStringSource = RoleTemplateScript.of(j -> j + .withJson(new StringReader("{\"source\": \"string\"}"))); + assertTrue(withStringSource.source().isQueryString()); + RoleTemplateScript withStoredScript = RoleTemplateScript.of(j -> j + .withJson(new StringReader("{\"id\": \"foo\"}"))); + assertTrue(!withStoredScript.id().isEmpty()); + } +} + diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonJsonpGeneratorTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonJsonpGeneratorTest.java new file mode 100644 index 000000000..c6244159d --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonJsonpGeneratorTest.java @@ -0,0 +1,91 @@ +/* + * 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. + */ + +package clients.rest5_client.json.jackson; + +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import jakarta.json.Json; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonGenerator; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.StringWriter; + +public class JacksonJsonpGeneratorTest extends Assertions { + + @Test + public void testWrite(){ + StringWriter sw = new StringWriter(); + JsonGenerator generator = new JacksonJsonpMapper().jsonProvider().createGenerator(sw); + + generator.writeStartObject(); + + // Boolean + generator.write("bool1", true); + generator.writeKey("bool2"); + generator.write(false); + + // String + generator.write("str1", "foo"); + generator.writeKey("str2"); + generator.write("bar"); + + // Integer + generator.write("int1", 42); + generator.writeKey("int2"); + generator.write(1337); + + // Long + generator.write("long1", 123456789012345L); + generator.writeKey("long2"); + generator.write(123456789012345L); + + generator.write("double1", 0.001); + generator.writeKey("double2"); + generator.write(12345.6789); + + // JsonValue + JsonValue jsonValue = Json.createObjectBuilder() + .add("bool", true) + .add("str", "foo") + .add("int", 42) + .add("long", 123456789012345L) + .add("double", 12345.6789) + .build(); + + generator.write("value", jsonValue); + + generator.close(); + + assertEquals("{" + + "\"bool1\":true," + + "\"bool2\":false," + + "\"str1\":\"foo\"," + + "\"str2\":\"bar\"," + + "\"int1\":42," + + "\"int2\":1337," + + "\"long1\":123456789012345," + + "\"long2\":123456789012345," + + "\"double1\":0.001," + + "\"double2\":12345.6789," + + "\"value\":{\"bool\":true,\"str\":\"foo\",\"int\":42,\"long\":123456789012345,\"double\":12345.6789}" + + "}", sw.toString()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonJsonpParserTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonJsonpParserTest.java new file mode 100644 index 000000000..bf7baef77 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonJsonpParserTest.java @@ -0,0 +1,195 @@ +/* + * 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. + */ + +package clients.rest5_client.json.jackson; + +import co.elastic.clients.elasticsearch.core.MsearchResponse; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.jackson.JacksonJsonProvider; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.testkit.ModelTestCase; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParser.Event; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; + +public class JacksonJsonpParserTest extends ModelTestCase { + + private static final String json = + "{ 'foo': 'fooValue', 'bar': { 'baz': 1}, 'quux': [true] }".replace('\'', '"'); + + @Test + public void testEventStream() { + + JacksonJsonProvider provider = new JacksonJsonProvider(); + JsonParser parser = provider.createParser(new StringReader(json)); + + assertEquals(Event.START_OBJECT, parser.next()); + + assertEquals(Event.KEY_NAME, parser.next()); + assertEquals("foo", parser.getString()); + + assertEquals(Event.VALUE_STRING, parser.next()); + assertEquals("fooValue", parser.getString()); + + // test it sometimes, but not always to detect invalid state management + assertTrue(parser.hasNext()); + + assertEquals(Event.KEY_NAME, parser.next()); + assertEquals("bar", parser.getString()); + + assertEquals(Event.START_OBJECT, parser.next()); + + assertEquals(Event.KEY_NAME, parser.next()); + assertEquals("baz", parser.getString()); + + assertTrue(parser.hasNext()); + assertEquals(Event.VALUE_NUMBER, parser.next()); + assertEquals(1, parser.getInt()); + + assertEquals(Event.END_OBJECT, parser.next()); + + assertEquals(Event.KEY_NAME, parser.next()); + assertEquals("quux", parser.getString()); + + assertEquals(Event.START_ARRAY, parser.next()); + + assertEquals(Event.VALUE_TRUE, parser.next()); + + assertEquals(Event.END_ARRAY, parser.next()); + assertEquals(Event.END_OBJECT, parser.next()); + + assertFalse(parser.hasNext()); + } + + @Test + public void testForbidValueGettersAfterHasNext() { + + JacksonJsonProvider provider = new JacksonJsonProvider(); + JsonParser parser = provider.createParser(new StringReader(json)); + + assertEquals(Event.START_OBJECT, parser.next()); + assertEquals(Event.KEY_NAME, parser.next()); + assertEquals(Event.VALUE_STRING, parser.next()); + assertEquals("fooValue", parser.getString()); + + assertTrue(parser.hasNext()); + + try { + assertEquals("fooValue", parser.getString()); + fail(); + } catch (IllegalStateException e) { + // expected + } + } + + @Test + void testMultiSearchResponse() { + String json = + "{\n" + + " \"took\" : 1,\n" + + " \"responses\" : [\n" + + " {\n" + + " \"error\" : {\n" + + " \"root_cause\" : [\n" + + " {\n" + + " \"type\" : \"index_not_found_exception\",\n" + + " \"reason\" : \"no such index [foo_bar]\",\n" + + " \"resource.type\" : \"index_or_alias\",\n" + + " \"resource.id\" : \"foo_bar\",\n" + + " \"index_uuid\" : \"_na_\",\n" + + " \"index\" : \"foo_bar\"\n" + + " }\n" + + " ],\n" + + " \"type\" : \"index_not_found_exception\",\n" + + " \"reason\" : \"no such index [foo_bar]\",\n" + + " \"resource.type\" : \"index_or_alias\",\n" + + " \"resource.id\" : \"foo_bar\",\n" + + " \"index_uuid\" : \"_na_\",\n" + + " \"index\" : \"foo_bar\"\n" + + " },\n" + + " \"status\" : 404\n" + + " },\n" + + " {\n" + + " \"took\" : 1,\n" + + " \"timed_out\" : false,\n" + + " \"_shards\" : {\n" + + " \"total\" : 1,\n" + + " \"successful\" : 1,\n" + + " \"skipped\" : 0,\n" + + " \"failed\" : 0\n" + + " },\n" + + " \"hits\" : {\n" + + " \"total\" : {\n" + + " \"value\" : 5,\n" + + " \"relation\" : \"eq\"\n" + + " },\n" + + " \"max_score\" : 1.0,\n" + + " \"hits\" : [\n" + + " {\n" + + " \"_index\" : \"foo\",\n" + + " \"_id\" : \"Wr0ApoEBa_iiaABtVM57\",\n" + + " \"_score\" : 1.0,\n" + + " \"_source\" : {\n" + + " \"x\" : 1,\n" + + " \"y\" : true\n" + + " }\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"status\" : 200\n" + + " }\n" + + " ]\n" + + "}\n"; + + JsonpMapper mapper = new JacksonJsonpMapper(); + mapper = mapper.withAttribute("co.elastic.clients:Deserializer:_global.msearch.Response.TDocument", + JsonpDeserializer.of(Foo.class)); + @SuppressWarnings("unchecked") + MsearchResponse response = fromJson(json, MsearchResponse.class, mapper); + + assertEquals(2, response.responses().size()); + assertEquals(404, response.responses().get(0).failure().status()); + assertEquals(200, response.responses().get(1).result().status()); + } + + public static class Foo { + private int x; + private boolean y; + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public boolean isY() { + return y; + } + + public void setY(boolean y) { + this.y = y; + } + } + +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonMapperTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonMapperTest.java new file mode 100644 index 000000000..ee7b46e88 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonMapperTest.java @@ -0,0 +1,103 @@ +/* + * 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. + */ + +package clients.rest5_client.json.jackson; + +import co.elastic.clients.elasticsearch.core.search.Hit; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +public class JacksonMapperTest extends ModelTestCase { + + @Test + public void testCustomDeserializer() { + // See https://github.com/elastic/elasticsearch-java/issues/120 + JsonpMapper jsonpMapper = new JacksonJsonpMapper(); + + String json = "{\"_index\":\"foo\",\"_id\":\"1\",\"_source\":{\"model\":\"Foo\",\"age\":42}}"; + + Hit testDataHit = fromJson(json, + Hit.createHitDeserializer(JsonpDeserializer.of(TestData.class)), + jsonpMapper + ); + TestData data = testDataHit.source(); + assertEquals("Foo", data.theModel); + assertEquals(42, data.theAge); + } + + @JsonDeserialize(using = TestData.TestDeserializer.class) + public static class TestData { + public String theModel; + public int theAge; + + public static class TestDeserializer extends JsonDeserializer { + + @Override + public TestData deserialize(JsonParser jp, DeserializationContext ctx) throws IOException { + JsonNode node = jp.getCodec().readTree(jp); + + TestData res = new TestData(); + if (node.has("age")) { + res.theAge = node.get("age").asInt(); + } + if (node.has("model")) { + res.theModel = node.get("model").asText(); + } + return res; + } + } + } + + @Test + public void testSingleValueAsList() { + JsonpMapper jsonpMapper = new JacksonJsonpMapper(); + + String json = "{\"_index\":\"foo\",\"_id\":\"1\",\"_source\":{\"emp_no\":42,\"job_positions\":\"SWE\"}}"; + + Hit testDataHit = fromJson(json, + Hit.createHitDeserializer(JsonpDeserializer.of(EmpData.class)), + jsonpMapper + ); + EmpData data = testDataHit.source(); + assertEquals(42, data.empNo); + assertEquals(Collections.singletonList("SWE"), data.jobPositions); + } + + @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) + @JsonIgnoreProperties(ignoreUnknown = true) + public static class EmpData { + public int empNo; + public List jobPositions; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JsonEnumTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JsonEnumTest.java new file mode 100644 index 000000000..4b4db97f1 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JsonEnumTest.java @@ -0,0 +1,56 @@ +/* + * 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. + */ + +package clients.rest5_client.json.jackson; + +import co.elastic.clients.elasticsearch._types.query_dsl.SimpleQueryStringFlag; +import co.elastic.clients.elasticsearch._types.query_dsl.SimpleQueryStringQuery; +import co.elastic.clients.testkit.ModelTestCase; +import org.junit.jupiter.api.Test; + +public class JsonEnumTest extends ModelTestCase { + + @Test + public void testPipeSeparatedEnum() { + { + // Empty flags + String jsonNoFlags = "{\"query\":\"foo\"}"; + SimpleQueryStringQuery q = SimpleQueryStringQuery.of(b -> b + .query("foo") + ); + q = checkJsonRoundtrip(q, jsonNoFlags); + assertEquals("foo", q.query()); + assertTrue(q.flags().isEmpty()); + } + + { + // With flags + String jsonWithFlags = "{\"flags\":\"AND|NEAR\",\"query\":\"foo\"}"; + SimpleQueryStringQuery q = SimpleQueryStringQuery.of(b -> b + .query("foo") + .flags(SimpleQueryStringFlag.And, SimpleQueryStringFlag.Near) + ); + q = checkJsonRoundtrip(q, jsonWithFlags); + assertEquals("foo", q.query()); + assertEquals(2, q.flags().size()); + assertEquals(SimpleQueryStringFlag.And, q.flags().get(0)); + assertEquals(SimpleQueryStringFlag.Near, q.flags().get(1)); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JsonValueParserTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JsonValueParserTest.java new file mode 100644 index 000000000..936bf9091 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JsonValueParserTest.java @@ -0,0 +1,79 @@ +/* + * 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. + */ + +package clients.rest5_client.json.jackson; + +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import jakarta.json.JsonObject; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonParser; + +import java.io.StringReader; +import java.util.Map; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class JsonValueParserTest extends Assertions { + + public static class Data { + public Map data; + } + + @Test + public void testFloatsShouldDeserializeAsFloats() throws Exception { + // When using Jackson to target a map of objects, values with a decimal separator + // should deserialize as a double even if they fit in an int or long. + // See https://github.com/elastic/elasticsearch-java/issues/156 + + String json = "{\"data\": {\"value\": 1.4778125E7, \"value2\": 1.4778125E7 }}"; + JsonpMapper mapper = new JacksonJsonpMapper(); + + { + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + Data data = mapper.deserialize(parser, Data.class); + + Double d = (Double)data.data.get("value"); + assertEquals(1.4778125E7, d, 0.001); + } + + { + // Test with buffering used in union resolution + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + parser.next(); + JsonObject object = parser.getObject(); + + // Test equals/hashcode + JsonValue v = object.getJsonObject("data").get("value"); + JsonValue v2 = object.getJsonObject("data").get("value2"); + + assertEquals(v.hashCode(), v2.hashCode()); + assertEquals(v, v2); + + parser = JsonpUtils.jsonValueParser(object, mapper); + Data data = mapper.deserialize(parser, Data.class); + + Double d = (Double)data.data.get("value"); + assertEquals(1.4778125E7, d, 0.001); + } + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/testkit/MockHttpClient.java b/java-client/src/test/java/co/elastic/clients/rest5_client/testkit/MockHttpClient.java new file mode 100644 index 000000000..7b22abaa6 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/testkit/MockHttpClient.java @@ -0,0 +1,157 @@ +/* + * 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. + */ + +package clients.rest5_client.testkit; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.transport.ElasticsearchTransportBase; +import co.elastic.clients.transport.TransportException; +import co.elastic.clients.transport.TransportOptions; +import co.elastic.clients.transport.http.TransportHttpClient; +import co.elastic.clients.util.BinaryData; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; + +public class MockHttpClient implements TransportHttpClient { + + private static final Response NotFound = new MockResponse(404, null); + + Map responses = new ConcurrentHashMap<>(); + + public MockHttpClient add(String path, String contentType, byte[] data) { + responses.put(path, new MockResponse(200, BinaryData.of(data, contentType))); + return this; + } + + public MockHttpClient add(String path, String contentType, String text) { + responses.put(path, new MockResponse(200, BinaryData.of(text.getBytes(StandardCharsets.UTF_8), contentType))); + return this; + } + + public ElasticsearchClient client() { + return client(new ModelTestCase() {}.mapper); + } + + public ElasticsearchClient client(JsonpMapper mapper) { + return new ElasticsearchClient(new ElasticsearchTransportBase(this, null, mapper) { + @Override + public void close() throws IOException { + super.close(); + } + }); + } + + + @Override + public Response performRequest( + String endpointId, @Nullable TransportHttpClient.Node node, Request request, TransportOptions option + ) throws IOException { + Response response = responses.get(request.path()); + + if (response == null) { + throw new TransportException(NotFound, "Not found", endpointId); + } + + return response; + } + + @Override + public CompletableFuture performRequestAsync( + String endpointId, @Nullable TransportHttpClient.Node node, Request request, TransportOptions options + ) { + CompletableFuture result = new CompletableFuture<>(); + try { + Response response = performRequest(endpointId, node, request, options); + result.complete(response); + } catch (Exception e) { + result.completeExceptionally(e); + } + return result; + } + + @Override + public void close() throws IOException { + } + + private static class MockResponse implements Response { + + private final int statusCode; + private final BinaryData body; + private final Map headers; + + MockResponse(int statusCode, BinaryData body) { + this.statusCode = statusCode; + this.headers = new HashMap<>(); + this.body = body; + + if (body != null) { + headers.put("content-type", body.contentType()); + } + headers.put("x-elastic-product", "Elasticsearch"); + } + + @Override + public Node node() { + return null; + } + + @Override + public int statusCode() { + return statusCode; + } + + @Nullable + @Override + public String header(String name) { + return headers.get(name.toLowerCase()); + } + + @Override + public List headers(String name) { + String header = header(name); + return header == null ? null : Collections.singletonList(header); + } + + @Nullable + @Override + public BinaryData body() throws IOException { + return body; + } + + @Nullable + @Override + public Object originalResponse() { + return null; + } + + @Override + public void close() throws IOException { + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/testkit/ModelTestCase.java b/java-client/src/test/java/co/elastic/clients/rest5_client/testkit/ModelTestCase.java new file mode 100644 index 000000000..7ea2f9deb --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/testkit/ModelTestCase.java @@ -0,0 +1,151 @@ +/* + * 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. + */ + +package clients.rest5_client.testkit; + +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.SimpleJsonpMapper; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import org.junit.jupiter.api.Assertions; + +import java.io.StringReader; +import java.io.StringWriter; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.EnumSet; +import java.util.Random; + +/** + * Base class for tests that encode/decode json + */ +public abstract class ModelTestCase extends Assertions { + + protected enum JsonImpl { Jsonb, Jackson, Simple }; + + // Same value for all tests in a test run + private static final int RAND = new Random().nextInt(100); + + protected final JsonImpl jsonImpl; + protected final JsonpMapper mapper; + + private static JsonImpl chooseJsonImpl(EnumSet jsonImplCandidates, int rand) { + // Converting an EnumSet to an array always uses the same order. + return jsonImplCandidates.toArray(new JsonImpl[jsonImplCandidates.size()])[rand % jsonImplCandidates.size()]; + } + + private static JsonpMapper createMapper(JsonImpl jsonImpl, int rand) { + switch(jsonImpl) { + case Jsonb: + System.out.println("Using a JsonB mapper (rand = " + rand + ")."); + return new JsonbJsonpMapper(); + + case Jackson: + System.out.println("Using a Jackson mapper (rand = " + rand + ")."); + return new JacksonJsonpMapper(); + + default: + System.out.println("Using a simple mapper (rand = " + rand + ")."); + return SimpleJsonpMapper.INSTANCE; + } + } + + protected ModelTestCase(EnumSet jsonImplCandidates, int rand) { + jsonImpl = chooseJsonImpl(jsonImplCandidates, rand); + mapper = createMapper(jsonImpl, rand); + } + + protected ModelTestCase(EnumSet jsonImplCandidates) { + this(jsonImplCandidates, RAND); + } + + protected ModelTestCase(JsonImpl jsonImpl) { + this(EnumSet.of(jsonImpl), RAND); + } + + protected ModelTestCase(int rand) { + this(EnumSet.allOf(JsonImpl.class), rand); + } + + protected ModelTestCase() { + this(EnumSet.allOf(JsonImpl.class), RAND); + } + + protected String toJson(T value) { + return toJson(value, mapper); + } + + public static String toJson(T value, JsonpMapper mapper) { + StringWriter sw = new StringWriter(); + JsonProvider provider = mapper.jsonProvider(); + JsonGenerator generator = provider.createGenerator(sw); + mapper.serialize(value, generator); + generator.close(); + return sw.toString(); + } + + public static T fromJson(String json, Class clazz, JsonpMapper mapper) { + return fromJson(json, (Type)clazz, mapper); + } + + public static T fromJson(String json, Type type, JsonpMapper mapper) { + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + return mapper.deserialize(parser, type); + } + + protected T fromJson(String json, Class clazz) { + return fromJson(json, clazz, mapper); + } + + protected T fromJson(String json, Type type) { + return fromJson(json, type, mapper); + } + + @SuppressWarnings("unchecked") + protected T checkJsonRoundtrip(T value, String expectedJson) { + assertEquals(expectedJson, toJson(value)); + return fromJson(expectedJson, (Class)value.getClass()); + } + + protected T fromJson(String json, JsonpDeserializer deserializer) { + return fromJson(json, deserializer, mapper); + } + + protected T fromJson(String json, JsonpDeserializer deserializer, JsonpMapper mapper) { + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + return deserializer.deserialize(parser, mapper); + } + + + public static void assertGetterType(Class expected, Class clazz, String name) { + Method method; + try { + method = clazz.getMethod(name); + } catch (NoSuchMethodException e) { + fail("Getter '" + clazz.getName() + "." + name + "' doesn't exist"); + return; + } + + assertSame(expected, method.getReturnType()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/RequestOptionsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/RequestOptionsTest.java new file mode 100644 index 000000000..be80b949f --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/RequestOptionsTest.java @@ -0,0 +1,164 @@ +/* + * 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. + */ + +package clients.rest5_client.transport; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import co.elastic.clients.transport.TransportException; +import co.elastic.clients.transport.Version; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import com.sun.net.httpserver.HttpServer; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.NameValuePair; +import org.apache.hc.core5.net.URLEncodedUtils; +import org.elasticsearch.client.ResponseException; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; + +public class RequestOptionsTest extends Assertions { + + private static HttpServer httpServer; + private static RestClient restClient; + + @BeforeEach + public void classSetup() throws IOException { + + httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + httpServer.createContext("/", ex -> { + if (ex.getRequestMethod().equals("HEAD")) { + // Call to ping() + ex.sendResponseHeaders(200, -1); + } + + // Call to info() + // Send back all request headers with a 501 that will cause an exception where we can access the LLRC response + ex.getResponseHeaders().putAll(ex.getRequestHeaders()); + ex.sendResponseHeaders(501, 0); + OutputStreamWriter out = new OutputStreamWriter(ex.getResponseBody(), StandardCharsets.UTF_8); + for (Map.Entry> header: ex.getRequestHeaders().entrySet()) { + out.write("header-"); + out.write(header.getKey().toLowerCase(Locale.ROOT)); + out.write("="); + out.write(header.getValue().get(0)); + out.write("\n"); + } + final List params = URLEncodedUtils.parse(ex.getRequestURI(), StandardCharsets.UTF_8); + for (NameValuePair param: params) { + out.write("param-"); + out.write(param.getName()); + out.write("="); + out.write(param.getValue()); + } + out.close(); + }); + + httpServer.start(); + restClient = RestClient.builder(new HttpHost("http",httpServer.getAddress().getHostString(), + httpServer.getAddress().getPort())).build(); + } + + @AfterEach + public void classTearDown() throws IOException { + httpServer.stop(0); + restClient.close(); + } + + private Properties getProps(ElasticsearchClient client) throws IOException { + ResponseException ex = assertThrows(ResponseException.class, client::info); + assertEquals(501, ex.getResponse().getStatusCode()); + Properties result = new Properties(); + result.load(ex.getResponse().getEntity().getContent()); + return result; + } + + @Test + public void testNonNullClientOptions() { + final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); + final ElasticsearchClient client = new ElasticsearchClient(trsp); + + assertNotNull(client._transportOptions()); + assertSame(trsp.options(), client._transportOptions()); + } + + @Test + public void testDefaultHeaders() throws IOException { + final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); + final ElasticsearchClient client = new ElasticsearchClient(trsp); + + Properties props = getProps(client); + + assertTrue(props.getProperty("header-user-agent").startsWith("elastic-java/" + Version.VERSION.toString())); + assertTrue(props.getProperty("header-x-elastic-client-meta").contains("es=")); + assertTrue(props.getProperty("header-x-elastic-client-meta").contains("hl=2")); + assertEquals( + "application/vnd.elasticsearch+json; compatible-with=" + Version.VERSION.major(), + props.getProperty("header-accept") + ); + } + + @Test + public void testClientHeader() throws IOException { + final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); + final ElasticsearchClient client = new ElasticsearchClient(trsp) + .withTransportOptions(b -> b + .addHeader("X-Foo", "Bar") + .addHeader("uSer-agEnt", "MegaClient/1.2.3") + ); + + Properties props = getProps(client); + assertEquals("Bar", props.getProperty("header-x-foo")); + assertEquals("MegaClient/1.2.3", props.getProperty("header-user-agent")); + } + + @Test + public void testQueryParameter() throws IOException { + final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); + final ElasticsearchClient client = new ElasticsearchClient(trsp) + .withTransportOptions(trsp.options().with( + b -> b.setParameter("format", "pretty") + ) + ); + + Properties props = getProps(client); + assertEquals("pretty", props.getProperty("param-format")); + } + + @Test + public void testMissingProductHeader() { + final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); + final ElasticsearchClient client = new ElasticsearchClient(trsp); + + final TransportException ex = assertThrows(TransportException.class, client::ping); + assertTrue(ex.getMessage().contains("Missing [X-Elastic-Product] header")); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportTest.java new file mode 100644 index 000000000..249b698de --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportTest.java @@ -0,0 +1,159 @@ +/* + * 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. + */ + +package clients.rest5_client.transport; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.TransportException; +import co.elastic.clients.transport.http.RepeatableBodyResponse; +import co.elastic.clients.transport.http.TransportHttpClient; +import co.elastic.clients.transport.rest_client.RestClientOptions; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.util.BinaryData; +import com.sun.net.httpserver.HttpServer; +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.Collections; + +import static co.elastic.clients.util.ContentType.APPLICATION_JSON; + +public class TransportTest extends Assertions { + + @Test + public void testXMLResponse() throws Exception { + HttpServer httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), + 0), 0); + + httpServer.createContext("/_cat/indices", exchange -> { + exchange.sendResponseHeaders(401, 0); + OutputStream out = exchange.getResponseBody(); + out.write( + "Error".getBytes(StandardCharsets.UTF_8) + ); + out.close(); + }); + + httpServer.start(); + InetSocketAddress address = httpServer.getAddress(); + + RestClient restClient = RestClient + .builder(new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort())) + .build(); + + ElasticsearchClient esClient = new ElasticsearchClient(new RestClientTransport(restClient, + new JacksonJsonpMapper())); + + TransportException ex = Assertions.assertThrows( + TransportException.class, + () -> esClient.cat().indices() + ); + + httpServer.stop(0); + + assertEquals(401, ex.statusCode()); + assertEquals("es/cat.indices", ex.endpointId()); + + // Original response is transport-dependent + Response restClientResponse = (Response) ex.response().originalResponse(); + assertEquals(401, restClientResponse.getStatusCode()); + } + + + @Test + public void testOriginalJsonBodyRetrievalException() throws Exception { + HttpServer httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), + 0), 0); + + httpServer.createContext("/_cat/indices", exchange -> { + exchange.getResponseHeaders().put("Content-Type", Collections.singletonList(APPLICATION_JSON)); + exchange.getResponseHeaders().put("X-Elastic-Product", Collections.singletonList("Elasticsearch" + )); + exchange.sendResponseHeaders(200, 0); + OutputStream out = exchange.getResponseBody(); + out.write( + "definitely not json".getBytes(StandardCharsets.UTF_8) + ); + out.close(); + }); + + httpServer.start(); + + RestClient restClient = RestClient + .builder(new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort())) + .build(); + + // no transport options, response is not RepeatableBodyResponse, original body cannot be retrieved + ElasticsearchClient esClient = new ElasticsearchClient(new RestClientTransport(restClient, + new JacksonJsonpMapper())); + + TransportException ex = Assertions.assertThrows( + TransportException.class, + () -> esClient.cat().indices() + ); + + assertEquals(200, ex.statusCode()); + assertNotEquals(RepeatableBodyResponse.class, ex.response().getClass()); + + // setting transport option + RestClientOptions options = new RestClientOptions(RequestOptions.DEFAULT, true); + + ElasticsearchTransport transport = new RestClientTransport( + restClient, new JacksonJsonpMapper(), options); + + ElasticsearchClient esClientOptions = new ElasticsearchClient(transport); + + ex = Assertions.assertThrows( + TransportException.class, + () -> esClientOptions.cat().indices() + ); + + httpServer.stop(0); + + assertEquals(200, ex.statusCode()); + //TODO apparently the new byteentity is always repeatable + // no need for the whole RepeatableBodyResponse if true? + //assertEquals(RepeatableBodyResponse.class, ex.response().getClass()); + + try (TransportHttpClient.Response repeatableResponse = ex.response()){ + BinaryData body = repeatableResponse.body(); + StringBuilder sb = new StringBuilder(); + BufferedReader br = new BufferedReader(new InputStreamReader(body.asInputStream())); + String read; + + while ((read = br.readLine()) != null) { + sb.append(read); + } + br.close(); + assertEquals("definitely not json",sb.toString()); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportUtilsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportUtilsTest.java new file mode 100644 index 000000000..2ae0700f7 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportUtilsTest.java @@ -0,0 +1,121 @@ +/* + * 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. + */ + +package clients.rest5_client.transport; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.ElasticsearchTestServer; +import co.elastic.clients.json.SimpleJsonpMapper; +import co.elastic.clients.transport.TransportUtils; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.message.BasicHeader; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.testcontainers.elasticsearch.ElasticsearchContainer; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.util.Base64; +import java.util.Optional; + +public class TransportUtilsTest extends Assertions { + + @Test + public void testNoSslContext() { + assertThrows( + SSLHandshakeException.class, + () -> checkConnection(null) + ); + } + + @Test + public void testCaCertificate() throws Exception { + byte[] cert = ElasticsearchTestServer.global().container().caCertAsBytes().get(); + + checkConnection( + TransportUtils.sslContextFromHttpCaCrt(new ByteArrayInputStream(cert)) + ); + } + + @Test void testCaFingerprint() throws Exception { + byte[] pemCert = ElasticsearchTestServer.global().container().caCertAsBytes().get(); + + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + Certificate x509cert = cf.generateCertificate(new ByteArrayInputStream(pemCert)); + + // Compute SHA-256 fingerprint, which is what ES outputs at start time + String fingerprint = fingerprint(x509cert.getEncoded(), "SHA-256"); + + checkConnection( + TransportUtils.sslContextFromCaFingerprint(fingerprint) + ); + } + + @Test void testInvalidFingerprint() throws Exception { + // Build a dummy SHA-256 signature + String fingerprint = fingerprint("foobar".getBytes(StandardCharsets.UTF_8), "SHA-256"); + + assertThrows( + SSLHandshakeException.class, + () -> checkConnection( + TransportUtils.sslContextFromCaFingerprint(fingerprint) + ) + ); + } + + private void checkConnection(SSLContext sslContext) throws Exception { + ElasticsearchContainer container = ElasticsearchTestServer.global().container(); + + var creds = Base64.getEncoder().encodeToString("elastic:changeme".getBytes()); + + RestClient restClient = RestClient.builder(new HttpHost("https", "localhost", + container.getMappedPort(9200))) + .setSslContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())) + .setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Basic " + creds) + }).build(); + + RestClientTransport transport = new RestClientTransport(restClient, SimpleJsonpMapper.INSTANCE); + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + assertNotNull(esClient.info()); + } + + private String fingerprint(byte[] bytes, String algorithm) throws Exception { + byte[] fingerprint; + MessageDigest md = MessageDigest.getInstance(algorithm); + md.update(bytes); + fingerprint = md.digest(); + + StringBuilder sb = new StringBuilder(fingerprint.length * 2); + for(byte b: fingerprint) { + sb.append(String.format("%02x", b)); + } + + return sb.toString(); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/VersionInfoTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/VersionInfoTest.java new file mode 100644 index 000000000..83aecaa4f --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/VersionInfoTest.java @@ -0,0 +1,34 @@ +/* + * 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. + */ + +package clients.rest5_client.transport; + +import co.elastic.clients.transport.ElasticsearchTransportBase; +import co.elastic.clients.transport.VersionInfo; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class VersionInfoTest { + + @Test + public void testClientMeta() { + String version = VersionInfo.VERSION; + Assertions.assertTrue(ElasticsearchTransportBase.getClientMeta().startsWith("es=" + version + ",jv=")); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BinaryEndpointTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BinaryEndpointTest.java new file mode 100644 index 000000000..90c65f540 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BinaryEndpointTest.java @@ -0,0 +1,130 @@ +/* + * 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. + */ + +package clients.rest5_client.transport.endpoints; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.ElasticsearchTestServer; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.json.SimpleJsonpMapper; +import co.elastic.clients.transport.TransportOptions; +import co.elastic.clients.transport.endpoints.BinaryEndpoint; +import co.elastic.clients.transport.endpoints.BinaryResponse; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import com.sun.net.httpserver.HttpServer; +import org.apache.commons.io.IOUtils; +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; + +public class BinaryEndpointTest extends Assertions { + + /** Collected headers by test name */ + private static HttpServer httpServer; + + @BeforeAll + public static void setup() throws IOException { + httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + + // Register a handler on the core.exists("capture-handler/{name}") endpoint that will capture request headers. + httpServer.createContext("/foo/_mvt/bar/1/0/0", exchange -> { + // Reply with an empty 200 response + exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); + exchange.getResponseHeaders().set("Content-Type", "application/vnd.hello-world"); + exchange.sendResponseHeaders(200, 0); + exchange.getResponseBody().write("Hello world".getBytes(StandardCharsets.UTF_8)); + exchange.close(); + }); + + httpServer.start(); + } + + @AfterAll + public static void cleanup() { + httpServer.stop(0); + httpServer = null; + } + + @Test + public void testMvtSearch() throws IOException { + RestClient llrc = RestClient.builder( + new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) + ).build(); + + RestClientTransport transport = new RestClientTransport(llrc, new SimpleJsonpMapper()); + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + BinaryResponse resp = esClient.searchMvt(s -> s + .index("foo") + .field("bar") + .x(0) + .y(0) + .zoom(1) + ); + + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[256]; + + try(InputStream input = resp.content()) { + int len; + while ((len = input.read(buffer)) > 0) { + baos.write(buffer, 0, len); + } + } + + assertEquals("application/vnd.hello-world", resp.contentType()); + assertEquals("Hello world", baos.toString(StandardCharsets.UTF_8.name())); + } + + @Test + public void convertJsonToBinaryEndpoint() throws IOException { + + ElasticsearchClient esClient = ElasticsearchTestServer.global().client(); + + // Create the search request + SearchRequest request = SearchRequest.of(b -> b); + + // Create a binary endpoint from the regular search endpoint. It will not deserialize + // the response and instead will just return the raw response input stream. + BinaryEndpoint binarySearchEndpoint = SearchRequest._ENDPOINT.withBinaryResponse(); + + // Force typed_keys to false, so that aggregations names do not hold type information + TransportOptions options = esClient._transportOptions().toBuilder() + .setParameter("typed_keys", "false") + .build(); + + // Call Elasticsearch by providing the transport the request and endpoint + BinaryResponse binaryResponse = esClient._transport().performRequest(request, binarySearchEndpoint, options); + + // Do something with the response + String response = IOUtils.toString(binaryResponse.content(), StandardCharsets.UTF_8); + assertTrue(response.matches("\\{\"took\":\\d+,\"timed_out\":false.*")); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BooleanEndpointTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BooleanEndpointTest.java new file mode 100644 index 000000000..e2e95a5c9 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BooleanEndpointTest.java @@ -0,0 +1,37 @@ +/* + * 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. + */ + +package clients.rest5_client.transport.endpoints; + +import co.elastic.clients.elasticsearch.core.ExistsRequest; +import co.elastic.clients.elasticsearch.security.SamlCompleteLogoutRequest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class BooleanEndpointTest extends Assertions { + + @Test + public void testHasRequestBody() { + ExistsRequest er = ExistsRequest.of(r -> r.index("foo").id("1")); + assertNull(ExistsRequest._ENDPOINT.body(er)); + + SamlCompleteLogoutRequest sclr = SamlCompleteLogoutRequest.of(r -> r.ids("1").realm("r")); + assertNotNull(SamlCompleteLogoutRequest._ENDPOINT.body(sclr)); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/EndpointBaseTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/EndpointBaseTest.java new file mode 100644 index 000000000..2bd5db313 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/EndpointBaseTest.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package clients.rest5_client.transport.endpoints; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch.core.PingRequest; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.endpoints.BooleanResponse; +import co.elastic.clients.transport.endpoints.EndpointBase; +import org.junit.jupiter.api.Test; + +public class EndpointBaseTest extends ModelTestCase { + + @Test + public void testPathEncoding() { + assertEquals("abCD12;-_*", pathEncode("abCD12;-_*")); + assertEquals("XYZ%5B", pathEncode("XYZ[")); + assertEquals("xyz%7B", pathEncode("xyz{")); + assertEquals("foo%2Fbar", pathEncode("foo/bar")); + assertEquals("foo%20bar", pathEncode("foo bar")); + assertEquals("f%C3%AAl%C3%A9", pathEncode("fêlé")); + } + + private String pathEncode(String s) { + StringBuilder sb = new StringBuilder(); + EndpointBase.pathEncode(s, sb); + return sb.toString(); + } + + @Test + public void testErrorDecoding() { + Endpoint endpoint = PingRequest._ENDPOINT; + + { + String json = "{\"error\":\"some error\"}"; + + ErrorResponse response = fromJson(json, endpoint.errorDeserializer(404)); + assertEquals(404, response.status()); + assertEquals("some error", response.error().reason()); + assertEquals("http_status_404", response.error().type()); + } + + { + String json = "{\"status\":401,\"error\":{\"type\":\"the_error_type\",\"reason\":\"some error\"}}"; + + ErrorResponse response = fromJson(json, endpoint.errorDeserializer(404)); + assertEquals(401, response.status()); // value in response body has precedence + assertEquals("some error", response.error().reason()); + assertEquals("the_error_type", response.error().type()); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/SimpleEndpointTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/SimpleEndpointTest.java new file mode 100644 index 000000000..f6ee72e0e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/SimpleEndpointTest.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package clients.rest5_client.transport.endpoints; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.core.CountResponse; +import co.elastic.clients.testkit.MockHttpClient; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.ElasticsearchTransportBase; +import co.elastic.clients.transport.TransportOptions; +import co.elastic.clients.transport.http.TransportHttpClient; +import org.jetbrains.annotations.Nullable; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class SimpleEndpointTest extends ModelTestCase { + + @Test + public void testNoBodyForEmptyObject() throws Exception { + + List requests = new ArrayList<>(); + + MockHttpClient httpClient = new MockHttpClient() { + @Override + public Response performRequest( + String endpointId, @Nullable Node node, Request request, TransportOptions option + ) throws IOException { + requests.add(request); + return super.performRequest(endpointId, node, request, option); + } + }; + + httpClient.add("/_count", "application/json", toJson( + CountResponse.of(c -> c + .count(1) + .shards(s -> s.successful(1).failed(0).total(1)) + ))); + + ElasticsearchTransport transport = new ElasticsearchTransportBase(httpClient, null, mapper) {}; + ElasticsearchClient client = new ElasticsearchClient(transport, null); + + client.count(); + client.count(c -> c.q("foo:bar")); + client.count(c -> c.query(q -> q.term(t -> t.field("foo").value("bar")))); + + assertNull(requests.get(0).body()); + assertNull(requests.get(1).body()); + assertNotNull(requests.get(2).body()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/http/HeaderMapTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/http/HeaderMapTest.java new file mode 100644 index 000000000..df898203c --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/http/HeaderMapTest.java @@ -0,0 +1,79 @@ +/* + * 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. + */ + +package clients.rest5_client.transport.http; + +import co.elastic.clients.transport.http.HeaderMap; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Iterator; +import java.util.Map; + +class HeaderMapTest extends Assertions { + + @Test + public void testCaseSensitivity() { + HeaderMap headers = new HeaderMap(); + + headers.put("Foo", "bar"); + assertEquals("bar", headers.get("Foo")); + assertEquals("bar", headers.get("foo")); + assertEquals("bar", headers.get("fOO")); + + headers.put("foo", "baz"); + assertEquals("baz", headers.get("Foo")); + assertEquals("baz", headers.get("foo")); + assertEquals("baz", headers.get("fOO")); + } + + @Test + public void testLock() { + HeaderMap headers = new HeaderMap(); + + headers.put("foo", "bar"); + + HeaderMap locked = headers.locked(); + assertEquals("bar", headers.get("Foo")); + + assertThrows(UnsupportedOperationException.class, () -> { + locked.put("foo", "baz"); + }); + + assertThrows(UnsupportedOperationException.class, () -> { + Iterator> iterator = locked.entrySet().iterator(); + assertEquals("bar", iterator.next().getValue()); + iterator.remove(); + }); + + headers.put("foo", "baz"); + assertEquals("baz", headers.get("Foo")); + assertEquals("bar", locked.get("Foo")); + } + + @Test + public void testAdd() { + HeaderMap headers = new HeaderMap(); + + headers.add("Foo", "bar"); + headers.add("foo", "baz"); + + assertEquals("bar; baz", headers.get("Foo")); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/instrumentation/OpenTelemetryForElasticsearchTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/instrumentation/OpenTelemetryForElasticsearchTest.java new file mode 100644 index 000000000..d839840e0 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/instrumentation/OpenTelemetryForElasticsearchTest.java @@ -0,0 +1,277 @@ +/* + * 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. + */ + +package clients.rest5_client.transport.instrumentation; + +import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.query_dsl.Query; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.instrumentation.Instrumentation; +import co.elastic.clients.transport.instrumentation.OpenTelemetryForElasticsearch; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import com.sun.net.httpserver.HttpServer; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class OpenTelemetryForElasticsearchTest { + private static final String INDEX = "test-index"; + private static final String DOC_ID = "1234567"; + private static final String DOC_RESPONSE = "{\n" + + " \"_index\": \"" + INDEX + "\",\n" + + " \"_id\": \"" + DOC_ID + "\",\n" + + " \"_version\": 1,\n" + + " \"_seq_no\": 0,\n" + + " \"_primary_term\": 1,\n" + + " \"found\": true,\n" + + " \"_source\": {\n" + + " \"@timestamp\": \"2099-11-15T14:12:12\",\n" + + " \"message\": \"GET /search HTTP/1.1 200 1070000\"\n" + + " }\n" + + "}"; + private static final String SEARCH_RESPONSE = "{\n" + + " \"took\": 5,\n" + + " \"timed_out\": false,\n" + + " \"_shards\": {\n" + + " \"total\": 1,\n" + + " \"successful\": 1,\n" + + " \"skipped\": 0,\n" + + " \"failed\": 0\n" + + " },\n" + + " \"hits\": {\n" + + " \"total\": {\n" + + " \"value\": 1,\n" + + " \"relation\": \"eq\"\n" + + " },\n" + + " \"max_score\": 1.3862942,\n" + + " \"hits\": [\n" + + " {\n" + + " \"_index\": \"" + INDEX + "\",\n" + + " \"_id\": \"" + DOC_ID + "\",\n" + + " \"_score\": 1.3862942,\n" + + " \"_source\": {\n" + + " \"@timestamp\": \"2099-11-15T14:12:12\",\n" + + " \"message\": \"GET /search HTTP/1.1 200 1070000\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + public static final String DB_OPERATION = "db.operation"; + public static final String URL_FULL = "url.full"; + public static final String SERVER_ADDRESS = "server.address"; + public static final String SERVER_PORT = "server.port"; + // has been renamed in 1.21 from http.method - see https://github.com/open-telemetry/semantic-conventions/blob/main/schemas/1.21.0 + public static final String HTTP_REQUEST_METHOD = "http.request.method"; + private static HttpServer httpServer; + private static MockSpanExporter spanExporter; + private static OpenTelemetry openTelemetry; + private static RestClient restClient; + private static RestClientTransport transport; + private static ElasticsearchClient client; + private static ElasticsearchAsyncClient asyncClient; + + @BeforeAll + public static void setup() throws IOException { + setupOTel(); + setupHttpServer(); + setupClient(); + } + + @AfterAll + public static void cleanUp() throws IOException { + httpServer.stop(0); + transport.close(); + } + + private static void setupClient() { + restClient = + RestClient.builder(new HttpHost(httpServer.getAddress().getAddress(), httpServer.getAddress().getPort())).build(); + + Instrumentation instrumentation = new OpenTelemetryForElasticsearch(openTelemetry, false); + + transport = new RestClientTransport(restClient, new JacksonJsonpMapper(), null, instrumentation); + + client = new ElasticsearchClient(transport); + asyncClient = new ElasticsearchAsyncClient(transport); + } + + private static void setupHttpServer() throws IOException { + httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + + // handler for GetRequest + httpServer.createContext("/" + INDEX + "/_doc/" + DOC_ID, exchange -> { + exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); + exchange.getResponseHeaders().set("Content-Type", "application/json"); + exchange.sendResponseHeaders(200, 0); + exchange.getResponseBody().write(DOC_RESPONSE.getBytes()); + exchange.close(); + }); + + // handler for SearchRequest + httpServer.createContext("/" + INDEX + "/_search", exchange -> { + exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); + exchange.getResponseHeaders().set("Content-Type", "application/json"); + exchange.sendResponseHeaders(200, 0); + exchange.getResponseBody().write(SEARCH_RESPONSE.getBytes()); + exchange.close(); + }); + + httpServer.start(); + } + + private static void setupOTel() { + Resource resource = Resource.getDefault() + .merge(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, "es-api-test"))); + + spanExporter = new MockSpanExporter(); + + SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() + .addSpanProcessor(SimpleSpanProcessor.create(spanExporter)) + .setResource(resource) + .build(); + + openTelemetry = OpenTelemetrySdk.builder() + .setTracerProvider(sdkTracerProvider) + .build(); + } + + @BeforeEach + public void reset() { + spanExporter.reset(); + } + + @Test + public void testGetRequest() throws IOException, InterruptedException { + client.get(r -> r.index(INDEX).id(DOC_ID).refresh(true), Object.class); + Assertions.assertEquals(spanExporter.getSpans().size(), 1); + SpanData span = spanExporter.getSpans().get(0); + Assertions.assertEquals("get", span.getName()); + Assertions.assertEquals("get", span.getAttributes().get(AttributeKey.stringKey(DB_OPERATION))); + Assertions.assertEquals("GET", span.getAttributes().get(AttributeKey.stringKey(HTTP_REQUEST_METHOD))); + Assertions.assertEquals("elasticsearch", span.getAttributes().get(SemanticAttributes.DB_SYSTEM)); + + String url = "http://" + httpServer.getAddress().getHostName() + ":" + httpServer.getAddress().getPort() + + "/" + INDEX + "/_doc/" + DOC_ID + "?refresh=true"; + Assertions.assertEquals(url, span.getAttributes().get(AttributeKey.stringKey(URL_FULL))); + Assertions.assertEquals(httpServer.getAddress().getHostName(), span.getAttributes().get(AttributeKey.stringKey(SERVER_ADDRESS))); + Assertions.assertEquals(httpServer.getAddress().getPort(), span.getAttributes().get(AttributeKey.longKey(SERVER_PORT))); + + // Path parts + Assertions.assertEquals(DOC_ID, span.getAttributes().get(AttributeKey.stringKey("db.elasticsearch.path_parts.id"))); + } + + @Test + public void testSearchRequest() throws IOException, InterruptedException { + // A client that will capture requests + ElasticsearchClient client = new ElasticsearchClient(new RestClientTransport( + restClient, this.client._jsonpMapper(), null, new OpenTelemetryForElasticsearch(openTelemetry, true)) + ); + SearchRequest req = SearchRequest.of(r -> r.index(INDEX).query(q -> q.term(t -> t.field("x").value("y")))); + String queryAsString = JsonpUtils.toJsonString(req, client._jsonpMapper()); + client.search(req, Object.class); + Assertions.assertEquals(spanExporter.getSpans().size(), 1); + SpanData span = spanExporter.getSpans().get(0); + Assertions.assertEquals("search", span.getName()); + Assertions.assertEquals(queryAsString, span.getAttributes().get(SemanticAttributes.DB_STATEMENT)); + } + + @Test + public void testAsyncSearchRequest() throws IOException, InterruptedException, TimeoutException, ExecutionException { + Query query = Query.of(q -> q.term(t -> t.field("x").value("y"))); + Future future = asyncClient.search(r -> r.index(INDEX).query(query), Object.class); + future.get(2, TimeUnit.SECONDS); + spanExporter.awaitNumSpans(1, 2000); + Assertions.assertEquals(spanExporter.getSpans().size(), 1); + SpanData span = spanExporter.getSpans().get(0); + Assertions.assertEquals("search", span.getName()); + + // We're not capturing bodies by default + Assertions.assertNull(span.getAttributes().get(SemanticAttributes.DB_STATEMENT)); + } + + private static class MockSpanExporter implements SpanExporter { + + private final List spans = new ArrayList(); + + @Override + public CompletableResultCode export(Collection spans) { + this.spans.addAll(spans); + synchronized (this) { + notifyAll(); + } + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode flush() { + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode shutdown() { + spans.clear(); + return CompletableResultCode.ofSuccess(); + } + + public List getSpans() { + return spans; + } + + public void reset() { + spans.clear(); + } + + public synchronized void awaitNumSpans(int num, long timeoutMillis) throws InterruptedException { + while(spans.size() < num){ + wait(timeoutMillis); + } + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/MultiBufferEntityTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/MultiBufferEntityTest.java new file mode 100644 index 000000000..5461a0c93 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/MultiBufferEntityTest.java @@ -0,0 +1,100 @@ +/* + * 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. + */ + +package clients.rest5_client.transport.rest_client; + +import co.elastic.clients.elasticsearch.core.BulkRequest; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.endpoints.BinaryResponse; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import com.sun.net.httpserver.HttpServer; +import org.apache.commons.io.IOUtils; +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; + +public class MultiBufferEntityTest { + + @Test + public void testBulkRequest() throws IOException { + + HttpServer httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + + httpServer.createContext("/_bulk", exchange -> { + exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); + byte[] bytes = IOUtils.toByteArray(exchange.getRequestBody()); + exchange.sendResponseHeaders(200, 0); + exchange.getResponseBody().write(bytes); + exchange.close(); + }); + + httpServer.start(); + + RestClient restClient = + RestClient.builder(new HttpHost(httpServer.getAddress().getAddress(), httpServer.getAddress().getPort())).build(); + + BulkRequest req = BulkRequest.of(_0 -> _0 + .operations(_1 -> _1 + .create(_2 -> _2 + .index("foo") + .id("abc") + .document("abc-doc") + )) + .operations(_1 -> _1 + .create(_2 -> _2 + .index("foo") + .id("def") + .document("def-doc") + )) + .operations(_1 -> _1 + .update(_2 -> _2 + .index("foo") + .id("gh") + .action(_3 -> _3 + .docAsUpsert(true) + .doc("gh-doc")) + ) + ) + ); + RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); + + BinaryResponse binaryResponse = transport.performRequest(req, BulkRequest._ENDPOINT.withBinaryResponse(), null); + + String str = IOUtils.toString(binaryResponse.content(), StandardCharsets.UTF_8); + + httpServer.stop(0); + transport.close(); + + Assertions.assertEquals( + "{\"create\":{\"_id\":\"abc\",\"_index\":\"foo\"}}\n" + + "\"abc-doc\"\n" + + "{\"create\":{\"_id\":\"def\",\"_index\":\"foo\"}}\n" + + "\"def-doc\"\n" + + "{\"update\":{\"_id\":\"gh\",\"_index\":\"foo\"}}\n" + + "{\"doc\":\"gh-doc\",\"doc_as_upsert\":true}\n", + str + ); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/RestClientOptionsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/RestClientOptionsTest.java new file mode 100644 index 000000000..7e835e687 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/RestClientOptionsTest.java @@ -0,0 +1,204 @@ +/* + * 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. + */ + +package clients.rest5_client.transport.rest_client; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.SimpleJsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.Version; +import co.elastic.clients.transport.endpoints.BooleanResponse; +import co.elastic.clients.transport.rest_client.RestClientOptions; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpServer; +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +class RestClientOptionsTest extends Assertions { + + /** Collected headers by test name */ + private static Map collectedHeaders; + private static final AtomicInteger testCounter = new AtomicInteger(); + private static HttpServer httpServer; + + private static final String MIME_TYPE = "application/vnd.elasticsearch+json; compatible-with=" + Version.VERSION.major(); + + @BeforeAll + public static void setup() throws IOException { + collectedHeaders = new ConcurrentHashMap<>(); + httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + + // Register a handler on the core.exists("capture-handler/{name}") endpoint that will capture request headers. + httpServer.createContext("/capture-headers/_doc/", exchange -> { + String testName = exchange.getRequestURI().getPath().substring("/capture-headers/_doc/".length()); + System.out.println(exchange.getResponseHeaders()); + System.out.println(); + collectedHeaders.put(testName, exchange.getRequestHeaders()); + + // Reply with an empty 200 response + exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); + exchange.sendResponseHeaders(200, -1); + exchange.close(); + }); + + httpServer.start(); + } + + @AfterAll + public static void cleanup() { + httpServer.stop(0); + httpServer = null; + collectedHeaders = null; + } + + private ElasticsearchTransport newRestClientTransport(RestClient restClient, JsonpMapper mapper) { + return newRestClientTransport(restClient, mapper, null); + } + + private ElasticsearchTransport newRestClientTransport(RestClient restClient, JsonpMapper mapper, RestClientOptions options) { + return new RestClientTransport(restClient, mapper, options); + //return new RestClientMonolithTransport(restClient, mapper, options); + } + + /** + * Make a server call, capture request headers and check their consistency. + * + * @return the name of the entry in collectedHeaders for further inspection. + */ + private String checkHeaders(ElasticsearchClient esClient) throws IOException { + String testName = "test-" + testCounter.incrementAndGet(); + BooleanResponse exists = esClient.exists(r -> r.index("capture-headers").id(testName)); + assertTrue(exists.value()); + + Headers headers = collectedHeaders.get(testName); + assertNotNull(headers, "No headers collected for test " + testName); + + assertNotNull(headers.get("X-elastic-client-meta"), "Missing client meta header"); + assertEquals(RestClientOptions.CLIENT_META_VALUE, headers.get("X-elastic-client-meta").get(0)); + assertNotNull(headers.get("Accept"), "Missing 'Accept' header"); + assertEquals(MIME_TYPE, headers.get("Accept").get(0)); + + for (Map.Entry> entry: headers.entrySet()) { + System.out.println(entry.getKey() + " " + entry.getValue()); + } + + return testName; + } + + private void checkUserAgent(String testName, String value) { + Headers headers = collectedHeaders.get(testName); + assertNotNull(headers, "No headers collected for test " + testName); + assertNotNull(headers.get("User-Agent"), "Missing 'User-Agent' header"); + assertEquals(value, headers.get("User-Agent").get(0)); + } + + @Test + void testNoRequestOptions() throws Exception { + RestClient llrc = RestClient.builder( + new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) + ).build(); + + ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper()); + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + String id = checkHeaders(esClient); + checkUserAgent(id, RestClientOptions.USER_AGENT_VALUE); + } + + @Test + void testTransportRequestOptions() throws Exception { + RestClient llrc = RestClient.builder( + new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) + ).build(); + + ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper(), + new RestClientOptions.Builder(RequestOptions.DEFAULT.toBuilder()).build() + ); + ElasticsearchClient esClient = new ElasticsearchClient(transport); + + String id = checkHeaders(esClient); + checkUserAgent(id, RestClientOptions.USER_AGENT_VALUE); + } + + @Test + void testClientRequestOptions() throws Exception { + RestClient llrc = RestClient.builder( + new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) + ).build(); + + ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper()); + ElasticsearchClient esClient = new ElasticsearchClient(transport).withTransportOptions( + new RestClientOptions.Builder(RequestOptions.DEFAULT.toBuilder()).build() + ); + + String id = checkHeaders(esClient); + checkUserAgent(id, RestClientOptions.USER_AGENT_VALUE); + } + + @Test + void testLambdaOptionsBuilder() throws Exception { + RestClient llrc = RestClient.builder( + new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) + ).build(); + + ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper()); + ElasticsearchClient esClient = new ElasticsearchClient(transport) + .withTransportOptions(o -> o + .addHeader("Foo", "bar") + .addHeader("x-elastic-client-meta", "foo-bar-client") + ); + + String id = checkHeaders(esClient); + checkUserAgent(id, RestClientOptions.USER_AGENT_VALUE); + } + + @Test + void testRequestOptionsOverridingBuiltin() throws Exception { + RequestOptions options = RequestOptions.DEFAULT.toBuilder() + .addHeader("user-agent", "FooBarAgent/1.0") + .addHeader("x-elastic-client-meta", "foo-bar-client") + .build(); + + RestClient llrc = RestClient.builder( + new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) + ).build(); + + ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper(), new RestClientOptions(options,false)); + ElasticsearchClient esClient = new ElasticsearchClient(transport); + // Should not override client meta + String id = checkHeaders(esClient); + // overriding user-agent is ok + checkUserAgent(id, "FooBarAgent/1.0"); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/util/DateTimeTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/util/DateTimeTest.java new file mode 100644 index 000000000..75aa4054b --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/util/DateTimeTest.java @@ -0,0 +1,140 @@ +/* + * 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. + */ + +package clients.rest5_client.util; + +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.util.DateTime; +import org.junit.jupiter.api.Test; + +import java.time.Instant; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +public class DateTimeTest extends ModelTestCase { + + long millis = 1643822172348L; + String millisJson = "1643822172348"; + + String text = "2022-02-02T17:16:12.348Z"; + String textJson = "\"" + text + "\""; + + @Test + public void testMillis() { + DateTime dateTime; + + dateTime = DateTime.ofEpochMilli(millis); + assertEquals(millis, dateTime.toInstant().toEpochMilli()); + + // Millis, no format + dateTime = checkJsonRoundtrip(DateTime.ofEpochMilli(millis), millisJson); + assertEquals(millis, dateTime.toEpochMilli()); + assertNull(dateTime.formatter); + + // Millis, roundtrip through ISO format + dateTime = checkJsonRoundtrip(DateTime.ofEpochMilli(millis, DateTimeFormatter.ISO_INSTANT), textJson); + assertEquals(millis, dateTime.toEpochMilli()); + assertNull(dateTime.formatter); + } + + @Test + public void testText() { + + DateTime dateTime; + + // Millis as string + dateTime = fromJson("\"1643822172348\"", DateTime.class); + assertEquals(millis, dateTime.toEpochMilli()); + assertNull(dateTime.formatter); + + DateTime dateTimeOrig = dateTime; + + // test STRICT_DATE_OPTIONAL_TIME_FORMATTER + dateTime = fromJson(textJson, DateTime.class); + assertEquals(text, dateTime.toString()); + + assertEquals(dateTime, dateTimeOrig); + + dateTime = fromJson("\"2022-02-27\"", DateTime.class); + assertEquals("2022-02-27T00:00:00Z", dateTime.toInstant().toString()); + + dateTime = fromJson("\"2022-02\"", DateTime.class); + assertEquals("2022-02-01T00:00:00Z", dateTime.toInstant().toString()); + + dateTime = fromJson("\"2022\"", DateTime.class); + assertEquals("2022-01-01T00:00:00Z", dateTime.toInstant().toString()); + + assertEquals("\"2022\"", toJson(dateTime)); + + } + + @Test + public void testInvalidString() { + + // Invalid values should be accepted, and an exception thrown + // only when we parse the value. + // This lazy parsing allows application code that doesn't access + // ill-formed data to not fail on deserialization. + DateTime dateTime = fromJson("\"foobar\"", DateTime.class); + assertEquals("foobar", dateTime.getString()); + + assertThrows(DateTimeParseException.class, dateTime::toInstant); + } + + @Test + public void testInstant() { + + DateTime dateTime; + + dateTime = DateTime.of(text, DateTimeFormatter.ISO_INSTANT); + assertEquals(millis, dateTime.toInstant().toEpochMilli()); + + assertEquals(millis, dateTime.toInstant(DateTimeFormatter.ISO_INSTANT).toEpochMilli()); + + Instant inst = Instant.ofEpochMilli(millis); + + dateTime = DateTime.of(inst); + assertEquals(millisJson, toJson(dateTime)); + + dateTime = DateTime.of(inst, DateTimeFormatter.ISO_DATE_TIME); + assertEquals(textJson, toJson(dateTime)); + + } + + @Test + public void testZonedDateTime() { + + DateTime dateTime; + ZonedDateTime zdt; + + // With timezone information + dateTime = fromJson("\"2022-02-02T18:16:12.348+01:00\"", DateTime.class); + assertEquals(millis, dateTime.toEpochMilli()); + + zdt = dateTime.toZonedDateTime(); + assertEquals(3600, zdt.getOffset().getTotalSeconds()); + + zdt = dateTime.toZonedDateTime(DateTimeFormatter.ISO_ZONED_DATE_TIME); + assertEquals(millis, zdt.toInstant().toEpochMilli()); + + assertEquals(millis, DateTime.of(millisJson).toZonedDateTime().toInstant().toEpochMilli()); + + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/util/DuplicateResourceFinderTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/util/DuplicateResourceFinderTest.java new file mode 100644 index 000000000..360cea822 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/util/DuplicateResourceFinderTest.java @@ -0,0 +1,41 @@ +/* + * 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. + */ + +package clients.rest5_client.util; + +import co.elastic.clients.util.DuplicateResourceFinder; +import com.fasterxml.jackson.databind.ext.CoreXMLSerializers; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class DuplicateResourceFinderTest extends Assertions { + + @Test + public void testDuplicateCheck() { + + Exception e = assertThrows(RuntimeException.class, () -> { + DuplicateResourceFinder.ensureClassUniqueness(CoreXMLSerializers.class); + }); + assertTrue(e.getMessage().contains("Several versions of")); + + // Disabling the test should not throw an exception + DuplicateResourceFinder.enableCheck(false); + DuplicateResourceFinder.ensureClassUniqueness(CoreXMLSerializers.class); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/util/NamedValueTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/util/NamedValueTest.java new file mode 100644 index 000000000..c01c62131 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/util/NamedValueTest.java @@ -0,0 +1,50 @@ +/* + * 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. + */ + +package clients.rest5_client.util; + +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.aggregations.TermsAggregation; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.util.NamedValue; +import org.junit.jupiter.api.Test; + +class NamedValueTest extends ModelTestCase { + + @Test + public void testTermAggregation() { + + String json = "{\"order\":[{\"a\":\"asc\"},{\"b\":\"desc\"}]}"; + + TermsAggregation ta = TermsAggregation.of(b -> b + .order(NamedValue.of("a", SortOrder.Asc)) + .order(NamedValue.of("b", SortOrder.Desc) + ) + ); + + ta = checkJsonRoundtrip(ta, json); + + assertEquals(2, ta.order().size()); + + assertEquals("a", ta.order().get(0).name()); + assertEquals(SortOrder.Asc, ta.order().get(0).value()); + assertEquals("b", ta.order().get(1).name()); + assertEquals(SortOrder.Desc, ta.order().get(1).value()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/util/PairTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/util/PairTest.java new file mode 100644 index 000000000..04d45879e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/util/PairTest.java @@ -0,0 +1,47 @@ +/* + * 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. + */ + +package clients.rest5_client.util; + +import co.elastic.clients.elasticsearch._types.FieldValue; +import co.elastic.clients.testkit.ModelTestCase; +import co.elastic.clients.elasticsearch.watcher.Condition; +import co.elastic.clients.elasticsearch.watcher.ConditionOp; +import co.elastic.clients.util.NamedValue; +import co.elastic.clients.util.Pair; +import org.junit.jupiter.api.Test; + +class PairTest extends ModelTestCase { + + @Test + public void testCondition() { + + String json = "{\"compare\":{\"foo\":{\"eq\":\"bar\"}}}"; + + Condition c = Condition.of(b -> b + .compare(NamedValue.of("foo", Pair.of(ConditionOp.Eq, FieldValue.of("bar")))) + ); + + c = checkJsonRoundtrip(c, json); + + assertEquals("foo", c.compare().name()); + assertEquals(ConditionOp.Eq, c.compare().value().key()); + assertEquals("bar", c.compare().value().value().stringValue()); + } +} From 894bea9800c31663acd8fab3e7b269abc5fc8555 Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Tue, 25 Mar 2025 11:39:46 +0100 Subject: [PATCH 09/38] fixing tests --- .../builders/ElasticsearchClientBuilder.java | 14 +- .../documentation/DocTestsTransport.java | 2 +- .../api_conventions/ApiConventionsTest.java | 2 +- .../api_conventions/LoadingJsonTest.java | 2 +- .../getting_started/ConnectingTest.java | 2 +- .../troubleshooting/TroubleShootingTests.java | 2 +- .../documentation/usage/AggregationsTest.java | 2 +- .../documentation/usage/IndexingBulkTest.java | 2 +- .../documentation/usage/IndexingTest.java | 2 +- .../documentation/usage/Product.java | 2 +- .../documentation/usage/ReadingTest.java | 2 +- .../documentation/usage/SearchingTest.java | 2 +- .../ElasticsearchTestServer.java | 2 +- .../_helpers/builders/ClientBuildersTest.java | 2 +- .../bulk/BulkIngesterRetryPolicyTest.java | 2 +- .../_helpers/bulk/BulkIngesterTest.java | 2 +- .../esql/EsqlAdapterEndToEndTest.java | 2 +- .../_helpers/esql/EsqlAdapterTest.java | 2 +- .../elasticsearch/end_to_end/RequestTest.java | 2 +- .../experiments/ClientTests.java | 2 +- .../experiments/ParsingTests.java | 2 +- .../experiments/UnionVariant.java | 2 +- .../elasticsearch/experiments/api/Bar.java | 2 +- .../experiments/api/DateMathTimeUnit.java | 2 +- .../experiments/api/FooOptRequest.java | 2 +- .../experiments/api/FooRequest.java | 2 +- .../experiments/api/FooResponse.java | 2 +- .../experiments/api/query2/BoolQuery.java | 2 +- .../experiments/api/query2/Query.java | 2 +- .../experiments/api/query2/QueryTest.java | 2 +- .../experiments/api/query2/TermsQuery.java | 2 +- .../experiments/api/query2/Union2.java | 2 +- .../experiments/base/Client.java | 2 +- .../experiments/base/PrimitiveUtils.java | 2 +- .../experiments/base/Variants.java | 2 +- .../experiments/containers/SomeUnion.java | 2 +- .../experiments/containers/SomeUnionTest.java | 2 +- .../containers/SomeUnionVariant.java | 2 +- .../experiments/containers/UVariantA.java | 2 +- .../experiments/containers/UVariantB.java | 2 +- .../experiments/generics/GenericClass.java | 2 +- .../inheritance/InheritanceTest.java | 2 +- .../inheritance/base/BaseClass.java | 2 +- .../inheritance/child/ChildClass.java | 2 +- .../inheritance/final_/FinalClass.java | 2 +- .../experiments/package-info.java | 2 +- .../elasticsearch/model/BehaviorsTest.java | 2 +- .../elasticsearch/model/BuiltinTypesTest.java | 2 +- .../model/ClassStructureTest.java | 2 +- .../model/CodeAdditionsTests.java | 2 +- .../elasticsearch/model/EndpointTest.java | 2 +- .../elasticsearch/model/EnumTest.java | 2 +- .../model/RequestEncodingTest.java | 2 +- .../model/SerializationTest.java | 2 +- .../elasticsearch/model/TypedKeysTest.java | 2 +- .../elasticsearch/model/UnionTests.java | 2 +- .../elasticsearch/model/VariantsTest.java | 2 +- .../elasticsearch/model/package-info.java | 2 +- .../spec_issues/SpecIssuesTest.java | 2 +- .../rest5_client/json/JsonDataTest.java | 176 ---------- .../json/JsonpDeserializerBaseTest.java | 51 --- .../json/JsonpDeserializerTest.java | 43 --- .../rest5_client/json/JsonpMapperTest.java | 210 ----------- .../json/JsonpMappingExceptionTest.java | 113 ------ .../rest5_client/json/JsonpUtilsTest.java | 332 ------------------ .../json/LazyDeserializerTest.java | 70 ---- .../json/ObjectBuilderDeserializerTest.java | 50 --- .../rest5_client/json/WithJsonTest.java | 190 ---------- .../jackson/JacksonJsonpGeneratorTest.java | 91 ----- .../json/jackson/JacksonJsonpParserTest.java | 195 ---------- .../json/jackson/JacksonMapperTest.java | 103 ------ .../json/jackson/JsonEnumTest.java | 56 --- .../json/jackson/JsonValueParserTest.java | 79 ----- .../rest5_client/testkit/MockHttpClient.java | 157 --------- .../rest5_client/testkit/ModelTestCase.java | 151 -------- .../transport/RequestOptionsTest.java | 2 +- .../rest5_client/transport/TransportTest.java | 2 +- .../transport/TransportUtilsTest.java | 8 +- .../transport/VersionInfoTest.java | 34 -- .../endpoints/BinaryEndpointTest.java | 2 +- .../endpoints/BooleanEndpointTest.java | 2 +- .../transport/endpoints/EndpointBaseTest.java | 2 +- .../endpoints/SimpleEndpointTest.java | 2 +- .../transport/http/HeaderMapTest.java | 2 +- .../OpenTelemetryForElasticsearchTest.java | 2 +- .../rest_client/MultiBufferEntityTest.java | 2 +- .../rest_client/RestClientOptionsTest.java | 2 +- .../rest5_client/util/DateTimeTest.java | 140 -------- .../util/DuplicateResourceFinderTest.java | 41 --- .../rest5_client/util/NamedValueTest.java | 50 --- .../clients/rest5_client/util/PairTest.java | 47 --- 91 files changed, 81 insertions(+), 2456 deletions(-) delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonDataTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpDeserializerBaseTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpDeserializerTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpMapperTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpMappingExceptionTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpUtilsTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/LazyDeserializerTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/ObjectBuilderDeserializerTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/WithJsonTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonJsonpGeneratorTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonJsonpParserTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonMapperTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JsonEnumTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JsonValueParserTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/testkit/MockHttpClient.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/testkit/ModelTestCase.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/VersionInfoTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/util/DateTimeTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/util/DuplicateResourceFinderTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/util/NamedValueTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/util/PairTest.java diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java index 524b10275..e225828b1 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java @@ -110,11 +110,15 @@ public ElasticsearchClient build() { }); } - try { - restClientBuilder.setSslContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } + restClientBuilder.setHttpClientConfigCallback(hc -> { + try { + return hc + .setSSLContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + ); if (this.mapper == null) { ObjectMapper mapper = JsonMapper.builder().build(); diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/DocTestsTransport.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/DocTestsTransport.java index 2f2cb263e..b96fc98fc 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/DocTestsTransport.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/DocTestsTransport.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.documentation; +package co.elastic.clients.rest5_client.documentation; import co.elastic.clients.json.JsonpMapper; import co.elastic.clients.json.jackson.JacksonJsonpMapper; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/ApiConventionsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/ApiConventionsTest.java index 90cd160d4..b91b9a1f4 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/ApiConventionsTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/ApiConventionsTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.documentation.api_conventions; +package co.elastic.clients.rest5_client.documentation.api_conventions; import co.elastic.clients.documentation.DocTestsTransport; import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/LoadingJsonTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/LoadingJsonTest.java index 3207b4678..5716b5665 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/LoadingJsonTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/LoadingJsonTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.documentation.api_conventions; +package co.elastic.clients.rest5_client.documentation.api_conventions; import co.elastic.clients.documentation.DocTestsTransport; import co.elastic.clients.elasticsearch.ElasticsearchClient; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/getting_started/ConnectingTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/getting_started/ConnectingTest.java index 58f3b6803..ac5c28033 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/getting_started/ConnectingTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/getting_started/ConnectingTest.java @@ -18,7 +18,7 @@ */ //TODO rewrite -package clients.rest5_client.documentation.getting_started; +package co.elastic.clients.rest5_client.documentation.getting_started; public class ConnectingTest { diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/troubleshooting/TroubleShootingTests.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/troubleshooting/TroubleShootingTests.java index 55d6ee416..cc3084bdd 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/troubleshooting/TroubleShootingTests.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/troubleshooting/TroubleShootingTests.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.documentation.troubleshooting; +package co.elastic.clients.rest5_client.documentation.troubleshooting; import co.elastic.clients.documentation.DocTestsTransport; import co.elastic.clients.elasticsearch.ElasticsearchClient; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/AggregationsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/AggregationsTest.java index cde2ff832..1c4807e13 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/AggregationsTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/AggregationsTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.documentation.usage; +package co.elastic.clients.rest5_client.documentation.usage; import co.elastic.clients.documentation.DocTestsTransport; import co.elastic.clients.elasticsearch.ElasticsearchClient; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingBulkTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingBulkTest.java index 2175813be..f6e4bf1fc 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingBulkTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingBulkTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.documentation.usage; +package co.elastic.clients.rest5_client.documentation.usage; import co.elastic.clients.documentation.DocTestsTransport; import co.elastic.clients.documentation.usage.Product; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingTest.java index 7ad0ea9b5..807c5453d 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.documentation.usage; +package co.elastic.clients.rest5_client.documentation.usage; import co.elastic.clients.documentation.DocTestsTransport; import co.elastic.clients.documentation.usage.Product; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/Product.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/Product.java index 28f31e8b7..768ab1c5a 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/Product.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/Product.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.documentation.usage; +package co.elastic.clients.rest5_client.documentation.usage; public class Product { private String sku; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/ReadingTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/ReadingTest.java index 9c63b18ae..baf205821 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/ReadingTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/ReadingTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.documentation.usage; +package co.elastic.clients.rest5_client.documentation.usage; import co.elastic.clients.documentation.DocTestsTransport; import co.elastic.clients.documentation.usage.Product; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/SearchingTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/SearchingTest.java index 404057902..d5a2486f4 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/SearchingTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/SearchingTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.documentation.usage; +package co.elastic.clients.rest5_client.documentation.usage; import co.elastic.clients.documentation.DocTestsTransport; import co.elastic.clients.documentation.usage.Product; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/ElasticsearchTestServer.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/ElasticsearchTestServer.java index 0edaf3ec3..28befa943 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/ElasticsearchTestServer.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/ElasticsearchTestServer.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch; +package co.elastic.clients.rest5_client.elasticsearch; import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; import co.elastic.clients.elasticsearch.ElasticsearchClient; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/builders/ClientBuildersTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/builders/ClientBuildersTest.java index 525c98201..8fded816d 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/builders/ClientBuildersTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/builders/ClientBuildersTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch._helpers.builders; +package co.elastic.clients.rest5_client.elasticsearch._helpers.builders; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch._helpers.builders.ElasticsearchClientBuilder; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java index c5d86b2b8..c6fdc085d 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch._helpers.bulk; +package co.elastic.clients.rest5_client.elasticsearch._helpers.bulk; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch._helpers.bulk.BulkIngester; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterTest.java index 207574632..cdad3e9dc 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch._helpers.bulk; +package co.elastic.clients.rest5_client.elasticsearch._helpers.bulk; import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; import co.elastic.clients.elasticsearch.ElasticsearchClient; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java index 8ae60957f..b22c98018 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch._helpers.esql; +package co.elastic.clients.rest5_client.elasticsearch._helpers.esql; import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; import co.elastic.clients.elasticsearch.ElasticsearchClient; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterTest.java index 863b5f844..6300a208e 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch._helpers.esql; +package co.elastic.clients.rest5_client.elasticsearch._helpers.esql; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch._helpers.esql.jdbc.ResultSetEsqlAdapter; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/end_to_end/RequestTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/end_to_end/RequestTest.java index 31ed61407..18caf2e0e 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/end_to_end/RequestTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/end_to_end/RequestTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.end_to_end; +package co.elastic.clients.rest5_client.elasticsearch.end_to_end; import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; import co.elastic.clients.elasticsearch.ElasticsearchClient; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ClientTests.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ClientTests.java index 1e96ad2e4..b13c92557 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ClientTests.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ClientTests.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments; +package co.elastic.clients.rest5_client.elasticsearch.experiments; import co.elastic.clients.elasticsearch.experiments.api.Bar; import co.elastic.clients.elasticsearch.experiments.api.FooRequest; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ParsingTests.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ParsingTests.java index d461a2e75..37f094194 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ParsingTests.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ParsingTests.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments; +package co.elastic.clients.rest5_client.elasticsearch.experiments; import co.elastic.clients.elasticsearch.experiments.api.FooRequest; import co.elastic.clients.json.JsonpUtils; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/UnionVariant.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/UnionVariant.java index 5d869e6f9..86905d4ad 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/UnionVariant.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/UnionVariant.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments; +package co.elastic.clients.rest5_client.elasticsearch.experiments; /** * An implementation of a variant type. diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/Bar.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/Bar.java index fa2e4635a..bcba71fd1 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/Bar.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/Bar.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.api; +package co.elastic.clients.rest5_client.elasticsearch.experiments.api; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/DateMathTimeUnit.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/DateMathTimeUnit.java index 6dcf252be..8412ca3e9 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/DateMathTimeUnit.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/DateMathTimeUnit.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.api; +package co.elastic.clients.rest5_client.elasticsearch.experiments.api; import co.elastic.clients.json.JsonEnum; import co.elastic.clients.json.JsonpDeserializer; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooOptRequest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooOptRequest.java index 509de500e..9cd1dbb26 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooOptRequest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooOptRequest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.api; +package co.elastic.clients.rest5_client.elasticsearch.experiments.api; import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch.experiments.api.Bar; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooRequest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooRequest.java index 6330c04c4..3c18ef890 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooRequest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooRequest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.api; +package co.elastic.clients.rest5_client.elasticsearch.experiments.api; import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch.experiments.api.Bar; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooResponse.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooResponse.java index c28d9eb54..3a3e0095a 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooResponse.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooResponse.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.api; +package co.elastic.clients.rest5_client.elasticsearch.experiments.api; import co.elastic.clients.json.JsonpDeserializer; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/BoolQuery.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/BoolQuery.java index ca3894aae..1a84f9c52 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/BoolQuery.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/BoolQuery.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.api.query2; +package co.elastic.clients.rest5_client.elasticsearch.experiments.api.query2; import co.elastic.clients.elasticsearch.experiments.api.query2.Query; import co.elastic.clients.elasticsearch.experiments.api.query2.Union2; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Query.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Query.java index 6c2f47e2b..b8719a7e4 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Query.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Query.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.api.query2; +package co.elastic.clients.rest5_client.elasticsearch.experiments.api.query2; import co.elastic.clients.elasticsearch.experiments.UnionVariant; import co.elastic.clients.elasticsearch.experiments.api.query2.BoolQuery; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/QueryTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/QueryTest.java index 228f15572..f04890033 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/QueryTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/QueryTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.api.query2; +package co.elastic.clients.rest5_client.elasticsearch.experiments.api.query2; import co.elastic.clients.elasticsearch.experiments.api.query2.BoolQuery; import co.elastic.clients.elasticsearch.experiments.api.query2.Query; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/TermsQuery.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/TermsQuery.java index e42883171..057e7ba76 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/TermsQuery.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/TermsQuery.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.api.query2; +package co.elastic.clients.rest5_client.elasticsearch.experiments.api.query2; import co.elastic.clients.elasticsearch.experiments.api.query2.Query; import co.elastic.clients.json.JsonpDeserializer; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Union2.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Union2.java index 55c8e4279..fe7b3131d 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Union2.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Union2.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.api.query2; +package co.elastic.clients.rest5_client.elasticsearch.experiments.api.query2; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpDeserializerBase; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Client.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Client.java index a2482a298..acf35affc 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Client.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Client.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.base; +package co.elastic.clients.rest5_client.elasticsearch.experiments.base; import co.elastic.clients.elasticsearch.experiments.api.FooRequest; import co.elastic.clients.elasticsearch.experiments.api.FooResponse; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/PrimitiveUtils.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/PrimitiveUtils.java index a6122f198..b245854d7 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/PrimitiveUtils.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/PrimitiveUtils.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.base; +package co.elastic.clients.rest5_client.elasticsearch.experiments.base; /** * Support functions for primitive fields in generated classes diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Variants.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Variants.java index 37c09a99b..923724c27 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Variants.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Variants.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.base; +package co.elastic.clients.rest5_client.elasticsearch.experiments.base; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnion.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnion.java index 7438accbc..d82caa6dd 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnion.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnion.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.containers; +package co.elastic.clients.rest5_client.elasticsearch.experiments.containers; /* // @variants internal tag='type' interface SomeUnion = UnionItemA | UnionItemB; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionTest.java index ee1134298..ab73106f8 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.containers; +package co.elastic.clients.rest5_client.elasticsearch.experiments.containers; import co.elastic.clients.elasticsearch.experiments.containers.SomeUnion; import co.elastic.clients.elasticsearch.experiments.containers.UVariantA; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionVariant.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionVariant.java index 6f17060eb..28c75901b 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionVariant.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionVariant.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.containers; +package co.elastic.clients.rest5_client.elasticsearch.experiments.containers; import co.elastic.clients.elasticsearch.experiments.UnionVariant; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantA.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantA.java index c921b58db..0e5ed9741 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantA.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantA.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.containers; +package co.elastic.clients.rest5_client.elasticsearch.experiments.containers; import co.elastic.clients.elasticsearch.experiments.containers.SomeUnionVariant; import co.elastic.clients.json.JsonpDeserializable; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantB.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantB.java index 95ac7be92..46c3fed5e 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantB.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantB.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.containers; +package co.elastic.clients.rest5_client.elasticsearch.experiments.containers; import co.elastic.clients.elasticsearch.experiments.containers.SomeUnionVariant; import co.elastic.clients.json.JsonpDeserializable; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/generics/GenericClass.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/generics/GenericClass.java index ce97f5ca0..31e403ac9 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/generics/GenericClass.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/generics/GenericClass.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.generics; +package co.elastic.clients.rest5_client.elasticsearch.experiments.generics; import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.json.JsonpDeserializer; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/InheritanceTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/InheritanceTest.java index b20f24641..f568f4e58 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/InheritanceTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/InheritanceTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.inheritance; +package co.elastic.clients.rest5_client.elasticsearch.experiments.inheritance; import co.elastic.clients.elasticsearch.experiments.inheritance.child.ChildClass; import co.elastic.clients.elasticsearch.experiments.inheritance.final_.FinalClass; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/base/BaseClass.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/base/BaseClass.java index aeba6b6d7..f03039a32 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/base/BaseClass.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/base/BaseClass.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.inheritance.base; +package co.elastic.clients.rest5_client.elasticsearch.experiments.inheritance.base; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/child/ChildClass.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/child/ChildClass.java index 3b0a1c88d..ca202ce63 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/child/ChildClass.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/child/ChildClass.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.inheritance.child; +package co.elastic.clients.rest5_client.elasticsearch.experiments.inheritance.child; import co.elastic.clients.elasticsearch.experiments.inheritance.base.BaseClass; import co.elastic.clients.json.JsonpDeserializer; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/final_/FinalClass.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/final_/FinalClass.java index 72c87d347..c106a3446 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/final_/FinalClass.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/final_/FinalClass.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.experiments.inheritance.final_; +package co.elastic.clients.rest5_client.elasticsearch.experiments.inheritance.final_; import co.elastic.clients.elasticsearch.experiments.inheritance.child.ChildClass; import co.elastic.clients.json.JsonpDeserializer; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/package-info.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/package-info.java index b5569000c..42ec31f8b 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/package-info.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/package-info.java @@ -20,4 +20,4 @@ /** * Experiments for the design of high-level client classes and usage illustration of the XContent-related classes. */ -package clients.rest5_client.elasticsearch.experiments; +package co.elastic.clients.rest5_client.elasticsearch.experiments; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BehaviorsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BehaviorsTest.java index 7a4272bf3..f3446b293 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BehaviorsTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BehaviorsTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.model; +package co.elastic.clients.rest5_client.elasticsearch.model; import co.elastic.clients.elasticsearch._types.ErrorCause; import co.elastic.clients.elasticsearch._types.FieldSort; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BuiltinTypesTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BuiltinTypesTest.java index dc85a1045..45ce86c4b 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BuiltinTypesTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BuiltinTypesTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.model; +package co.elastic.clients.rest5_client.elasticsearch.model; import co.elastic.clients.elasticsearch._types.FieldValue; import co.elastic.clients.elasticsearch._types.SortOptions; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/ClassStructureTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/ClassStructureTest.java index f18287b22..20c2aa65b 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/ClassStructureTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/ClassStructureTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.model; +package co.elastic.clients.rest5_client.elasticsearch.model; import co.elastic.clients.elasticsearch._types.ErrorCause; import co.elastic.clients.elasticsearch._types.SortOrder; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/CodeAdditionsTests.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/CodeAdditionsTests.java index 4de302087..3fd26aade 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/CodeAdditionsTests.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/CodeAdditionsTests.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.model; +package co.elastic.clients.rest5_client.elasticsearch.model; import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery; import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EndpointTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EndpointTest.java index ba3afac8e..67c32dff3 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EndpointTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EndpointTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.model; +package co.elastic.clients.rest5_client.elasticsearch.model; import co.elastic.clients.elasticsearch._types.ExpandWildcard; import co.elastic.clients.elasticsearch.core.ExistsRequest; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EnumTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EnumTest.java index 62adc3577..7eaeab4fc 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EnumTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EnumTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.model; +package co.elastic.clients.rest5_client.elasticsearch.model; import co.elastic.clients.elasticsearch._types.Bytes; import co.elastic.clients.elasticsearch._types.Refresh; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/RequestEncodingTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/RequestEncodingTest.java index 9789f2a38..5333f90ee 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/RequestEncodingTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/RequestEncodingTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.model; +package co.elastic.clients.rest5_client.elasticsearch.model; import co.elastic.clients.elasticsearch.core.SearchRequest; import co.elastic.clients.json.jsonb.JsonbJsonpMapper; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/SerializationTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/SerializationTest.java index 8b3ad9662..3cb76ac1c 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/SerializationTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/SerializationTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.model; +package co.elastic.clients.rest5_client.elasticsearch.model; import co.elastic.clients.elasticsearch.cat.NodesResponse; import co.elastic.clients.elasticsearch.core.GetSourceResponse; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/TypedKeysTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/TypedKeysTest.java index 605bb5254..ea98bc10f 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/TypedKeysTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/TypedKeysTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.model; +package co.elastic.clients.rest5_client.elasticsearch.model; import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; import co.elastic.clients.elasticsearch._types.aggregations.AvgAggregate; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/UnionTests.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/UnionTests.java index b0208edf6..7dd6296d0 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/UnionTests.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/UnionTests.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.model; +package co.elastic.clients.rest5_client.elasticsearch.model; import co.elastic.clients.elasticsearch._types.GeoLocation; import co.elastic.clients.elasticsearch._types.LatLonGeoLocation; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/VariantsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/VariantsTest.java index e68d674dd..1e699a898 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/VariantsTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/VariantsTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.model; +package co.elastic.clients.rest5_client.elasticsearch.model; import co.elastic.clients.elasticsearch._types.analysis.Analyzer; import co.elastic.clients.elasticsearch._types.mapping.Property; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/package-info.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/package-info.java index 11503ca8b..034f71bcd 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/package-info.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/package-info.java @@ -21,4 +21,4 @@ * Tests that verify correct types and serialization/deserialization of the API specification model using API * structures that cover the various model features */ -package clients.rest5_client.elasticsearch.model; +package co.elastic.clients.rest5_client.elasticsearch.model; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/spec_issues/SpecIssuesTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/spec_issues/SpecIssuesTest.java index e5117ffcd..7f4d1a648 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/spec_issues/SpecIssuesTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/spec_issues/SpecIssuesTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.elasticsearch.spec_issues; +package co.elastic.clients.rest5_client.elasticsearch.spec_issues; import co.elastic.clients.documentation.usage.Product; import co.elastic.clients.elasticsearch.ElasticsearchClient; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonDataTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonDataTest.java deleted file mode 100644 index ea1a4ac70..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonDataTest.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.json; - -import co.elastic.clients.elasticsearch.core.search.Hit; -import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; -import co.elastic.clients.json.DelegatingDeserializer; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpMapperBase; -import co.elastic.clients.json.JsonpMapperTest; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.JsonString; -import jakarta.json.JsonValue; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import org.junit.jupiter.api.Test; - -import java.io.Reader; -import java.io.StringReader; -import java.io.StringWriter; - -public class JsonDataTest extends ModelTestCase { - -// public JsonDataTest() { -// super(JsonImpl.Jackson); -// } - - public static > B withJson(B builder, Reader json, JsonpMapper mapper) { - JsonpDeserializer classDeser = JsonpMapperBase.findDeserializer(builder.getClass().getEnclosingClass()); - - @SuppressWarnings("unchecked") - ObjectDeserializer builderDeser = (ObjectDeserializer) DelegatingDeserializer.unwrap(classDeser); - - JsonParser parser = mapper.jsonProvider().createParser(json); - builderDeser.deserialize(builder, parser, mapper, parser.next()); - return builder; - } - - @Test - public void testBuilderDeserializerHack() { - - CreateIndexRequest.Builder b = new CreateIndexRequest.Builder(); - - // Required request parameter - b.index("foo"); - - // Read body from JSON - withJson(b, new StringReader("{\"aliases\": {\"foo\": {\"is_hidden\": true}}}"), new JacksonJsonpMapper()); - - CreateIndexRequest createIndexRequest = b.build(); - } - - @Test - public void testParsing() { - if (jsonImpl == JsonImpl.Simple) { - return; // Doesn't support user-defined object mapping - } - - String json = "{\"children\":[{\"doubleValue\":3.2,\"intValue\":2}],\"doubleValue\":2.1,\"intValue\":1," + - "\"stringValue\":\"foo\"}"; - - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - - JsonData data = JsonData.from(parser, mapper); - checkClass(data); - assertEquals("foo", data.toJson().asJsonObject().getString("stringValue")); - - JsonpMapperTest.SomeClass to = data.to(JsonpMapperTest.SomeClass.class); - assertEquals("foo", to.getStringValue()); - } - - @Test - public void testSerializeObject() { - if (jsonImpl == JsonImpl.Simple) { - return; // Doesn't support user-defined object mapping - } - - String json = "{\"children\":[{\"doubleValue\":3.2,\"intValue\":2}],\"doubleValue\":2.1,\"intValue\":1," + - "\"stringValue\":\"foo\"}"; - - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - JsonpMapperTest.SomeClass sc = - mapper.deserialize(parser, JsonpMapperTest.SomeClass.class); - - assertEquals("foo", sc.getStringValue()); - assertEquals(1, sc.getChildren().size()); - assertEquals(2, sc.getChildren().get(0).getIntValue()); - // All good - - JsonData data = JsonData.of(sc); - - StringWriter sw = new StringWriter(); - JsonGenerator generator = mapper.jsonProvider().createGenerator(sw); - - data.serialize(generator, mapper); - generator.close(); - - assertEquals(json, sw.toString()); - } - - @Test - public void testSerializeValueOrBuffer() { - String json = "{\"children\":[{\"doubleValue\":3.2,\"intValue\":2}],\"doubleValue\":2.1,\"intValue\":1," + - "\"stringValue\":\"foo\"}"; - - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - - JsonData data = JsonData.from(parser, mapper); - checkClass(data); - - assertEquals(json, toJson(data, mapper)); - } - - @Test - public void testConvert() { - - JsonData json = JsonData.of("foo"); - - final JsonValue value = json.toJson(mapper); - - assertEquals(JsonValue.ValueType.STRING, value.getValueType()); - assertEquals("foo", ((JsonString)value).getString()); - } - - @Test - public void testFieldValues() { - // Specific test for https://github.com/elastic/elasticsearch-java/issues/548 which led to buffered JsonData - - String json = "{\"_index\":\"idx\",\"_id\":\"doc_id\",\"fields\":{\"bar\":\"Bar value\",\"foo\":1}}"; - - Hit hit = fromJson(json, Hit.createHitDeserializer(JsonpDeserializer.voidDeserializer())); - - assertEquals(1, hit.fields().get("foo").to(Integer.class)); - assertEquals("Bar value", hit.fields().get("bar").to(String.class)); - - checkClass(hit.fields().get("foo")); - checkClass(hit.fields().get("bar")); - - assertEquals(json, toJson(hit)); - } - - private void checkClass(JsonData data) { - String name = data.getClass().getName(); - switch (jsonImpl) { - case Jackson: - assertEquals(name, "co.elastic.clients.json.jackson.JacksonJsonBuffer"); - break; - - case Jsonb: - case Simple: - assertEquals(name, "co.elastic.clients.json.JsonDataImpl"); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpDeserializerBaseTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpDeserializerBaseTest.java deleted file mode 100644 index 982b0811a..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpDeserializerBaseTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.json; - -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.testkit.ModelTestCase; -import jakarta.json.stream.JsonParser; -import org.junit.jupiter.api.Test; - -import java.util.List; - -public class JsonpDeserializerBaseTest extends ModelTestCase { - - @Test - public void testArrayDeserializer() { - - JsonpDeserializer> deser = - JsonpDeserializer.arrayDeserializer(JsonpDeserializer.integerDeserializer()); - - assertFalse(deser.nativeEvents().contains(JsonParser.Event.VALUE_NUMBER)); - assertTrue(deser.acceptedEvents().contains(JsonParser.Event.VALUE_NUMBER)); - - List values = fromJson("[ 42, 43 ]", deser); - assertEquals(2, values.size()); - assertEquals(42, values.get(0)); - assertEquals(43, values.get(1)); - - // Single value representation - values = fromJson("42", deser); - assertEquals(1, values.size()); - assertEquals(42, values.get(0)); - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpDeserializerTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpDeserializerTest.java deleted file mode 100644 index f0e854e9b..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpDeserializerTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.json; - -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.testkit.ModelTestCase; -import jakarta.json.stream.JsonParser; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; -import java.util.List; - -public class JsonpDeserializerTest extends ModelTestCase { - - @Test - public void testNullStringInArray() { - JsonpDeserializer> deser = JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()); - - JsonParser parser = mapper.jsonProvider().createParser(new StringReader("[\"a\", null, \"b\"]")); - List list = deser.deserialize(parser, mapper); - - assertEquals("a", list.get(0)); - assertNull(list.get(1)); - assertEquals("b", list.get(2)); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpMapperTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpMapperTest.java deleted file mode 100644 index 2866abc23..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpMapperTest.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.json; - -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import jakarta.json.JsonArray; -import jakarta.json.JsonNumber; -import jakarta.json.bind.spi.JsonbProvider; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import org.eclipse.parsson.JsonProviderImpl; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; -import java.io.StringWriter; -import java.lang.reflect.Type; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class JsonpMapperTest extends Assertions { - - String json = "{\"children\":[{\"doubleValue\":3.2,\"intValue\":2}],\"doubleValue\":2.1,\"intValue\":1," + - "\"stringValue\":\"foo\"}"; - - @Test - public void testJsonb() { - JsonpMapper mapper = new JsonbJsonpMapper(new JsonProviderImpl(), JsonbProvider.provider()); - testSerialize(mapper, json); - testDeserialize(mapper, json); - testLargeNumber(mapper); - } - - @Test - public void testJackson() { - JacksonJsonpMapper mapper = new JacksonJsonpMapper(); - testSerialize(mapper, json); - testDeserialize(mapper, json); - testLargeNumber(mapper); - } - - @Test - public void testJacksonCustomMapper() { - ObjectMapper jkMapper = new ObjectMapper(); - jkMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); - jkMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - - JacksonJsonpMapper mapper = new JacksonJsonpMapper(jkMapper); - - String json = "{\"children\":[{\"double_value\":3.2,\"int_value\":2}],\"double_value\":2.1,\"int_value\":1," + - "\"string_value\":\"foo\"}"; - - testSerialize(mapper, json); - testDeserialize(mapper, json); - } - - @Test - public void testDeserializeWithType() { - - String json = "{\"foo\":{\"int_value\":1,\"double_value\":1.0},\"bar\":{\"int_value\":2,\"double_value\":2.0}}"; - - ObjectMapper jkMapper = new ObjectMapper(); - jkMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); - JacksonJsonpMapper mapper = new JacksonJsonpMapper(jkMapper); - - // With type erasure, map values are raw json nodes - { - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - Map map = new HashMap<>(); - map = mapper.deserialize(parser, (Type) map.getClass()); - - Map finalMap = map; - assertThrows(ClassCastException.class, () -> { - assertEquals(1, finalMap.get("foo").intValue); - }); - } - - // Use a j.l.reflect.Type to deserialize map values correctly - { - TypeReference> typeRef = new TypeReference>() {}; - - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - Map map = mapper.deserialize(parser, typeRef.getType()); - - System.out.println(map); - assertEquals(1, map.get("foo").intValue); - assertEquals(2, map.get("bar").intValue); - } - } - - private void testSerialize(JsonpMapper mapper, String expected) { - - SomeClass something = new SomeClass(); - something.setIntValue(1); - something.setDoubleValue(2.1); - something.setStringValue("foo"); - - SomeClass other = new SomeClass(); - other.setIntValue(2); - other.setDoubleValue(3.2); - something.setChildren(Collections.singletonList(other)); - - StringWriter strw = new StringWriter(); - JsonGenerator generator = mapper.jsonProvider().createGenerator(strw); - - mapper.serialize(something, generator); - - generator.close(); - - assertEquals(expected, strw.getBuffer().toString()); - } - - private void testDeserialize(JsonpMapper mapper, String json) { - - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - SomeClass parsed = mapper.deserialize(parser, SomeClass.class); - - assertEquals(1, parsed.getIntValue()); - assertEquals(2.1, parsed.getDoubleValue(), 0.0); - assertEquals("foo", parsed.getStringValue()); - - List children = parsed.getChildren(); - assertEquals(1, children.size()); - - SomeClass child = children.get(0); - - assertEquals(2, child.getIntValue()); - assertEquals(3.2, child.getDoubleValue(), 0.0); - assertNull(child.getStringValue()); - assertNull(child.getChildren()); - } - - private void testLargeNumber(JsonpMapper mapper) { - String json = "[1e999999]"; - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - parser.next(); - - JsonArray array = parser.getValue().asJsonArray(); - - JsonNumber number = array.getJsonNumber(0); - - assertTrue(Double.isInfinite(number.doubleValue())); - - Assertions.assertThrows(Exception.class, number::bigIntegerValue); - } - - public static class SomeClass { - private List children; - private double doubleValue; - private int intValue; - private String stringValue; - - public int getIntValue() { - return intValue; - } - - public void setIntValue(int intValue) { - this.intValue = intValue; - } - - public String getStringValue() { - return stringValue; - } - - public void setStringValue(String stringValue) { - this.stringValue = stringValue; - } - - public double getDoubleValue() { - return doubleValue; - } - - public void setDoubleValue(double doubleValue) { - this.doubleValue = doubleValue; - } - - public List getChildren() { - return children; - } - - public void setChildren(List children) { - this.children = children; - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpMappingExceptionTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpMappingExceptionTest.java deleted file mode 100644 index 260df72ed..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpMappingExceptionTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.json; - -import co.elastic.clients.elasticsearch._types.mapping.TypeMapping; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.json.JsonpMappingException; -import co.elastic.clients.json.SimpleJsonpMapper; -import co.elastic.clients.testkit.ModelTestCase; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; - -public class JsonpMappingExceptionTest extends ModelTestCase { - - @Test - public void testObjectAndArrayPath() { - - String json = "{" + - " \"took\" : 9," + - " \"timed_out\" : false," + - " \"_shards\" : {" + - " \"total\" : 1," + - " \"successful\" : 1," + - " \"skipped\" : 0," + - " \"failed\" : 0" + - " }," + - " \"hits\" : {" + - " \"total\" : {" + - " \"value\" : 1," + - " \"relation\" : \"eq\"" + - " }," + - " \"max_score\" : 1.0," + - " \"hits\" : [" + - " {" + - " \"_index\" : \"test\"," + - " \"_id\" : \"8aSerXUBs1w7Wkuj31zd\"," + - " \"_score\" : \"1.0\"," + - " \"_source\" : {" + - " \"foo\" : \"bar\"" + - " }" + - " }," + - " {" + - " \"_index\" : \"test\"," + - " \"_id\" : \"8aSerXUBs1w7Wkuj31zd\"," + - " \"_score\" : \"abc\"," + // <====== error here - " \"_source\" : {" + - " \"foo\" : \"bar\"" + - " }" + - " }" + - " ]" + - " }" + - "}"; - - JsonpMappingException e = assertThrows(JsonpMappingException.class, () -> { - // withJson() will read values of the generic parameter type as JsonData - SearchResponse r = SearchResponse.of(b -> b - .withJson(new StringReader(json)) - ); - }); - - assertTrue(e.getMessage().contains("Error deserializing co.elastic.clients.elasticsearch.core.search.Hit")); - assertTrue(e.getMessage().contains("java.lang.NumberFormatException")); - - // Also checks array index in path - assertEquals("hits.hits[1]._score", e.path()); - } - - @Test - public void testLookAhead() { - - String json = - "{" + - " \"properties\": { " + - " \"foo-bar\": {" + - " \"type\": \"text\"," + - " \"baz\": false" + - " }" + - " }" + - "}"; - - // Error deserializing co.elastic.clients.elasticsearch._types.mapping.TextProperty: - // Unknown field 'baz' (JSON path: properties['foo-bar'].baz) (...line no=1, column no=36, offset=35) - - JsonpMappingException e = assertThrows(JsonpMappingException.class, () -> { - fromJson(json, TypeMapping.class, SimpleJsonpMapper.INSTANCE_REJECT_UNKNOWN_FIELDS); - }); - - // Check escaping of non identifier path elements and path from map elements - assertEquals("properties['foo-bar'].baz", e.path()); - - String msg = e.getMessage(); - assertTrue(msg.contains("Unknown field 'baz'")); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpUtilsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpUtilsTest.java deleted file mode 100644 index ad87eba18..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/json/JsonpUtilsTest.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.json; - -import co.elastic.clients.elasticsearch.core.search.Hit; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.elasticsearch.security.IndexPrivilege; -import co.elastic.clients.elasticsearch.security.IndicesPrivileges; -import co.elastic.clients.elasticsearch.security.RoleTemplateScript; -import co.elastic.clients.elasticsearch.security.UserIndicesPrivileges; -import co.elastic.clients.util.AllowForbiddenApis; -import jakarta.json.JsonException; -import jakarta.json.spi.JsonProvider; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; -import java.io.StringWriter; -import java.net.URL; -import java.util.Collections; -import java.util.Enumeration; -import java.util.function.Consumer; - -public class JsonpUtilsTest extends ModelTestCase { - - @Test - @AllowForbiddenApis("Testing JsonpUtil.provider()") - public void testProviderLoading() { - // See https://github.com/elastic/elasticsearch-java/issues/163 - - // Create an empty non-delegating classloader and set it as the context classloader. It simulates a - // plugin system that doesn't set the context classloader to the plugins classloader. - ClassLoader emptyLoader = new ClassLoader() { - @Override - public Enumeration getResources(String name) { - return Collections.emptyEnumeration(); - } - }; - - ClassLoader savedLoader = Thread.currentThread().getContextClassLoader(); - try { - Thread.currentThread().setContextClassLoader(emptyLoader); - - assertThrows(JsonException.class, () -> { - assertNotNull(JsonProvider.provider()); - }); - - assertNotNull(JsonpUtils.provider()); - - } finally { - Thread.currentThread().setContextClassLoader(savedLoader); - } - } - - @Test - @AllowForbiddenApis("Testing JsonpUtil.provider()") - public void testProviderCache() { - // A new provider at each call - assertNotSame(JsonpUtils.findProvider(), JsonpUtils.findProvider()); - - // Result is cached - assertSame(JsonpUtils.provider(), JsonpUtils.provider()); - } - - @Test - public void testObjectToString() { - // Test that we call toString() on application classes. - Hit hit = Hit.of(h -> h - .source(new SomeUserData()) - .index("idx") - .id("id1") - ); - assertEquals("Hit: {\"_index\":\"idx\",\"_id\":\"id1\",\"_source\":\"Some user data\"}", hit.toString()); - } - - private static class SomeUserData { - @Override - public String toString() { - return "Some user data"; - } - } - - @Test - public void testLargeObjectToString() { - // Build a large string - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 1001; i++) { - sb.append("0123456789"); - } - - String text = sb.toString(); - assertEquals(10010, text.length()); - - Hit hit = Hit.of(h -> h - .source(text) - .index("idx") - .id("id1") - ); - - String toString = hit.toString(); - - assertEquals(10000 + "Hit: ".length() + "...".length(), toString.length()); - assertTrue(toString.startsWith("Hit: ")); - assertTrue(toString.endsWith("...")); - } - - @Test - public void testSerializeDoubleOrNull() { - // ---- Double values - assertEquals("{\"a\":null}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, Double.NaN, Double.NaN))); - assertEquals("{\"a\":1.0}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, 1.0, Double.NaN))); - - assertEquals("{\"a\":null}", - orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY))); - assertEquals("{\"a\":1.0}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, 1.0, Double.POSITIVE_INFINITY))); - - assertEquals("{\"a\":null}", - orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY))); - assertEquals("{\"a\":1.0}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, 1.0, Double.NEGATIVE_INFINITY))); - - assertEquals("{\"a\":null}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, Double.NaN, 0.0))); - - // Serialize defined default values - assertEquals("{\"a\":0.0}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, 0.0, 0.0))); - - } - - @Test - public void testSerializeIntOrNull() { - assertEquals("{\"a\":null}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, Integer.MAX_VALUE, Integer.MAX_VALUE))); - assertEquals("{\"a\":1}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, 1, Integer.MAX_VALUE))); - assertEquals("{\"a\":1}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, 1, 0))); - - // Integer.MAX_VALUE is valid if not the default value - assertEquals("{\"a\":2147483647}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, Integer.MAX_VALUE, 0))); - assertEquals("{\"a\":2147483647}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, Integer.MAX_VALUE, Integer.MIN_VALUE))); - - // Serialize non infinite default values - assertEquals("{\"a\":0}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, 0, 0))); - } - - @Test - public void testJsonString() { - // Single value - { - IndicesPrivileges priv = IndicesPrivileges.of(i -> i - .names("bar") - .query(q -> q.term(t -> t.field("baz").value(1))) - .privileges(IndexPrivilege.All.jsonValue()) - ); - - String json = "{\"names\":[\"bar\"],\"privileges\":[\"all\"],\"query\":\"{\\\"term\\\":{\\\"baz\\\":{\\\"value\\\":1}}}\"}"; - - assertEquals(json, toJson(priv)); - - priv = fromJson(json, IndicesPrivileges.class); - assertEquals("baz", priv.query().term().field()); - } - - // Single value template - { - IndicesPrivileges priv = IndicesPrivileges.of(i -> i - .names("bar") - .query(q -> q._custom("template", RoleTemplateScript.of(s -> s.id("foo")))) - .privileges(IndexPrivilege.All.jsonValue()) - ); - - String json = "{\"names\":[\"bar\"],\"privileges\":[\"all\"],\"query\":\"{\\\"template\\\":{\\\"id\\\":\\\"foo\\\"}}\"}"; - - assertEquals(json, toJson(priv)); - - priv = fromJson(json, IndicesPrivileges.class); - assertEquals("foo", priv.query()._custom().to(RoleTemplateScript.class).id()); - } - - // Array value - { - UserIndicesPrivileges priv = UserIndicesPrivileges.of(i -> i - .names("bar") - .query(q -> q.term(t -> t.field("baz").value(1))) - .privileges(IndexPrivilege.All.jsonValue()) - .allowRestrictedIndices(false) - ); - - String json = "{\"names\":[\"bar\"],\"privileges\":[\"all\"],\"query\":[\"{\\\"term\\\":{\\\"baz\\\":{\\\"value\\\":1}}}\"]," + - "\"allow_restricted_indices\":false}"; - - assertEquals(json, toJson(priv)); - - priv = fromJson(json, UserIndicesPrivileges.class); - assertEquals("baz", priv.query().get(0).term().field()); - } - } - - @Test - public void testCopy() { - // Tests round-tripping a json document that contains all event types and various kinds of nesting - - String json = "{\n" + - " \"p1\": \"str1\",\n" + - " \"p2\": 42,\n" + - " \"p3\": [\"str31\", \"str32\"],\n" + - " \"p4\": {\n" + - " \"p41\": \"str41\",\n" + - " \"p42\": [\"str421\", \"str422\"],\n" + - " \"p43\": {\n" + - " \"p431\": \"str431\"\n" + - " },\n" + - " \"p44\": true,\n" + - " \"p45\": false,\n" + - " \"p46\": 3.14\n" + - " },\n" + - " \"p5\": [{\n" + - " \"p51\": {\n" + - " \"p511\": \"str511\"\n" + - " }\n" + - " }],\n" + - " \"p6\": null\n" + - "}\n"; - - json = normalizeIndent(json); - - JsonProvider provider = JsonpUtils.provider(); - - JsonParser parser = provider.createParser(new StringReader(json)); - StringWriter sw = new StringWriter(); - JsonGenerator generator = provider.createGenerator(sw); - - JsonpUtils.copy(parser, generator); - parser.close(); - generator.close(); - - assertEquals(json, sw.toString()); - } - - private static String orNullHelper(Consumer c) { - StringWriter sw = new StringWriter(); - JsonGenerator generator = JsonpUtils.provider().createGenerator(sw); - - generator.writeStartObject(); - generator.writeKey("a"); - c.accept(generator); - generator.writeEnd(); - generator.close(); - - return sw.toString(); - } - - /** - * Normalizes the whitespace and indentation of a JSON string by parsing it and copying it to a string generator. - */ - private static String normalizeIndent(String json) { - JsonParser parser = JsonpUtils.provider().createParser(new StringReader(json)); - StringWriter sw = new StringWriter(); - JsonGenerator generator = JsonpUtils.provider().createGenerator(sw); - - copyAll(parser, generator); - - parser.close(); - generator.close(); - return sw.toString(); - } - - private static void copyAll(JsonParser parser, JsonGenerator generator) { - while(parser.hasNext()) { - switch (parser.next()) { - case START_OBJECT: - generator.writeStartObject(); - break; - - case END_OBJECT: - generator.writeEnd(); - break; - - case START_ARRAY: - generator.writeStartArray(); - break; - - case END_ARRAY: - generator.writeEnd(); - break; - - case KEY_NAME: - generator.writeKey(parser.getString()); - break; - - case VALUE_STRING: - generator.write(parser.getString()); - break; - - case VALUE_NULL: - generator.writeNull(); - break; - - case VALUE_TRUE: - generator.write(true); - break; - - case VALUE_FALSE: - generator.write(false); - break; - - case VALUE_NUMBER: - if (parser.isIntegralNumber()) { - generator.write(parser.getLong()); - } else { - generator.write(parser.getBigDecimal()); - } - break; - } - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/LazyDeserializerTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/LazyDeserializerTest.java deleted file mode 100644 index b8c3199ef..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/json/LazyDeserializerTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.json; - -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.LazyDeserializer; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.util.concurrent.CompletableFuture; - -public class LazyDeserializerTest extends Assertions { - - @Test - public void testConcurrentInit() throws Exception { - // See https://github.com/elastic/elasticsearch-java/issues/58 - - final LazyDeserializer ld = new LazyDeserializer<>(JsonpDeserializer::stringDeserializer); - - CompletableFuture> fut1; - CompletableFuture> fut2; - - // Lock the mutex and start 2 threads that will compete for it. - synchronized (ld) { - fut1 = futureUnwrap(ld); - fut2 = futureUnwrap(ld); - } - - // We should see the same non-null results everywhere - assertNotNull(fut1.get()); - assertNotNull(fut2.get()); - - final JsonpDeserializer unwrapped = ld.unwrap(); - assertEquals(unwrapped, fut1.get()); - assertEquals(unwrapped, fut2.get()); - - } - - private CompletableFuture> futureUnwrap(LazyDeserializer d) { - - final CompletableFuture> result = new CompletableFuture<>(); - - new Thread(() -> { - try { - result.complete(d.unwrap()); - } catch (Throwable e) { - result.completeExceptionally(e); - } - }).start(); - - return result; - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/ObjectBuilderDeserializerTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/ObjectBuilderDeserializerTest.java deleted file mode 100644 index 0cbf19ab2..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/json/ObjectBuilderDeserializerTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.json; - -import co.elastic.clients.elasticsearch._types.mapping.TextProperty; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.elasticsearch.transform.UpdateTransformRequest; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; - -public class ObjectBuilderDeserializerTest extends ModelTestCase { - - @Test - public void testNullObjectValue() { - // Should also accept null for optional values - String json = "{ \"index_prefixes\": null }"; - fromJson(json, TextProperty.class); - } - - @Test - public void testNullObjectValueInFunctionBuilder() { - String json = "{\n" + - " \"retention_policy\": null\n" + - " }"; - - UpdateTransformRequest.Builder builder = new UpdateTransformRequest.Builder(); - builder.transformId("foo"); - builder.withJson(new StringReader(json)); - builder.build(); - } - -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/WithJsonTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/WithJsonTest.java deleted file mode 100644 index 87558d1bc..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/json/WithJsonTest.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.json; - -import co.elastic.clients.elasticsearch._types.Script; -import co.elastic.clients.elasticsearch._types.SlicedScroll; -import co.elastic.clients.elasticsearch._types.mapping.Property; -import co.elastic.clients.elasticsearch._types.mapping.TextProperty; -import co.elastic.clients.elasticsearch._types.query_dsl.Query; -import co.elastic.clients.elasticsearch._types.query_dsl.TermQuery; -import co.elastic.clients.elasticsearch.core.IndexRequest; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.indices.PutIndicesSettingsRequest; -import co.elastic.clients.elasticsearch.security.RoleTemplateScript; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.testkit.ModelTestCase; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; - -public class WithJsonTest extends ModelTestCase { - - @Test - public void testRequestWithGenericValueBody() { - String json = "{\"foo\": \"bar\", \"baz\": 1}"; - - IndexRequest req = IndexRequest.of(b -> b - .index("index") // required path parameter (cannot be expressed in json) - .withJson(new StringReader(json)) - ); - - assertEquals("index", req.index()); - assertEquals("bar", req.document().toJson().asJsonObject().getString("foo")); - assertEquals(1, req.document().toJson().asJsonObject().getInt("baz")); - } - - @Test - public void testRequestWithValueBody() { - String json = "{" + - "\"analyze\": {" + - " \"max_token_count\": 12" + - " }" + - "}"; - - PutIndicesSettingsRequest req = PutIndicesSettingsRequest.of(b -> b - .withJson(new StringReader(json)) - ); - - assertEquals(12, req.settings().analyze().maxTokenCount().intValue()); - } - - @Test - public void testRegularObject() { - String json = "{\"field\": \"foo\", \"id\": 12}"; - - SlicedScroll s = SlicedScroll.of(b -> b - .withJson(new StringReader(json)) - .max(34) // required property not present in the json - ); - - assertEquals("foo", s.field()); - assertEquals("12", s.id()); - assertEquals(34, s.max()); - } - - @Test - public void testObjectWithGenericParam() { - - String json = "{" + - " \"took\" : 9," + - " \"timed_out\" : false," + - " \"_shards\" : {" + - " \"total\" : 1," + - " \"successful\" : 1," + - " \"skipped\" : 0," + - " \"failed\" : 0" + - " }," + - " \"hits\" : {" + - " \"total\" : {" + - " \"value\" : 1," + - " \"relation\" : \"eq\"" + - " }," + - " \"max_score\" : 1.0," + - " \"hits\" : [" + - " {" + - " \"_index\" : \"test\"," + - " \"_id\" : \"8aSerXUBs1w7Wkuj31zd\"," + - " \"_score\" : 1.0," + - " \"_source\" : {" + - " \"foo\" : \"bar\"" + - " }" + - " }" + - " ]" + - " }" + - "}"; - - // withJson() will read values of the generic parameter type as JsonData - SearchResponse r = SearchResponse.of(b -> b - .withJson(new StringReader(json)) - ); - - assertEquals(1, r.hits().total().value()); - assertEquals("bar", r.hits().hits().get(0).source().toJson().asJsonObject().getString("foo")); - } - - @Test - public void testTypeWithParent() { - - String json = "{\"source\": \"return doc;\"}"; - - Script is = Script.of(b -> b - .withJson(new StringReader(json)) - ); - - assertEquals("return doc;", is.source()); - } - - @Test - public void testContainerTaggedUnion() { - String json = "{" + - " \"term\": {" + - " \"user.id\": {" + - " \"value\": \"kimchy\"," + - " \"boost\": 1.0" + - " }" + - " }" + - " }"; - - Query q = Query.of(b -> b - .withJson(new StringReader(json)) - ); - - TermQuery tq = q.term(); - assertEquals("user.id", tq.field()); - assertEquals("kimchy", tq.value().stringValue()); - assertEquals(1.0, tq.boost(), 0.001); - } - - @Test - public void testInternallyTaggedUnion() { - String json = "{ " + - " \"type\": \"text\"," + - " \"fields\": {" + - " \"some_field\": { " + - " \"type\": \"keyword\"," + - " \"normalizer\": \"lowercase\"" + - " }" + - " }" + - " }"; - - Property p = Property.of(b -> b - .withJson(new StringReader(json)) - ); - - TextProperty tp = p.text(); - assertEquals("lowercase", tp.fields().get("some_field").keyword().normalizer()); - } - - @Test - public void testExternalTaggedUnion() { - - RoleTemplateScript withSource = RoleTemplateScript.of(j -> j - .withJson(new StringReader("{\"source\": {\"match\": {\"category\": \"click\"}}}"))); - assertTrue(withSource.source().isQueryObject()); - RoleTemplateScript withStringSource = RoleTemplateScript.of(j -> j - .withJson(new StringReader("{\"source\": \"string\"}"))); - assertTrue(withStringSource.source().isQueryString()); - RoleTemplateScript withStoredScript = RoleTemplateScript.of(j -> j - .withJson(new StringReader("{\"id\": \"foo\"}"))); - assertTrue(!withStoredScript.id().isEmpty()); - } -} - diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonJsonpGeneratorTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonJsonpGeneratorTest.java deleted file mode 100644 index c6244159d..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonJsonpGeneratorTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.json.jackson; - -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import jakarta.json.Json; -import jakarta.json.JsonValue; -import jakarta.json.stream.JsonGenerator; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.StringWriter; - -public class JacksonJsonpGeneratorTest extends Assertions { - - @Test - public void testWrite(){ - StringWriter sw = new StringWriter(); - JsonGenerator generator = new JacksonJsonpMapper().jsonProvider().createGenerator(sw); - - generator.writeStartObject(); - - // Boolean - generator.write("bool1", true); - generator.writeKey("bool2"); - generator.write(false); - - // String - generator.write("str1", "foo"); - generator.writeKey("str2"); - generator.write("bar"); - - // Integer - generator.write("int1", 42); - generator.writeKey("int2"); - generator.write(1337); - - // Long - generator.write("long1", 123456789012345L); - generator.writeKey("long2"); - generator.write(123456789012345L); - - generator.write("double1", 0.001); - generator.writeKey("double2"); - generator.write(12345.6789); - - // JsonValue - JsonValue jsonValue = Json.createObjectBuilder() - .add("bool", true) - .add("str", "foo") - .add("int", 42) - .add("long", 123456789012345L) - .add("double", 12345.6789) - .build(); - - generator.write("value", jsonValue); - - generator.close(); - - assertEquals("{" + - "\"bool1\":true," + - "\"bool2\":false," + - "\"str1\":\"foo\"," + - "\"str2\":\"bar\"," + - "\"int1\":42," + - "\"int2\":1337," + - "\"long1\":123456789012345," + - "\"long2\":123456789012345," + - "\"double1\":0.001," + - "\"double2\":12345.6789," + - "\"value\":{\"bool\":true,\"str\":\"foo\",\"int\":42,\"long\":123456789012345,\"double\":12345.6789}" + - "}", sw.toString()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonJsonpParserTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonJsonpParserTest.java deleted file mode 100644 index bf7baef77..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonJsonpParserTest.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.json.jackson; - -import co.elastic.clients.elasticsearch.core.MsearchResponse; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.jackson.JacksonJsonProvider; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.testkit.ModelTestCase; -import jakarta.json.stream.JsonParser; -import jakarta.json.stream.JsonParser.Event; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; - -public class JacksonJsonpParserTest extends ModelTestCase { - - private static final String json = - "{ 'foo': 'fooValue', 'bar': { 'baz': 1}, 'quux': [true] }".replace('\'', '"'); - - @Test - public void testEventStream() { - - JacksonJsonProvider provider = new JacksonJsonProvider(); - JsonParser parser = provider.createParser(new StringReader(json)); - - assertEquals(Event.START_OBJECT, parser.next()); - - assertEquals(Event.KEY_NAME, parser.next()); - assertEquals("foo", parser.getString()); - - assertEquals(Event.VALUE_STRING, parser.next()); - assertEquals("fooValue", parser.getString()); - - // test it sometimes, but not always to detect invalid state management - assertTrue(parser.hasNext()); - - assertEquals(Event.KEY_NAME, parser.next()); - assertEquals("bar", parser.getString()); - - assertEquals(Event.START_OBJECT, parser.next()); - - assertEquals(Event.KEY_NAME, parser.next()); - assertEquals("baz", parser.getString()); - - assertTrue(parser.hasNext()); - assertEquals(Event.VALUE_NUMBER, parser.next()); - assertEquals(1, parser.getInt()); - - assertEquals(Event.END_OBJECT, parser.next()); - - assertEquals(Event.KEY_NAME, parser.next()); - assertEquals("quux", parser.getString()); - - assertEquals(Event.START_ARRAY, parser.next()); - - assertEquals(Event.VALUE_TRUE, parser.next()); - - assertEquals(Event.END_ARRAY, parser.next()); - assertEquals(Event.END_OBJECT, parser.next()); - - assertFalse(parser.hasNext()); - } - - @Test - public void testForbidValueGettersAfterHasNext() { - - JacksonJsonProvider provider = new JacksonJsonProvider(); - JsonParser parser = provider.createParser(new StringReader(json)); - - assertEquals(Event.START_OBJECT, parser.next()); - assertEquals(Event.KEY_NAME, parser.next()); - assertEquals(Event.VALUE_STRING, parser.next()); - assertEquals("fooValue", parser.getString()); - - assertTrue(parser.hasNext()); - - try { - assertEquals("fooValue", parser.getString()); - fail(); - } catch (IllegalStateException e) { - // expected - } - } - - @Test - void testMultiSearchResponse() { - String json = - "{\n" + - " \"took\" : 1,\n" + - " \"responses\" : [\n" + - " {\n" + - " \"error\" : {\n" + - " \"root_cause\" : [\n" + - " {\n" + - " \"type\" : \"index_not_found_exception\",\n" + - " \"reason\" : \"no such index [foo_bar]\",\n" + - " \"resource.type\" : \"index_or_alias\",\n" + - " \"resource.id\" : \"foo_bar\",\n" + - " \"index_uuid\" : \"_na_\",\n" + - " \"index\" : \"foo_bar\"\n" + - " }\n" + - " ],\n" + - " \"type\" : \"index_not_found_exception\",\n" + - " \"reason\" : \"no such index [foo_bar]\",\n" + - " \"resource.type\" : \"index_or_alias\",\n" + - " \"resource.id\" : \"foo_bar\",\n" + - " \"index_uuid\" : \"_na_\",\n" + - " \"index\" : \"foo_bar\"\n" + - " },\n" + - " \"status\" : 404\n" + - " },\n" + - " {\n" + - " \"took\" : 1,\n" + - " \"timed_out\" : false,\n" + - " \"_shards\" : {\n" + - " \"total\" : 1,\n" + - " \"successful\" : 1,\n" + - " \"skipped\" : 0,\n" + - " \"failed\" : 0\n" + - " },\n" + - " \"hits\" : {\n" + - " \"total\" : {\n" + - " \"value\" : 5,\n" + - " \"relation\" : \"eq\"\n" + - " },\n" + - " \"max_score\" : 1.0,\n" + - " \"hits\" : [\n" + - " {\n" + - " \"_index\" : \"foo\",\n" + - " \"_id\" : \"Wr0ApoEBa_iiaABtVM57\",\n" + - " \"_score\" : 1.0,\n" + - " \"_source\" : {\n" + - " \"x\" : 1,\n" + - " \"y\" : true\n" + - " }\n" + - " }\n" + - " ]\n" + - " },\n" + - " \"status\" : 200\n" + - " }\n" + - " ]\n" + - "}\n"; - - JsonpMapper mapper = new JacksonJsonpMapper(); - mapper = mapper.withAttribute("co.elastic.clients:Deserializer:_global.msearch.Response.TDocument", - JsonpDeserializer.of(Foo.class)); - @SuppressWarnings("unchecked") - MsearchResponse response = fromJson(json, MsearchResponse.class, mapper); - - assertEquals(2, response.responses().size()); - assertEquals(404, response.responses().get(0).failure().status()); - assertEquals(200, response.responses().get(1).result().status()); - } - - public static class Foo { - private int x; - private boolean y; - - public int getX() { - return x; - } - - public void setX(int x) { - this.x = x; - } - - public boolean isY() { - return y; - } - - public void setY(boolean y) { - this.y = y; - } - } - -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonMapperTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonMapperTest.java deleted file mode 100644 index ee7b46e88..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JacksonMapperTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.json.jackson; - -import co.elastic.clients.elasticsearch.core.search.Hit; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonNaming; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.Collections; -import java.util.List; - -public class JacksonMapperTest extends ModelTestCase { - - @Test - public void testCustomDeserializer() { - // See https://github.com/elastic/elasticsearch-java/issues/120 - JsonpMapper jsonpMapper = new JacksonJsonpMapper(); - - String json = "{\"_index\":\"foo\",\"_id\":\"1\",\"_source\":{\"model\":\"Foo\",\"age\":42}}"; - - Hit testDataHit = fromJson(json, - Hit.createHitDeserializer(JsonpDeserializer.of(TestData.class)), - jsonpMapper - ); - TestData data = testDataHit.source(); - assertEquals("Foo", data.theModel); - assertEquals(42, data.theAge); - } - - @JsonDeserialize(using = TestData.TestDeserializer.class) - public static class TestData { - public String theModel; - public int theAge; - - public static class TestDeserializer extends JsonDeserializer { - - @Override - public TestData deserialize(JsonParser jp, DeserializationContext ctx) throws IOException { - JsonNode node = jp.getCodec().readTree(jp); - - TestData res = new TestData(); - if (node.has("age")) { - res.theAge = node.get("age").asInt(); - } - if (node.has("model")) { - res.theModel = node.get("model").asText(); - } - return res; - } - } - } - - @Test - public void testSingleValueAsList() { - JsonpMapper jsonpMapper = new JacksonJsonpMapper(); - - String json = "{\"_index\":\"foo\",\"_id\":\"1\",\"_source\":{\"emp_no\":42,\"job_positions\":\"SWE\"}}"; - - Hit testDataHit = fromJson(json, - Hit.createHitDeserializer(JsonpDeserializer.of(EmpData.class)), - jsonpMapper - ); - EmpData data = testDataHit.source(); - assertEquals(42, data.empNo); - assertEquals(Collections.singletonList("SWE"), data.jobPositions); - } - - @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) - @JsonIgnoreProperties(ignoreUnknown = true) - public static class EmpData { - public int empNo; - public List jobPositions; - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JsonEnumTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JsonEnumTest.java deleted file mode 100644 index 4b4db97f1..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JsonEnumTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.json.jackson; - -import co.elastic.clients.elasticsearch._types.query_dsl.SimpleQueryStringFlag; -import co.elastic.clients.elasticsearch._types.query_dsl.SimpleQueryStringQuery; -import co.elastic.clients.testkit.ModelTestCase; -import org.junit.jupiter.api.Test; - -public class JsonEnumTest extends ModelTestCase { - - @Test - public void testPipeSeparatedEnum() { - { - // Empty flags - String jsonNoFlags = "{\"query\":\"foo\"}"; - SimpleQueryStringQuery q = SimpleQueryStringQuery.of(b -> b - .query("foo") - ); - q = checkJsonRoundtrip(q, jsonNoFlags); - assertEquals("foo", q.query()); - assertTrue(q.flags().isEmpty()); - } - - { - // With flags - String jsonWithFlags = "{\"flags\":\"AND|NEAR\",\"query\":\"foo\"}"; - SimpleQueryStringQuery q = SimpleQueryStringQuery.of(b -> b - .query("foo") - .flags(SimpleQueryStringFlag.And, SimpleQueryStringFlag.Near) - ); - q = checkJsonRoundtrip(q, jsonWithFlags); - assertEquals("foo", q.query()); - assertEquals(2, q.flags().size()); - assertEquals(SimpleQueryStringFlag.And, q.flags().get(0)); - assertEquals(SimpleQueryStringFlag.Near, q.flags().get(1)); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JsonValueParserTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JsonValueParserTest.java deleted file mode 100644 index 936bf9091..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/json/jackson/JsonValueParserTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.json.jackson; - -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import jakarta.json.JsonObject; -import jakarta.json.JsonValue; -import jakarta.json.stream.JsonParser; - -import java.io.StringReader; -import java.util.Map; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class JsonValueParserTest extends Assertions { - - public static class Data { - public Map data; - } - - @Test - public void testFloatsShouldDeserializeAsFloats() throws Exception { - // When using Jackson to target a map of objects, values with a decimal separator - // should deserialize as a double even if they fit in an int or long. - // See https://github.com/elastic/elasticsearch-java/issues/156 - - String json = "{\"data\": {\"value\": 1.4778125E7, \"value2\": 1.4778125E7 }}"; - JsonpMapper mapper = new JacksonJsonpMapper(); - - { - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - Data data = mapper.deserialize(parser, Data.class); - - Double d = (Double)data.data.get("value"); - assertEquals(1.4778125E7, d, 0.001); - } - - { - // Test with buffering used in union resolution - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - parser.next(); - JsonObject object = parser.getObject(); - - // Test equals/hashcode - JsonValue v = object.getJsonObject("data").get("value"); - JsonValue v2 = object.getJsonObject("data").get("value2"); - - assertEquals(v.hashCode(), v2.hashCode()); - assertEquals(v, v2); - - parser = JsonpUtils.jsonValueParser(object, mapper); - Data data = mapper.deserialize(parser, Data.class); - - Double d = (Double)data.data.get("value"); - assertEquals(1.4778125E7, d, 0.001); - } - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/testkit/MockHttpClient.java b/java-client/src/test/java/co/elastic/clients/rest5_client/testkit/MockHttpClient.java deleted file mode 100644 index 7b22abaa6..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/testkit/MockHttpClient.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.testkit; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.transport.ElasticsearchTransportBase; -import co.elastic.clients.transport.TransportException; -import co.elastic.clients.transport.TransportOptions; -import co.elastic.clients.transport.http.TransportHttpClient; -import co.elastic.clients.util.BinaryData; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; - -public class MockHttpClient implements TransportHttpClient { - - private static final Response NotFound = new MockResponse(404, null); - - Map responses = new ConcurrentHashMap<>(); - - public MockHttpClient add(String path, String contentType, byte[] data) { - responses.put(path, new MockResponse(200, BinaryData.of(data, contentType))); - return this; - } - - public MockHttpClient add(String path, String contentType, String text) { - responses.put(path, new MockResponse(200, BinaryData.of(text.getBytes(StandardCharsets.UTF_8), contentType))); - return this; - } - - public ElasticsearchClient client() { - return client(new ModelTestCase() {}.mapper); - } - - public ElasticsearchClient client(JsonpMapper mapper) { - return new ElasticsearchClient(new ElasticsearchTransportBase(this, null, mapper) { - @Override - public void close() throws IOException { - super.close(); - } - }); - } - - - @Override - public Response performRequest( - String endpointId, @Nullable TransportHttpClient.Node node, Request request, TransportOptions option - ) throws IOException { - Response response = responses.get(request.path()); - - if (response == null) { - throw new TransportException(NotFound, "Not found", endpointId); - } - - return response; - } - - @Override - public CompletableFuture performRequestAsync( - String endpointId, @Nullable TransportHttpClient.Node node, Request request, TransportOptions options - ) { - CompletableFuture result = new CompletableFuture<>(); - try { - Response response = performRequest(endpointId, node, request, options); - result.complete(response); - } catch (Exception e) { - result.completeExceptionally(e); - } - return result; - } - - @Override - public void close() throws IOException { - } - - private static class MockResponse implements Response { - - private final int statusCode; - private final BinaryData body; - private final Map headers; - - MockResponse(int statusCode, BinaryData body) { - this.statusCode = statusCode; - this.headers = new HashMap<>(); - this.body = body; - - if (body != null) { - headers.put("content-type", body.contentType()); - } - headers.put("x-elastic-product", "Elasticsearch"); - } - - @Override - public Node node() { - return null; - } - - @Override - public int statusCode() { - return statusCode; - } - - @Nullable - @Override - public String header(String name) { - return headers.get(name.toLowerCase()); - } - - @Override - public List headers(String name) { - String header = header(name); - return header == null ? null : Collections.singletonList(header); - } - - @Nullable - @Override - public BinaryData body() throws IOException { - return body; - } - - @Nullable - @Override - public Object originalResponse() { - return null; - } - - @Override - public void close() throws IOException { - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/testkit/ModelTestCase.java b/java-client/src/test/java/co/elastic/clients/rest5_client/testkit/ModelTestCase.java deleted file mode 100644 index 7ea2f9deb..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/testkit/ModelTestCase.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.testkit; - -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.SimpleJsonpMapper; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import jakarta.json.spi.JsonProvider; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import org.junit.jupiter.api.Assertions; - -import java.io.StringReader; -import java.io.StringWriter; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.util.EnumSet; -import java.util.Random; - -/** - * Base class for tests that encode/decode json - */ -public abstract class ModelTestCase extends Assertions { - - protected enum JsonImpl { Jsonb, Jackson, Simple }; - - // Same value for all tests in a test run - private static final int RAND = new Random().nextInt(100); - - protected final JsonImpl jsonImpl; - protected final JsonpMapper mapper; - - private static JsonImpl chooseJsonImpl(EnumSet jsonImplCandidates, int rand) { - // Converting an EnumSet to an array always uses the same order. - return jsonImplCandidates.toArray(new JsonImpl[jsonImplCandidates.size()])[rand % jsonImplCandidates.size()]; - } - - private static JsonpMapper createMapper(JsonImpl jsonImpl, int rand) { - switch(jsonImpl) { - case Jsonb: - System.out.println("Using a JsonB mapper (rand = " + rand + ")."); - return new JsonbJsonpMapper(); - - case Jackson: - System.out.println("Using a Jackson mapper (rand = " + rand + ")."); - return new JacksonJsonpMapper(); - - default: - System.out.println("Using a simple mapper (rand = " + rand + ")."); - return SimpleJsonpMapper.INSTANCE; - } - } - - protected ModelTestCase(EnumSet jsonImplCandidates, int rand) { - jsonImpl = chooseJsonImpl(jsonImplCandidates, rand); - mapper = createMapper(jsonImpl, rand); - } - - protected ModelTestCase(EnumSet jsonImplCandidates) { - this(jsonImplCandidates, RAND); - } - - protected ModelTestCase(JsonImpl jsonImpl) { - this(EnumSet.of(jsonImpl), RAND); - } - - protected ModelTestCase(int rand) { - this(EnumSet.allOf(JsonImpl.class), rand); - } - - protected ModelTestCase() { - this(EnumSet.allOf(JsonImpl.class), RAND); - } - - protected String toJson(T value) { - return toJson(value, mapper); - } - - public static String toJson(T value, JsonpMapper mapper) { - StringWriter sw = new StringWriter(); - JsonProvider provider = mapper.jsonProvider(); - JsonGenerator generator = provider.createGenerator(sw); - mapper.serialize(value, generator); - generator.close(); - return sw.toString(); - } - - public static T fromJson(String json, Class clazz, JsonpMapper mapper) { - return fromJson(json, (Type)clazz, mapper); - } - - public static T fromJson(String json, Type type, JsonpMapper mapper) { - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - return mapper.deserialize(parser, type); - } - - protected T fromJson(String json, Class clazz) { - return fromJson(json, clazz, mapper); - } - - protected T fromJson(String json, Type type) { - return fromJson(json, type, mapper); - } - - @SuppressWarnings("unchecked") - protected T checkJsonRoundtrip(T value, String expectedJson) { - assertEquals(expectedJson, toJson(value)); - return fromJson(expectedJson, (Class)value.getClass()); - } - - protected T fromJson(String json, JsonpDeserializer deserializer) { - return fromJson(json, deserializer, mapper); - } - - protected T fromJson(String json, JsonpDeserializer deserializer, JsonpMapper mapper) { - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - return deserializer.deserialize(parser, mapper); - } - - - public static void assertGetterType(Class expected, Class clazz, String name) { - Method method; - try { - method = clazz.getMethod(name); - } catch (NoSuchMethodException e) { - fail("Getter '" + clazz.getName() + "." + name + "' doesn't exist"); - return; - } - - assertSame(expected, method.getReturnType()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/RequestOptionsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/RequestOptionsTest.java index be80b949f..7a02763c5 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/RequestOptionsTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/RequestOptionsTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.transport; +package co.elastic.clients.rest5_client.transport; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.jsonb.JsonbJsonpMapper; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportTest.java index 249b698de..3cda2671b 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.transport; +package co.elastic.clients.rest5_client.transport; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.jackson.JacksonJsonpMapper; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportUtilsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportUtilsTest.java index 2ae0700f7..c66b986a2 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportUtilsTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportUtilsTest.java @@ -17,17 +17,17 @@ * under the License. */ -package clients.rest5_client.transport; +package co.elastic.clients.rest5_client.transport; import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.ElasticsearchTestServer; +import co.elastic.clients.rest5_client.elasticsearch.ElasticsearchTestServer; import co.elastic.clients.json.SimpleJsonpMapper; import co.elastic.clients.transport.TransportUtils; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.rest5_client.low_level.RestClient; +import co.elastic.clients.transport.rest5_client.RestClientTransport; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.message.BasicHeader; -import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.testcontainers.elasticsearch.ElasticsearchContainer; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/VersionInfoTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/VersionInfoTest.java deleted file mode 100644 index 83aecaa4f..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/VersionInfoTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.transport; - -import co.elastic.clients.transport.ElasticsearchTransportBase; -import co.elastic.clients.transport.VersionInfo; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class VersionInfoTest { - - @Test - public void testClientMeta() { - String version = VersionInfo.VERSION; - Assertions.assertTrue(ElasticsearchTransportBase.getClientMeta().startsWith("es=" + version + ",jv=")); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BinaryEndpointTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BinaryEndpointTest.java index 90c65f540..1dad3b44a 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BinaryEndpointTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BinaryEndpointTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.transport.endpoints; +package co.elastic.clients.rest5_client.transport.endpoints; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch.ElasticsearchTestServer; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BooleanEndpointTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BooleanEndpointTest.java index e2e95a5c9..47e94c889 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BooleanEndpointTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BooleanEndpointTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.transport.endpoints; +package co.elastic.clients.rest5_client.transport.endpoints; import co.elastic.clients.elasticsearch.core.ExistsRequest; import co.elastic.clients.elasticsearch.security.SamlCompleteLogoutRequest; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/EndpointBaseTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/EndpointBaseTest.java index 2bd5db313..0d82c9dbc 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/EndpointBaseTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/EndpointBaseTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.transport.endpoints; +package co.elastic.clients.rest5_client.transport.endpoints; import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch.core.PingRequest; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/SimpleEndpointTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/SimpleEndpointTest.java index f6ee72e0e..ed0b77c50 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/SimpleEndpointTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/SimpleEndpointTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.transport.endpoints; +package co.elastic.clients.rest5_client.transport.endpoints; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch.core.CountResponse; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/http/HeaderMapTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/http/HeaderMapTest.java index df898203c..8143d0079 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/http/HeaderMapTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/http/HeaderMapTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.transport.http; +package co.elastic.clients.rest5_client.transport.http; import co.elastic.clients.transport.http.HeaderMap; import org.junit.jupiter.api.Assertions; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/instrumentation/OpenTelemetryForElasticsearchTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/instrumentation/OpenTelemetryForElasticsearchTest.java index d839840e0..d0866cae8 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/instrumentation/OpenTelemetryForElasticsearchTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/instrumentation/OpenTelemetryForElasticsearchTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.transport.instrumentation; +package co.elastic.clients.rest5_client.transport.instrumentation; import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; import co.elastic.clients.elasticsearch.ElasticsearchClient; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/MultiBufferEntityTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/MultiBufferEntityTest.java index 5461a0c93..8d2e27075 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/MultiBufferEntityTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/MultiBufferEntityTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.transport.rest_client; +package co.elastic.clients.rest5_client.transport.rest_client; import co.elastic.clients.elasticsearch.core.BulkRequest; import co.elastic.clients.json.jackson.JacksonJsonpMapper; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/RestClientOptionsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/RestClientOptionsTest.java index 7e835e687..ecdbdaa97 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/RestClientOptionsTest.java +++ b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/RestClientOptionsTest.java @@ -17,7 +17,7 @@ * under the License. */ -package clients.rest5_client.transport.rest_client; +package co.elastic.clients.rest5_client.transport.rest_client; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.JsonpMapper; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/util/DateTimeTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/util/DateTimeTest.java deleted file mode 100644 index 75aa4054b..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/util/DateTimeTest.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.util; - -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.util.DateTime; -import org.junit.jupiter.api.Test; - -import java.time.Instant; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; - -public class DateTimeTest extends ModelTestCase { - - long millis = 1643822172348L; - String millisJson = "1643822172348"; - - String text = "2022-02-02T17:16:12.348Z"; - String textJson = "\"" + text + "\""; - - @Test - public void testMillis() { - DateTime dateTime; - - dateTime = DateTime.ofEpochMilli(millis); - assertEquals(millis, dateTime.toInstant().toEpochMilli()); - - // Millis, no format - dateTime = checkJsonRoundtrip(DateTime.ofEpochMilli(millis), millisJson); - assertEquals(millis, dateTime.toEpochMilli()); - assertNull(dateTime.formatter); - - // Millis, roundtrip through ISO format - dateTime = checkJsonRoundtrip(DateTime.ofEpochMilli(millis, DateTimeFormatter.ISO_INSTANT), textJson); - assertEquals(millis, dateTime.toEpochMilli()); - assertNull(dateTime.formatter); - } - - @Test - public void testText() { - - DateTime dateTime; - - // Millis as string - dateTime = fromJson("\"1643822172348\"", DateTime.class); - assertEquals(millis, dateTime.toEpochMilli()); - assertNull(dateTime.formatter); - - DateTime dateTimeOrig = dateTime; - - // test STRICT_DATE_OPTIONAL_TIME_FORMATTER - dateTime = fromJson(textJson, DateTime.class); - assertEquals(text, dateTime.toString()); - - assertEquals(dateTime, dateTimeOrig); - - dateTime = fromJson("\"2022-02-27\"", DateTime.class); - assertEquals("2022-02-27T00:00:00Z", dateTime.toInstant().toString()); - - dateTime = fromJson("\"2022-02\"", DateTime.class); - assertEquals("2022-02-01T00:00:00Z", dateTime.toInstant().toString()); - - dateTime = fromJson("\"2022\"", DateTime.class); - assertEquals("2022-01-01T00:00:00Z", dateTime.toInstant().toString()); - - assertEquals("\"2022\"", toJson(dateTime)); - - } - - @Test - public void testInvalidString() { - - // Invalid values should be accepted, and an exception thrown - // only when we parse the value. - // This lazy parsing allows application code that doesn't access - // ill-formed data to not fail on deserialization. - DateTime dateTime = fromJson("\"foobar\"", DateTime.class); - assertEquals("foobar", dateTime.getString()); - - assertThrows(DateTimeParseException.class, dateTime::toInstant); - } - - @Test - public void testInstant() { - - DateTime dateTime; - - dateTime = DateTime.of(text, DateTimeFormatter.ISO_INSTANT); - assertEquals(millis, dateTime.toInstant().toEpochMilli()); - - assertEquals(millis, dateTime.toInstant(DateTimeFormatter.ISO_INSTANT).toEpochMilli()); - - Instant inst = Instant.ofEpochMilli(millis); - - dateTime = DateTime.of(inst); - assertEquals(millisJson, toJson(dateTime)); - - dateTime = DateTime.of(inst, DateTimeFormatter.ISO_DATE_TIME); - assertEquals(textJson, toJson(dateTime)); - - } - - @Test - public void testZonedDateTime() { - - DateTime dateTime; - ZonedDateTime zdt; - - // With timezone information - dateTime = fromJson("\"2022-02-02T18:16:12.348+01:00\"", DateTime.class); - assertEquals(millis, dateTime.toEpochMilli()); - - zdt = dateTime.toZonedDateTime(); - assertEquals(3600, zdt.getOffset().getTotalSeconds()); - - zdt = dateTime.toZonedDateTime(DateTimeFormatter.ISO_ZONED_DATE_TIME); - assertEquals(millis, zdt.toInstant().toEpochMilli()); - - assertEquals(millis, DateTime.of(millisJson).toZonedDateTime().toInstant().toEpochMilli()); - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/util/DuplicateResourceFinderTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/util/DuplicateResourceFinderTest.java deleted file mode 100644 index 360cea822..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/util/DuplicateResourceFinderTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.util; - -import co.elastic.clients.util.DuplicateResourceFinder; -import com.fasterxml.jackson.databind.ext.CoreXMLSerializers; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -class DuplicateResourceFinderTest extends Assertions { - - @Test - public void testDuplicateCheck() { - - Exception e = assertThrows(RuntimeException.class, () -> { - DuplicateResourceFinder.ensureClassUniqueness(CoreXMLSerializers.class); - }); - assertTrue(e.getMessage().contains("Several versions of")); - - // Disabling the test should not throw an exception - DuplicateResourceFinder.enableCheck(false); - DuplicateResourceFinder.ensureClassUniqueness(CoreXMLSerializers.class); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/util/NamedValueTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/util/NamedValueTest.java deleted file mode 100644 index c01c62131..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/util/NamedValueTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.util; - -import co.elastic.clients.elasticsearch._types.SortOrder; -import co.elastic.clients.elasticsearch._types.aggregations.TermsAggregation; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.util.NamedValue; -import org.junit.jupiter.api.Test; - -class NamedValueTest extends ModelTestCase { - - @Test - public void testTermAggregation() { - - String json = "{\"order\":[{\"a\":\"asc\"},{\"b\":\"desc\"}]}"; - - TermsAggregation ta = TermsAggregation.of(b -> b - .order(NamedValue.of("a", SortOrder.Asc)) - .order(NamedValue.of("b", SortOrder.Desc) - ) - ); - - ta = checkJsonRoundtrip(ta, json); - - assertEquals(2, ta.order().size()); - - assertEquals("a", ta.order().get(0).name()); - assertEquals(SortOrder.Asc, ta.order().get(0).value()); - assertEquals("b", ta.order().get(1).name()); - assertEquals(SortOrder.Desc, ta.order().get(1).value()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/util/PairTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/util/PairTest.java deleted file mode 100644 index 04d45879e..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/util/PairTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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. - */ - -package clients.rest5_client.util; - -import co.elastic.clients.elasticsearch._types.FieldValue; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.elasticsearch.watcher.Condition; -import co.elastic.clients.elasticsearch.watcher.ConditionOp; -import co.elastic.clients.util.NamedValue; -import co.elastic.clients.util.Pair; -import org.junit.jupiter.api.Test; - -class PairTest extends ModelTestCase { - - @Test - public void testCondition() { - - String json = "{\"compare\":{\"foo\":{\"eq\":\"bar\"}}}"; - - Condition c = Condition.of(b -> b - .compare(NamedValue.of("foo", Pair.of(ConditionOp.Eq, FieldValue.of("bar")))) - ); - - c = checkJsonRoundtrip(c, json); - - assertEquals("foo", c.compare().name()); - assertEquals(ConditionOp.Eq, c.compare().value().key()); - assertEquals("bar", c.compare().value().value().stringValue()); - } -} From 49b4348e9dfc73fd8df1ddf983bed539100f94b8 Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Tue, 25 Mar 2025 17:41:36 +0100 Subject: [PATCH 10/38] flatten low level client folder structure --- .../low_level/{producer => }/BasicAsyncEntityProducer.java | 4 ++-- .../{consumer => }/BasicAsyncResponseConsumer.java | 2 +- .../low_level/{consumer => }/BufferedByteConsumer.java | 4 ++-- .../rest5_client/low_level/{utils => }/Constants.java | 2 +- .../{node/selector => }/HasAttributeNodeSelector.java | 4 +--- .../{consumer => }/HttpAsyncResponseConsumerFactory.java | 4 ++-- .../transport/rest5_client/low_level/{node => }/Node.java | 3 +-- .../low_level/{node/selector => }/NodeSelector.java | 6 +----- .../{node/selector => }/PreferHasAttributeNodeSelector.java | 4 +--- .../transport/rest5_client/low_level/RequestLogger.java | 1 - .../transport/rest5_client/low_level/RequestOptions.java | 1 - .../transport/rest5_client/low_level/RestClient.java | 3 --- .../transport/rest5_client/low_level/RestClientBuilder.java | 2 -- 13 files changed, 12 insertions(+), 28 deletions(-) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/{producer => }/BasicAsyncEntityProducer.java (96%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/{consumer => }/BasicAsyncResponseConsumer.java (97%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/{consumer => }/BufferedByteConsumer.java (95%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/{utils => }/Constants.java (75%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/{node/selector => }/HasAttributeNodeSelector.java (93%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/{consumer => }/HttpAsyncResponseConsumerFactory.java (95%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/{node => }/Node.java (98%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/{node/selector => }/NodeSelector.java (91%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/{node/selector => }/PreferHasAttributeNodeSelector.java (95%) diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/producer/BasicAsyncEntityProducer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncEntityProducer.java similarity index 96% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/producer/BasicAsyncEntityProducer.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncEntityProducer.java index 40250139a..8fdd297a4 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/producer/BasicAsyncEntityProducer.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncEntityProducer.java @@ -1,4 +1,4 @@ -package co.elastic.clients.transport.rest5_client.low_level.producer; +package co.elastic.clients.transport.rest5_client.low_level; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.nio.AsyncEntityProducer; @@ -13,7 +13,7 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicReference; -import static co.elastic.clients.transport.rest5_client.low_level.utils.Constants.DEFAULT_BUFFER_INITIAL_CAPACITY; +import static co.elastic.clients.transport.rest5_client.low_level.Constants.DEFAULT_BUFFER_INITIAL_CAPACITY; /** * Basic implementation of {@link AsyncEntityProducer} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/BasicAsyncResponseConsumer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncResponseConsumer.java similarity index 97% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/BasicAsyncResponseConsumer.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncResponseConsumer.java index da7ae514d..22dc180b5 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/BasicAsyncResponseConsumer.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncResponseConsumer.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level.consumer; +package co.elastic.clients.transport.rest5_client.low_level; import org.apache.hc.core5.http.ClassicHttpResponse; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/BufferedByteConsumer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BufferedByteConsumer.java similarity index 95% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/BufferedByteConsumer.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BufferedByteConsumer.java index 2ad0f046d..debd8f9bc 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/BufferedByteConsumer.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BufferedByteConsumer.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level.consumer; +package co.elastic.clients.transport.rest5_client.low_level; import org.apache.hc.core5.http.ContentTooLongException; import org.apache.hc.core5.http.ContentType; @@ -26,7 +26,7 @@ import java.nio.ByteBuffer; -import static co.elastic.clients.transport.rest5_client.low_level.utils.Constants.DEFAULT_BUFFER_INITIAL_CAPACITY; +import static co.elastic.clients.transport.rest5_client.low_level.Constants.DEFAULT_BUFFER_INITIAL_CAPACITY; public class BufferedByteConsumer extends AbstractBinAsyncEntityConsumer { diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/utils/Constants.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Constants.java similarity index 75% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/utils/Constants.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Constants.java index f731168de..ec8962151 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/utils/Constants.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Constants.java @@ -1,4 +1,4 @@ -package co.elastic.clients.transport.rest5_client.low_level.utils; +package co.elastic.clients.transport.rest5_client.low_level; public class Constants { // default buffer limit is 100MB diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/HasAttributeNodeSelector.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HasAttributeNodeSelector.java similarity index 93% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/HasAttributeNodeSelector.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HasAttributeNodeSelector.java index 20062ad95..c979a3a80 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/HasAttributeNodeSelector.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HasAttributeNodeSelector.java @@ -17,9 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level.node.selector; - -import co.elastic.clients.transport.rest5_client.low_level.node.Node; +package co.elastic.clients.transport.rest5_client.low_level; import java.util.Iterator; import java.util.List; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/HttpAsyncResponseConsumerFactory.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpAsyncResponseConsumerFactory.java similarity index 95% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/HttpAsyncResponseConsumerFactory.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpAsyncResponseConsumerFactory.java index 1d94ca171..7730c3837 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/consumer/HttpAsyncResponseConsumerFactory.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpAsyncResponseConsumerFactory.java @@ -16,13 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level.consumer; +package co.elastic.clients.transport.rest5_client.low_level; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.nio.AsyncResponseConsumer; import org.apache.hc.core5.http.nio.support.AbstractAsyncResponseConsumer; -import static co.elastic.clients.transport.rest5_client.low_level.utils.Constants.DEFAULT_BUFFER_LIMIT; +import static co.elastic.clients.transport.rest5_client.low_level.Constants.DEFAULT_BUFFER_LIMIT; /** * Factory used to create instances of {@link AsyncResponseConsumer}. Each request retry needs its own diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/Node.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Node.java similarity index 98% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/Node.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Node.java index 32ec1e845..29a0ef916 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/Node.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Node.java @@ -17,9 +17,8 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level.node; +package co.elastic.clients.transport.rest5_client.low_level; -import co.elastic.clients.transport.rest5_client.low_level.node.selector.NodeSelector; import org.apache.hc.core5.http.HttpHost; import java.util.List; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/NodeSelector.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/NodeSelector.java similarity index 91% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/NodeSelector.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/NodeSelector.java index 1231e7785..2c112dc59 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/NodeSelector.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/NodeSelector.java @@ -17,11 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level.node.selector; - -import co.elastic.clients.transport.rest5_client.low_level.RestClient; -import co.elastic.clients.transport.rest5_client.low_level.RestClientBuilder; -import co.elastic.clients.transport.rest5_client.low_level.node.Node; +package co.elastic.clients.transport.rest5_client.low_level; import java.util.Iterator; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/PreferHasAttributeNodeSelector.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/PreferHasAttributeNodeSelector.java similarity index 95% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/PreferHasAttributeNodeSelector.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/PreferHasAttributeNodeSelector.java index 91a69977a..6526ec071 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/node/selector/PreferHasAttributeNodeSelector.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/PreferHasAttributeNodeSelector.java @@ -17,9 +17,7 @@ * under the License. */ -package co.elastic.clients.transport.rest5_client.low_level.node.selector; - -import co.elastic.clients.transport.rest5_client.low_level.node.Node; +package co.elastic.clients.transport.rest5_client.low_level; import java.util.Iterator; import java.util.List; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestLogger.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestLogger.java index 06c309b53..517bca27c 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestLogger.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestLogger.java @@ -19,7 +19,6 @@ package co.elastic.clients.transport.rest5_client.low_level; -import co.elastic.clients.transport.rest5_client.low_level.node.Node; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hc.client5.http.classic.methods.HttpUriRequest; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptions.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptions.java index 079e37bc2..a60d87db9 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptions.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptions.java @@ -19,7 +19,6 @@ package co.elastic.clients.transport.rest5_client.low_level; -import co.elastic.clients.transport.rest5_client.low_level.consumer.HttpAsyncResponseConsumerFactory; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.message.BasicHeader; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClient.java index 5dcb7c154..fa1b771d9 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClient.java @@ -18,9 +18,6 @@ */ package co.elastic.clients.transport.rest5_client.low_level; -import co.elastic.clients.transport.rest5_client.low_level.node.Node; -import co.elastic.clients.transport.rest5_client.low_level.node.selector.NodeSelector; -import co.elastic.clients.transport.rest5_client.low_level.producer.BasicAsyncEntityProducer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hc.client5.http.ClientProtocolException; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilder.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilder.java index 4c8000a1b..c932225b3 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilder.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilder.java @@ -20,8 +20,6 @@ package co.elastic.clients.transport.rest5_client.low_level; -import co.elastic.clients.transport.rest5_client.low_level.node.Node; -import co.elastic.clients.transport.rest5_client.low_level.node.selector.NodeSelector; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; From ae24edcc9205591000e72da8a290fc3875426830 Mon Sep 17 00:00:00 2001 From: Sylvain Wallez Date: Wed, 26 Mar 2025 11:47:15 +0100 Subject: [PATCH 11/38] Move things around, remove duplicated tests --- .../rest_client/RestTransportClientTest.java | 8 +- .../clients/esql/article/EsqlArticle.java | 2 +- .../ElasticsearchClientBuilder.java | 16 +- ...Client.java => Rest5ClientHttpClient.java} | 26 +- ...ntOptions.java => Rest5ClientOptions.java} | 20 +- ...ansport.java => Rest5ClientTransport.java} | 18 +- .../rest5_client/low_level/Cancellable.java | 2 +- .../rest5_client/low_level/NodeSelector.java | 4 +- .../low_level/RequestOptions.java | 4 +- .../low_level/ResponseListener.java | 4 +- .../{RestClient.java => Rest5Client.java} | 32 +- ...ntBuilder.java => Rest5ClientBuilder.java} | 38 +- .../low_level/WarningFailureException.java | 4 +- .../rest_client/RestClientHttpClient.java | 2 +- .../documentation/DocTestsTransport.java | 4 + .../ElasticsearchTestServer.java | 53 +- .../_helpers}/ClientBuildersTest.java | 3 +- .../model/BehaviorsTest2.java} | 7 +- .../documentation/DocTestsTransport.java | 119 ---- .../api_conventions/ApiConventionsTest.java | 366 ---------- .../api_conventions/LoadingJsonTest.java | 193 ------ .../getting_started/ConnectingTest.java | 191 ------ .../troubleshooting/TroubleShootingTests.java | 93 --- .../documentation/usage/AggregationsTest.java | 107 --- .../documentation/usage/IndexingBulkTest.java | 214 ------ .../documentation/usage/IndexingTest.java | 209 ------ .../documentation/usage/Product.java | 57 -- .../documentation/usage/ReadingTest.java | 98 --- .../documentation/usage/SearchingTest.java | 198 ------ .../ElasticsearchTestServer.java | 294 -------- .../bulk/BulkIngesterRetryPolicyTest.java | 546 --------------- .../_helpers/bulk/BulkIngesterTest.java | 627 ------------------ .../esql/EsqlAdapterEndToEndTest.java | 205 ------ .../_helpers/esql/EsqlAdapterTest.java | 119 ---- .../elasticsearch/end_to_end/RequestTest.java | 494 -------------- .../experiments/ClientTests.java | 108 --- .../experiments/ParsingTests.java | 76 --- .../experiments/UnionVariant.java | 31 - .../elasticsearch/experiments/api/Bar.java | 82 --- .../experiments/api/DateMathTimeUnit.java | 49 -- .../experiments/api/FooOptRequest.java | 278 -------- .../experiments/api/FooRequest.java | 317 --------- .../experiments/api/FooResponse.java | 27 - .../experiments/api/query2/BoolQuery.java | 175 ----- .../experiments/api/query2/Query.java | 207 ------ .../experiments/api/query2/QueryTest.java | 46 -- .../experiments/api/query2/TermsQuery.java | 108 --- .../experiments/api/query2/Union2.java | 154 ----- .../experiments/base/Client.java | 48 -- .../experiments/base/PrimitiveUtils.java | 41 -- .../experiments/base/Variants.java | 155 ----- .../experiments/containers/SomeUnion.java | 155 ----- .../experiments/containers/SomeUnionTest.java | 86 --- .../containers/SomeUnionVariant.java | 25 - .../experiments/containers/UVariantA.java | 83 --- .../experiments/containers/UVariantB.java | 83 --- .../experiments/generics/GenericClass.java | 123 ---- .../inheritance/InheritanceTest.java | 97 --- .../inheritance/base/BaseClass.java | 77 --- .../inheritance/child/ChildClass.java | 93 --- .../inheritance/final_/FinalClass.java | 98 --- .../experiments/package-info.java | 23 - .../elasticsearch/model/BuiltinTypesTest.java | 273 -------- .../model/ClassStructureTest.java | 361 ---------- .../model/CodeAdditionsTests.java | 49 -- .../elasticsearch/model/EndpointTest.java | 94 --- .../elasticsearch/model/EnumTest.java | 61 -- .../model/RequestEncodingTest.java | 59 -- .../model/SerializationTest.java | 134 ---- .../elasticsearch/model/TypedKeysTest.java | 299 --------- .../elasticsearch/model/UnionTests.java | 354 ---------- .../elasticsearch/model/VariantsTest.java | 351 ---------- .../elasticsearch/model/package-info.java | 24 - .../spec_issues/SpecIssuesTest.java | 316 --------- .../endpoints/BinaryEndpointTest.java | 130 ---- .../endpoints/BooleanEndpointTest.java | 37 -- .../transport/endpoints/EndpointBaseTest.java | 70 -- .../endpoints/SimpleEndpointTest.java | 71 -- .../transport/http/HeaderMapTest.java | 79 --- .../OpenTelemetryForElasticsearchTest.java | 277 -------- .../clients/transport/RequestOptionsTest.java | 5 +- .../rest5_client}/MultiBufferEntityTest.java | 11 +- .../rest5_client}/RequestOptionsTest.java | 21 +- .../rest5_client/Rest5ClientOptionsTest.java} | 56 +- .../rest5_client}/TransportTest.java | 24 +- .../rest5_client}/TransportUtilsTest.java | 11 +- 86 files changed, 201 insertions(+), 10188 deletions(-) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{RestClientHttpClient.java => Rest5ClientHttpClient.java} (91%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{RestClientOptions.java => Rest5ClientOptions.java} (92%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/{RestClientTransport.java => Rest5ClientTransport.java} (62%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/{RestClient.java => Rest5Client.java} (97%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/{RestClientBuilder.java => Rest5ClientBuilder.java} (90%) rename java-client/src/test/java/co/elastic/clients/{rest5_client/elasticsearch/_helpers/builders => elasticsearch/_helpers}/ClientBuildersTest.java (95%) rename java-client/src/test/java/co/elastic/clients/{rest5_client/elasticsearch/model/BehaviorsTest.java => elasticsearch/model/BehaviorsTest2.java} (98%) delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/DocTestsTransport.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/ApiConventionsTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/LoadingJsonTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/getting_started/ConnectingTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/troubleshooting/TroubleShootingTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/AggregationsTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingBulkTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/Product.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/ReadingTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/SearchingTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/ElasticsearchTestServer.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/end_to_end/RequestTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ClientTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ParsingTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/UnionVariant.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/Bar.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/DateMathTimeUnit.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooOptRequest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooRequest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooResponse.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/BoolQuery.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Query.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/QueryTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/TermsQuery.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Union2.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Client.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/PrimitiveUtils.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Variants.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnion.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionVariant.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantA.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantB.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/generics/GenericClass.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/InheritanceTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/base/BaseClass.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/child/ChildClass.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/final_/FinalClass.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/package-info.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BuiltinTypesTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/ClassStructureTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/CodeAdditionsTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EndpointTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EnumTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/RequestEncodingTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/SerializationTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/TypedKeysTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/UnionTests.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/VariantsTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/package-info.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/spec_issues/SpecIssuesTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BinaryEndpointTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BooleanEndpointTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/EndpointBaseTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/SimpleEndpointTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/http/HeaderMapTest.java delete mode 100644 java-client/src/test/java/co/elastic/clients/rest5_client/transport/instrumentation/OpenTelemetryForElasticsearchTest.java rename java-client/src/test/java/co/elastic/clients/{rest5_client/transport/rest_client => transport/rest5_client}/MultiBufferEntityTest.java (88%) rename java-client/src/test/java/co/elastic/clients/{rest5_client/transport => transport/rest5_client}/RequestOptionsTest.java (87%) rename java-client/src/test/java/co/elastic/clients/{rest5_client/transport/rest_client/RestClientOptionsTest.java => transport/rest5_client/Rest5ClientOptionsTest.java} (76%) rename java-client/src/test/java/co/elastic/clients/{rest5_client/transport => transport/rest5_client}/TransportTest.java (88%) rename java-client/src/test/java/co/elastic/clients/{rest5_client/transport => transport/rest5_client}/TransportUtilsTest.java (89%) diff --git a/example-transports/src/test/java/co/elastic/clients/transport/rest_client/RestTransportClientTest.java b/example-transports/src/test/java/co/elastic/clients/transport/rest_client/RestTransportClientTest.java index d0d29569e..446965cbe 100644 --- a/example-transports/src/test/java/co/elastic/clients/transport/rest_client/RestTransportClientTest.java +++ b/example-transports/src/test/java/co/elastic/clients/transport/rest_client/RestTransportClientTest.java @@ -20,21 +20,21 @@ package co.elastic.clients.transport.rest_client; import co.elastic.clients.transport.TransportHttpClientTest; -import co.elastic.clients.transport.rest5_client.RestClientHttpClient; +import co.elastic.clients.transport.rest5_client.Rest5ClientHttpClient; import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; -public class RestTransportClientTest extends TransportHttpClientTest { +public class RestTransportClientTest extends TransportHttpClientTest { public RestTransportClientTest() { super(createClient()); } - private static RestClientHttpClient createClient() { + private static Rest5ClientHttpClient createClient() { RestClient restClient = RestClient.builder( new HttpHost(server.getAddress().getAddress(), server.getAddress().getPort(), "http") ).build(); - return new RestClientHttpClient(restClient); + return new Rest5ClientHttpClient(restClient); } } diff --git a/examples/esql-article/src/main/java/co/elastic/clients/esql/article/EsqlArticle.java b/examples/esql-article/src/main/java/co/elastic/clients/esql/article/EsqlArticle.java index 9544db0c2..e73af8fac 100644 --- a/examples/esql-article/src/main/java/co/elastic/clients/esql/article/EsqlArticle.java +++ b/examples/esql-article/src/main/java/co/elastic/clients/esql/article/EsqlArticle.java @@ -25,7 +25,7 @@ import co.elastic.clients.elasticsearch.core.bulk.BulkOperation; import co.elastic.clients.json.jackson.JacksonJsonpMapper; import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.rest5_client.RestClientTransport; +import co.elastic.clients.transport.rest_client.RestClientTransport; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.MappingIterator; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/rest5_client/ElasticsearchClientBuilder.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/rest5_client/ElasticsearchClientBuilder.java index 4e673dedd..736758467 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/rest5_client/ElasticsearchClientBuilder.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/rest5_client/ElasticsearchClientBuilder.java @@ -22,10 +22,10 @@ import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.JsonpMapper; import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.rest5_client.RestClientOptions; -import co.elastic.clients.transport.rest5_client.RestClientTransport; -import co.elastic.clients.transport.rest5_client.low_level.RestClient; -import co.elastic.clients.transport.rest5_client.low_level.RestClientBuilder; +import co.elastic.clients.transport.rest5_client.Rest5ClientOptions; +import co.elastic.clients.transport.rest5_client.Rest5ClientTransport; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; +import co.elastic.clients.transport.rest5_client.low_level.Rest5ClientBuilder; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.json.JsonMapper; import org.apache.hc.core5.http.Header; @@ -48,7 +48,7 @@ public class ElasticsearchClientBuilder { private String apiKey; private SSLContext sslContext; private JsonpMapper mapper; - private RestClientOptions transportOptions; + private Rest5ClientOptions transportOptions; public ElasticsearchClientBuilder host(String url) throws URISyntaxException { this.host = HttpHost.create(url); @@ -81,7 +81,7 @@ public ElasticsearchClientBuilder jsonMapper(JsonpMapper mapper) { return this; } - public ElasticsearchClientBuilder transportOptions(RestClientOptions transportOptions) { + public ElasticsearchClientBuilder transportOptions(Rest5ClientOptions transportOptions) { this.transportOptions = transportOptions; return this; } @@ -97,7 +97,7 @@ public ElasticsearchClient build() { } } - RestClientBuilder restClientBuilder = RestClient.builder(host); + Rest5ClientBuilder restClientBuilder = Rest5Client.builder(host); if (this.username != null && this.password != null) { var cred = Base64.getEncoder().encodeToString((username + ":" + password).getBytes()); @@ -125,7 +125,7 @@ public ElasticsearchClient build() { this.mapper = new JacksonJsonpMapper(mapper); } - RestClientTransport transport = new RestClientTransport(restClientBuilder.build(), mapper, transportOptions); + Rest5ClientTransport transport = new Rest5ClientTransport(restClientBuilder.build(), mapper, transportOptions); return new ElasticsearchClient(transport); } } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientHttpClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java similarity index 91% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientHttpClient.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java index cb2633680..792434303 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientHttpClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java @@ -26,7 +26,7 @@ import co.elastic.clients.transport.rest5_client.low_level.ESRequest; import co.elastic.clients.transport.rest5_client.low_level.ESResponse; import co.elastic.clients.transport.rest5_client.low_level.ResponseListener; -import co.elastic.clients.transport.rest5_client.low_level.RestClient; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; import co.elastic.clients.util.BinaryData; import co.elastic.clients.util.NoCopyByteArrayOutputStream; import org.apache.hc.core5.http.ContentType; @@ -48,13 +48,13 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; -public class RestClientHttpClient implements TransportHttpClient { +public class Rest5ClientHttpClient implements TransportHttpClient { private static final ConcurrentHashMap ContentTypeCache = new ConcurrentHashMap<>(); /** * The {@code Future} implementation returned by async requests. - * It wraps the RestClient's cancellable and propagates cancellation. + * It wraps the Rest5Client's cancellable and propagates cancellation. */ private static class RequestFuture extends CompletableFuture { private volatile Cancellable cancellable; @@ -69,28 +69,28 @@ public boolean cancel(boolean mayInterruptIfRunning) { } } - private final RestClient restClient; + private final Rest5Client restClient; - public RestClientHttpClient(RestClient restClient) { + public Rest5ClientHttpClient(Rest5Client restClient) { this.restClient = restClient; } /** * Returns the underlying low level Rest Client used by this transport. */ - public RestClient restClient() { + public Rest5Client restClient() { return this.restClient; } @Override - public RestClientOptions createOptions(@Nullable TransportOptions options) { - return RestClientOptions.of(options); + public Rest5ClientOptions createOptions(@Nullable TransportOptions options) { + return Rest5ClientOptions.of(options); } @Override public Response performRequest(String endpointId, @Nullable Node node, Request request, TransportOptions options) throws IOException { - RestClientOptions rcOptions = RestClientOptions.of(options); + Rest5ClientOptions rcOptions = Rest5ClientOptions.of(options); ESRequest restRequest = createRestRequest(request, rcOptions); ESResponse restResponse = restClient.performRequest(restRequest); return new RestResponse(restResponse); @@ -105,7 +105,7 @@ public CompletableFuture performRequestAsync( ESRequest restRequest; try { - RestClientOptions rcOptions = RestClientOptions.of(options); + Rest5ClientOptions rcOptions = Rest5ClientOptions.of(options); restRequest = createRestRequest(request, rcOptions); } catch (Throwable thr) { // Terminate early @@ -133,7 +133,7 @@ public void close() throws IOException { this.restClient.close(); } - private ESRequest createRestRequest(Request request, RestClientOptions options) { + private ESRequest createRestRequest(Request request, Rest5ClientOptions options) { ESRequest clientReq = new ESRequest( request.method(), request.path() ); @@ -146,10 +146,10 @@ private ESRequest createRestRequest(Request request, RestClientOptions options) int headerCount = requestHeaders.size(); if ((body == null && headerCount != 3) || headerCount != 4) { if (options == null) { - options = RestClientOptions.initialOptions(); + options = Rest5ClientOptions.initialOptions(); } - RestClientOptions.Builder builder = options.toBuilder(); + Rest5ClientOptions.Builder builder = options.toBuilder(); for (Map.Entry header : requestHeaders.entrySet()) { builder.setHeader(header.getKey(), header.getValue()); } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientOptions.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientOptions.java similarity index 92% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientOptions.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientOptions.java index f861edef0..713357e03 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientOptions.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientOptions.java @@ -38,7 +38,7 @@ import java.util.function.Function; import java.util.stream.Collectors; -public class RestClientOptions implements TransportOptions { +public class Rest5ClientOptions implements TransportOptions { private final RequestOptions options; @@ -49,13 +49,13 @@ public class RestClientOptions implements TransportOptions { @VisibleForTesting static final String USER_AGENT_VALUE = getUserAgent(); - static RestClientOptions of(@Nullable TransportOptions options) { + static Rest5ClientOptions of(@Nullable TransportOptions options) { if (options == null) { return initialOptions(); } - if (options instanceof RestClientOptions) { - return (RestClientOptions)options; + if (options instanceof Rest5ClientOptions) { + return (Rest5ClientOptions)options; } final Builder builder = new Builder(RequestOptions.DEFAULT.toBuilder()); @@ -65,7 +65,7 @@ static RestClientOptions of(@Nullable TransportOptions options) { return builder.build(); } - public RestClientOptions(RequestOptions options, boolean keepResponseBodyOnException) { + public Rest5ClientOptions(RequestOptions options, boolean keepResponseBodyOnException) { this.keepResponseBodyOnException = keepResponseBodyOnException; this.options = addBuiltinHeaders(options.toBuilder()).build(); } @@ -203,13 +203,13 @@ public TransportOptions.Builder keepResponseBodyOnException(boolean value) { } @Override - public RestClientOptions build() { - return new RestClientOptions(addBuiltinHeaders(builder).build(), keepResponseBodyOnException); + public Rest5ClientOptions build() { + return new Rest5ClientOptions(addBuiltinHeaders(builder).build(), keepResponseBodyOnException); } } - static RestClientOptions initialOptions() { - return new RestClientOptions(RequestOptions.DEFAULT, false); + static Rest5ClientOptions initialOptions() { + return new Rest5ClientOptions(RequestOptions.DEFAULT, false); } private static RequestOptions.Builder addBuiltinHeaders(RequestOptions.Builder builder) { @@ -219,7 +219,7 @@ private static RequestOptions.Builder addBuiltinHeaders(RequestOptions.Builder b builder.addHeader(HeaderMap.USER_AGENT, USER_AGENT_VALUE); } if (builder.getHeaders().stream().noneMatch(h -> h.getName().equalsIgnoreCase(HeaderMap.ACCEPT))) { - builder.addHeader(HeaderMap.ACCEPT, RestClientTransport.JSON_CONTENT_TYPE); + builder.addHeader(HeaderMap.ACCEPT, Rest5ClientTransport.JSON_CONTENT_TYPE); } return builder; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientTransport.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java similarity index 62% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientTransport.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java index 2fb481c09..e30353d7f 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/RestClientTransport.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java @@ -22,27 +22,27 @@ import co.elastic.clients.json.JsonpMapper; import co.elastic.clients.transport.ElasticsearchTransportBase; import co.elastic.clients.transport.instrumentation.Instrumentation; -import co.elastic.clients.transport.rest5_client.low_level.RestClient; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; -public class RestClientTransport extends ElasticsearchTransportBase { +public class Rest5ClientTransport extends ElasticsearchTransportBase { - private final RestClient restClient; + private final Rest5Client restClient; - public RestClientTransport(RestClient restClient, JsonpMapper jsonpMapper) { + public Rest5ClientTransport(Rest5Client restClient, JsonpMapper jsonpMapper) { this(restClient, jsonpMapper, null); } - public RestClientTransport(RestClient restClient, JsonpMapper jsonpMapper, RestClientOptions options) { - super(new RestClientHttpClient(restClient), options, jsonpMapper, null); + public Rest5ClientTransport(Rest5Client restClient, JsonpMapper jsonpMapper, Rest5ClientOptions options) { + super(new Rest5ClientHttpClient(restClient), options, jsonpMapper, null); this.restClient = restClient; } - public RestClientTransport(RestClient restClient, JsonpMapper jsonpMapper, RestClientOptions options, Instrumentation instrumentation) { - super(new RestClientHttpClient(restClient), options, jsonpMapper, instrumentation); + public Rest5ClientTransport(Rest5Client restClient, JsonpMapper jsonpMapper, Rest5ClientOptions options, Instrumentation instrumentation) { + super(new Rest5ClientHttpClient(restClient), options, jsonpMapper, instrumentation); this.restClient = restClient; } - public RestClient restClient() { + public Rest5Client restClient() { return this.restClient; } } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Cancellable.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Cancellable.java index 77992fcfa..8cc8d2391 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Cancellable.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Cancellable.java @@ -26,7 +26,7 @@ /** * Represents an operation that can be cancelled. * Returned when executing async requests through - * {@link RestClient#performRequestAsync(ESRequest, ResponseListener)}, so that the request + * {@link Rest5Client#performRequestAsync(ESRequest, ResponseListener)}, so that the request * can be cancelled if needed. Cancelling a request will result in calling * {@link HttpUriRequestBase#abort()} on the underlying * request object, which will in turn cancel its corresponding {@link java.util.concurrent.Future}. diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/NodeSelector.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/NodeSelector.java index 2c112dc59..80a2aba4e 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/NodeSelector.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/NodeSelector.java @@ -24,7 +24,7 @@ /** * Selects nodes that can receive requests. Used to keep requests away * from master nodes or to send them to nodes with a particular attribute. - * Use with {@link RestClientBuilder#setNodeSelector(NodeSelector)}. + * Use with {@link Rest5ClientBuilder#setNodeSelector(NodeSelector)}. */ public interface NodeSelector { /** @@ -37,7 +37,7 @@ public interface NodeSelector { * This may be called twice per request: first for "living" nodes that * have not been blacklisted by previous errors. If the selector removes * all nodes from the list or if there aren't any living nodes then the - * {@link RestClient} will call this method with a list of "dead" nodes. + * {@link Rest5Client} will call this method with a list of "dead" nodes. *

* Implementers should not rely on the ordering of the nodes. */ diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptions.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptions.java index a60d87db9..7df4dd4f1 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptions.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptions.java @@ -111,7 +111,7 @@ public HttpAsyncResponseConsumerFactory getHttpAsyncResponseConsumerFactory() { /** * How this request should handle warnings. If null (the default) then * this request will default to the behavior dictacted by - * {@link RestClientBuilder#setStrictDeprecationMode}. + * {@link Rest5ClientBuilder#setStrictDeprecationMode}. *

* This can be set to {@link WarningsHandler#PERMISSIVE} if the client * should ignore all warnings which is the same behavior as setting @@ -274,7 +274,7 @@ public Builder setHttpAsyncResponseConsumerFactory(HttpAsyncResponseConsumerFact /** * How this request should handle warnings. If null (the default) then * this request will default to the behavior dictacted by - * {@link RestClientBuilder#setStrictDeprecationMode}. + * {@link Rest5ClientBuilder#setStrictDeprecationMode}. *

* This can be set to {@link WarningsHandler#PERMISSIVE} if the client * should ignore all warnings which is the same behavior as setting diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseListener.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseListener.java index 5994b107c..079a50405 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseListener.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseListener.java @@ -20,12 +20,12 @@ package co.elastic.clients.transport.rest5_client.low_level; /** - * Listener to be provided when calling async performRequest methods provided by {@link RestClient}. + * Listener to be provided when calling async performRequest methods provided by {@link Rest5Client}. * Those methods that do accept a listener will return immediately, execute asynchronously, and notify * the listener whenever the request yielded a response, or failed with an exception. * *

- * Note that it is not safe to call {@link RestClient#close()} from either of these + * Note that it is not safe to call {@link Rest5Client#close()} from either of these * callbacks. */ public interface ResponseListener { diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java similarity index 97% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClient.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java index fa1b771d9..ec5c9bce7 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java @@ -90,7 +90,7 @@ /** * Client that connects to an Elasticsearch cluster through HTTP. *

- * Must be created using {@link RestClientBuilder}, which allows to set all the different options or just + * Must be created using {@link Rest5ClientBuilder}, which allows to set all the different options or just * rely on defaults. * The hosts that are part of the cluster need to be provided at creation time, but can also be replaced later * by calling {@link #setNodes(Collection)}. @@ -110,11 +110,11 @@ * Requests can be traced by enabling trace logging for "tracer". The trace logger outputs requests and * responses in curl format. */ -public class RestClient implements Closeable { +public class Rest5Client implements Closeable { public static final String IGNORE_RESPONSE_CODES_PARAM = "ignore"; - private static final Log logger = LogFactory.getLog(RestClient.class); + private static final Log logger = LogFactory.getLog(Rest5Client.class); private final CloseableHttpAsyncClient client; // We don't rely on default headers supported by HttpAsyncClient as those cannot be replaced. @@ -130,7 +130,7 @@ public class RestClient implements Closeable { private final boolean compressionEnabled; private final boolean metaHeaderEnabled; - RestClient( + Rest5Client( CloseableHttpAsyncClient client, Header[] defaultHeaders, List nodes, @@ -153,14 +153,14 @@ public class RestClient implements Closeable { } /** - * Returns a new {@link RestClientBuilder} to help with {@link RestClient} creation. + * Returns a new {@link Rest5ClientBuilder} to help with {@link Rest5Client} creation. * Creates a new builder instance and sets the nodes that the client will send requests to. * * @param cloudId a valid elastic cloud cloudId that will route to a cluster. The cloudId is located in * the user console https://cloud.elastic.co and will resemble a string like the following * optionalHumanReadableName:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRlbGFzdGljc2VhcmNoJGtpYmFuYQ== */ - public static RestClientBuilder builder(String cloudId) { + public static Rest5ClientBuilder builder(String cloudId) { // there is an optional first portion of the cloudId that is a human readable string, but it is not // used. if (cloudId.contains(":")) { @@ -201,18 +201,18 @@ public static RestClientBuilder builder(String cloudId) { } /** - * Returns a new {@link RestClientBuilder} to help with {@link RestClient} creation. + * Returns a new {@link Rest5ClientBuilder} to help with {@link Rest5Client} creation. * Creates a new builder instance and sets the hosts that the client will send requests to. *

* Prefer this to {@link #builder(HttpHost...)} if you have metadata up front about the nodes. * If you don't either one is fine. */ - public static RestClientBuilder builder(Node... nodes) { - return new RestClientBuilder(nodes == null ? null : Arrays.asList(nodes)); + public static Rest5ClientBuilder builder(Node... nodes) { + return new Rest5ClientBuilder(nodes == null ? null : Arrays.asList(nodes)); } /** - * Returns a new {@link RestClientBuilder} to help with {@link RestClient} creation. + * Returns a new {@link Rest5ClientBuilder} to help with {@link Rest5Client} creation. * Creates a new builder instance and sets the nodes that the client will send requests to. *

* You can use this if you do not have metadata up front about the nodes. If you do, prefer @@ -220,12 +220,12 @@ public static RestClientBuilder builder(Node... nodes) { * * @see Node#Node(HttpHost) */ - public static RestClientBuilder builder(HttpHost... hosts) { + public static Rest5ClientBuilder builder(HttpHost... hosts) { if (hosts == null || hosts.length == 0) { throw new IllegalArgumentException("hosts must not be null nor empty"); } List nodes = Arrays.stream(hosts).map(Node::new).collect(Collectors.toList()); - return new RestClientBuilder(nodes); + return new Rest5ClientBuilder(nodes); } /** @@ -828,7 +828,7 @@ private class InternalRequest { setHeaders(httpRequest, request.getOptions().getHeaders()); setRequestConfig(httpRequest, request.getOptions().getRequestConfig()); this.warningsHandler = request.getOptions().getWarningsHandler() == null - ? RestClient.this.warningsHandler + ? Rest5Client.this.warningsHandler : request.getOptions().getWarningsHandler(); } @@ -849,11 +849,11 @@ private void setHeaders(HttpRequest req, Collection

requestHeaders) { req.addHeader("Accept-Encoding", "gzip"); } if (metaHeaderEnabled) { - if (!req.containsHeader(RestClientBuilder.META_HEADER_NAME)) { - req.setHeader(RestClientBuilder.META_HEADER_NAME, RestClientBuilder.META_HEADER_VALUE); + if (!req.containsHeader(Rest5ClientBuilder.META_HEADER_NAME)) { + req.setHeader(Rest5ClientBuilder.META_HEADER_NAME, Rest5ClientBuilder.META_HEADER_VALUE); } } else { - req.removeHeaders(RestClientBuilder.META_HEADER_NAME); + req.removeHeaders(Rest5ClientBuilder.META_HEADER_NAME); } } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilder.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5ClientBuilder.java similarity index 90% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilder.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5ClientBuilder.java index c932225b3..b6362147f 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilder.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5ClientBuilder.java @@ -46,13 +46,13 @@ import static co.elastic.clients.transport.rest5_client.low_level.LanguageRuntimeVersions.getRuntimeMetadata; /** - * Helps creating a new {@link RestClient}. Allows to set the most common http client configuration options + * Helps creating a new {@link Rest5Client}. Allows to set the most common http client configuration options * when internally * creating the underlying {@link org.apache.hc.client5.http.async.HttpAsyncClient}. Also allows to provide * an externally created * {@link org.apache.hc.client5.http.async.HttpAsyncClient} in case additional customization is needed. */ -public final class RestClientBuilder { +public final class Rest5ClientBuilder { public static final int DEFAULT_CONNECT_TIMEOUT_MILLIS = 1000; public static final int DEFAULT_SOCKET_TIMEOUT_MILLIS = 30000; public static final int DEFAULT_MAX_CONN_PER_ROUTE = 10; @@ -71,7 +71,7 @@ public final class RestClientBuilder { private final List nodes; private CloseableHttpAsyncClient httpClient; private Header[] defaultHeaders = EMPTY_HEADERS; - private RestClient.FailureListener failureListener; + private Rest5Client.FailureListener failureListener; private SSLContext sslContext; private String pathPrefix; private NodeSelector nodeSelector = NodeSelector.ANY; @@ -84,7 +84,7 @@ public final class RestClientBuilder { // can't find it. // Better have incomplete telemetry than crashing user applications. String version = null; - try (InputStream is = RestClient.class.getResourceAsStream("version.properties")) { + try (InputStream is = Rest5Client.class.getResourceAsStream("version.properties")) { if (is != null) { Properties versions = new Properties(); versions.load(is); @@ -142,7 +142,7 @@ public final class RestClientBuilder { * * @throws IllegalArgumentException if {@code nodes} is {@code null} or empty. */ - RestClientBuilder(List nodes) { + Rest5ClientBuilder(List nodes) { if (nodes == null || nodes.isEmpty()) { throw new IllegalArgumentException("nodes must not be null or empty"); } @@ -160,7 +160,7 @@ public final class RestClientBuilder { * * @throws NullPointerException if {@code httpAsyncClient} is {@code null}. */ - public RestClientBuilder setCustomRestClient(CloseableHttpAsyncClient httpAsyncClient) { + public Rest5ClientBuilder setCustomRestClient(CloseableHttpAsyncClient httpAsyncClient) { Objects.requireNonNull(httpAsyncClient, "custom rest client must not be null"); this.httpClient = httpAsyncClient; return this; @@ -171,7 +171,7 @@ public RestClientBuilder setCustomRestClient(CloseableHttpAsyncClient httpAsyncC * * @throws NullPointerException if {@code httpAsyncClient} is {@code null}. */ - public RestClientBuilder setSslContext(SSLContext sslContext) { + public Rest5ClientBuilder setSslContext(SSLContext sslContext) { Objects.requireNonNull(sslContext, "ssl context must not be null"); this.sslContext = sslContext; return this; @@ -184,7 +184,7 @@ public RestClientBuilder setSslContext(SSLContext sslContext) { * * @throws NullPointerException if {@code defaultHeaders} or any header is {@code null}. */ - public RestClientBuilder setDefaultHeaders(Header[] defaultHeaders) { + public Rest5ClientBuilder setDefaultHeaders(Header[] defaultHeaders) { Objects.requireNonNull(defaultHeaders, "defaultHeaders must not be null"); for (Header defaultHeader : defaultHeaders) { Objects.requireNonNull(defaultHeader, "default header must not be null"); @@ -195,11 +195,11 @@ public RestClientBuilder setDefaultHeaders(Header[] defaultHeaders) { /** - * Sets the {@link RestClient.FailureListener} to be notified for each request failure + * Sets the {@link Rest5Client.FailureListener} to be notified for each request failure * * @throws NullPointerException if {@code failureListener} is {@code null}. */ - public RestClientBuilder setFailureListener(RestClient.FailureListener failureListener) { + public Rest5ClientBuilder setFailureListener(Rest5Client.FailureListener failureListener) { Objects.requireNonNull(failureListener, "failureListener must not be null"); this.failureListener = failureListener; return this; @@ -221,7 +221,7 @@ public RestClientBuilder setFailureListener(RestClient.FailureListener failureLi * @throws NullPointerException if {@code pathPrefix} is {@code null}. * @throws IllegalArgumentException if {@code pathPrefix} is empty, or ends with more than one '/'. */ - public RestClientBuilder setPathPrefix(String pathPrefix) { + public Rest5ClientBuilder setPathPrefix(String pathPrefix) { this.pathPrefix = cleanPathPrefix(pathPrefix); return this; } @@ -254,7 +254,7 @@ public static String cleanPathPrefix(String pathPrefix) { * * @throws NullPointerException if the provided nodeSelector is null */ - public RestClientBuilder setNodeSelector(NodeSelector nodeSelector) { + public Rest5ClientBuilder setNodeSelector(NodeSelector nodeSelector) { Objects.requireNonNull(nodeSelector, "nodeSelector must not be null"); this.nodeSelector = nodeSelector; return this; @@ -264,7 +264,7 @@ public RestClientBuilder setNodeSelector(NodeSelector nodeSelector) { * Whether the REST client should return any response containing at least * one warning header as a failure. */ - public RestClientBuilder setStrictDeprecationMode(boolean strictDeprecationMode) { + public Rest5ClientBuilder setStrictDeprecationMode(boolean strictDeprecationMode) { this.strictDeprecationMode = strictDeprecationMode; return this; } @@ -274,7 +274,7 @@ public RestClientBuilder setStrictDeprecationMode(boolean strictDeprecationMode) * "Accept-Encoding: gzip" * header to receive compressed responses. */ - public RestClientBuilder setCompressionEnabled(boolean compressionEnabled) { + public Rest5ClientBuilder setCompressionEnabled(boolean compressionEnabled) { this.compressionEnabled = compressionEnabled; return this; } @@ -288,20 +288,20 @@ public RestClientBuilder setCompressionEnabled(boolean compressionEnabled) { * other * environment information. Defaults to {@code true}. */ - public RestClientBuilder setMetaHeaderEnabled(boolean metadataEnabled) { + public Rest5ClientBuilder setMetaHeaderEnabled(boolean metadataEnabled) { this.metaHeaderEnabled = metadataEnabled; return this; } /** - * Creates a new {@link RestClient} based on the provided configuration. + * Creates a new {@link Rest5Client} based on the provided configuration. */ - public RestClient build() { + public Rest5Client build() { if (failureListener == null) { - failureListener = new RestClient.FailureListener(); + failureListener = new Rest5Client.FailureListener(); } CloseableHttpAsyncClient httpClient = this.createHttpClient(); - RestClient restClient = new RestClient( + Rest5Client restClient = new Rest5Client( httpClient, defaultHeaders, nodes, diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/WarningFailureException.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/WarningFailureException.java index e0e8dfbbf..b50f083aa 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/WarningFailureException.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/WarningFailureException.java @@ -25,8 +25,8 @@ /** * This exception is used to indicate that one or more {@link ESResponse#getWarnings()} exist - * and is typically used when the {@link RestClient} is set to fail by setting - * {@link RestClientBuilder#setStrictDeprecationMode(boolean)} to `true`. + * and is typically used when the {@link Rest5Client} is set to fail by setting + * {@link Rest5ClientBuilder#setStrictDeprecationMode(boolean)} to `true`. */ // This class extends RuntimeException in order to deal with wrapping that is done in FutureUtils on exception. // if the exception is not of type ElasticsearchException or RuntimeException it will be wrapped in a UncategorizedExecutionException diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java index 1bcc06b05..a3afede4a 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java @@ -51,7 +51,7 @@ public class RestClientHttpClient implements TransportHttpClient { /** * The {@code Future} implementation returned by async requests. - * It wraps the RestClient's cancellable and propagates cancellation. + * It wraps the Rest5Client's cancellable and propagates cancellation. */ private static class RequestFuture extends CompletableFuture { private volatile Cancellable cancellable; diff --git a/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java b/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java index 6d1c41eb5..b8a71eed2 100644 --- a/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java +++ b/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java @@ -73,6 +73,10 @@ public boolean keepResponseBodyOnException() { public Builder toBuilder() { return null; } + + @Override + public void updateToken(String token) { + } }; public void setResult(Object result) { diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java index 9fca54c03..c41e2b3bf 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java @@ -30,6 +30,8 @@ import co.elastic.clients.transport.endpoints.DelegatingJsonEndpoint; import co.elastic.clients.transport.rest_client.RestClientTransport; import org.apache.commons.io.FileUtils; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.message.BasicHeader; import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; @@ -51,14 +53,13 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Base64; +import java.util.Optional; public class ElasticsearchTestServer implements AutoCloseable { private final String[] plugins; private volatile ElasticsearchContainer container; private final JsonpMapper mapper = new JsonbJsonpMapper(); - private RestClient restClient; - private ElasticsearchTransport transport; private ElasticsearchClient client; private static ElasticsearchTestServer global; @@ -102,18 +103,54 @@ public ElasticsearchTestServer(String... plugins) { this.plugins = plugins; } + public ElasticsearchClient createRest4Client(String url, SSLContext sslContext) { + BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); + credsProv.setCredentials( + AuthScope.ANY, new UsernamePasswordCredentials("elastic", "changeme") + ); + var restClient = RestClient.builder(HttpHost.create(url)) + .setHttpClientConfigCallback(hc -> hc + .setDefaultCredentialsProvider(credsProv) + .setSSLContext(sslContext) + ) + .build(); + var transport = new RestClientTransport(restClient, mapper); + return new ElasticsearchClient(transport); + } + +// protected void setup(String url, SSLContext sslContext) { +// try { +// org.apache.hc.core5.http.HttpHost host = org.apache.hc.core5.http.HttpHost.create(url); +// +// var pwd = Base64.getEncoder().encodeToString("elastic:changeme".getBytes()); +// +// +// restClient = Rest5Client.builder(org.apache.hc.core5.http.HttpHost.create(url)) +// .setSslContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())) +// .setDefaultHeaders(new Header[]{ +// new BasicHeader("Authorization", "Basic " + pwd) +// }) +// //.setCompressionEnabled(true) +// .build(); +// } catch (Exception e) { +// throw new RuntimeException(e); +// } +// transport = new Rest5ClientTransport(restClient, mapper); +// client = new ElasticsearchClient(transport); +// } + protected void setup(String url, SSLContext sslContext) { BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); credsProv.setCredentials( AuthScope.ANY, new UsernamePasswordCredentials("elastic", "changeme") ); - restClient = RestClient.builder(HttpHost.create(url)) + var restClient = RestClient.builder(HttpHost.create(url)) .setHttpClientConfigCallback(hc -> hc .setDefaultCredentialsProvider(credsProv) .setSSLContext(sslContext) ) .build(); - transport = new RestClientTransport(restClient, mapper); + var transport = new RestClientTransport(restClient, mapper); client = new ElasticsearchClient(transport); } @@ -263,14 +300,6 @@ public ElasticsearchContainer container() { return this.container; } - public RestClient restClient() { - return restClient; - } - - public ElasticsearchTransport transport() { - return transport; - } - public JsonpMapper mapper() { return mapper; } diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/builders/ClientBuildersTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java similarity index 95% rename from java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/builders/ClientBuildersTest.java rename to java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java index 8fded816d..0c686520a 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/builders/ClientBuildersTest.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java @@ -17,11 +17,10 @@ * under the License. */ -package co.elastic.clients.rest5_client.elasticsearch._helpers.builders; +package co.elastic.clients.elasticsearch._helpers; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch._helpers.builders.ElasticsearchClientBuilder; -import co.elastic.clients.elasticsearch.core.SearchRequest; import co.elastic.clients.transport.rest_client.RestClientOptions; import co.elastic.clients.transport.rest_client.RestClientTransport; import org.elasticsearch.client.RequestOptions; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BehaviorsTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/BehaviorsTest2.java similarity index 98% rename from java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BehaviorsTest.java rename to java-client/src/test/java/co/elastic/clients/elasticsearch/model/BehaviorsTest2.java index f3446b293..0cf76cf29 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BehaviorsTest.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/BehaviorsTest2.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.rest5_client.elasticsearch.model; +package co.elastic.clients.elasticsearch.model; import co.elastic.clients.elasticsearch._types.ErrorCause; import co.elastic.clients.elasticsearch._types.FieldSort; @@ -35,7 +35,6 @@ import co.elastic.clients.elasticsearch.connector.UpdateIndexNameRequest; import co.elastic.clients.elasticsearch.core.rank_eval.RankEvalQuery; import co.elastic.clients.elasticsearch.core.search.SourceFilter; -import co.elastic.clients.elasticsearch.model.ClassStructureTest; import co.elastic.clients.json.JsonData; import co.elastic.clients.json.LazyDeserializer; import co.elastic.clients.json.ObjectDeserializer; @@ -43,7 +42,7 @@ import co.elastic.clients.util.MapBuilder; import org.junit.jupiter.api.Test; -public class BehaviorsTest extends ModelTestCase { +public class BehaviorsTest2 extends ModelTestCase { /** * Test for SingleKeyDictionary transformed to a behavior. For regular fields, see NamedValue tests in {@link ClassStructureTest} @@ -250,7 +249,7 @@ public void testObjectShortcutProperty() { assertEquals("foo", req.query().term().field()); assertEquals("bar", req.query().term().value().stringValue()); } - + @Test public void testFunctionScoreQuery() { String shortcut = diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/DocTestsTransport.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/DocTestsTransport.java deleted file mode 100644 index b96fc98fc..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/DocTestsTransport.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.documentation; - -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.TransportOptions; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.function.Function; - -/** - * A transport implementation that always returns the same result. Used for doc snippets where we can to check - * compilation and do very simple tests. - */ -public class DocTestsTransport implements ElasticsearchTransport { - - private final JsonpMapper mapper = new JacksonJsonpMapper( - new ObjectMapper().setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE) - ); - - private final ThreadLocal result = new ThreadLocal<>(); - - private final TransportOptions options = new TransportOptions() { - @Override - public Collection> headers() { - return Collections.emptyList(); - } - - @Override - public Map queryParameters() { - return Collections.emptyMap(); - } - - @Override - public Function, Boolean> onWarnings() { - return null; - } - - @Override - public void updateToken(String token) { - - } - - @Override - public boolean keepResponseBodyOnException() { - return false; - } - - @Override - public Builder toBuilder() { - return null; - } - }; - - public void setResult(Object result) { - this.result.set(result); - } - - @Override - @SuppressWarnings("unchecked") - public ResponseT performRequest( - RequestT request, - Endpoint endpoint, - @Nullable TransportOptions options - ) throws IOException { - return (ResponseT) result.get(); - } - - @Override - @SuppressWarnings("unchecked") - public CompletableFuture performRequestAsync(RequestT request, Endpoint endpoint, @Nullable TransportOptions options) { - CompletableFuture future = new CompletableFuture<>(); - future.complete((ResponseT) result.get()); - return future; - } - - @Override - public JsonpMapper jsonpMapper() { - return mapper; - } - - @Override - public TransportOptions options() { - return options; - } - - @Override - public void close() throws IOException { - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/ApiConventionsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/ApiConventionsTest.java deleted file mode 100644 index b91b9a1f4..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/ApiConventionsTest.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.documentation.api_conventions; - -import co.elastic.clients.documentation.DocTestsTransport; -import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._types.NodeStatistics; -import co.elastic.clients.elasticsearch._types.SortOrder; -import co.elastic.clients.elasticsearch._types.aggregations.Aggregation; -import co.elastic.clients.elasticsearch._types.query_dsl.Query; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.indices.Alias; -import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; -import co.elastic.clients.elasticsearch.indices.CreateIndexResponse; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.util.ApiTypeHelper; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import jakarta.json.JsonArray; -import jakarta.json.JsonObject; -import jakarta.json.JsonValue; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.StringReader; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ApiConventionsTest extends Assertions { - - private static class SomeApplicationData {} - - private DocTestsTransport transport = new DocTestsTransport(); - Logger logger = LoggerFactory.getLogger(this.getClass()); - - public void blockingAndAsync() throws Exception { - - //tag::blocking-and-async - // Synchronous blocking client - ElasticsearchClient client = new ElasticsearchClient(transport); - - if (client.exists(b -> b.index("products").id("foo")).value()) { - logger.info("product exists"); - } - - // Asynchronous non-blocking client - ElasticsearchAsyncClient asyncClient = - new ElasticsearchAsyncClient(transport); - - asyncClient - .exists(b -> b.index("products").id("foo")) - .whenComplete((response, exception) -> { - if (exception != null) { - logger.error("Failed to index", exception); - } else { - logger.info("Product exists"); - } - }); - //end::blocking-and-async - - } - - public void builders() throws Exception { - ElasticsearchClient client = new ElasticsearchClient(transport); - - //tag::builders - CreateIndexResponse createResponse = client.indices().create( - new CreateIndexRequest.Builder() - .index("my-index") - .aliases("foo", - new Alias.Builder().isWriteIndex(true).build() - ) - .build() - ); - //end::builders - } - - public void builderLambdas() throws Exception { - ElasticsearchClient client = new ElasticsearchClient(transport); - - //tag::builder-lambdas - CreateIndexResponse createResponse = client.indices() - .create(createIndexBuilder -> createIndexBuilder - .index("my-index") - .aliases("foo", aliasBuilder -> aliasBuilder - .isWriteIndex(true) - ) - ); - //end::builder-lambdas - } - - public void builderLambdasShort() throws Exception { - ElasticsearchClient client = new ElasticsearchClient(transport); - - //tag::builder-lambdas-short - CreateIndexResponse createResponse = client.indices() - .create(c -> c - .index("my-index") - .aliases("foo", a -> a - .isWriteIndex(true) - ) - ); - //end::builder-lambdas-short - } - - public void builderIntervals() throws Exception { - ObjectMapper mapper = new ObjectMapper(); - mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); - ElasticsearchClient client = new ElasticsearchClient(transport); - - //tag::builder-intervals - SearchResponse results = client - .search(b0 -> b0 - .query(b1 -> b1 - .intervals(b2 -> b2 - .field("my_text") - .allOf(b3 -> b3 - .ordered(true) - .intervals(b4 -> b4 - .match(b5 -> b5 - .query("my favorite food") - .maxGaps(0) - .ordered(true) - ) - ) - .intervals(b4 -> b4 - .anyOf(b5 -> b5 - .intervals(b6 -> b6 - .match(b7 -> b7 - .query("hot water") - ) - ) - .intervals(b6 -> b6 - .match(b7 -> b7 - .query("cold porridge") - ) - ) - ) - ) - ) - ) - ), - SomeApplicationData.class // <1> - ); - //end::builder-intervals - } - - @Test - public void variantCreation() { - //tag::variant-creation - Query query = new Query.Builder() - .term(t -> t // <1> - .field("name") // <2> - .value(v -> v.stringValue("foo")) - ) - .build(); // <3> - //end::variant-creation - - //tag::variant-navigation - assertEquals("foo", query.term().value().stringValue()); - //end::variant-navigation - - //tag::variant-kind - if (query.isTerm()) { // <1> - doSomething(query.term()); - } - - switch(query._kind()) { // <2> - case Term: - doSomething(query.term()); - break; - case Intervals: - doSomething(query.intervals()); - break; - default: - doSomething(query._kind(), query._get()); // <3> - } - //end::variant-kind - } - - //tag::custom-variant-types - public static class SphereDistanceAggregate { - private final List buckets; - @JsonCreator - public SphereDistanceAggregate( - @JsonProperty("buckets") List buckets - ) { - this.buckets = buckets; - } - public List buckets() { - return buckets; - }; - } - - public static class Bucket { - private final double key; - private final double docCount; - @JsonCreator - public Bucket( - @JsonProperty("key") double key, - @JsonProperty("doc_count") double docCount) { - this.key = key; - this.docCount = docCount; - } - public double key() { - return key; - } - public double docCount() { - return docCount; - } - } - //end::custom-variant-types - - @Test - public void customVariants() throws Exception { - - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0},\n" + - "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]},\n" + - "\"aggregations\":{\"sphere-distance#neighbors\":{\"buckets\":[{\"key\": 1.0,\"doc_count\":1}]}}}"; - - transport.setResult(SearchResponse.of(b -> b.withJson( - transport.jsonpMapper().jsonProvider().createParser(new StringReader(json)), - transport.jsonpMapper()) - )); - - //tag::custom-variant-creation - Map params = new HashMap<>(); // <1> - params.put("interval", 10); - params.put("scale", "log"); - params.put("origin", new Double[]{145.0, 12.5, 1649.0}); - - SearchRequest request = SearchRequest.of(r -> r - .index("stars") - .aggregations("neighbors", agg -> agg - ._custom("sphere-distance", params) // <2> - ) - ); - //end::custom-variant-creation - - { - //tag::custom-variant-navigation-json - SearchResponse response = esClient.search(request, Void.class); // <1> - - JsonData neighbors = response - .aggregations().get("neighbors") - ._custom(); // <2> - - JsonArray buckets = neighbors.toJson() // <3> - .asJsonObject() - .getJsonArray("buckets"); - - for (JsonValue item : buckets) { - JsonObject bucket = item.asJsonObject(); - double key = bucket.getJsonNumber("key").doubleValue(); - double docCount = bucket.getJsonNumber("doc_count").longValue(); - doSomething(key, docCount); - } - //end::custom-variant-navigation-json - } - - { - //tag::custom-variant-navigation-typed - SearchResponse response = esClient.search(request, Void.class); - - SphereDistanceAggregate neighbors = response - .aggregations().get("neighbors") - ._custom() - .to(SphereDistanceAggregate.class); // <1> - - for (Bucket bucket : neighbors.buckets()) { - doSomething(bucket.key(), bucket.docCount()); - } - //end::custom-variant-navigation-typed - } - } - - @Test - public void collections() { - //tag::collections-list - // Prepare a list of index names - List names = Arrays.asList("idx-a", "idx-b", "idx-c"); - - // Prepare cardinality aggregations for fields "foo" and "bar" - Map cardinalities = new HashMap<>(); - cardinalities.put("foo-count", Aggregation.of(a -> a.cardinality(c -> c.field("foo")))); - cardinalities.put("bar-count", Aggregation.of(a -> a.cardinality(c -> c.field("bar")))); - - // Prepare an aggregation that computes the average of the "size" field - final Aggregation avgSize = Aggregation.of(a -> a.avg(v -> v.field("size"))); - - SearchRequest search = SearchRequest.of(r -> r - // Index list: - // - add all elements of a list - .index(names) - // - add a single element - .index("idx-d") - // - add a vararg list of elements - .index("idx-e", "idx-f", "idx-g") - - // Sort order list: add elements defined by builder lambdas - .sort(s -> s.field(f -> f.field("foo").order(SortOrder.Asc))) - .sort(s -> s.field(f -> f.field("bar").order(SortOrder.Desc))) - - // Aggregation map: - // - add all entries of an existing map - .aggregations(cardinalities) - // - add a key/value entry - .aggregations("avg-size", avgSize) - // - add a key/value defined by a builder lambda - .aggregations("price-histogram", - a -> a.histogram(h -> h.field("price"))) - ); - //end::collections-list - - } - - @Test - public void optionalCollections() { - //tag::optional-collections - NodeStatistics stats = NodeStatistics.of(b -> b - .total(1) - .failed(0) - .successful(1) - ); - - // The `failures` list was not provided. - // - it's not null - assertNotNull(stats.failures()); - // - it's empty - assertEquals(0, stats.failures().size()); - // - and if needed we can know it was actually not defined - assertFalse(ApiTypeHelper.isDefined(stats.failures())); - //end::optional-collections - } - - private void doSomething(Object... o) { - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/LoadingJsonTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/LoadingJsonTest.java deleted file mode 100644 index 5716b5665..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/api_conventions/LoadingJsonTest.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.documentation.api_conventions; - -import co.elastic.clients.documentation.DocTestsTransport; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; -import co.elastic.clients.elasticsearch._types.aggregations.CalendarInterval; -import co.elastic.clients.elasticsearch.core.IndexRequest; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; -import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; -import co.elastic.clients.elasticsearch.indices.CreateIndexResponse; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.json.JsonData; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -public class LoadingJsonTest extends ModelTestCase { - - private final DocTestsTransport transport = new DocTestsTransport(); - private final ElasticsearchClient client = new ElasticsearchClient(transport); - - private static final SearchResponse searchResponse = SearchResponse.of(b -> b - .aggregations(new HashMap<>()) - .took(0) - .timedOut(false) - .hits(h -> h - .total(t -> t.value(0).relation(TotalHitsRelation.Eq)) - .hits(new ArrayList<>()) - ) - .shards(s -> s - .total(1) - .failed(0) - .successful(1) - ) - ); - - @Test - public void loadIndexDefinition() throws IOException { - - transport.setResult(CreateIndexResponse.of(b -> b - .index("some-index") - .shardsAcknowledged(true) - .acknowledged(true) - )); - - //tag::load-index - InputStream input = this.getClass() - .getResourceAsStream("some-index.json"); //<1> - - CreateIndexRequest req = CreateIndexRequest.of(b -> b - .index("some-index") - .withJson(input) //<2> - ); - - boolean created = client.indices().create(req).acknowledged(); - //end::load-index - } - - @Disabled - @Test - public void ingestDocument() throws IOException { - - File dataDir = null; - - //tag::ingest-data - FileReader file = new FileReader(new File(dataDir, "document-1.json")); - - IndexRequest req; //<1> - - req = IndexRequest.of(b -> b - .index("some-index") - .withJson(file) - ); - - client.index(req); - //end::ingest-data - } - - @Test - public void query1() throws IOException { - transport.setResult(searchResponse); - - //tag::query - Reader queryJson = new StringReader( - "{" + - " \"query\": {" + - " \"range\": {" + - " \"@timestamp\": {" + - " \"gt\": \"now-1w\"" + - " }" + - " }" + - " }" + - "}"); - - SearchRequest aggRequest = SearchRequest.of(b -> b - .withJson(queryJson) //<1> - .aggregations("max-cpu", a1 -> a1 //<2> - .dateHistogram(h -> h - .field("@timestamp") - .calendarInterval(CalendarInterval.Hour) - ) - .aggregations("max", a2 -> a2 - .max(m -> m.field("host.cpu.usage")) - ) - ) - .size(0) - ); - - Map aggs = client - .search(aggRequest, Void.class) //<3> - .aggregations(); - //end::query - } - - @Test - public void query2() throws IOException { - transport.setResult(searchResponse); - - //tag::query-and-agg - Reader queryJson = new StringReader( - "{" + - " \"query\": {" + - " \"range\": {" + - " \"@timestamp\": {" + - " \"gt\": \"now-1w\"" + - " }" + - " }" + - " }," + - " \"size\": 100" + //<1> - "}"); - - Reader aggregationJson = new StringReader( - "{" + - " \"size\": 0, " + //<2> - " \"aggregations\": {" + - " \"hours\": {" + - " \"date_histogram\": {" + - " \"field\": \"@timestamp\"," + - " \"interval\": \"hour\"" + - " }," + - " \"aggregations\": {" + - " \"max-cpu\": {" + - " \"max\": {" + - " \"field\": \"host.cpu.usage\"" + - " }" + - " }" + - " }" + - " }" + - " }" + - "}"); - - SearchRequest aggRequest = SearchRequest.of(b -> b - .withJson(queryJson) //<3> - .withJson(aggregationJson) //<4> - .ignoreUnavailable(true) //<5> - ); - - Map aggs = client - .search(aggRequest, Void.class) - .aggregations(); - //end::query-and-agg - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/getting_started/ConnectingTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/getting_started/ConnectingTest.java deleted file mode 100644 index ac5c28033..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/getting_started/ConnectingTest.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * 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. - */ - -//TODO rewrite -package co.elastic.clients.rest5_client.documentation.getting_started; - -public class ConnectingTest { - - /*@Disabled // we don't have a running ES - @Test - public void createClient() throws Exception { - //tag::create-client - // URL and API key - String serverUrl = "https://localhost:9200"; - String apiKey = "VnVhQ2ZHY0JDZGJrU..."; - - // Create the low-level client - RestClient restClient = RestClient - .builder(HttpHost.create(serverUrl)) - .setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "ApiKey " + apiKey) - }) - .build(); - - // Create the transport with a Jackson mapper - ElasticsearchTransport transport = new RestClientTransport( - restClient, new JacksonJsonpMapper()); - - // And create the API client - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - // Use the client... - - // Close the client, also closing the underlying transport object and network connections. - esClient.close(); - //end::create-client - - //tag::first-request - SearchResponse search = esClient.search(s -> s - .index("products") - .query(q -> q - .term(t -> t - .field("name") - .value(v -> v.stringValue("bicycle")) - )), - Product.class); - - for (Hit hit: search.hits().hits()) { - processProduct(hit.source()); - } - //end::first-request - } - - @Disabled // we don't have a running ES - @Test - public void createClientWithOpenTelemetry() throws Exception { - //tag::create-client-otel - // URL and API key - String serverUrl = "https://localhost:9200"; - String apiKey = "VnVhQ2ZHY0JDZGJrU..."; - - // Create the low-level client - RestClient restClient = RestClient - .builder(HttpHost.create(serverUrl)) - .setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "ApiKey " + apiKey) - }) - .build(); - // Create and configure custom OpenTelemetry instance - OpenTelemetry customOtel = OpenTelemetrySdk.builder().build(); - - // Create Instrumentation instance using the custom OpenTelemetry instance - // Second constructor argument allows to enable/disable search body capturing - OpenTelemetryForElasticsearch esOtelInstrumentation = - new OpenTelemetryForElasticsearch(customOtel, false); - - // Create the transport with the custom Instrumentation instance - ElasticsearchTransport transport = new RestClientTransport( - restClient, new JacksonJsonpMapper(), null, esOtelInstrumentation - ); - - // And create the API client - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - // Use the client... - - // Close the client, also closing the underlying transport object and network connections. - esClient.close(); - //end::create-client-otel - } - - @Disabled // we don't have a running ES - @Test - public void createSecureClientCert() throws Exception { - - // Create the low-level client - String host = "localhost"; - int port = 9200; - String login = "elastic"; - String password = "changeme"; - - //tag::create-secure-client-cert - File certFile = new File("/path/to/http_ca.crt"); - - SSLContext sslContext = TransportUtils - .sslContextFromHttpCaCrt(certFile); // <1> - - BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); // <2> - credsProv.setCredentials( - AuthScope.ANY, new UsernamePasswordCredentials(login, password) - ); - - RestClient restClient = RestClient - .builder(new HttpHost(host, port, "https")) // <3> - .setHttpClientConfigCallback(hc -> hc - .setSSLContext(sslContext) // <4> - .setDefaultCredentialsProvider(credsProv) - ) - .build(); - - // Create the transport and the API client - ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - // Use the client... - - // Close the client, also closing the underlying transport object and network connections. - esClient.close(); - //end::create-secure-client-cert - } - - @Disabled // we don't have a running ES - @Test - public void createSecureClientFingerPrint() throws Exception { - - // Create the low-level client - String host = "localhost"; - int port = 9200; - String login = "elastic"; - String password = "changeme"; - - //tag::create-secure-client-fingerprint - String fingerprint = ""; - - SSLContext sslContext = TransportUtils - .sslContextFromCaFingerprint(fingerprint); // <1> - - BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); // <2> - credsProv.setCredentials( - AuthScope.ANY, new UsernamePasswordCredentials(login, password) - ); - - RestClient restClient = RestClient - .builder(new HttpHost(host, port, "https")) // <3> - .setHttpClientConfigCallback(hc -> hc - .setSSLContext(sslContext) // <4> - .setDefaultCredentialsProvider(credsProv) - ) - .build(); - - // Create the transport and the API client - ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - // Use the client... - - // Close the client, also closing the underlying transport object and network connections. - esClient.close(); - //end::create-secure-client-fingerprint - } - - private void processProduct(Product p) {}*/ - -} - diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/troubleshooting/TroubleShootingTests.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/troubleshooting/TroubleShootingTests.java deleted file mode 100644 index cc3084bdd..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/troubleshooting/TroubleShootingTests.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.documentation.troubleshooting; - -import co.elastic.clients.documentation.DocTestsTransport; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpMapperFeatures; -import jakarta.json.stream.JsonGenerator; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.StringWriter; -import java.util.Collections; - -public class TroubleShootingTests extends Assertions { - - @Test - public void testMapProperty() { - - SearchResponse searchResponse = new SearchResponse.Builder() - .aggregations( - "price", _2 -> _2 - .avg(_3 -> _3.value(3.14)) - ) - // Required properties on a SearchResponse - .took(1) - .shards(_1 -> _1.successful(1).failed(0).total(1)) - .hits(_1 -> _1 - .total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)) - .hits(Collections.emptyList()) - ) - .timedOut(false) - .build(); - - String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + - "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]},\"aggregations\":{\"avg#price\":{\"value\":3.14}}}"; - - DocTestsTransport transport = new DocTestsTransport(); - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - { - //tag::aggregation-typed-keys - JsonpMapper mapper = esClient._jsonpMapper(); - - StringWriter writer = new StringWriter(); - try (JsonGenerator generator = mapper.jsonProvider().createGenerator(writer)) { - mapper.serialize(searchResponse, generator); - } - String result = writer.toString(); - - // The aggregation property provides the "avg" type and "price" name - assertTrue(result.contains("\"aggregations\":{\"avg#price\":{\"value\":3.14}}}")); - //end::aggregation-typed-keys - } - - { - //tag::aggregation-no-typed-keys - // Create a new mapper with the typed_keys feature disabled - JsonpMapper mapper = esClient._jsonpMapper() - .withAttribute(JsonpMapperFeatures.SERIALIZE_TYPED_KEYS, false); - - StringWriter writer = new StringWriter(); - try (JsonGenerator generator = mapper.jsonProvider().createGenerator(writer)) { - mapper.serialize(searchResponse, generator); - } - String result = writer.toString(); - - // The aggregation only provides the "price" name - assertTrue(result.contains("\"aggregations\":{\"price\":{\"value\":3.14}}}")); - //end::aggregation-no-typed-keys - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/AggregationsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/AggregationsTest.java deleted file mode 100644 index 1c4807e13..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/AggregationsTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.documentation.usage; - -import co.elastic.clients.documentation.DocTestsTransport; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._types.aggregations.HistogramBucket; -import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery; -import co.elastic.clients.elasticsearch._types.query_dsl.Query; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.json.JsonData; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; - -public class AggregationsTest extends ModelTestCase { - - private final DocTestsTransport transport = new DocTestsTransport(); - private final ElasticsearchClient esClient = new ElasticsearchClient(transport); - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - private static final SearchResponse searchResponse = SearchResponse.of(b -> b - .aggregations(new HashMap<>()) - .took(0) - .timedOut(false) - .hits(h -> h - .total(t -> t.value(0).relation(TotalHitsRelation.Eq)) - .hits(new ArrayList<>()) - ) - .shards(s -> s - .total(1) - .failed(0) - .successful(1) - ) - .aggregations("price-histogram", a -> a.histogram(h -> h - .buckets(bu -> bu.array(Collections.singletonList(HistogramBucket.of(hb -> hb - .key(50).docCount(1) - )))) - )) - ); - - @Test - public void priceHistogram() throws Exception { - - transport.setResult(searchResponse); - - //tag::price-histo-request - String searchText = "bike"; - - Query query = MatchQuery.of(m -> m - .field("name") - .query(searchText) - )._toQuery(); - - SearchResponse response = esClient.search(b -> b - .index("products") - .size(0) // <1> - .query(query) // <2> - .aggregations("price-histogram", a -> a // <3> - .histogram(h -> h // <4> - .field("price") - .interval(50.0) - ) - ), - Void.class // <5> - ); - //end::price-histo-request - - //tag::price-histo-response - List buckets = response.aggregations() - .get("price-histogram") // <1> - .histogram() // <2> - .buckets().array(); // <3> - - for (HistogramBucket bucket: buckets) { - logger.info("There are " + bucket.docCount() + - " bikes under " + bucket.key()); - } - - //end::price-histo-response - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingBulkTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingBulkTest.java deleted file mode 100644 index f6e4bf1fc..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingBulkTest.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.documentation.usage; - -import co.elastic.clients.documentation.DocTestsTransport; -import co.elastic.clients.documentation.usage.Product; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._helpers.bulk.BulkIngester; -import co.elastic.clients.elasticsearch._helpers.bulk.BulkListener; -import co.elastic.clients.elasticsearch.core.BulkRequest; -import co.elastic.clients.elasticsearch.core.BulkResponse; -import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.util.BinaryData; -import co.elastic.clients.util.ContentType; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.jupiter.api.Test; - -import java.io.File; -import java.io.FileInputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.TimeUnit; - -public class IndexingBulkTest extends ModelTestCase { - - private final DocTestsTransport transport = new DocTestsTransport(); - private final ElasticsearchClient esClient = new ElasticsearchClient(transport); - - private final Log logger = LogFactory.getLog(this.getClass()); - - BulkResponse result = BulkResponse.of(r -> r - .errors(false) - .items(Collections.emptyList()) - .took(1) - ); - - private List fetchProducts() { - List list = new ArrayList<>(); - list.add(new co.elastic.clients.documentation.usage.Product("bk-1", "City Bike", 123.0)); - list.add(new co.elastic.clients.documentation.usage.Product("bk-2", "Mountain Bike", 134.0)); - return list; - } - - @Test - public void indexBulk() throws Exception { - transport.setResult(result); - - //tag::bulk-objects - List products = fetchProducts(); - - BulkRequest.Builder br = new BulkRequest.Builder(); - - for (Product product : products) { - br.operations(op -> op //<1> - .index(idx -> idx //<2> - .index("products") //<3> - .id(product.getSku()) - .document(product) - ) - ); - } - - BulkResponse result = esClient.bulk(br.build()); - - // Log errors, if any - if (result.errors()) { - logger.error("Bulk had errors"); - for (BulkResponseItem item: result.items()) { - if (item.error() != null) { - logger.error(item.error().reason()); - } - } - } - //end::bulk-objects - } - - @Test - public void indexBulkJson() throws Exception { - transport.setResult(result); - - File logDir = new File("."); - - //tag::bulk-json - // List json log files in the log directory - File[] logFiles = logDir.listFiles( - file -> file.getName().matches("log-.*\\.json") - ); - - BulkRequest.Builder br = new BulkRequest.Builder(); - - for (File file: logFiles) { - FileInputStream input = new FileInputStream(file); - BinaryData data = BinaryData.of(IOUtils.toByteArray(input), ContentType.APPLICATION_JSON); - - br.operations(op -> op - .index(idx -> idx - .index("logs") - .document(data) - ) - ); - } - //end::bulk-json - } - - @Test - public void useBulkIndexer() throws Exception { - - File logDir = new File("."); - File[] logFiles = logDir.listFiles( - file -> file.getName().matches("log-.*\\.json") - ); - - //tag::bulk-ingester-setup - BulkIngester ingester = BulkIngester.of(b -> b - .client(esClient) // <1> - .maxOperations(100) // <2> - .flushInterval(1, TimeUnit.SECONDS) // <3> - ); - - for (File file: logFiles) { - FileInputStream input = new FileInputStream(file); - BinaryData data = BinaryData.of(IOUtils.toByteArray(input), ContentType.APPLICATION_JSON); - - ingester.add(op -> op // <4> - .index(idx -> idx - .index("logs") - .document(data) - ) - ); - } - - ingester.close(); // <5> - //end::bulk-ingester-setup - - } - - @Test - public void useBulkIndexerWithContext() throws Exception { - - File[] logFiles = new File[]{}; - - //tag::bulk-ingester-context - BulkListener listener = new BulkListener() { // <1> - @Override - public void beforeBulk(long executionId, BulkRequest request, List contexts) { - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, BulkResponse response) { - // The request was accepted, but may contain failed items. - // The "context" list gives the file name for each bulk item. - logger.debug("Bulk request " + executionId + " completed"); - for (int i = 0; i < contexts.size(); i++) { - BulkResponseItem item = response.items().get(i); - if (item.error() != null) { - // Inspect the failure cause - logger.error("Failed to index file " + contexts.get(i) + " - " + item.error().reason()); - } - } - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, Throwable failure) { - // The request could not be sent - logger.debug("Bulk request " + executionId + " failed", failure); - } - }; - - BulkIngester ingester = BulkIngester.of(b -> b - .client(esClient) - .maxOperations(100) - .flushInterval(1, TimeUnit.SECONDS) - .listener(listener) // <2> - ); - - for (File file: logFiles) { - FileInputStream input = new FileInputStream(file); - BinaryData data = BinaryData.of(IOUtils.toByteArray(input), ContentType.APPLICATION_JSON); - - ingester.add(op -> op - .index(idx -> idx - .index("logs") - .document(data) - ), - file.getName() // <3> - ); - } - - ingester.close(); - //end::bulk-ingester-context - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingTest.java deleted file mode 100644 index 807c5453d..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/IndexingTest.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.documentation.usage; - -import co.elastic.clients.documentation.DocTestsTransport; -import co.elastic.clients.documentation.usage.Product; -import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._types.Result; -import co.elastic.clients.elasticsearch.core.IndexRequest; -import co.elastic.clients.elasticsearch.core.IndexResponse; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.json.JsonData; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Reader; -import java.io.StringReader; - -public class IndexingTest extends ModelTestCase { - - private final DocTestsTransport transport = new DocTestsTransport(); - private final ElasticsearchClient esClient = new ElasticsearchClient(transport); - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - IndexResponse result = IndexResponse.of(r -> r - .index("product") - .id("bk-1") - .version(1) - .primaryTerm(1L) - .seqNo(1L) - .result(Result.Created) - .shards(s -> s.total(1).successful(1).failed(0)) - ); - - @Test - @Disabled - public void createIndex() throws Exception { - //tag::create-products-index - esClient.indices().create(c -> c - .index("products") - ); - //end::create-products-index - } - - @Test - @Disabled - public void deleteIndex() throws Exception { - //tag::delete-products-index - esClient.indices().delete(d -> d - .index("products") - ); - //end::delete-products-index - } - - @Test - public void singleDocumentDSL() throws Exception { - - // Stub response - transport.setResult(result); - - //tag::single-doc-dsl - co.elastic.clients.documentation.usage.Product product = new co.elastic.clients.documentation.usage.Product("bk-1", "City bike", 123.0); - - IndexResponse response = esClient.index(i -> i - .index("products") - .id(product.getSku()) - .document(product) - ); - - logger.info("Indexed with version " + response.version()); - //end::single-doc-dsl - } - - @Test - public void singleDocumentDSLwithOf() throws Exception { - - // Stub response - transport.setResult(result); - - //tag::single-doc-dsl-of - co.elastic.clients.documentation.usage.Product product = new co.elastic.clients.documentation.usage.Product("bk-1", "City bike", 123.0); - - IndexRequest request = IndexRequest.of(i -> i - .index("products") - .id(product.getSku()) - .document(product) - ); - - IndexResponse response = esClient.index(request); - - logger.info("Indexed with version " + response.version()); - //end::single-doc-dsl-of - } - - @Test - public void singleDocumentBuilder() throws Exception { - - // Stub response - transport.setResult(result); - - //tag::single-doc-builder - co.elastic.clients.documentation.usage.Product product = new co.elastic.clients.documentation.usage.Product("bk-1", "City bike", 123.0); - - IndexRequest.Builder indexReqBuilder = new IndexRequest.Builder<>(); - indexReqBuilder.index("product"); - indexReqBuilder.id(product.getSku()); - indexReqBuilder.document(product); - - IndexResponse response = esClient.index(indexReqBuilder.build()); - - logger.info("Indexed with version " + response.version()); - //end::single-doc-builder - } - - @Test - public void singleDocumentDSLAsync() throws Exception { - - // Stub response - transport.setResult(result); - - //tag::single-doc-dsl-async - ElasticsearchAsyncClient esAsyncClient = new ElasticsearchAsyncClient(transport); - - co.elastic.clients.documentation.usage.Product product = new co.elastic.clients.documentation.usage.Product("bk-1", "City bike", 123.0); - - esAsyncClient.index(i -> i - .index("products") - .id(product.getSku()) - .document(product) - ).whenComplete((response, exception) -> { - if (exception != null) { - logger.error("Failed to index", exception); - } else { - logger.info("Indexed with version " + response.version()); - } - }); - //end::single-doc-dsl-async - } - - @Test - public void singleDocumentJson() throws Exception { - // Stub response - transport.setResult(result); - - //tag::single-doc-json - Reader input = new StringReader( - "{'@timestamp': '2022-04-08T13:55:32Z', 'level': 'warn', 'message': 'Some log message'}" - .replace('\'', '"')); - - IndexRequest request = IndexRequest.of(i -> i - .index("logs") - .withJson(input) - ); - - IndexResponse response = esClient.index(request); - - logger.info("Indexed with version " + response.version()); - //end::single-doc-json - - assertEquals("warn", request.document().toJson().asJsonObject().getString("level")); - assertEquals( - "{\"@timestamp\":\"2022-04-08T13:55:32Z\",\"level\":\"warn\",\"message\":\"Some log message\"}", - toJson(request) - ); - } - - @Test - public void deleteDocument() throws Exception { - //tag::single-doc-delete - esClient.delete(d -> d.index("products").id("bk-1")); - //end::single-doc-delete - } - - @Test - @Disabled - public void updateDoc() throws Exception { - //tag::single-doc-update - co.elastic.clients.documentation.usage.Product product = new co.elastic.clients.documentation.usage.Product("bk-1", "City bike", 123.0); - - esClient.update(u -> u - .index("products") - .id("bk-1") - .upsert(product), - Product.class - ); - //end::single-doc-update - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/Product.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/Product.java deleted file mode 100644 index 768ab1c5a..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/Product.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.documentation.usage; - -public class Product { - private String sku; - private String name; - private double price; - - public Product() {} - public Product(String sku, String name, double price) { - this.sku = sku; - this.name = name; - this.price = price; - } - - public String getSku() { - return sku; - } - - public void setSku(String sku) { - this.sku = sku; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public double getPrice() { - return this.price; - } - - public void setPrice(double price) { - this.price = price; - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/ReadingTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/ReadingTest.java deleted file mode 100644 index baf205821..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/ReadingTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.documentation.usage; - -import co.elastic.clients.documentation.DocTestsTransport; -import co.elastic.clients.documentation.usage.Product; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.core.GetResponse; -import co.elastic.clients.testkit.ModelTestCase; -import com.fasterxml.jackson.databind.node.ObjectNode; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ReadingTest extends ModelTestCase { - - private final DocTestsTransport transport = new DocTestsTransport(); - private final ElasticsearchClient esClient = new ElasticsearchClient(transport); - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - @Test - public void getById() throws Exception { - - transport.setResult(GetResponse.of(r -> r - .found(true) - .index("products") - .id("bk-1") - .version(1L) - .seqNo(0L) - .primaryTerm(0L) - .source(new co.elastic.clients.documentation.usage.Product("bk-1", "City Bike", 123.0)) - )); - - //tag::get-by-id - GetResponse response = esClient.get(g -> g - .index("products") // <1> - .id("bk-1"), - co.elastic.clients.documentation.usage.Product.class // <2> - ); - - if (response.found()) { - Product product = response.source(); - logger.info("Product name " + product.getName()); - } else { - logger.info ("Product not found"); - } - //end::get-by-id - - } - - @Test - public void getByIdJson() throws Exception { - - transport.setResult(GetResponse.of(r -> r - .found(true) - .index("products") - .id("bk-1") - .version(1L) - .seqNo(0L) - .primaryTerm(0L) - .source(fromJson("{\"name\":\"City Bike\"}", ObjectNode.class, transport.jsonpMapper())) - )); - - //tag::get-by-id-json - GetResponse response = esClient.get(g -> g - .index("products") - .id("bk-1"), - ObjectNode.class // <1> - ); - - if (response.found()) { - ObjectNode json = response.source(); - String name = json.get("name").asText(); - logger.info("Product name " + name); - } else { - logger.info("Product not found"); - } - //end::get-by-id-json - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/SearchingTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/SearchingTest.java deleted file mode 100644 index d5a2486f4..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/documentation/usage/SearchingTest.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.documentation.usage; - -import co.elastic.clients.documentation.DocTestsTransport; -import co.elastic.clients.documentation.usage.Product; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery; -import co.elastic.clients.elasticsearch._types.query_dsl.Query; -import co.elastic.clients.elasticsearch._types.query_dsl.RangeQuery; -import co.elastic.clients.elasticsearch.core.PutScriptResponse; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.core.SearchTemplateResponse; -import co.elastic.clients.elasticsearch.core.search.Hit; -import co.elastic.clients.elasticsearch.core.search.TotalHits; -import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; -import co.elastic.clients.json.JsonData; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -public class SearchingTest { - - private final DocTestsTransport transport = new DocTestsTransport(); - private final ElasticsearchClient esClient = new ElasticsearchClient(transport); - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - private static final SearchResponse searchResponse = SearchResponse.of(b -> b - .aggregations(new HashMap<>()) - .took(0) - .timedOut(false) - .hits(h -> h - .total(t -> t.value(0).relation(TotalHitsRelation.Eq)) - .hits(new ArrayList<>()) - ) - .shards(s -> s - .total(1) - .failed(0) - .successful(1) - ) - ); - - @Test - public void searchSimpleMatch() throws Exception { - transport.setResult(searchResponse); - - //tag::search-getting-started - String searchText = "bike"; - - SearchResponse response = esClient.search(s -> s - .index("products") - .query(q -> q - .match(t -> t - .field("name") - .query(searchText) - ) - ), - co.elastic.clients.documentation.usage.Product.class - ); - //end::search-getting-started - } - @Test - public void searchMatch() throws Exception { - - transport.setResult(searchResponse); - //tag::search-simple - - String searchText = "bike"; - - SearchResponse response = esClient.search(s -> s - .index("products") // <1> - .query(q -> q // <2> - .match(t -> t // <3> - .field("name") // <4> - .query(searchText) - ) - ), - co.elastic.clients.documentation.usage.Product.class // <5> - ); - - TotalHits total = response.hits().total(); - boolean isExactResult = total.relation() == TotalHitsRelation.Eq; - - if (isExactResult) { - logger.info("There are " + total.value() + " results"); - } else { - logger.info("There are more than " + total.value() + " results"); - } - - List> hits = response.hits().hits(); - for (Hit hit: hits) { - co.elastic.clients.documentation.usage.Product product = hit.source(); - logger.info("Found product " + product.getSku() + ", score " + hit.score()); - } - //end::search-simple - } - - @Test - public void searchNested() throws Exception { - transport.setResult(searchResponse); - //tag::search-nested - String searchText = "bike"; - double maxPrice = 200.0; - - // Search by product name - Query byName = MatchQuery.of(m -> m // <1> - .field("name") - .query(searchText) - )._toQuery(); // <2> - - // Search by max price - Query byMaxPrice = RangeQuery.of(r -> r - .number(n -> n - .field("price") - .gte(maxPrice)) // <3> - )._toQuery(); - - // Combine name and price queries to search the product index - SearchResponse response = esClient.search(s -> s - .index("products") - .query(q -> q - .bool(b -> b // <4> - .must(byName) // <5> - .must(byMaxPrice) - ) - ), - co.elastic.clients.documentation.usage.Product.class - ); - - List> hits = response.hits().hits(); - for (Hit hit: hits) { - co.elastic.clients.documentation.usage.Product product = hit.source(); - logger.info("Found product " + product.getSku() + ", score " + hit.score()); - } - //end::search-nested - } - - @Test - public void searchTemplate() throws Exception { - - transport.setResult(PutScriptResponse.of(r -> r.acknowledged(true))); - - //tag::search-template-script - // Create a script - esClient.putScript(r -> r - .id("query-script") // <1> - .script(s -> s - .lang("mustache") - .source("{\"query\":{\"match\":{\"{{field}}\":\"{{value}}\"}}}") - )); - //end::search-template-script - - transport.setResult(SearchTemplateResponse.of(r -> r - .hits(searchResponse.hits()) - .took(searchResponse.took()) - .timedOut(false) - .shards(searchResponse.shards()) - )); - - //tag::search-template-query - SearchTemplateResponse response = esClient.searchTemplate(r -> r - .index("some-index") - .id("query-script") // <1> - .params("field", JsonData.of("some-field")) // <2> - .params("value", JsonData.of("some-data")), - co.elastic.clients.documentation.usage.Product.class - ); - - List> hits = response.hits().hits(); - for (Hit hit: hits) { - Product product = hit.source(); - logger.info("Found product " + product.getSku() + ", score " + hit.score()); - } - //end::search-template-query - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/ElasticsearchTestServer.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/ElasticsearchTestServer.java deleted file mode 100644 index 28befa943..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/ElasticsearchTestServer.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch; - -import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.JsonEndpoint; -import co.elastic.clients.transport.Version; -import co.elastic.clients.transport.endpoints.DelegatingJsonEndpoint; -import co.elastic.clients.transport.rest_client.RestClientTransport; -import org.apache.commons.io.FileUtils; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.message.BasicHeader; -import org.elasticsearch.client.RestClient; -import org.testcontainers.elasticsearch.ElasticsearchContainer; -import org.testcontainers.images.builder.ImageFromDockerfile; -import org.testcontainers.shaded.org.apache.commons.io.IOUtils; -import org.testcontainers.utility.DockerImageName; - -import javax.net.ssl.SSLContext; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.time.Duration; -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.Base64; -import java.util.Optional; - -public class ElasticsearchTestServer implements AutoCloseable { - - private final String[] plugins; - private volatile ElasticsearchContainer container; - private final JsonpMapper mapper = new JsonbJsonpMapper(); - private RestClient restClient; - private ElasticsearchTransport transport; - private ElasticsearchClient client; - - private static ElasticsearchTestServer global; - - private static final String artifactsApiUrl = "https://artifacts-api.elastic.co/v1/versions/"; - - public static synchronized ElasticsearchTestServer global() { - if (global == null) { - - // Try localhost:9200 - try { - String localUrl = "http://localhost:9200"; - HttpURLConnection connection = (HttpURLConnection) new URL(localUrl).openConnection(); - connection.setRequestProperty("Authorization", "Basic " + - Base64.getEncoder().encodeToString("elastic:changeme".getBytes(StandardCharsets.UTF_8))); - - try (InputStream input = connection.getInputStream()) { - String content = IOUtils.toString(input, StandardCharsets.UTF_8); - if (content.contains("You Know, for Search")) { - System.out.println("Found a running ES server at http://localhost:9200/"); - - global = new ElasticsearchTestServer(); - global.setup(localUrl, null); - } - } - } catch (Exception e) { - // Create container - System.out.println("Starting global ES test server."); - global = new ElasticsearchTestServer(); - global.start(); - } - - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - System.out.println("Stopping global ES test server."); - global.close(); - })); - } - return global; - } - - public ElasticsearchTestServer(String... plugins) { - this.plugins = plugins; - } - - protected void setup(String url, SSLContext sslContext) { - try { - HttpHost host = HttpHost.create(url); - - var pwd = Base64.getEncoder().encodeToString("elastic:changeme".getBytes()); - - - restClient = RestClient.builder(HttpHost.create(url)) - .setSslContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())) - .setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "Basic " + pwd) - }) - //.setCompressionEnabled(true) - .build(); - } catch (Exception e) { - throw new RuntimeException(e); - } - transport = new RestClientTransport(restClient, mapper); - client = new ElasticsearchClient(transport); - } - - private Version selectLatestVersion(Version version, String info) { - if (info.contains(version.toString())) { - return version; - } - // if no version X.Y.0 was found, we give up - if (version.maintenance() == 0) { - throw new RuntimeException("Elasticsearch server container version: " + version + " not yet " + - "available"); - } - return selectLatestVersion(new Version(version.major(), version.minor(), version.maintenance() - 1, - false), info); - } - - private String fetchAndWriteVersionInfo(File file) throws IOException { - String versionInfo = IOUtils.toString(new URL(artifactsApiUrl), StandardCharsets.UTF_8); - FileUtils.writeStringToFile(file, versionInfo, StandardCharsets.UTF_8); - return versionInfo; - } - - private Version getLatestAvailableServerVersion(Version version) { - try { - // check if there's cached information - ClassLoader classLoader = getClass().getClassLoader(); - URL location = classLoader.getResource("./co/elastic/clients/version.json"); - - // writing the info on file before returning - if (location == null) { - File file = new File(classLoader.getResource("./co/elastic/clients").getFile() + "/version" + - ".json"); - String versionInfo = fetchAndWriteVersionInfo(file); - return selectLatestVersion(version, versionInfo); - } - - File file = new File(location.getFile()); - - // info file was found, but it's expired - if (Instant.ofEpochMilli(file.lastModified()).isBefore(Instant.now().minus(24, - ChronoUnit.HOURS))) { - String versionInfo = fetchAndWriteVersionInfo(file); - return selectLatestVersion(version, versionInfo); - } - - // info file exists and it has new info - String versionInfo = FileUtils.readFileToString(file, StandardCharsets.UTF_8); - return selectLatestVersion(version, versionInfo); - - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public synchronized ElasticsearchTestServer start() { - if (this.client != null) { - return this; - } - - Version version = getLatestAvailableServerVersion(Version.VERSION); - - // using specific stable version for tests with plugins - if (plugins.length > 0) { - version = Version.VERSION.major() < 8 ? new Version(7, 17, 25, false) : new Version(8, 16, 0, - false); - } - - String esImage = "docker.elastic.co/elasticsearch/elasticsearch:" + version; - - DockerImageName image; - if (plugins.length == 0) { - image = DockerImageName.parse(esImage); - } else { - String esWithPluginsImage = new ImageFromDockerfile() - .withDockerfileFromBuilder(b -> { - b.from(esImage); - for (String plugin : plugins) { - b.run("/usr/share/elasticsearch/bin/elasticsearch-plugin", "install", plugin); - } - } - ).get(); - - image = DockerImageName - .parse(esWithPluginsImage) - .asCompatibleSubstituteFor("docker.elastic.co/elasticsearch/elasticsearch"); - } - - container = new ElasticsearchContainer(image) - .withEnv("ES_JAVA_OPTS", "-Xms256m -Xmx256m") - .withEnv("path.repo", "/tmp") // for snapshots - .withStartupTimeout(Duration.ofSeconds(30)) - .withPassword("changeme"); - container.start(); - - boolean useTLS = version.major() >= 8; - - SSLContext sslContext = useTLS ? container.createSslContextFromCa() : null; - String url = (useTLS ? "https://" : "http://") + container.getHttpHostAddress(); - - setup(url, sslContext); - - return this; - } - - /** - * Send a request to a server and return the response as JSON. Useful to debug response format issues. - */ - public static JsonData getJsonResponse(ElasticsearchClient client, Req request) throws IOException { - - JsonEndpoint endpoint; - - try { - @SuppressWarnings("unchecked") - JsonEndpoint endpoint0 = (JsonEndpoint) request.getClass() - .getDeclaredField("_ENDPOINT").get(null); - endpoint = endpoint0; - } catch (IllegalAccessException | NoSuchFieldException e) { - throw new RuntimeException(e); - } - - DelegatingJsonEndpoint jsonEndpoint = - new DelegatingJsonEndpoint(endpoint) { - @Override - public JsonpDeserializer responseDeserializer() { - return JsonData._DESERIALIZER; - } - }; - - return client._transport().performRequest(request, jsonEndpoint, client._transportOptions()); - } - - @Override - public void close() { - if (this == global) { - // Closed with a shutdown hook - return; - } - - if (container != null) { - container.stop(); - } - container = null; - } - - public ElasticsearchContainer container() { - return this.container; - } - - public RestClient restClient() { - return restClient; - } - - public ElasticsearchTransport transport() { - return transport; - } - - public JsonpMapper mapper() { - return mapper; - } - - public ElasticsearchClient client() { - return client; - } - - public ElasticsearchAsyncClient asyncClient() { - return new ElasticsearchAsyncClient(client._transport(), client._transportOptions()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java deleted file mode 100644 index c6fdc085d..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterRetryPolicyTest.java +++ /dev/null @@ -1,546 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch._helpers.bulk; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._helpers.bulk.BulkIngester; -import co.elastic.clients.elasticsearch._helpers.bulk.BulkListener; -import co.elastic.clients.elasticsearch._types.ErrorCause; -import co.elastic.clients.elasticsearch.core.BulkRequest; -import co.elastic.clients.elasticsearch.core.BulkResponse; -import co.elastic.clients.elasticsearch.core.bulk.BulkOperation; -import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; -import co.elastic.clients.elasticsearch.core.bulk.CreateOperation; -import co.elastic.clients.elasticsearch.core.bulk.DeleteOperation; -import co.elastic.clients.elasticsearch.core.bulk.IndexOperation; -import co.elastic.clients.elasticsearch.core.bulk.OperationType; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.SimpleJsonpMapper; -import co.elastic.clients.transport.BackoffPolicy; -import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.TransportOptions; -import org.jetbrains.annotations.Nullable; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class BulkIngesterRetryPolicyTest { - - protected static ElasticsearchClient client; - protected static TestTransport transport; - protected static CountingListener listener; - - private BulkOperation create = BulkOperation.of(b -> b.create(c -> c.index("foo").id("1").document("1"))); - private BulkOperation index = BulkOperation.of(b -> b.index(c -> c.index("fooo").id("2").document("2"))); - private BulkOperation indexFail = BulkOperation.of(b -> b.index(c -> c.index("fail").id("2").document( - "2"))); - private BulkOperation delete = BulkOperation.of(b -> b.delete(c -> c.index("foooo").id("3"))); - private BulkOperation deleteFail = BulkOperation.of(b -> b.delete(c -> c.index("fail").id("3"))); - - @BeforeEach - public void setup() { - transport = new TestTransport(); - client = new ElasticsearchClient(transport); - listener = new CountingListener(); - } - - @Test - public void retryTestNoScheduledFlushNoContext() throws Exception { - - // First test, partial success, other will succeed after retrying - { - BulkIngester ingester = newBasicBulkIngester(listener); - - ingester.add(create); - ingester.add(index); - ingester.add(index); - - ingester.close(); - - // 1 instant success, 2 retried, but succeeded. can be either 2 or 3 depending on the retries, - // if they get scheduled at the same exact time - assertTrue(listener.requests.get() == 2 || listener.requests.get() == 3); - // eventually all 3 have to succeed - assertTrue(listener.successOperations.get() == 3); - - // 1 for the create and first try for the indexes, 2 + 2 for both index retries, - // which could be scheduled at the same time, so from 3 to 5 - assertTrue(listener.sentRequestsTotal.get() >= 3 && listener.sentRequestsTotal.get() <= 5); - } - - // Second test, all requests will succeed after retrying - { - transport.reset(); - listener.reset(); - - BulkIngester ingester = newBasicBulkIngester(listener); - - ingester.add(index); - ingester.add(index); - ingester.add(index); - ingester.add(index); - - ingester.close(); - - // between 1 and 4, depending on scheduler - assertTrue(listener.requests.get() >= 1 && listener.requests.get() <= 4); - // eventually all 4 have to succeed - assertTrue(listener.successOperations.get() == 4); - // between 3 and 9, depending on scheduler - assertTrue(listener.sentRequestsTotal.get() >= 3 && listener.sentRequestsTotal.get() <= 9); - } - - // Third test, only one retryable (will succeed), other permanent failures - { - transport.reset(); - listener.reset(); - - BulkIngester ingester = newBasicBulkIngester(listener); - - ingester.add(index); - ingester.add(delete); - ingester.add(delete); - - ingester.close(); - - // 2 failed will be handled together, then 1 retry - assertTrue(listener.requests.get() == 2); - - assertTrue(listener.successOperations.get() == 1); - assertTrue(listener.errorOperations.get() == 2); - // 1 initial + 2 retries - assertTrue(listener.sentRequestsTotal.get() == 3); - } - - // Fourth test, all requests will be retried until policy allows, then fail - { - transport.reset(); - listener.reset(); - - BulkIngester ingester = newBasicBulkIngester(listener); - - ingester.add(indexFail); - ingester.add(indexFail); - ingester.add(indexFail); - - ingester.close(); - - // from 1 to 3 depending on scheduling - assertTrue(listener.requests.get() >= 1 && listener.requests.get() <= 3); - - assertTrue(listener.successOperations.get() == 0); - assertTrue(listener.errorOperations.get() == 3); - // between 8 and 24, depending on scheduler - assertTrue(listener.sentRequestsTotal.get() >= 8 && listener.sentRequestsTotal.get() <= 24); - } - - // Fifth test, one exception that will make everything else fail, no retries triggered - { - transport.reset(); - listener.reset(); - - BulkIngester ingester = newBasicBulkIngester(listener); - - ingester.add(index); - ingester.add(create); - ingester.add(deleteFail); - - ingester.close(); - - // just the one - assertTrue(listener.requests.get() == 1); - - assertTrue(listener.successOperations.get() == 0); - assertTrue(listener.errorOperations.get() == 3); - - // just the one - assertTrue(listener.sentRequestsTotal.get() == 1); - } - - // Sixth test, a mix of everything - { - transport.reset(); - listener.reset(); - - BulkIngester ingester = newBasicBulkIngester(listener); - - ingester.add(create); - ingester.add(index); - ingester.add(indexFail); - ingester.add(delete); - ingester.add(create); - ingester.add(index); - ingester.add(indexFail); - ingester.add(delete); - - ingester.close(); - - // from 2 to 4 depending on scheduling - assertTrue(listener.requests.get() >= 1 && listener.successOperations.get() <= 4); - - assertTrue(listener.successOperations.get() == 4); - assertTrue(listener.errorOperations.get() == 4); - - // between 8 and 18, depending on scheduler - assertTrue(listener.sentRequestsTotal.get() >= 8 && listener.sentRequestsTotal.get() <= 18); - } - - transport.close(); - } - - @Test - public void retryTestFlushAndContextExponentialBackoff() throws Exception { - - // One success, other will succeed after retrying, other will fail eventually - { - BulkIngester ingester = newBulkIngesterWithFlushAndContextAndLongExponential(listener); - - ingester.add(create, 1); - ingester.add(indexFail, 2); - ingester.add(index, 3); - - ingester.close(); - - // should be 3 separate requests sent, one instant, one after a few retries, the last one error. - assertTrue(listener.requests.get() == 3); - // 2 will succeed, one will fail - assertTrue(listener.successOperations.get() == 2); - assertTrue(listener.errorOperations.get() == 1); - // between 8 and 10, depending on scheduler (first one + 2 retries for index + 8 retries for - // indexfail) - assertTrue(listener.sentRequestsTotal.get() >= 8 && listener.sentRequestsTotal.get() <= 11); - // checking order of contexts after send confirmed - Iterator iter = listener.sentContexts.iterator(); - // first one being completed is create - assertTrue(iter.next().equals(1)); - // second one is index, which will take only 2 retries - assertTrue(iter.next().equals(3)); - // last one is indexFail, taking 8 retries to fail - assertTrue(iter.next().equals(2)); - } - - transport.close(); - } - - @Test - public void retryTestNoFlushAndContextExponentialBackoff() throws Exception { - - // One success, other will succeed after retrying, other will fail eventually - { - BulkIngester ingester = newBulkIngesterNoFlushAndContextAndLongExponential(listener); - - ingester.add(create, 1); - ingester.add(indexFail, 2); - ingester.add(index, 3); - - ingester.close(); - - // should be 3 separate requests sent, one instant, one after a few retries, the last one error. - assertTrue(listener.requests.get() == 3); - // 2 will succeed, one will fail - assertTrue(listener.successOperations.get() == 2); - assertTrue(listener.errorOperations.get() == 1); - // between 8 and 10, depending on scheduler (first one + 2 retries for index + 8 retries for - // indexfail) - assertTrue(listener.sentRequestsTotal.get() >= 8 && listener.sentRequestsTotal.get() <= 11); - // checking order of contexts after send confirmed - Iterator iter = listener.sentContexts.iterator(); - // first one being completed is create - assertTrue(iter.next().equals(1)); - // second one is index, which will take only 2 retries - assertTrue(iter.next().equals(3)); - // last one is indexFail, taking 8 retries to fail - assertTrue(iter.next().equals(2)); - } - - transport.close(); - } - - @Test - public void retryMultiThreadStressTest() throws InterruptedException, IOException { - - // DISCLAIMER: this configuration is highly inefficient and only used here to showcase an extreme - // situation where the number of adding threads greatly exceeds the number of concurrent requests - // handled by the ingester. It's strongly recommended to always tweak maxConcurrentRequests - // accordingly. - BulkIngester ingester = BulkIngester.of(b -> b - .client(client) - .listener(listener) - .flushInterval(5, TimeUnit.SECONDS) - .backoffPolicy(BackoffPolicy.constantBackoff(50L, 8))); - - ExecutorService executor = Executors.newFixedThreadPool(50); - - // sends create operations, but once every 1000, one index operation will be sent, - // and once every 5000 an indexFail - for (int i = 0; i < 100000; i++) { - int ii = i; - Runnable thread = () -> { - int finalI = ii; - if (ii % 1000 == 0) { - ingester.add(index, ii); - } else if (ii % 5000 == 0) { - ingester.add(indexFail, ii); - } else { - ingester.add(create, ii); - } - }; - executor.submit(thread); - } - - executor.awaitTermination(10, TimeUnit.SECONDS); - ingester.close(); - - // all operations will succeed eventually, so the total has to be 100000 - assertTrue(listener.successOperations.get() == 100000); - assertTrue(listener.sentContexts.size() == 100000); - assertTrue(listener.errorOperations.get() == 0); - // it's difficult to predict how many requests will be sent, but considering they will be sent - // in batches of 1000, without retries it should be exactly 100, considering that 100 out of - // 100000 will be retried 3 times and 20 will be retried 8 times, if they don't get batched together - // with the others it could result in a total of 560, which is highly unlikely. - // more reasonably there will be between 100 and 300 requests sent. - assertTrue(listener.sentRequestsTotal.get() >= 100 && listener.sentRequestsTotal.get() <= 300); - // same reasoning - assertTrue(listener.requests.get() >= 100 && listener.requests.get() <= 300); - - transport.close(); - } - - - private static class TestTransport implements ElasticsearchTransport { - public final AtomicInteger requestsStarted = new AtomicInteger(); - public final AtomicInteger requestsCompleted = new AtomicInteger(); - public final AtomicInteger operations = new AtomicInteger(); - - public ConcurrentHashMap retryFailures = new ConcurrentHashMap<>(); - - - private final ExecutorService executor = Executors.newCachedThreadPool(); - - @Override - public ResponseT performRequest( - RequestT request, - Endpoint endpoint, - @Nullable TransportOptions options - ) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture performRequestAsync(RequestT request, Endpoint endpoint, @Nullable TransportOptions options) { - - BulkRequest bulk = (BulkRequest) request; - requestsStarted.incrementAndGet(); - operations.addAndGet(bulk.operations().size()); - - if (bulk.operations().isEmpty()) { - System.out.println("No operations!"); - } - - // For testing purposes, different result depending on the operation type. - // Create will always succeed - // Index will always return 429 for 2 times, then 200. Index with index name "fail" will only - // return 429. - // Delete will always return 404. Delete with index name "fail" will throw transport exception. - - try { - - List items = new ArrayList<>(); - for (BulkOperation op : bulk.operations()) { - OperationType operationType = OperationType.Create; - ErrorCause error = null; - int status = 200; - String index = null; - switch (op._kind()) { - case Index: - index = ((IndexOperation) op._get()).index(); - operationType = OperationType.Index; - retryFailures.putIfAbsent(op, 0); - boolean isStillRetrying = retryFailures.computeIfPresent(op, (k, v) -> v + 1) > 2; - error = isStillRetrying && !index.equals("fail") ? null : - ErrorCause.of(e -> e.reason("some error")); - status = isStillRetrying && !index.equals("fail") ? 200 : 429; - break; - case Delete: - index = ((DeleteOperation) op._get()).index(); - if (index.equals("fail")) { - throw new RuntimeException("error"); - } - operationType = OperationType.Delete; - error = ErrorCause.of(e -> e.reason("some error")); - status = 404; - break; - default: - index = ((CreateOperation) op._get()).index(); - break; - } - ErrorCause finalError = error; - int finalStatus = status; - OperationType finalOperationType = operationType; - String finalIndex = index; - items.add(BulkResponseItem.of(b -> b - .index(finalIndex) - .operationType(finalOperationType) - .status(finalStatus) - .error(finalError))); - } - - CompletableFuture response = new CompletableFuture<>(); - executor.submit(() -> { - requestsCompleted.incrementAndGet(); - response.complete(BulkResponse.of(r -> r.errors(false).items(items).took(3))); - }); - - @SuppressWarnings("unchecked") - CompletableFuture result = (CompletableFuture) response; - return result; - } catch (RuntimeException e) { - CompletableFuture future = new CompletableFuture<>(); - future.completeExceptionally(e); - executor.submit(() -> { - future.completeExceptionally(e); - }); - return future; - } - } - - @Override - public JsonpMapper jsonpMapper() { - return SimpleJsonpMapper.INSTANCE; - } - - @Override - public TransportOptions options() { - return null; - } - - @Override - public void close() throws IOException { - executor.shutdown(); - try { - executor.awaitTermination(1, TimeUnit.SECONDS); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - - public void reset() { - requestsStarted.set(0); - requestsCompleted.set(0); - operations.set(0); - retryFailures = new ConcurrentHashMap<>(); - } - } - - private static class CountingListener implements BulkListener { - public final AtomicInteger sentRequestsTotal = new AtomicInteger(); - public final AtomicInteger successOperations = new AtomicInteger(); - public final AtomicInteger errorOperations = new AtomicInteger(); - public final AtomicInteger requests = new AtomicInteger(); - public final ConcurrentLinkedQueue sentContexts = new ConcurrentLinkedQueue<>(); - - @Override - public void beforeBulk(long executionId, BulkRequest request, List contexts) { - sentRequestsTotal.incrementAndGet(); - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, - BulkResponse response) { - for (BulkResponseItem item : response.items()) { - if (item.error() != null) { - errorOperations.incrementAndGet(); - } else { - successOperations.incrementAndGet(); - } - } - if (contexts.stream().anyMatch(Objects::nonNull)) { - sentContexts.addAll(contexts); - } - requests.incrementAndGet(); - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, - Throwable failure) { - failure.printStackTrace(); - errorOperations.addAndGet(request.operations().size()); - if (contexts.stream().anyMatch(Objects::nonNull)) { - sentContexts.addAll(contexts); - } - requests.incrementAndGet(); - } - - public void reset() { - successOperations.set(0); - errorOperations.set(0); - requests.set(0); - sentRequestsTotal.set(0); - } - } - - private BulkIngester newBasicBulkIngester(BulkListener listener) { - return BulkIngester.of(b -> b - .client(client) - .maxOperations(10) - .maxConcurrentRequests(10) - .listener(listener) - .backoffPolicy(BackoffPolicy.constantBackoff(50L, 8)) - ); - } - - private BulkIngester newBulkIngesterWithFlushAndContextAndLongExponential(BulkListener listener) { - return BulkIngester.of(b -> b - .client(client) - .maxOperations(10) - .maxConcurrentRequests(10) - .listener(listener) - .flushInterval(1000, TimeUnit.MILLISECONDS) - .backoffPolicy(BackoffPolicy.exponentialBackoff(100L, 8)) - ); - } - - private BulkIngester newBulkIngesterNoFlushAndContextAndLongExponential(BulkListener listener) { - return BulkIngester.of(b -> b - .client(client) - .maxOperations(10) - .maxConcurrentRequests(10) - .listener(listener) - .backoffPolicy(BackoffPolicy.exponentialBackoff(100L, 8)) - ); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterTest.java deleted file mode 100644 index cdad3e9dc..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/bulk/BulkIngesterTest.java +++ /dev/null @@ -1,627 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch._helpers.bulk; - -import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.ElasticsearchTestServer; -import co.elastic.clients.elasticsearch._helpers.bulk.BulkIngester; -import co.elastic.clients.elasticsearch._helpers.bulk.BulkListener; -import co.elastic.clients.elasticsearch._helpers.bulk.IngesterOperation; -import co.elastic.clients.elasticsearch._helpers.bulk.RetryableBulkOperation; -import co.elastic.clients.elasticsearch.core.BulkRequest; -import co.elastic.clients.elasticsearch.core.BulkResponse; -import co.elastic.clients.elasticsearch.core.bulk.BulkOperation; -import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; -import co.elastic.clients.elasticsearch.core.bulk.OperationType; -import co.elastic.clients.elasticsearch.end_to_end.RequestTest; -import co.elastic.clients.elasticsearch.indices.IndicesStatsResponse; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.SimpleJsonpMapper; -import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.TransportOptions; -import org.jetbrains.annotations.Nullable; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -class BulkIngesterTest extends Assertions { - - private static final BulkResponseItem successItem = BulkResponseItem.of(i -> i - .index("foo") - .status(200) - .operationType(OperationType.Delete) - ); - - private static final BulkOperation operation = BulkOperation.of(op -> op - .delete(d -> d.index("foo").id("bar")) - ); - - private void printStats(BulkIngester ingester) { - System.out.printf("Ingester - operations: %d (%d), requests: %d (%d)%n", - ingester.operationsCount(), ingester.operationContentionsCount(), - ingester.requestCount(), ingester.requestContentionsCount() - ); - } - - private void printStats(CountingListener listener) { - System.out.printf("Listener - operations: %d, requests: %d%n", - listener.operations.get(), - listener.requests.get() - ); - } - - private void printStats(TestTransport transport) { - System.out.printf("Transport - operations: %d, requests: %d (%d completed)%n", - transport.operations.get(), - transport.requestsStarted.get(), - transport.requestsCompleted.get() - ); - } - - @Test - public void basicTestFlush() throws Exception { - // Prime numbers, so that we have leftovers to flush before shutting down - multiThreadTest(7, 3, 5, 101, true); - } - - @Test - public void basicTestFlushWithInternalScheduler() throws Exception { - // Prime numbers, so that we have leftovers to flush before shutting down - multiThreadTest(7, 3, 5, 101, false); - } - - @Test - public void basicTestNoFlush() throws Exception { - // Will have nothing to flush on close. - multiThreadTest(10, 3, 5, 100, true); - } - - @Test - public void basicTestNoFlushWithInternalScheduler() throws Exception { - // Will have nothing to flush on close. - multiThreadTest(10, 3, 5, 100, false); - } - - private void multiThreadTest(int maxOperations, int maxRequests, int numThreads, int numOperations, - boolean externalScheduler) throws Exception { - - CountingListener listener = new CountingListener(); - TestTransport transport = new TestTransport(); - ElasticsearchAsyncClient client = new ElasticsearchAsyncClient(transport); - ScheduledExecutorService scheduler; - if (externalScheduler) { - scheduler = Executors.newSingleThreadScheduledExecutor(r -> { - Thread t = Executors.defaultThreadFactory().newThread(r); - t.setName("my-bulk-ingester-executor#"); - t.setDaemon(true); - return t; - }); - } else { - scheduler = null; - } - - BulkIngester ingester = BulkIngester.of(b -> b - .client(client) - .maxOperations(maxOperations) - .maxConcurrentRequests(maxRequests) - .scheduler(scheduler) - .listener(listener) - ); - - CountDownLatch latch = new CountDownLatch(numThreads); - for (int i = 0; i < numThreads; i++) { - new Thread(() -> { - try { - Thread.sleep((long)(Math.random() * 100)); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - for (int j = 0; j < numOperations; j++) { - ingester.add(operation); - } - - latch.countDown(); - }).start(); - } - - latch.await(); - - ingester.close(); - transport.close(); - if (scheduler != null) scheduler.shutdownNow(); - - printStats(ingester); - printStats(listener); - printStats(transport); - - int expectedOperations = numThreads * numOperations; - assertEquals(expectedOperations, ingester.operationsCount()); - assertEquals(expectedOperations, listener.operations.get()); - assertEquals(expectedOperations, transport.operations.get()); - - int expectedRequests = expectedOperations / maxOperations + ((expectedOperations % maxOperations == 0) ? 0 : 1) ; - - assertEquals(expectedRequests, ingester.requestCount()); - assertEquals(expectedRequests, listener.requests.get()); - assertEquals(expectedRequests, transport.requestsStarted.get()); - } - - @Test - public void multiThreadStressTest() throws InterruptedException, IOException { - - String index = "bulk-ingester-stress-test"; - ElasticsearchClient client = ElasticsearchTestServer.global().client(); - - // DISCLAIMER: this configuration is highly inefficient and only used here to showcase an extreme - // situation where the number of adding threads greatly exceeds the number of concurrent requests - // handled by the ingester. It's strongly recommended to always tweak maxConcurrentRequests accordingly. - BulkIngester ingester = BulkIngester.of(b -> b - .client(client) - .globalSettings(s -> s.index(index)) - .flushInterval(5, TimeUnit.SECONDS) - ); - - RequestTest.AppData appData = new RequestTest.AppData(); - appData.setIntValue(42); - appData.setMsg("Some message"); - - ExecutorService executor = Executors.newFixedThreadPool(50); - - for (int i = 0; i < 100000; i++) { - int ii = i; - Runnable thread = () -> { - int finalI = ii; - ingester.add(_1 -> _1 - .create(_2 -> _2 - .id(String.valueOf(finalI)) - .document(appData) - )); - }; - executor.submit(thread); - } - - executor.awaitTermination(10,TimeUnit.SECONDS); - ingester.close(); - - client.indices().refresh(); - - IndicesStatsResponse indexStats = client.indices().stats(g -> g.index(index)); - - assertTrue(indexStats.indices().get(index).primaries().docs().count()==100000); - } - - @Test - public void sizeLimitTest() throws Exception { - TestTransport transport = new TestTransport(); - - long operationSize = IngesterOperation.of(new RetryableBulkOperation<>(operation, null, null), transport.jsonpMapper()).size(); - - BulkIngester ingester = BulkIngester.of(b -> b - .client(new ElasticsearchAsyncClient(transport)) - // Set size limit just above operation's size, leading to 2 operations per request - .maxSize(operationSize + 1) - ); - - for (int i = 0; i < 10; i++) { - ingester.add(operation); - } - - ingester.close(); - transport.close(); - - assertEquals(10, ingester.operationsCount()); - assertEquals(5, ingester.requestCount()); - } - - @Test - public void periodicFlushTest() throws Exception { - TestTransport transport = new TestTransport(); - - BulkIngester ingester = BulkIngester.of(b -> b - .client(new ElasticsearchAsyncClient(transport)) - // Flush every 50 ms - .flushInterval(50, TimeUnit.MILLISECONDS) - // Disable other flushing limits - .maxSize(-1) - .maxOperations(-1) - .maxConcurrentRequests(Integer.MAX_VALUE-1) - ); - - // Add an operation every 100 ms to give time - // to the flushing timer to kick in. - for (int i = 0; i < 10; i++) { - ingester.add(operation); - Thread.sleep(100); - } - - ingester.close(); - transport.close(); - - // We should have one operation per request - assertEquals(10, ingester.operationsCount()); - assertEquals(10, ingester.requestCount()); - } - - @Test - public void failingListener() throws Exception { - TestTransport transport = new TestTransport(); - AtomicInteger failureCount = new AtomicInteger(); - AtomicReference> lastContexts = new AtomicReference<>(); - AtomicReference lastRequest = new AtomicReference<>(); - - BulkListener listener = new BulkListener() { - @Override - public void beforeBulk(long executionId, BulkRequest request, List contexts) { - // So that we can test that it's non-empty - lastContexts.set(contexts); - lastRequest.set(request); - - if (executionId == 1) { - // Fail before the request is sent - failureCount.incrementAndGet(); - throw new RuntimeException("Before bulk failure"); - } - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, BulkResponse response) { - if (executionId == 2) { - // Fail after the request is sent - failureCount.incrementAndGet(); - throw new RuntimeException("After bulk failure"); - } - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, Throwable failure) { - - } - }; - - BulkIngester ingester = BulkIngester.of(b -> b - .client(new ElasticsearchAsyncClient(transport)) - // Flush every 50 ms - .flushInterval(50, TimeUnit.MILLISECONDS) - // Disable other flushing limits - .maxSize(-1) - .maxOperations(-1) - .maxConcurrentRequests(Integer.MAX_VALUE - 1) - .listener(listener) - ); - - // Add an operation every 100 ms to give time - // to the flushing timer to kick in. - for (int i = 0; i < 10; i++) { - ingester.add(operation); - Thread.sleep(100); - } - - ingester.close(); - transport.close(); - - // We should have one operation per request - assertEquals(10, ingester.operationsCount()); - assertEquals(10, ingester.requestCount()); - // Transport hasn't seen the request where beforeBulk failed - assertEquals(9, transport.requestsStarted.get()); - - assertEquals(2, failureCount.get()); - - // Also test context list when no values were provided - assertTrue(lastRequest.get().operations().size() > 0); - assertEquals(lastRequest.get().operations().size(), lastContexts.get().size()); - } - - @Test - public void withContextValues() throws Exception { - TestTransport transport = new TestTransport(); - List allRequests = Collections.synchronizedList(new ArrayList<>()); - List> allContexts = Collections.synchronizedList(new ArrayList<>()); - - BulkListener listener = new BulkListener() { - @Override - public void beforeBulk(long executionId, BulkRequest request, List contexts) { - allRequests.add(request); - allContexts.add(contexts); - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, BulkResponse response) { - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, Throwable failure) { - } - }; - - BulkIngester ingester = BulkIngester.of(b -> b - .client(new ElasticsearchAsyncClient(transport)) - // Split every 10 operations - .maxOperations(10) - .listener(listener) - ); - - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - // Set a context only after 5, so that we test filling with nulls. - Integer context = j < 5 ? null : i*10 + j; - ingester.add(operation, context); - } - } - - ingester.close(); - transport.close(); - - // We should have 10 operations per request - assertEquals(100, ingester.operationsCount()); - assertEquals(10, ingester.requestCount()); - - for (int i = 0; i < 10; i++) { - List contexts = allContexts.get(i); - for (int j = 0; j < 10; j++) { - if (j < 5) { - assertNull(contexts.get(j)); - } else { - assertEquals(contexts.get(j), i*10 + j); - } - } - } - } - - @Test - public void testGlobalSettings() throws Exception { - AtomicReference storedRequest = new AtomicReference<>(); - - TestTransport transport = new TestTransport(); - CountingListener listener = new CountingListener() { - @Override - public void beforeBulk(long executionId, BulkRequest request, List contexts) { - super.beforeBulk(executionId, request, contexts); - storedRequest.set(request); - } - }; - - BulkIngester ingester = BulkIngester.of(b -> b - .client(new ElasticsearchAsyncClient(transport)) - .listener(listener) - .globalSettings(s -> s - .index("foo") - .routing("bar") - ) - ); - - ingester.add(operation); - - ingester.close(); - transport.close(); - - assertEquals(1, ingester.operationsCount()); - assertEquals(1, ingester.requestCount()); - - assertEquals("foo", storedRequest.get().index()); - assertEquals("bar", storedRequest.get().routing()); - } - - @Test - public void pipelineTest() { - String json = "{\"create\":{\"_id\":\"some_id\",\"_index\":\"some_idx\",\"pipeline\":\"pipe\",\"require_alias\":true}}"; - JsonpMapper mapper = new SimpleJsonpMapper(); - - BulkOperation create = BulkOperation.of(o -> o.create(c -> c - .pipeline("pipe") - .requireAlias(true) - .index("some_idx") - .id("some_id") - .document("Some doc") - )); - - String createStr = JsonpUtils.toJsonString(create, mapper); - assertEquals(json, createStr); - - BulkOperation create1 = IngesterOperation.of(new RetryableBulkOperation<>(create, null, null), mapper) - .repeatableOperation().operation(); - - String create1Str = JsonpUtils.toJsonString(create1, mapper); - assertEquals(json, create1Str); - } - - @Test - public void endToEndTest() throws Exception { - String index = "bulk-ingester-test"; - ElasticsearchClient client = ElasticsearchTestServer.global().client(); - - BulkIngester ingester = BulkIngester.of(b -> b - .client(client) - .globalSettings(s -> s.index(index)) - ); - - RequestTest.AppData appData = new RequestTest.AppData(); - appData.setIntValue(42); - appData.setMsg("Some message"); - - ingester.add(_1 -> _1 - .create(_2 -> _2 - .id("abc") - .document(appData) - )); - - ingester.add(_1 -> _1 - .create(_2 -> _2 - .id("def") - .document(appData) - )); - - ingester.add(_1 -> _1 - .update(_2 -> _2 - .id("gh") - .action(_3 -> _3 - .docAsUpsert(true) - .doc(appData)) - )); - - // Closing waits until all pending requests are completed - ingester.close(); - - for (String id : Arrays.asList("abc", "def", "gh")) { - assertEquals( - 42, - client.get(b -> b - .index(index) - .id(id), - RequestTest.AppData.class - ).source().getIntValue() - ); - } - - client.indices().delete(d -> d.index(index)); - - } - - @Test - public void testConfigValidation() { - - BulkIngester.Builder b = new BulkIngester.Builder<>(); - - assertThrows(IllegalArgumentException.class, () -> { - b.flushInterval(-1, TimeUnit.MILLISECONDS); - }); - - assertThrows(IllegalArgumentException.class, () -> { - b.maxConcurrentRequests(0); - }); - - assertThrows(IllegalArgumentException.class, () -> { - b.maxSize(-2); - }); - - assertThrows(IllegalArgumentException.class, () -> { - b.maxOperations(-2); - }); - - assertThrows(IllegalStateException.class, () -> { - b.maxSize(-1).maxOperations(-1).build(); - }); - } - - //----------------------------------------------------------------------------------------------------------------- - - private static class CountingListener implements BulkListener { - public final AtomicInteger operations = new AtomicInteger(); - public final AtomicInteger requests = new AtomicInteger(); - @Override - public void beforeBulk(long executionId, BulkRequest request, List contexts) { - - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, BulkResponse response) { - operations.addAndGet(request.operations().size()); - requests.incrementAndGet(); - } - - @Override - public void afterBulk(long executionId, BulkRequest request, List contexts, Throwable failure) { - failure.printStackTrace(); - operations.addAndGet(request.operations().size()); - requests.incrementAndGet(); - } - } - - private static class TestTransport implements ElasticsearchTransport { - public final AtomicInteger requestsStarted = new AtomicInteger(); - public final AtomicInteger requestsCompleted = new AtomicInteger(); - public final AtomicInteger operations = new AtomicInteger(); - - private final ExecutorService executor = Executors.newCachedThreadPool(); - - @Override - public ResponseT performRequest( - RequestT request, - Endpoint endpoint, - @Nullable TransportOptions options - ) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture performRequestAsync(RequestT request, Endpoint endpoint, @Nullable TransportOptions options) { - - BulkRequest bulk = (BulkRequest) request; - requestsStarted.incrementAndGet(); - operations.addAndGet(bulk.operations().size()); - - if (bulk.operations().size() == 0) { - System.out.println("No operations!"); - } - - List items = new ArrayList<>(); - for (int i = 0; i < bulk.operations().size(); i++) { - items.add(successItem); - } - - CompletableFuture response = new CompletableFuture<>(); - executor.submit(() -> { - requestsCompleted.incrementAndGet(); - response.complete(BulkResponse.of(r -> r.errors(false).items(items).took(3))); - }); - - @SuppressWarnings("unchecked") - CompletableFuture result = (CompletableFuture)response; - return result; - } - - @Override - public JsonpMapper jsonpMapper() { - return SimpleJsonpMapper.INSTANCE; - } - - @Override - public TransportOptions options() { - return null; - } - - @Override - public void close() throws IOException { - executor.shutdown(); - try { - executor.awaitTermination(1, TimeUnit.SECONDS); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java deleted file mode 100644 index b22c98018..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch._helpers.esql; - -import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.ElasticsearchTestServer; -import co.elastic.clients.elasticsearch._helpers.esql.EsqlAdapterTest; -import co.elastic.clients.elasticsearch._helpers.esql.jdbc.ResultSetEsqlAdapter; -import co.elastic.clients.elasticsearch._helpers.esql.objects.ObjectsEsqlAdapter; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.rest_client.RestClientTransport; -import org.apache.hc.core5.http.ContentType; -import org.apache.hc.core5.http.io.entity.ByteArrayEntity; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import com.fasterxml.jackson.databind.annotation.JsonNaming; -import org.apache.commons.io.IOUtils; - -import org.elasticsearch.client.Request; -import org.elasticsearch.client.RestClient; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.io.InputStream; -import java.sql.ResultSet; -import java.sql.Timestamp; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -public class EsqlAdapterEndToEndTest extends Assertions { - - static ElasticsearchClient esClient; - - @BeforeAll - public static void setup() throws Exception { - ElasticsearchClient global = ElasticsearchTestServer.global().client(); - RestClient restClient = ((RestClientTransport) global._transport()).restClient(); - esClient = new ElasticsearchClient(new RestClientTransport(restClient, new JacksonJsonpMapper())); - - esClient.indices().delete(d -> d.index("employees").ignoreUnavailable(true)); - - Request request = new Request("POST", "/employees/_bulk?refresh=true"); - - InputStream resourceAsStream = EsqlAdapterTest.class.getResourceAsStream("employees.ndjson"); - byte[] bytes = IOUtils.toByteArray(resourceAsStream); - request.setEntity(new ByteArrayEntity(bytes, ContentType.APPLICATION_JSON)); - - restClient.performRequest(request); - } - - @Test - public void resultSetTest() throws Exception { - - ResultSet rs = esClient.esql().query( - ResultSetEsqlAdapter.INSTANCE, - "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | SORT emp_no | LIMIT 300", - // Testing parameters. Note that FROM and LIMIT do not accept parameters - "10042", "10002" - ); - - { - assertTrue(rs.next()); - assertEquals("10002", rs.getString("emp_no")); - - // Single valued fields come back as single value even if other rows have multiple values - @SuppressWarnings("unchecked") - String job = (String) rs.getObject("job_positions"); - assertEquals("Senior Team Lead", job); - } - - { - assertTrue(rs.next()); - assertEquals("10042", rs.getString("emp_no")); - - java.sql.Date hireDate = rs.getDate("hire_date"); - assertEquals("1993-03-21", hireDate.toString()); - - Timestamp hireDate1 = rs.getTimestamp("hire_date"); - assertEquals( - "1993-03-21T00:00:00Z[UTC]", - DateTimeFormatter.ISO_DATE_TIME.format(hireDate1.toInstant().atZone(ZoneId.of("UTC"))) - ); - - @SuppressWarnings("unchecked") - List jobs = (List) rs.getObject("job_positions"); - - assertEquals(4, jobs.size()); - assertEquals("Architect", jobs.get(0)); - } - - assertFalse(rs.next()); - } - - @Test - public void objectsTest() throws Exception { - Iterable result = esClient.esql().query( - ObjectsEsqlAdapter.of(EmpData.class), - "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | SORT emp_no | LIMIT 300", - // Testing parameters. Note that FROM and LIMIT do not accept parameters - "10042", "10002" - ); - - Iterator it = result.iterator(); - - { - EmpData emp = it.next(); - assertEquals("10002", emp.empNo); - List jobPositions = emp.jobPositions; - // In addition to the value, this tests that single strings are correctly deserialized as a list - assertEquals(Arrays.asList("Senior Team Lead"), emp.jobPositions); - } - - { - EmpData emp = it.next(); - assertEquals("10042", emp.empNo); - assertEquals(4, emp.jobPositions.size()); - assertTrue(emp.jobPositions.contains("Architect")); - assertTrue(emp.jobPositions.contains("Business Analyst")); - assertTrue(emp.jobPositions.contains("Internship")); - assertTrue(emp.jobPositions.contains("Junior Developer")); - - assertEquals("1993-03-21T00:00:00Z[UTC]", - DateTimeFormatter.ISO_DATE_TIME.format(emp.hireDate.toInstant().atZone(ZoneId.of("UTC"))) - ); - } - - assertFalse(it.hasNext()); - - } - - @Test - public void asyncObjects() throws Exception { - - ElasticsearchAsyncClient asyncClient = new ElasticsearchAsyncClient(esClient._transport(), esClient._transportOptions()); - - - CompletableFuture> future = asyncClient.esql().query( - ObjectsEsqlAdapter.of(EmpData.class), - "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | SORT emp_no | LIMIT 300", - // Testing parameters. Note that FROM and LIMIT do not accept parameters - "10042", "10002" - ); - - future.thenApply(result -> { - Iterator it = result.iterator(); - - { - EmpData emp = it.next(); - assertEquals("10002", emp.empNo); - List jobPositions = emp.jobPositions; - // In addition to the value, this tests that single strings are correctly deserialized as a list - assertEquals(Arrays.asList("Senior Team Lead"), emp.jobPositions); - } - - { - EmpData emp = it.next(); - assertEquals("10042", emp.empNo); - assertEquals(4, emp.jobPositions.size()); - assertTrue(emp.jobPositions.contains("Architect")); - assertTrue(emp.jobPositions.contains("Business Analyst")); - assertTrue(emp.jobPositions.contains("Internship")); - assertTrue(emp.jobPositions.contains("Junior Developer")); - - assertEquals("1993-03-21T00:00:00Z[UTC]", - DateTimeFormatter.ISO_DATE_TIME.format(emp.hireDate.toInstant().atZone(ZoneId.of("UTC"))) - ); - } - - assertFalse(it.hasNext()); - return null; - } - ).get(); - } - - @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) - @JsonIgnoreProperties(ignoreUnknown = true) - public static class EmpData { - public String empNo; - public java.util.Date hireDate; - public List jobPositions; - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterTest.java deleted file mode 100644 index 6300a208e..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/_helpers/esql/EsqlAdapterTest.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch._helpers.esql; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._helpers.esql.jdbc.ResultSetEsqlAdapter; -import co.elastic.clients.elasticsearch._helpers.esql.objects.ObjectsEsqlAdapter; -import co.elastic.clients.elasticsearch.esql.EsqlFormat; -import co.elastic.clients.json.JsonpMappingException; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.testkit.MockHttpClient; -import co.elastic.clients.transport.endpoints.BinaryResponse; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.sql.ResultSet; -import java.sql.Types; - -public class EsqlAdapterTest extends Assertions { - - String json = "{\n" + - " \"took\": 10," + - " \"columns\": [\n" + - "\t{\"name\": \"avg_salary\", \"type\": \"double\"},\n" + - "\t{\"name\": \"lang\", \t\"type\": \"keyword\"}\n" + - " ],\n" + - " \"values\": [\n" + - "\t[43760.0, \"Spanish\"],\n" + - "\t[48644.0, \"French\"],\n" + - "\t[48832.0, \"German\"]\n" + - " ]\n" + - "}\n"; - - ElasticsearchClient esClient = new MockHttpClient() - .add("/_query", "application/json", json) - .client(new JacksonJsonpMapper()); // object deserializer needs a buffering mapper - - public static class Data { - public double avg_salary; - public String lang; - } - - @Test - public void testMissingColumns() throws IOException { - String badJson = "{\n" + - " \"took\": 10," + - " \"values\": [\n" + - "\t[43760.0, \"Spanish\"],\n" + - "\t[48644.0, \"French\"],\n" + - "\t[48832.0, \"German\"]\n" + - " ]\n" + - "}\n"; - - ElasticsearchClient esClient = new MockHttpClient() - .add("/_query", "application/json", badJson) - .client(new JacksonJsonpMapper()); - - JsonpMappingException jsonMappingException = assertThrows(JsonpMappingException.class, () -> { - esClient.esql().query( - ResultSetEsqlAdapter.INSTANCE, - "FROM employees | STATS avg_salary = AVG(salary) by country" - ); - }); - assertTrue(jsonMappingException.getMessage().contains("Expecting a 'columns' property")); - } - - @Test - public void testObjectDeserializer() throws IOException { - - BinaryResponse response = esClient.esql().query(q -> q - .query("FROM foo") - .format(EsqlFormat.Json) - ); - - Iterable data = esClient.esql().query( - new ObjectsEsqlAdapter<>(Data.class), - "FROM employees | STATS avg_salary = AVG(salary) by country" - ); - - for (Data d: data) { - System.out.println(d.lang + " " + d.avg_salary); - } - } - - @Test - public void testResultSetAdapter() throws Exception { - - ResultSet resultSet = esClient.esql().query( - ResultSetEsqlAdapter.INSTANCE, - "FROM employees | STATS avg_salary = AVG(salary) by country" - ); - - assertEquals(2, resultSet.getMetaData().getColumnCount()); - assertEquals(Types.DOUBLE, resultSet.getMetaData().getColumnType(1)); - assertEquals(Types.VARCHAR, resultSet.getMetaData().getColumnType(2)); - - while (resultSet.next()) { - System.out.println(resultSet.getDouble("avg_salary") + " " + resultSet.getString(2)); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/end_to_end/RequestTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/end_to_end/RequestTest.java deleted file mode 100644 index 18caf2e0e..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/end_to_end/RequestTest.java +++ /dev/null @@ -1,494 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.end_to_end; - -import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.ElasticsearchTestServer; -import co.elastic.clients.elasticsearch._types.ElasticsearchException; -import co.elastic.clients.elasticsearch._types.Refresh; -import co.elastic.clients.elasticsearch._types.aggregations.HistogramAggregate; -import co.elastic.clients.elasticsearch._types.mapping.Property; -import co.elastic.clients.elasticsearch.cat.NodesResponse; -import co.elastic.clients.elasticsearch.core.BulkResponse; -import co.elastic.clients.elasticsearch.core.ClearScrollResponse; -import co.elastic.clients.elasticsearch.core.ClosePointInTimeResponse; -import co.elastic.clients.elasticsearch.core.GetResponse; -import co.elastic.clients.elasticsearch.core.IndexResponse; -import co.elastic.clients.elasticsearch.core.MsearchResponse; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.core.bulk.OperationType; -import co.elastic.clients.elasticsearch.core.msearch.RequestItem; -import co.elastic.clients.elasticsearch.indices.CreateIndexResponse; -import co.elastic.clients.elasticsearch.indices.DiskUsageResponse; -import co.elastic.clients.elasticsearch.indices.GetIndexResponse; -import co.elastic.clients.elasticsearch.indices.GetIndicesSettingsResponse; -import co.elastic.clients.elasticsearch.indices.GetMappingResponse; -import co.elastic.clients.elasticsearch.indices.IndexState; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.transport.endpoints.BooleanResponse; -import co.elastic.clients.util.BinaryData; -import co.elastic.clients.util.ContentType; -import co.elastic.clients.util.DateTime; -import com.fasterxml.jackson.core.type.TypeReference; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.time.Instant; -import java.time.format.DateTimeFormatter; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; - -public class RequestTest extends Assertions { - - static ElasticsearchClient client; - - @BeforeAll - public static void setup() { - client = ElasticsearchTestServer.global().client(); - } - - @Test - public void testCount() throws Exception { - // Tests that a no-parameter method exists for endpoints that only have optional properties - assertTrue(client.count().count() >= 0); - } - - @Test - public void testBuildTime() throws Exception { - DateTime buildTime = client.info().version().buildDate(); - Instant early2020 = DateTimeFormatter.ISO_INSTANT.parse("2020-01-01T00:00:00Z", Instant::from); - - assertTrue(early2020.isBefore(buildTime.toInstant())); - } - - @Test - public void testIndexCreation() throws Exception { - ElasticsearchAsyncClient asyncClient = new ElasticsearchAsyncClient(client._transport()); - - // Ping the server - assertTrue(client.ping().value()); - - // Create an index... - final CreateIndexResponse createResponse = client.indices().create(b -> b.index("my-index")); - assertTrue(createResponse.acknowledged()); - assertTrue(createResponse.shardsAcknowledged()); - - // Find info about it, using the async client - CompletableFuture futureResponse = asyncClient.indices().get(b -> b.index("my-index")); - GetIndexResponse response = futureResponse.get(10, TimeUnit.SECONDS); - - Map indices = response.result(); - - assertEquals(1, indices.size()); - assertNotNull(indices.get("my-index")); - } - - @Test - public void testDataIngestion() throws Exception { - - String index = "ingest-test"; - - // Create an index - CreateIndexResponse createIndexResponse = client.indices().create(b -> b - .index(index) - ); - - assertEquals(index, createIndexResponse.index()); - - // Check that it actually exists. Example of a boolean response - BooleanResponse existsResponse = client.indices().exists(b -> b.index(index)); - assertTrue(existsResponse.value()); - - // Ingest some data - AppData appData = new AppData(); - appData.setIntValue(1337); - appData.setMsg("foo"); - - String docId = client.index(b -> b - .index(index) - .id("my/Id") // test with url-unsafe string - .document(appData) - .refresh(Refresh.True) // Make it visible for search - ).id(); - - assertEquals("my/Id", docId); - - // Check auto-created mapping - GetMappingResponse mapping = client.indices().getMapping(b -> b.index(index)); - assertEquals( - Property.Kind.Long, - mapping.get("ingest-test").mappings().properties().get("intValue")._kind() - ); - - // Query by id - AppData esData = client.get(b -> b - .index(index) - .id(docId) - , AppData.class - ).source(); - - assertEquals(1337, esData.getIntValue()); - assertEquals("foo", esData.getMsg()); - - // Query by id a non-existing document - final GetResponse notExists = client.get(b -> b - .index(index) - .id("some-random-id") - , AppData.class - ); - - assertFalse(notExists.found()); - assertNull(notExists.source()); - - // Search - SearchResponse search = client.search(b -> b - .index(index) - , AppData.class - ); - - long hits = search.hits().total().value(); - assertEquals(1, hits); - - esData = search.hits().hits().get(0).source(); - assertEquals(1337, esData.getIntValue()); - assertEquals("foo", esData.getMsg()); - - RequestItem item = RequestItem.of(_1 -> _1 - .header(_2 -> _2.index("test")) - .body(_2 -> _2.size(4)) - ); - - // MSearch: 1st search on an existing index, 2nd one on a non-existing index - final MsearchResponse msearch = client.msearch(_0 -> _0 - .searches(_1 -> _1 - .header(_3 -> _3.index(index)) - .body(_3 -> _3.query(_4 -> _4.matchAll(_5 -> _5))) - ).searches(_1 -> _1 - .header(_3 -> _3.index("non-existing")) - .body(_3 -> _3.query(_4 -> _4.matchAll(_5 -> _5))) - ) - , AppData.class); - - assertEquals(2, msearch.responses().size()); - assertTrue(msearch.responses().get(0).isResult()); - assertEquals(1, msearch.responses().get(0).result().hits().hits().size()); - assertTrue(msearch.responses().get(1).isFailure()); - assertEquals(404, msearch.responses().get(1).failure().status()); - } - - @Test - public void testBinaryDataIngestion() throws IOException { - String index = "binary-ingestion-test"; - String id = "foo-bar"; - - BinaryData data = BinaryData.of("{\"foo\":\"bar\"}".getBytes(), ContentType.APPLICATION_JSON); - - client.index(i -> i - .index(index) - .id(id) - .document(data) - .refresh(Refresh.True) - ); - - GetResponse getResponse = client.get(g -> g - .index(index) - .id(id) - , BinaryData.class - ); - - assertEquals(id, getResponse.id()); - assertEquals( - "{\"foo\":\"bar\"}", - new String(getResponse.source().asByteBuffer().array(), StandardCharsets.UTF_8) - ); - } - - @Test - public void testMappingWithType() throws IOException { - String index = "mapping-with-type"; - - // Ingest some data - Map map = new HashMap<>(); - AppData appData = new AppData(); - appData.setIntValue(1); - appData.setMsg("foo"); - map.put("foo", appData); - appData = new AppData(); - appData.setIntValue(2); - appData.setMsg("bar"); - map.put("bar", appData); - - String id = client.index(i -> i.index(index).document(map)).id(); - - TypeReference> typeRef = new TypeReference>() {}; - - Map result = client.>get(g -> g.index(index).id(id), typeRef.getType()).source(); - assertEquals(1, result.get("foo").intValue); - assertEquals(2, result.get("bar").intValue); - - } - - @Test - public void testCatRequest() throws IOException { - // Cat requests should have the "format=json" added by the transport - NodesResponse nodes = client.cat().nodes(_0 -> _0); - System.out.println(ModelTestCase.toJson(nodes, client._transport().jsonpMapper())); - - assertEquals(1, nodes.valueBody().size()); - assertEquals("*", nodes.valueBody().get(0).master()); - } - - @Test - public void testBulkRequest() throws IOException { - AppData appData = new AppData(); - appData.setIntValue(42); - appData.setMsg("Some message"); - - BulkResponse bulk = client.bulk(_0 -> _0 - .operations(_1 -> _1 - .create(_2 -> _2 - .index("foo") - .id("abc") - .document(appData) - )) - .operations(_1 -> _1 - .create(_2 -> _2 - .index("foo") - .id("def") - .document(appData) - )) - .operations(_1 -> _1 - .update(_2 -> _2 - .index("foo") - .id("gh") - .action(_3 -> _3 - .docAsUpsert(true) - .doc(appData)) - ) - ) - ); - - assertFalse(bulk.errors()); - assertEquals(3, bulk.items().size()); - assertEquals(OperationType.Create, bulk.items().get(0).operationType()); - assertEquals("foo", bulk.items().get(0).index()); - assertEquals(1L, bulk.items().get(0).version().longValue()); - assertEquals("foo", bulk.items().get(1).index()); - assertEquals(1L, bulk.items().get(1).version().longValue()); - assertEquals(42, client.get(b -> b.index("foo").id("gh"), AppData.class).source().intValue); - } - - @Test - public void testRefresh() throws IOException { - AppData appData = new AppData(); - appData.setIntValue(42); - appData.setMsg("Some message"); - - IndexResponse ir = client.index(_0 -> _0 - .index("test") - .id("1") - .document(appData) - .refresh(Refresh.WaitFor) - ); - - assertEquals("1", ir.id()); - } - - @Test public void errorResponse() throws Exception { - BooleanResponse exists = client.exists(_0 -> _0.index("doesnotexist").id("reallynot")); - assertFalse(exists.value()); - - ElasticsearchException ex = assertThrows(ElasticsearchException.class, () -> { - GetResponse response = client.get( - _0 -> _0.index("doesnotexist").id("reallynot"), String.class - ); - }); - - assertEquals("es/get", ex.endpointId()); - assertEquals(404, ex.status()); - assertEquals("index_not_found_exception", ex.error().type()); - assertEquals("doesnotexist", ex.error().metadata().get("index").to(String.class)); - - - ExecutionException ee = assertThrows(ExecutionException.class, () -> { - ElasticsearchAsyncClient aClient = new ElasticsearchAsyncClient(client._transport()); - GetResponse response = aClient.get( - _0 -> _0.index("doesnotexist").id("reallynot"), String.class - ).get(); - }); - - ex = ((ElasticsearchException) ee.getCause()); - assertEquals("es/get", ex.endpointId()); - assertEquals(404, ex.status()); - assertEquals("index_not_found_exception", ex.error().type()); - } - - @Test - public void testErrorStatusCodeWithValidResponse() throws IOException { - // https://github.com/elastic/elasticsearch-java/issues/36 - - // Some endpoints return a faulty status code 404 with a valid response. - // Transports should first try to decode an error, and if they fail because of missing properties for - // the error type, then try to decode the regular request. - - final ClearScrollResponse clearResponse = client.clearScroll(b -> b.scrollId( - "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ==") - ); - assertEquals(0, clearResponse.numFreed()); - - final ClosePointInTimeResponse closeResponse = client.closePointInTime(b -> b.id( - "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBY" + - "QADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA==")); - assertEquals(0, closeResponse.numFreed()); - } - - @Test - public void testSearchAggregation() throws IOException { - - client.create(_1 -> _1.index("products").id("A").document(new Product(5)).refresh(Refresh.True)); - client.create(_1 -> _1.index("products").id("B").document(new Product(15)).refresh(Refresh.True)); - client.create(_1 -> _1.index("products").id("C").document(new Product(25)).refresh(Refresh.True)); - - SearchResponse searchResponse = client.search(_1 -> _1 - .index("products") - .size(0) - .aggregations( - "prices", _3 -> _3 - .histogram(_4 -> _4 - .field("price") - .interval(10.0) - ).aggregations( - "average", _5 -> _5 - .avg(_6 -> _6.field("price")) - ) - ) - , Product.class - ); - - HistogramAggregate prices = searchResponse.aggregations().get("prices").histogram(); - assertEquals(3, prices.buckets().array().size()); - assertEquals(1, prices.buckets().array().get(0).docCount()); - assertEquals(5.0, prices.buckets().array().get(0).aggregations().get("average").avg().value(), 0.01); - - // We've set "size" to zero - assertEquals(0, searchResponse.hits().hits().size()); - - } - - @Test - public void testGetMapping() throws Exception { - // See also VariantsTest.testNestedTaggedUnionWithDefaultTag() - // and https://github.com/elastic/elasticsearch-java/issues/45 - String index = "testindex"; - - Map fields = Collections.singletonMap("keyword", Property.of(p -> p.keyword(k -> k.ignoreAbove(256)))); - Property text = Property.of(p -> p.text(t -> t.fields(fields))); - - client.indices().create(c -> c - .index(index) - .mappings(m -> m - .properties("id", text) - .properties("name", p -> p - .object(o -> o - .properties("first", text) - .properties("last", text) - ) - ) - ) - ); - - GetMappingResponse mr = client.indices().getMapping(mrb -> mrb.index(index)); - - assertNotNull(mr.result().get(index)); - assertNotNull(mr.result().get(index).mappings().properties().get("name").object()); - } - - @Test - public void testDefaultIndexSettings() throws IOException { - //https://github.com/elastic/elasticsearch-java/issues/46 - - String index = "index-settings"; - client.index(_1 -> _1.index(index).document(new Product(5)).refresh(Refresh.True)); - - GetIndicesSettingsResponse settings; - settings = client.indices().getSettings(b -> b.index(index).includeDefaults(true)); - assertNotNull(settings.get(index).defaults()); - - settings = client.indices().getSettings(b -> b.index(index)); - assertNull(settings.get(index).defaults()); - } - - @Test - public void testValueBodyResponse() throws Exception { - DiskUsageResponse resp = client.indices().diskUsage(b -> b - .index("*") - .allowNoIndices(true) - .runExpensiveTasks(true) - ); - - assertNotNull(resp.valueBody().toJson().asJsonObject().get("_shards")); - } - - public static class AppData { - private int intValue; - private String msg; - - public int getIntValue() { - return intValue; - } - - public void setIntValue(int intValue) { - this.intValue = intValue; - } - - public String getMsg() { - return msg; - } - - public void setMsg(String msg) { - this.msg = msg; - } - } - - public static class Product { - public double price; - - public Product() {} - public Product(double price) { - this.price = price; - } - - public double getPrice() { - return this.price; - } - - public void setPrice(double price) { - this.price = price; - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ClientTests.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ClientTests.java deleted file mode 100644 index b13c92557..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ClientTests.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments; - -import co.elastic.clients.elasticsearch.experiments.api.Bar; -import co.elastic.clients.elasticsearch.experiments.api.FooRequest; -import co.elastic.clients.elasticsearch.experiments.api.FooResponse; -import co.elastic.clients.elasticsearch.experiments.api.query2.Query; -import co.elastic.clients.elasticsearch.experiments.api.query2.TermsQuery; -import co.elastic.clients.elasticsearch.experiments.base.Client; -import co.elastic.clients.transport.Endpoint; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.Collections; - -public class ClientTests { - - @Test - public void testClient() throws Exception { - - Client client = new Client(){ - @Override - protected ResponseT performRequest( - RequestT request, Endpoint endpoint - ) throws IOException { - // don't care for now, we're testing compilation - return null; - } - }; - - client.foo(fb -> fb - .name("z") - .value(1) - .routing("fooo") - .query(q -> q - .bool(b-> b - .add_must(m -> m.terms((TermsQuery) null)) - ) - //.terms(tq -> tq.term("")) - .meta(Collections.emptyMap()) - ) - ); - - // Builders everywhere - FooResponse r1 = client.foo( - FooRequest.builder() - .name("z") - .value(1) - .bar(Bar.builder() - .name("Raise the bar") - .build() - ) - .build() - ); - - // Illustrates creating an object outside of the client call - TermsQuery filter = TermsQuery.builder() - .field("foo") - .term("bar") - .build(); - - Query filter2 = new Query.Builder() - .terms(t -> t - .field("foo") - .term("bar") - ).build(); - - // Fluid lambda-based builders - FooResponse r2 = client.foo(f -> f - .name("z") - .value(1) - .bar(bar -> bar - .name("Raise the bar") - ) - .query(q -> q - .bool(b -> b - .add_must(q1 -> q1.terms(filter)) - .add_must(q1 -> q1 - .terms(t -> t.field("a").term("b")) - ) - .add_must(q1 -> q1 - .terms(t -> t.field("a").term("b")) - ) - .minimumShouldMatch(2) - ) - ) - ); - } -} - diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ParsingTests.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ParsingTests.java deleted file mode 100644 index 37f094194..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/ParsingTests.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments; - -import co.elastic.clients.elasticsearch.experiments.api.FooRequest; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import jakarta.json.spi.JsonProvider; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import jakarta.json.stream.JsonParsingException; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; - -public class ParsingTests extends Assertions { - - @Test - public void testFoo() throws Exception { - - try { - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - FooRequest foo = FooRequest.builder() - .name("z") - .value(1) - .indices("a", "b", "c") - .bar(b -> b - .name("Raise the bar") - ) - .build(); - - JsonProvider provider = JsonpUtils.provider(); - JsonGenerator generator = provider.createGenerator(baos); - foo.serialize(generator, new JsonbJsonpMapper()); - - generator.close(); - String str = baos.toString(); - - assertEquals("{\"name\":\"z\",\"value\":1,\"indices\":[\"a\",\"b\",\"c\"],\"bar\":{\"name\":\"Raise the bar\"}}", str); - - JsonParser parser = provider.createParser(new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8))); - - FooRequest foo2 = FooRequest.parser().deserialize(parser, new JsonbJsonpMapper()); - - assertEquals(foo.name(), foo2.name()); - assertEquals(foo.value(), foo2.value()); - assertNull(foo2.size()); - assertEquals(foo.indices(), foo2.indices()); - assertEquals("Raise the bar", foo.bar().name()); - } catch (JsonParsingException je) { - throw new JsonParsingException(je.getMessage() + " at " + je.getLocation(), je, je.getLocation()); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/UnionVariant.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/UnionVariant.java deleted file mode 100644 index 86905d4ad..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/UnionVariant.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments; - -/** - * An implementation of a variant type. - */ -public interface UnionVariant { - - /** - * Get the type of this object when used as a variant - */ - Tag _variantType(); -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/Bar.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/Bar.java deleted file mode 100644 index bcba71fd1..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/Bar.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.api; - -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import javax.annotation.Nullable; - -public class Bar implements JsonpSerializable { - - private final String name; - - @Nullable - public String name() { - return this.name; - } - - public Bar(Builder builder) { - this.name = builder.name; - } - - @Override - public void serialize(JsonGenerator builder, JsonpMapper mapper) { - builder.writeStartObject(); - if (this.name != null) builder.write("name", this.name); - builder.writeEnd(); - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder implements ObjectBuilder { - private String name; - - public Builder name(@Nullable String name) { - this.name = name; - return this; - } - - public Bar build() { - return new Bar(this); - } - } - - private static final JsonpDeserializer PARSER; - - public static JsonpDeserializer parser() { - return PARSER; - } - - static { - ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); - - op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); - - PARSER = new ObjectBuilderDeserializer<>(op); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/DateMathTimeUnit.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/DateMathTimeUnit.java deleted file mode 100644 index 8412ca3e9..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/DateMathTimeUnit.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.api; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializer; - -public enum DateMathTimeUnit implements JsonEnum { - - Year("Y"), - Month("M"), - Day("D"), - Hour("h"), - Minute("m"), - Second("s"); - - private final String jsonValue; - - DateMathTimeUnit(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonpDeserializer PARSER; - - static { - PARSER = new Deserializer<>(DateMathTimeUnit.values()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooOptRequest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooOptRequest.java deleted file mode 100644 index 9cd1dbb26..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooOptRequest.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.api; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.elasticsearch.experiments.api.Bar; -import co.elastic.clients.elasticsearch.experiments.api.FooResponse; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.endpoints.SimpleEndpoint; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.OptionalInt; - -import static java.util.Objects.requireNonNull; - -// Implementing ToXContent is optional, only if there's a request body -public class FooOptRequest implements JsonpSerializable { - - //=========================================== - // Fields and getters - //=========================================== - - //------------------------------------------- - // A required String - - private final String name; - - @Nonnull - public final String name() { - return this.name; - } - - //------------------------------------------- - // An optional String - - private final String routing; - - @Nonnull - public final Optional routing() { - return Optional.ofNullable(this.routing); - } - - //------------------------------------------- - // A required primitive type - - private final int value; - - public int value() { - return this.value; - } - - //------------------------------------------- - // An optional primitive type - private final OptionalInt size; - - /** - * Description for field {@code size} - */ - @Nonnull - public final OptionalInt size() { - return this.size; - } - - //------------------------------------------- - // An optional array - - private final List indices; - - @Nonnull - public final Optional> indices() { - return Optional.ofNullable(this.indices); - } - - //------------------------------------------- - // An optional sub-object - - private final co.elastic.clients.elasticsearch.experiments.api.Bar bar; - - @Nonnull - public Optional bar() { - return Optional.ofNullable(this.bar); - } - - public FooOptRequest(Builder builder) { - this.name = builder.name; - this.routing = builder.routing; - this.value = builder.value; - this.size = builder.size == null ? OptionalInt.empty() : OptionalInt.of(builder.size); - this.indices = builder.indices; - this.bar = builder.bar; - } - - //=========================================== - // Serialization - //=========================================== - - - @Override - public void serialize(JsonGenerator builder, JsonpMapper mapper) { - builder.writeStartObject(); - - // Classic approach is to use the deserialization field's preferred name: - // - // if (buckets.isPresent()) builder.field(INT_FIELD.getPreferredName(), buckets.getAsInt()); - // - // In a generated code context we can use the string constant, which also avoids declaring ParseField if we - // only serialize (e.g. requests) - - // required field - builder.write("name", this.name); - - // optional field - if (this.routing != null) builder.write("routing", this.routing); - - // required field - builder.write("value", value); - - // optional field - if (this.size.isPresent()) builder.write("size", this.size.getAsInt()); - - // We could just call this and let the builder will handle it by itself with: - // - // if (this.indices != null) builder.field("indices", this.indices); - // - // But the logic is a bit involved (like checking circular dependencies) so we use a more direct implementation: - if (this.indices != null) { - builder.writeKey("indices").writeStartArray(); - for (String str : this.indices) builder.write(str); - builder.writeEnd(); - } - - if (this.bar != null) { - builder.writeKey("bar"); - this.bar.serialize(builder, mapper); - } - - builder.writeEnd(); - } - - //=========================================== - // Builder - //=========================================== - - public static Builder builder() { - return new Builder(); - } - - // Constructor with required fields - public static Builder builder(String name, int size) { - Builder result = new Builder(); - result.name(name); - result.size(size); - return result; - } - - public static class Builder implements ObjectBuilder { - private String name; - private String routing; - private int value; - private boolean value$isSet = false; - private Integer size; - private List indices; - private co.elastic.clients.elasticsearch.experiments.api.Bar bar; - - public final Builder name(@Nonnull String v) { - this.name = requireNonNull(v); - return this; - } - - public final Builder routing(@Nullable String v) { - this.routing = v; - return this; - } - - public final Builder value(int v) { - this.value = v; - this.value$isSet = true; - return this; - } - - public final Builder size(@Nullable Integer v) { - this.size = v; - return this; - } - - public final Builder indices(@Nullable List v) { - indices = v; - return this; - } - - // Convenience variant with varargs - public final Builder indices(String... v) { - indices = Arrays.asList(v); - return this; - } - - public Builder bar(@Nullable co.elastic.clients.elasticsearch.experiments.api.Bar v) { - bar = v; - return this; - } - - public Builder bar(@Nullable Bar.Builder v) { - bar = v.build(); - return this; - } - - public FooOptRequest build() { - requireNonNull(this.name, "Name was not set"); - requireTrue(this.value$isSet, "Value was not set"); - return new FooOptRequest(this); - } - } - - //=========================================== - // Deserialization - //=========================================== - -// // Only expose the most general interface to hide implementation details that may change over time. -// public static final ContextParser PARSER; -// -// static { -// ObjectParser op = -// new ObjectParser<>(FooOptRequest.class.getName(), FooOptRequest.Builder::new); -// -// op.declareString(Builder::name, new ParseField("name")); -// op.declareString(Builder::routing, new ParseField("routing")); -// -// op.declareInt(Builder::value, new ParseField("value")); -// op.declareInt(Builder::size, new ParseField("size")); -// -// op.declareStringArray(Builder::indices, new ParseField("indices")); -// op.declareObject(Builder::bar, Bar.PARSER, new ParseField("bar")); -// -// PARSER = new ObjectBuilderParser<>(op); -// } - - public static final Endpoint ENDPOINT = - new SimpleEndpoint( - "foo", - r -> "POST", - r -> "/foo", - SimpleEndpoint.emptyMap(), - SimpleEndpoint.emptyMap(), - SimpleEndpoint.emptyMap(), - true, - FooResponse.PARSER - ) { - }; - - public static void requireTrue(boolean v, String message) { - if (!v) throw new IllegalStateException(message); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooRequest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooRequest.java deleted file mode 100644 index 3c18ef890..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooRequest.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.api; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.elasticsearch.experiments.api.Bar; -import co.elastic.clients.elasticsearch.experiments.api.FooResponse; -import co.elastic.clients.elasticsearch.experiments.api.query2.Query; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.endpoints.SimpleEndpoint; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Arrays; -import java.util.List; -import java.util.function.Function; - -import static java.util.Objects.requireNonNull; - -// Implementing ToXContent is optional, only if there's a request body -public class FooRequest implements JsonpSerializable { - - //=========================================== - // Fields and getters - //=========================================== - - //------------------------------------------- - // A required String - - private final String name; - - @Nonnull - public final String name() { - return this.name; - } - - //------------------------------------------- - // An optional String - - private final String routing; - - @Nullable - public final String routing() { - return this.routing; - } - - //------------------------------------------- - // A required primitive type - - private final int value; - - public int value() { - return this.value; - } - - //------------------------------------------- - // An optional primitive type, represented as a nullable boxed value - - private final Integer size; - - /** - * Description for field {@code size} - */ - @Nullable - public final Integer size() { - return this.size; - } - - //------------------------------------------- - // An optional array - - private final List indices; - - /** - * A string[] property - */ - @Nullable - public final List indices() { - return this.indices; - } - - //------------------------------------------- - // An optional sub-object - - private final co.elastic.clients.elasticsearch.experiments.api.Bar bar; - - @Nullable - public co.elastic.clients.elasticsearch.experiments.api.Bar bar() { - return this.bar; - } - - //------------------------------------------- - // An optional query - - private final Query query; - - @Nullable - public Query query() { - return this.query; - } - - //------------------------------------------- - - public FooRequest(Builder builder) { - this.name = builder.name; - this.routing = builder.routing; - this.value = builder.value; - this.size = builder.size; - this.indices = builder.indices; - this.bar = builder.bar; - this.query = builder.query; - } - - - //=========================================== - // Builder - //=========================================== - - public static class Builder implements ObjectBuilder { - protected String name; - protected String routing; - protected int value; - protected boolean value$isSet = false; - protected Integer size; - protected List indices; - protected co.elastic.clients.elasticsearch.experiments.api.Bar bar; - protected Query query; - - public final Builder name(@Nonnull String v) { - this.name = requireNonNull(v); - return this; - } - - public final Builder routing(String v) { - this.routing = v; - return this; - } - - public final Builder value(int v) { - this.value = v; - this.value$isSet = true; - return this; - } - - public final Builder size(@Nullable Integer v) { - this.size = v; - return this; - } - - public final Builder indices(@Nullable List v) { - indices = v; - return this; - } - - // Convenience variant with varargs - public final Builder indices(String... v) { - indices = Arrays.asList(v); - return this; - } - - public Builder bar(@Nullable co.elastic.clients.elasticsearch.experiments.api.Bar v) { - bar = v; - return this; - } - - public Builder bar(Function> b) { - return bar(b.apply(new co.elastic.clients.elasticsearch.experiments.api.Bar.Builder()).build()); - } - - public Builder query(Query v) { - this.query = v; - return this; - } - - public Builder query(Function> b) { - return query(b.apply(new Query.Builder()).build()); - } - - public FooRequest build() { - requireNonNull(this.name, "'name' was not set"); - requireTrue(this.value$isSet, "'value' was not set"); - return new FooRequest(this); - } - } - - public static Builder builder() { - return new Builder(); - } - - // Constructor with required fields - public static Builder builder(String name, int size) { - Builder result = new Builder(); - result.name(name); - result.size(size); - return result; - } - - //=========================================== - // Serialization - //=========================================== - - @Override - public void serialize(JsonGenerator builder, JsonpMapper mapper) { - builder.writeStartObject(); - - // Classic approach is to use the deserialization field's preferred name: - // - // if (buckets.isPresent()) builder.field(INT_FIELD.getPreferredName(), buckets.getAsInt()); - // - // In a generated code context we can use the string constant, which also avoids declaring ParseField if we - // only serialize (e.g. requests) - - // required field - builder.write("name", this.name); - - // optional field - if (this.routing != null) builder.write("routing", this.routing); - - // required field - builder.write("value", value); - - // optional field - if (this.size != null) builder.write("size", this.size.intValue()); - - // We could just call this and let the builder will handle it by itself with: - // - // if (this.indices != null) builder.field("indices", this.indices); - // - // But the logic is a bit involved (like checking circular dependencies) so we use a more direct implementation: - if (this.indices != null) { - builder.writeKey("indices").writeStartArray(); - for (String str : this.indices) builder.write(str); - builder.writeEnd(); - } - - if (this.bar != null) { - builder.writeKey("bar"); - this.bar.serialize(builder, mapper); - } - - if (this.query != null) { - builder.writeKey("query"); - this.query.serialize(builder, mapper); - } - - builder.writeEnd(); - } - - //=========================================== - // Deserialization - // (formally not needed for requests) - //=========================================== - - private static final JsonpDeserializer PARSER; - - public static JsonpDeserializer parser() { - return PARSER; - } - - static { - ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); - - op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); - op.add(Builder::routing, JsonpDeserializer.stringDeserializer(), "routing"); - op.add(Builder::value, "value"); // primitive type - op.add(Builder::size, "size"); - op.add(Builder::indices, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), "indices"); - op.add(Builder::bar, Bar.parser(), "bar"); - op.add(Builder::query, Query.parser(), "query"); - - PARSER = new ObjectBuilderDeserializer<>(op); - } - - //=========================================== - // Endpoint - //=========================================== - - public static final Endpoint ENDPOINT = - new SimpleEndpoint<>( - "foo", - r -> "POST", - r -> "/foo", - SimpleEndpoint.emptyMap(), - SimpleEndpoint.emptyMap(), - SimpleEndpoint.emptyMap(), - true, - FooResponse.PARSER - ); - - public static void requireTrue(boolean v, String message) { - if (!v) throw new IllegalStateException(message); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooResponse.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooResponse.java deleted file mode 100644 index 3a3e0095a..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/FooResponse.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.api; - -import co.elastic.clients.json.JsonpDeserializer; - -public class FooResponse { - - public static JsonpDeserializer PARSER = null; -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/BoolQuery.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/BoolQuery.java deleted file mode 100644 index 1a84f9c52..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/BoolQuery.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.api.query2; - -import co.elastic.clients.elasticsearch.experiments.api.query2.Query; -import co.elastic.clients.elasticsearch.experiments.api.query2.Union2; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.function.Function; - -public class BoolQuery implements co.elastic.clients.elasticsearch.experiments.api.query2.Query.Variant, JsonpSerializable { - - private final Collection should; - private final Collection must; - private final co.elastic.clients.elasticsearch.experiments.api.query2.Union2 minimumShouldMatch; - - public BoolQuery(Builder builder) { - this.should = builder.should; - this.must = builder.must; - this.minimumShouldMatch = builder.minimumShouldMatch; - } - - @Override - public co.elastic.clients.elasticsearch.experiments.api.query2.Query.Kind _variantType() { - return co.elastic.clients.elasticsearch.experiments.api.query2.Query.Kind.Bool; - } - - public Collection should() { - return should; - } - - public Collection must() { - return must; - } - - public co.elastic.clients.elasticsearch.experiments.api.query2.Union2 minimumShouldMatch() { - return minimumShouldMatch; - } - - @Override - public void serialize(JsonGenerator builder, JsonpMapper mapper) { - builder.writeStartObject(); - - if (should != null) { - builder.writeKey("should"); - builder.writeStartArray(); - for (co.elastic.clients.elasticsearch.experiments.api.query2.Query v: should) v.serialize(builder, mapper); - builder.writeEnd(); - } - - if (should != null) { - builder.writeKey("must"); - builder.writeStartArray(); - for (co.elastic.clients.elasticsearch.experiments.api.query2.Query v: must) v.serialize(builder, mapper); - builder.writeEnd(); - } - - if (minimumShouldMatch != null) { - builder.writeKey("minimum_should_match"); - // Unions have to be expanded inline as serialization depends on the value type. - this.minimumShouldMatch.serialize(builder, mapper, - (v, b, p) -> builder.write(v), - (v, b, p) -> builder.write(v) - ); - } - - builder.writeEnd(); - } - - public static class Builder implements ObjectBuilder { - - private Collection should; - private Collection must; - private co.elastic.clients.elasticsearch.experiments.api.query2.Union2 minimumShouldMatch; - - public Builder should(Collection v) { - this.should = v; - return this; - } - - public Builder add_should(@Nullable co.elastic.clients.elasticsearch.experiments.api.query2.Query v) { - if (v == null) return this; - if (this.should == null) this.should = new ArrayList<>(); - this.should.add(v); - return this; - } - - public Builder add_should(Function> v) { - return add_should(v.apply(new co.elastic.clients.elasticsearch.experiments.api.query2.Query.Builder()).build()); - } - - public Builder must(Collection v) { - this.must = v; - return this; - } - - public Builder add_must(@Nullable co.elastic.clients.elasticsearch.experiments.api.query2.Query v) { - if (v == null) return this; - if (this.must == null) this.must = new ArrayList<>(); - this.must.add(v); - return this; - } - - public Builder add_must(Function> v) { - return add_must(v.apply(new co.elastic.clients.elasticsearch.experiments.api.query2.Query.Builder()).build()); - } - - // Expand all union members - // TODO: check unions with nested structures and fluent builders - public Builder minimumShouldMatch(int v) { - return minimumShouldMatch(co.elastic.clients.elasticsearch.experiments.api.query2.Union2.ofA(v)); - } - - public Builder minimumShouldMatch(String v) { - return minimumShouldMatch(co.elastic.clients.elasticsearch.experiments.api.query2.Union2.ofB(v)); - } - - public Builder minimumShouldMatch(co.elastic.clients.elasticsearch.experiments.api.query2.Union2 v) { - this.minimumShouldMatch = v; - return this; - } - - @Override - public BoolQuery build() { - return new BoolQuery(this); - } - } - - private static final JsonpDeserializer PARSER; - - public static JsonpDeserializer parser() { - return PARSER; - } - - static { - ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); - - op.add(Builder::must, JsonpDeserializer.arrayDeserializer(co.elastic.clients.elasticsearch.experiments.api.query2.Query.parser()), "must"); - op.add(Builder::should, JsonpDeserializer.arrayDeserializer(Query.parser()), "should"); - - op.add(Builder::minimumShouldMatch, new Union2.JsonpParser<>( - JsonpDeserializer.integerDeserializer(), - JsonpDeserializer.stringDeserializer() - ), "minimum_should_match"); - - PARSER = new ObjectBuilderDeserializer<>(op); - } - -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Query.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Query.java deleted file mode 100644 index b8719a7e4..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Query.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.api.query2; - -import co.elastic.clients.elasticsearch.experiments.UnionVariant; -import co.elastic.clients.elasticsearch.experiments.api.query2.BoolQuery; -import co.elastic.clients.elasticsearch.experiments.api.query2.TermsQuery; -import co.elastic.clients.json.BuildFunctionDeserializer; -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.TaggedUnion; -import co.elastic.clients.util.TaggedUnionUtils; -import jakarta.json.JsonValue; -import jakarta.json.stream.JsonGenerator; - -import java.util.Map; -import java.util.function.Function; - -public class Query implements TaggedUnion, JsonpSerializable { - - public interface Variant extends UnionVariant, JsonpSerializable { - default Query _toQuery() { - return new Query(this); - } - } - - public enum Kind implements JsonEnum { - Bool("bool"), - Terms("terms"); - - private final String jsonValue; - - Kind(String jsonValue) { - this.jsonValue = jsonValue; - } - - @Override - public String jsonValue() { - return null; - } - } - - private static final String BOOL = "bool"; - private static final String TERMS = "terms"; - - private final Kind _variantType; - private final Variant _variantValue; - - @Override - public Kind _kind() { - return _variantType; - } - - @Override - public Variant _get() { - return _variantValue; - } - - // A container-level property that lives besides the variant, like "meta" and "aggs" in aggregations - private Map meta; - - public Query(Variant value) { - this._variantType = value._variantType(); - this._variantValue = value; - } - - private Query(Builder builder) { - this._variantType = builder.$tag; - this._variantValue = builder.$variant; - - this.meta = builder.meta; - } - - // Accessors to container properties - public Map meta() { - return this.meta; - } - - public BoolQuery bool() { - return TaggedUnionUtils.get(this, Kind.Bool); - } - - public TermsQuery terms() { - return TaggedUnionUtils.get(this, Kind.Terms); - } - - @Override - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - generator.writeKey(_variantType.jsonValue); - if (_variantValue instanceof JsonpSerializable) { - ((JsonpSerializable) _variantValue).serialize(generator, mapper); - } else { - // Other serialization - } - if (meta != null) { - generator.writeStartObject("meta"); - for (Map.Entry e: meta.entrySet()) { - generator.write(e.getKey(), e.getValue()); - } - generator.writeEnd(); - } - generator.writeEnd(); - } - - public static class Builder { - - private Variant $variant; - private Kind $tag; - private Map meta; - - // Container properties - public Builder meta(Map value) { - this.meta = value; - return this; - } - - // Variants - // - // We return a container builder and not a builder. This is because a union accepts a single variant and we - // don't want to allow choosing more than one yet we still want to be able to set container-level properties - - public ContainerBuilder bool(BoolQuery v) { - this.$variant = v; - this.$tag = Kind.Bool; - return new ContainerBuilder(); - } - - // If we don't have container properties, the container builder is not necessary - public ObjectBuilder foo() { - return this::build; - } - - public ContainerBuilder bool(Function> f) { - return this.bool(f.apply(new BoolQuery.Builder()).build()); - } - - public ContainerBuilder terms(TermsQuery v) { - this.$variant = v; - this.$tag = Kind.Terms; - return new ContainerBuilder(); - } - - public ContainerBuilder terms(Function> f) { - return this.terms(f.apply(new TermsQuery.Builder()).build()); - } - - // Protected, only called by the container - protected Query build() { - return new Query(this); - } - - /** - * A builder that only contains container-level properties. If we don't have such properties, this - * can be replaced with an {@code ObjectBuilder} - */ - public class ContainerBuilder implements ObjectBuilder { - - public ContainerBuilder meta(Map value) { - Builder.this.meta(value); - return this; - } - - public Query build() { - return Builder.this.build(); - } - } - } - - private static volatile JsonpDeserializer PARSER; - - public static JsonpDeserializer parser() { - if (PARSER == null) { - ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); - op.add(Builder::bool, BoolQuery.parser(), "bool"); - op.add(Builder::terms, TermsQuery.parser(), "terms"); - // parser for "meta" (a map) - - PARSER = new BuildFunctionDeserializer<>(op, Builder::build); - } - - return PARSER; - } - - -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/QueryTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/QueryTest.java deleted file mode 100644 index f04890033..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/QueryTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.api.query2; - -import co.elastic.clients.elasticsearch.experiments.api.query2.BoolQuery; -import co.elastic.clients.elasticsearch.experiments.api.query2.Query; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.util.Collection; - -public class QueryTest extends Assertions { - @Test - public void testQuery() { - co.elastic.clients.elasticsearch.experiments.api.query2.BoolQuery bq = new BoolQuery.Builder().build(); - - co.elastic.clients.elasticsearch.experiments.api.query2.Query q = new co.elastic.clients.elasticsearch.experiments.api.query2.Query(bq); - - assertEquals(co.elastic.clients.elasticsearch.experiments.api.query2.Query.Kind.Bool, q._kind()); - - co.elastic.clients.elasticsearch.experiments.api.query2.Query.Variant v = q._get(); - assertEquals(co.elastic.clients.elasticsearch.experiments.api.query2.Query.Kind.Bool, v._variantType()); - - co.elastic.clients.elasticsearch.experiments.api.query2.Query q1 = v._toQuery(); - - Collection must = q.bool().must(); - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/TermsQuery.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/TermsQuery.java deleted file mode 100644 index 057e7ba76..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/TermsQuery.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.api.query2; - -import co.elastic.clients.elasticsearch.experiments.api.query2.Query; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -public class TermsQuery implements JsonpSerializable, co.elastic.clients.elasticsearch.experiments.api.query2.Query.Variant { - - private final String field; - private final String term; - - public TermsQuery(Builder builder) { - this.field = builder.field; - this.term = builder.term; - } - - @Override - public co.elastic.clients.elasticsearch.experiments.api.query2.Query.Kind _variantType() { - return Query.Kind.Terms; - } - - public String field() { - return this.field; - } - - public String term() { - return this.term; - } - - @Override - public void serialize(JsonGenerator builder, JsonpMapper mapper) { - // We only serialize our content. It's the enclosing class responsibility to output the variant's discriminant. - // This allows using this class in non-variant contexts. - builder.writeStartObject(); - if (this.field != null) { - builder.write("field", this.field); - } - - if (this.term != null) { - builder.write("term", this.term); - } - - builder.writeEnd(); - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder implements ObjectBuilder { - - private String field; - private String term; - - public Builder field(String v) { - this.field = v; - return this; - } - - public Builder term(String v) { - this.term = v; - return this; - } - - @Override - public TermsQuery build() { - return new TermsQuery(this); - } - } - - private static final JsonpDeserializer PARSER; - - public static JsonpDeserializer parser() { - return PARSER; - } - - static { - ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); - op.add(Builder::field, JsonpDeserializer.stringDeserializer(), "field"); - op.add(Builder::term, JsonpDeserializer.stringDeserializer(), "term"); - - PARSER = new ObjectBuilderDeserializer<>(op); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Union2.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Union2.java deleted file mode 100644 index fe7b3131d..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/api/query2/Union2.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.api.query2; - -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpDeserializerBase; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.util.TriConsumer; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import jakarta.json.stream.JsonParser.Event; -import jakarta.json.stream.JsonParsingException; - -/** - * A tagged union (also known as variant, sum type or coproduct) with two members. - * - * The union's value is one (and only one) of the possible variants. The variant in use is defined by the - * {@link #tag()}'s value. - * - * @param type of the first variant - * @param type of the second variant - */ - -// Design note: we cannot require A and B, and by extension Union2, to implement JsonpSerializable as they can be builtin types -// like String or Integer - -public class Union2 { - - /** - * The variant tag. - */ - public enum Tag{A, B}; - - private final Tag tag; - private final Object value; - - private Union2(Tag tag, Object value) { - this.tag = tag; - this.value = value; - } - - /** - * Creates a variant {@code A}. - */ - public static Union2 ofA(A value) { - return new Union2<>(Tag.A, value); - } - - /** - * Creates a variant {@code B}. - */ - public static Union2 ofB(B value) { - return new Union2<>(Tag.B, value); - } - - /** - * Get the variant's tag of this union. - * - * @return the variant's tag - */ - public Tag tag() { - return tag; - } - - /** - * Get the variant {@code A} of this union. - * - * @return the variant's value - * @throws IllegalStateException if the union is not holding a variant {@code A} - */ - public A a() { - return getVariant(Tag.A); - } - - /** - * Get the variant {@code B} of this union. - * - * @return the variant's value - * @throws IllegalStateException if the union is not holding a variant {@code B} - */ - public B b() { - return getVariant(Tag.B); - } - - private T getVariant(Tag tag) { - if (this.tag != tag) throw new IllegalStateException("Union holds variant " + tag); - - @SuppressWarnings("unchecked") - T result = (T)value; - - return result; - } - - //----------------------------------------------------------------------------------------------- - // Serialization / deserialization - - public void serialize( - JsonGenerator builder, JsonpMapper params, - TriConsumer a, - TriConsumer b - ) { - switch (this.tag) { - case A: - a.accept(this.a(), builder, params); - case B: - b.accept(this.b(), builder, params); - } - } - - public static class JsonpParser extends JsonpDeserializerBase> { - - private final JsonpDeserializer parserA; - private final JsonpDeserializer parserB; - - public JsonpParser( - JsonpDeserializer parserA, - JsonpDeserializer parserB - ) { - super(allAcceptedEvents(parserA, parserB)); - this.parserA = parserA; - this.parserB = parserB; - } - - @Override - public Union2 deserialize(JsonParser parser, JsonpMapper mapper, Event event) { - if (parserA.accepts(event)) { - return Union2.ofA(parserA.deserialize(parser, mapper, event)); - - } else if (parserB.accepts(event)) { - return Union2.ofB(parserB.deserialize(parser, mapper, event)); - - } else { - throw new JsonParsingException("Unexpected event '" + event + "'", parser.getLocation()); - } - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Client.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Client.java deleted file mode 100644 index acf35affc..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Client.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.base; - -import co.elastic.clients.elasticsearch.experiments.api.FooRequest; -import co.elastic.clients.elasticsearch.experiments.api.FooResponse; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.Transport; -import co.elastic.clients.util.ObjectBuilder; - -import java.io.IOException; -import java.util.function.Function; - -public class Client { - - private Transport transport; - - public FooResponse foo(FooRequest request) throws IOException { - return performRequest(request, FooRequest.ENDPOINT); - } - - public FooResponse foo(Function> b) throws IOException { - return foo(b.apply(new FooRequest.Builder()).build()); - } - - protected ResponseT performRequest( - RequestT request, Endpoint endpoint - ) throws IOException { - return transport.performRequest(request, endpoint, null); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/PrimitiveUtils.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/PrimitiveUtils.java deleted file mode 100644 index b245854d7..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/PrimitiveUtils.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.base; - -/** - * Support functions for primitive fields in generated classes - */ -public class PrimitiveUtils { - public static int checkedValue(int value, boolean isSet) { - mustBeSet(isSet); - return value; - } - - public static long checkedValue(long value, boolean isSet) { - mustBeSet(isSet); - return value; - } - - private static void mustBeSet(boolean isSet) { - if (!isSet) { - throw new IllegalStateException("Value is not set"); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Variants.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Variants.java deleted file mode 100644 index 923724c27..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/base/Variants.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.base; - -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import jakarta.json.stream.JsonParsingException; - -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; - -/** - * Describes the variants of a transport class, providing their name and parsers. It is representation-agnostic. - */ -public class Variants { - - private Function, Builder> builderFunc; - - private Map, String> variantNames; - private Map> parsers; - - /** - * Builds a new {@code Variants} from a builder-creation function. This approach allows the object to be built lazily, - * which is needed for recursive variant data structures (e.g. a query can be a boolean query that itself contains - * other queries). - * - * This is required because cyclic dependencies between static class initialization code can lead to unexpected - * behaviour (a subclass static init may be called while static init of the parent class is not finished). - */ - public Variants(Function, Builder> b) { - this.builderFunc = b; - } - - public Variants(Builder builder) { - this.variantNames = builder.variantNames; - this.parsers = builder.parsers; - } - - public String variantName(Class clazz) { - build(); - return variantNames.get(clazz); - } - - public JsonpDeserializer variantParser(String name) { - build(); - return parsers.get(name); - } - - private void build() { - if (builderFunc != null) { - Builder builder = builderFunc.apply(new Builder<>()); - this.variantNames = builder.variantNames; - this.parsers = builder.parsers; - this.builderFunc = null; - } - } - - //------------------------------------------------------------------------------------------------------------------- - - public static Builder builder() { - return new Builder<>(); - } - - public static class Builder { - private final Map, String> variantNames = new HashMap<>(); - private final Map> parsers = new HashMap<>(); - - public Builder add(String name, Class clazz, JsonpDeserializer parser) { - variantNames.put(clazz, name); - parsers.put(name, parser); - return this; - } - - public Variants build() { - return new Variants<>(this); - } - } - - //------------------------------------------------------------------------------------------------------------------- - - /** - * Variant serializer/deserializer using externally tagged JSON. - *

- * See Enumerations in Serde.rs that clearly explains the - * various strategies to represent polymorphic values in JSON. - */ - public static class ExternallyTagged { - - /** - * Creates a parser for externally tagged variants - */ - public static JsonpDeserializer pparser(Variants variants) { - return JsonpDeserializer.of(EnumSet.of(JsonParser.Event.START_OBJECT), (parser, params) -> { - JsonpUtils.expectNextEvent(parser, JsonParser.Event.START_OBJECT); - JsonpUtils.expectNextEvent(parser, JsonParser.Event.KEY_NAME); - - String variant = parser.getString(); - JsonpDeserializer variantParser = variants.variantParser(variant); - - if (variantParser == null) { - throw new JsonParsingException("Unknown variant '" + variant + "'", parser.getLocation()); - } - - T result = variantParser.deserialize(parser, params); - - JsonpUtils.expectNextEvent(parser, JsonParser.Event.END_OBJECT); - - return result; - }); - } - - /** - * Serializes an externally tagged variant object - */ - - public static void serialize( - Variants variants, T v, JsonGenerator builder, JsonpMapper mapper - ) { - @SuppressWarnings("unchecked") - String variant = variants.variantName((Class)v.getClass()); - - if (variant == null) { - throw new IllegalArgumentException("No variant name found for " + v.getClass().getName()); - } - - builder.writeStartObject(); - builder.writeKey(variant); - v.serialize(builder, mapper); - builder.writeEnd(); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnion.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnion.java deleted file mode 100644 index d82caa6dd..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnion.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.containers; -/* - // @variants internal tag='type' - interface SomeUnion = UnionItemA | UnionItemB; - - interface VariantA { - type: 'variant_a' - variant_a_prop: String - } - - interface VariantB { - type: 'variant_b' - variant_b_prop: String - } -*/ - -import co.elastic.clients.elasticsearch.experiments.containers.SomeUnionVariant; -import co.elastic.clients.elasticsearch.experiments.containers.UVariantA; -import co.elastic.clients.elasticsearch.experiments.containers.UVariantB; -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.TaggedUnion; -import co.elastic.clients.util.TaggedUnionUtils; -import jakarta.json.stream.JsonGenerator; - -import java.util.function.Function; - -@JsonpDeserializable -public class SomeUnion implements TaggedUnion, JsonpSerializable { - - public enum Kind implements JsonEnum { - VariantA("variant_a"), - VariantB("variant_b"); - - private final String jsonValue; - - Kind(String jsonValue) { - this.jsonValue = jsonValue; - } - - @Override - public String jsonValue() { - return null; - } - } - - private final SomeUnionVariant _value; - private final Kind _type; - - public SomeUnion(Builder builder) { - this._value = builder._value; - this._type = builder._type; - } - - @Override - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - // Delegate to the variant object - if (_value instanceof JsonpSerializable) { - ((JsonpSerializable)_value).serialize(generator, mapper); - } - } - - @Override - public Kind _kind() { - return _type; - } - - @Override - public SomeUnionVariant _get() { - return _value; - } - - public UVariantA variantA() { - return TaggedUnionUtils.get(this, Kind.VariantA); - } - - public UVariantB variantB() { - return TaggedUnionUtils.get(this, Kind.VariantB); - } - - static class Builder { - - private SomeUnionVariant _value; - private Kind _type; - - // This "builder" doesn't allow building objects. It only contains methods to set a variant. - // These methods return a builder class with no other methods. This enforces the choice of one and only one - // variant at the type level (i.e. at compile time). - - // variant_a - - public ObjectBuilder variantA(UVariantA value) { - this._value = value; - this._type = Kind.VariantA; - final SomeUnion result = build(); - return () -> result; - } - - public ObjectBuilder variantA(Function fn) { - return this.variantA(fn.apply(new UVariantA.Builder()).build()); - } - - // variant_b - - public ObjectBuilder variantB(UVariantB value) { - this._value = value; - this._type = Kind.VariantB; - final SomeUnion result = build(); - return () -> result; - } - - public ObjectBuilder variantB(Function fn) { - return this.variantB(fn.apply(new UVariantB.Builder()).build()); - } - - protected SomeUnion build() { - return new SomeUnion(this); - } - } - - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, - SomeUnion::setupSomeUnionDeserializer, Builder::build); - - protected static void setupSomeUnionDeserializer(ObjectDeserializer op) { - op.add(Builder::variantA, UVariantA._DESERIALIZER, "variant_a"); - op.add(Builder::variantB, UVariantB._DESERIALIZER, "variant_b"); - - op.setTypeProperty("type", null); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionTest.java deleted file mode 100644 index ab73106f8..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.containers; - -import co.elastic.clients.elasticsearch.experiments.containers.SomeUnion; -import co.elastic.clients.elasticsearch.experiments.containers.UVariantA; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import jakarta.json.spi.JsonProvider; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import jakarta.json.stream.JsonParsingException; -import org.junit.jupiter.api.Test; - -import java.io.ByteArrayOutputStream; -import java.io.StringReader; - -public class SomeUnionTest extends ModelTestCase { - - co.elastic.clients.elasticsearch.experiments.containers.SomeUnion su = new co.elastic.clients.elasticsearch.experiments.containers.SomeUnion.Builder() - .variantA(a_ -> a_ - .name("a-name") - ).build(); - - String json = "{\"type\":\"variant_a\",\"name\":\"a-name\"}"; - - @Test - public void testContainerBuilder() { - assertEquals("a-name", su.variantA().name()); - } - - @Test - public void testDeserialization() { - co.elastic.clients.elasticsearch.experiments.containers.SomeUnion u = fromJson(json, co.elastic.clients.elasticsearch.experiments.containers.SomeUnion.class); - UVariantA uVariantA = u.variantA(); - assertEquals("a-name", uVariantA.name()); - } - - @Test - public void testSerialization() { - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - JsonProvider provider = JsonpUtils.provider(); - JsonGenerator generator = provider.createGenerator(baos); - - su.serialize(generator, new JsonbJsonpMapper()); - generator.close(); - - System.out.println(baos.toString()); - - assertEquals(json, baos.toString()); - - } - - @Test - public void testMissingVariantDeserialization() { - String json = "{}"; - - JsonProvider provider = JsonpUtils.provider(); - JsonParser parser = provider.createParser(new StringReader(json)); - - JsonParsingException e = assertThrows(JsonParsingException.class, () -> { - co.elastic.clients.elasticsearch.experiments.containers.SomeUnion c = SomeUnion._DESERIALIZER.deserialize(parser, new JsonbJsonpMapper()); - }); - - assertTrue(e.getMessage().contains("Property 'type' not found")); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionVariant.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionVariant.java deleted file mode 100644 index 28c75901b..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/SomeUnionVariant.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.containers; - -import co.elastic.clients.elasticsearch.experiments.UnionVariant; - -public interface SomeUnionVariant extends UnionVariant { -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantA.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantA.java deleted file mode 100644 index 0e5ed9741..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantA.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.containers; - -import co.elastic.clients.elasticsearch.experiments.containers.SomeUnionVariant; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import javax.annotation.Nullable; - -@JsonpDeserializable -public class UVariantA implements SomeUnionVariant, JsonpSerializable { - - private final String name; - - @Override - public String _variantType() { - return "variant_a"; - } - - @Nullable - public String name() { - return this.name; - } - - public UVariantA(Builder builder) { - this.name = builder.name; - } - - @Override - public void serialize(JsonGenerator builder, JsonpMapper mapper) { - builder.writeStartObject(); - // Write variant value - builder.write("type", _variantType()); - if (this.name != null) builder.write("name", this.name); - builder.writeEnd(); - } - - public static class Builder implements ObjectBuilder { - private String name; - - public Builder name(@Nullable String name) { - this.name = name; - return this; - } - - public UVariantA build() { - return new UVariantA(this); - } - } - - public static final JsonpDeserializer _DESERIALIZER; - - static { - ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); - op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); - op.ignore("type"); - _DESERIALIZER = new ObjectBuilderDeserializer<>(op); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantB.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantB.java deleted file mode 100644 index 46c3fed5e..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/containers/UVariantB.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.containers; - -import co.elastic.clients.elasticsearch.experiments.containers.SomeUnionVariant; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import javax.annotation.Nullable; - -@JsonpDeserializable -public class UVariantB implements SomeUnionVariant, JsonpSerializable { - - private final Integer number; - - @Override - public String _variantType() { - return "variant_a"; - } - - @Nullable - public Integer number () { - return this.number; - } - - public UVariantB(Builder builder) { - this.number = builder.number; - } - - @Override - public void serialize(JsonGenerator builder, JsonpMapper mapper) { - builder.writeStartObject(); - // Write variant value - builder.write("type", _variantType()); - if (this.number != null) builder.write("number", this.number); - builder.writeEnd(); - } - - public static class Builder implements ObjectBuilder { - private Integer number; - - public Builder number(@Nullable Integer number) { - this.number = number; - return this; - } - - public UVariantB build() { - return new UVariantB(this); - } - } - - public static final JsonpDeserializer _DESERIALIZER; - - static { - ObjectDeserializer op = new ObjectDeserializer<>(Builder::new); - op.add(Builder::number, JsonpDeserializer.integerDeserializer(), "number"); - op.ignore("type"); - _DESERIALIZER = new ObjectBuilderDeserializer<>(op); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/generics/GenericClass.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/generics/GenericClass.java deleted file mode 100644 index 31e403ac9..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/generics/GenericClass.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.generics; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpSerializer; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.endpoints.SimpleEndpoint; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import java.util.function.Supplier; - -public class GenericClass implements JsonpSerializable { - - // Serializers for generic parameters - private final JsonpSerializer genParamSerializer; - - // Properties - private final GenParam genParam; - - protected GenericClass(Builder builder) { - this.genParamSerializer = builder.genParamSerializer; - this.genParam = builder.genParam; - } - - public GenParam genParam() { - return this.genParam; - } - - @Override - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - generator.writeKey("genParam"); - JsonpUtils.serialize(genParam, generator, genParamSerializer, mapper); - generator.writeEnd(); - } - - public static class Builder implements ObjectBuilder> { - private GenParam genParam; - private JsonpSerializer genParamSerializer; - - /** - * Sets the JSON serializer for {@link GenParam} values. If not set, the client will try to find a suitable - * serializer in the {@link JsonpMapper} and will fail if none is found. - */ - // Internal generic parameters always call this method to avoid runtime lookup - public Builder genParamSerializer(JsonpSerializer value) { - this.genParamSerializer = value; - return this; - } - - public Builder genParam(GenParam value) { - this.genParam = value; - return this; - } - - @Override - public GenericClass build() { - return null; - } - } - - public static JsonpDeserializer> parser( - // A deserializer for each generic parameter - JsonpDeserializer getParamDeserializer - ) { - - return ObjectBuilderDeserializer.createForObject( - (Supplier>) Builder::new, - (op) -> GenericClass.setupParser(op, getParamDeserializer) - ); - } - - private static void setupParser(ObjectDeserializer> op, JsonpDeserializer deserializer) { - op.add(Builder::genParam, deserializer, "genParam"); - } - - - public static Endpoint, ErrorResponse> endpoint( - JsonpDeserializer genParamDeserializer - ) { - return new SimpleEndpoint<>( - "genclass", - // Request method - request -> "GET", - // Request path - request -> "/genclass", - // Path parameters - SimpleEndpoint.emptyMap(), - // Request parameters - SimpleEndpoint.emptyMap(), - // Headers - SimpleEndpoint.emptyMap(), - true, - GenericClass.parser(genParamDeserializer) - ); - } - -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/InheritanceTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/InheritanceTest.java deleted file mode 100644 index f568f4e58..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/InheritanceTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.inheritance; - -import co.elastic.clients.elasticsearch.experiments.inheritance.child.ChildClass; -import co.elastic.clients.elasticsearch.experiments.inheritance.final_.FinalClass; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import jakarta.json.spi.JsonProvider; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.ByteArrayOutputStream; -import java.io.StringReader; - -public class InheritanceTest extends Assertions { - - @Test - public void testSerialization() { - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - JsonProvider provider = JsonpUtils.provider(); - - FinalClass fc = new FinalClass.Builder() - // Start fields from the top of the hierarchy to test setter return values - .baseField("baseValue") - .childField("childValue") - .finalField("finalValue") - .build(); - - JsonGenerator generator = provider.createGenerator(baos); - fc.serialize(generator, new JsonbJsonpMapper()); - - generator.close(); - String str = baos.toString(); - - assertEquals("{\"baseField\":\"baseValue\",\"childField\":\"childValue\",\"finalField\":\"finalValue\"}", str); - - baos.reset(); - - ChildClass cc = new ChildClass.Builder() - // Start fields from the top of the hierarchy to test setter return values - .baseField("baseValue") - .childField("childValue") - .build(); - - generator = provider.createGenerator(baos); - cc.serialize(generator, new JsonbJsonpMapper()); - - generator.close(); - str = baos.toString(); - - assertEquals("{\"baseField\":\"baseValue\",\"childField\":\"childValue\"}", str); - } - - @Test - public void testDeserialization() { - JsonProvider provider = JsonpUtils.provider(); - - JsonParser parser = provider.createParser(new StringReader( - "{\"baseField\":\"baseValue\",\"childField\":\"childValue\",\"finalField\":\"finalValue\"}")); - - FinalClass fc = FinalClass.JSONP_PARSER.deserialize(parser, new JsonbJsonpMapper()); - - assertEquals("baseValue", fc.baseField()); - assertEquals("childValue", fc.childField()); - assertEquals("finalValue", fc.finalField()); - - - parser = provider.createParser(new StringReader( - "{\"baseField\":\"baseValue\",\"childField\":\"childValue\"}")); - - ChildClass cc = ChildClass.JSONP_PARSER.deserialize(parser, new JsonbJsonpMapper()); - - assertEquals("baseValue", cc.baseField()); - assertEquals("childValue", cc.childField()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/base/BaseClass.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/base/BaseClass.java deleted file mode 100644 index f03039a32..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/base/BaseClass.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.inheritance.base; - -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectDeserializer; -import jakarta.json.stream.JsonGenerator; - -import java.util.Objects; - -/** - * An abstract transport class - */ -public abstract class BaseClass implements JsonpSerializable { - - private final String baseField; - - public BaseClass(AbstractBuilder builder) { - this.baseField = Objects.requireNonNull(builder.baseField, "baseField"); - } - - public String baseField() { - return this.baseField; - } - - @Override - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - toJsonpInternal(generator, mapper); - generator.writeEnd(); - } - - protected void toJsonpInternal(JsonGenerator generator, JsonpMapper mapper) { - generator.write("baseField", this.baseField); - } - - //--------------------------------------------------------------------------------------------- - - // This is class protected as it's only of interest to subclasses. Yet public members are visible - // from the outside on public subclasses. - protected abstract static class AbstractBuilder> { - - private String baseField; - - public T baseField(String value) { - this.baseField = value; - return self(); - } - - protected abstract T self(); - } - - //--------------------------------------------------------------------------------------------- - - protected static > void setupBaseClassParser(ObjectDeserializer op) { - op.add(AbstractBuilder::baseField, JsonpDeserializer.stringDeserializer(), "baseField"); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/child/ChildClass.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/child/ChildClass.java deleted file mode 100644 index ca202ce63..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/child/ChildClass.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.inheritance.child; - -import co.elastic.clients.elasticsearch.experiments.inheritance.base.BaseClass; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import java.util.Objects; - -/** - * A concrete class that both inherits a parent class and has child classes - */ -public class ChildClass extends BaseClass implements JsonpSerializable { - - private final String childField; - - public ChildClass(AbstractBuilder builder) { - super(builder); - this.childField = Objects.requireNonNull(builder.childField, "childField"); - } - - public String childField() { - return this.childField; - } - - @Override - protected void toJsonpInternal(JsonGenerator generator, JsonpMapper params) { - super.toJsonpInternal(generator, params); - generator.write("childField", this.childField); - } - - //--------------------------------------------------------------------------------------------- - - protected abstract static class AbstractBuilder> extends BaseClass.AbstractBuilder { - - private String childField; - - public T childField(String value) { - this.childField = value; - return self(); - } - } - - // We cannot use AbstractBuilder directly, as it would cause a signature clash with subclasses on build(). - // And even without it, the generic parameter on AbstractBuilder is an implementation detail of builder - // inheritance that isn't needed nor nice in user applications. - public static class Builder extends AbstractBuilder implements ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - @Override - public ChildClass build() { - return new ChildClass(this); - } - } - - //--------------------------------------------------------------------------------------------- - - protected static > void setupChildClassParser(ObjectDeserializer op) { - BaseClass.setupBaseClassParser(op); - op.add(AbstractBuilder::childField, JsonpDeserializer.stringDeserializer(), "childField"); - } - - public static final JsonpDeserializer JSONP_PARSER = ObjectBuilderDeserializer.createForObject( - Builder::new, ChildClass::setupChildClassParser - ); - -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/final_/FinalClass.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/final_/FinalClass.java deleted file mode 100644 index c106a3446..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/inheritance/final_/FinalClass.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.experiments.inheritance.final_; - -import co.elastic.clients.elasticsearch.experiments.inheritance.child.ChildClass; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import java.util.Objects; - -/** - * A concrete class that inherits a parent class but has no child classes - */ -public final class FinalClass extends ChildClass { - - private final String finalField; - - public FinalClass(Builder builder) { - super(builder); - this.finalField = Objects.requireNonNull(builder.finalField, "finalField"); - } - - public String finalField() { - return this.finalField; - } - - @Override - protected void toJsonpInternal(JsonGenerator generator, JsonpMapper mapper) { - super.toJsonpInternal(generator, mapper); - generator.write("finalField", this.finalField); - } - - //--------------------------------------------------------------------------------------------- - - public static class Builder - extends AbstractBuilder - implements ObjectBuilder { - - private String finalField; - - public Builder finalField(String value) { - this.finalField = value; - return self(); - } - - @Override - protected Builder self() { - return this; - } - - @Override - public FinalClass build() { - return new FinalClass(this); - } - } - - //--------------------------------------------------------------------------------------------- - - private static void setupFinalClassParser(ObjectDeserializer op) { - ChildClass.setupChildClassParser(op); - op.add(Builder::finalField, JsonpDeserializer.stringDeserializer(), "finalField"); - } - - // Static methods cannot hide other static methods with a different return type or the same erased signature. - // Two possible solutions: - // - use different names, but having SomeClass.someClassParser() has some redundancy in the name - // - use a static field, as a static field can hide a static field of a different type in the parent class - // - // Our choice is to use different names for protected/private parser setup methods are they are hidden from - // the user and use a static field for the final parser, so that we can uniformly write SomeClass.PARSER - // (even if users should rarely have to interact directly with the parser). - - public static final JsonpDeserializer JSONP_PARSER = ObjectBuilderDeserializer.createForObject( - Builder::new, FinalClass::setupFinalClassParser - ); - -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/package-info.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/package-info.java deleted file mode 100644 index 42ec31f8b..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/experiments/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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. - */ - -/** - * Experiments for the design of high-level client classes and usage illustration of the XContent-related classes. - */ -package co.elastic.clients.rest5_client.elasticsearch.experiments; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BuiltinTypesTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BuiltinTypesTest.java deleted file mode 100644 index 45ce86c4b..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/BuiltinTypesTest.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.model; - -import co.elastic.clients.elasticsearch._types.FieldValue; -import co.elastic.clients.elasticsearch._types.SortOptions; -import co.elastic.clients.elasticsearch._types.SortOrder; -import co.elastic.clients.elasticsearch._types.aggregations.StatsAggregate; -import co.elastic.clients.elasticsearch._types.aggregations.StringStatsAggregate; -import co.elastic.clients.elasticsearch._types.query_dsl.SpanGapQuery; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.indices.IndexRoutingAllocationDisk; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.testkit.ModelTestCase; -import jakarta.json.stream.JsonParser; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; -import java.util.List; - -public class BuiltinTypesTest extends ModelTestCase { - - @Test - public void testPrimitiveTypes() { - - assertGetterType(Integer.class, SearchRequest.class, "size"); - - // Lenient boolean: 'threshold_enabled'?: boolean | string - assertGetterType(Boolean.class, IndexRoutingAllocationDisk.class, "thresholdEnabled"); - - } - - @Test - public void testLenientArray() { - // index: Indices --> type Indices = IndexName | IndexName[] - assertGetterType(List.class, SearchRequest.class, "index"); - } - - @Test - public void testNullArrayItem() { - // See https://github.com/elastic/elasticsearch-java/issues/66 - - String json = "[\"a\", null, \"c\"]"; - - // Types that don't accept null events should end up as null values in the list - { - JsonpDeserializer stringDeser = JsonpDeserializer.stringDeserializer(); - assertFalse(stringDeser.accepts(JsonParser.Event.VALUE_NULL)); - - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - - List stringList = JsonpDeserializer.arrayDeserializer(stringDeser).deserialize(parser, mapper); - assertEquals("a", stringList.get(0)); - assertNull(stringList.get(1)); - assertEquals("c", stringList.get(2)); - } - - // Types that do accept null events should end up as their null representation - { - assertTrue(FieldValue._DESERIALIZER.accepts(JsonParser.Event.VALUE_NULL)); - - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - List valueList = JsonpDeserializer.arrayDeserializer(FieldValue._DESERIALIZER).deserialize(parser, mapper); - - assertEquals("a", valueList.get(0)._get()); - assertTrue(valueList.get(1).isNull()); - assertEquals("c", valueList.get(2)._get()); - } - } - - @Test - public void testSpanGapQuery() { - // Hand-written class - SpanGapQuery q = SpanGapQuery.of(b -> b - .field("a-field") - .spanWidth(12) - ); - - q = checkJsonRoundtrip(q, "{\"a-field\":12}"); - - assertEquals("a-field", q.field()); - assertEquals(12, q.spanWidth()); - } - - @Test - public void testSortOptions() { - // Has a custom deserializer - // Examples: see https://www.elastic.co/guide/en/elasticsearch/reference/current/sort-search-results.html - - String json; - SortOptions sort; - - // Arbitrary field - sort = fromJson( - "{ \"post_date\" : {\"order\" : \"asc\", \"format\": \"strict_date_optional_time_nanos\"}}", - SortOptions.class); - - assertEquals("post_date", sort.field().field()); - assertEquals(SortOrder.Asc, sort.field().order()); - - sort = fromJson("{\n" + - " \"offer.price\" : {\n" + - " \"mode\" : \"avg\",\n" + - " \"order\" : \"asc\",\n" + - " \"nested\": {\n" + - " \"path\": \"offer\",\n" + - " \"filter\": {\n" + - " \"term\" : { \"offer.color\" : \"blue\" }\n" + - " }\n" + - " }\n" + - " }\n" + - " }", SortOptions.class); - - assertEquals("blue", sort.field().nested().filter().term().value().stringValue()); - - // Geo distance - sort = fromJson("{\n" + - " \"_geo_distance\" : {\n" + - " \"pin.location\" : {\n" + - " \"lat\" : 40,\n" + - " \"lon\" : -70\n" + - " },\n" + - " \"order\" : \"asc\",\n" + - " \"unit\" : \"km\"\n" + - " }\n" + - " }", SortOptions.class); - - assertEquals(40, sort.geoDistance().location().get(0).latlon().lat(), 0.1); - - // Simple string shortcuts - sort = fromJson("\"user\"", SortOptions.class); - assertEquals("user", sort.field().field()); - - sort = fromJson("\"_doc\"", SortOptions.class); - assertTrue(sort.isDoc()); - - sort = fromJson("\"_score\"", SortOptions.class); - assertTrue(sort.isScore()); - } - - @Test - public void testFieldValue() { - - FieldValue f; - - f = FieldValue.of(b -> b.nullValue()); - f = checkJsonRoundtrip(f, "null"); - assertTrue(f.isNull()); - assertEquals("null", f._toJsonString()); - - f = FieldValue.of(b -> b.doubleValue(1.23)); - f = checkJsonRoundtrip(f, "1.23"); - assertTrue(f.isDouble()); - assertEquals(1.23, f.doubleValue(), 0.01); - assertEquals("1.23", f._toJsonString()); - - f = FieldValue.of(b -> b.longValue(123)); - f = checkJsonRoundtrip(f, "123"); - assertTrue(f.isLong()); - assertEquals(123, f.longValue()); - assertEquals("123", f._toJsonString()); - - f = FieldValue.of(b -> b.booleanValue(true)); - f = checkJsonRoundtrip(f, "true"); - assertTrue(f.isBoolean()); - assertTrue(f.booleanValue()); - assertEquals("true", f._toJsonString()); - - f = FieldValue.of(b -> b.booleanValue(false)); - f = checkJsonRoundtrip(f, "false"); - assertTrue(f.isBoolean()); - assertFalse(f.booleanValue()); - assertEquals("false", f._toJsonString()); - - f = FieldValue.of(b -> b.stringValue("foo")); - f = checkJsonRoundtrip(f, "\"foo\""); - assertTrue(f.isString()); - assertEquals("foo", f.stringValue()); - assertEquals("foo", f._toJsonString()); - - } - - @Test - public void testNullableDouble() { - StatsAggregate stats; - - // Regular values - stats = StatsAggregate.statsAggregateOf(b -> b // Parent classes can't have an overloaded "of" method - .count(10) - .min(1.0) - .avg(1.5) - .max(2.0) - .sum(5.0) - ); - - stats = checkJsonRoundtrip(stats, "{\"count\":10,\"min\":1.0,\"max\":2.0,\"avg\":1.5,\"sum\":5.0}"); - assertEquals(10, stats.count()); - assertEquals(1.0, stats.min(), 0.01); - assertEquals(1.5, stats.avg(), 0.01); - assertEquals(2.0, stats.max(), 0.01); - assertEquals(5.0, stats.sum(), 0.01); - - // Missing values (Java mapping same as json) - String json = "{\"count\":0,\"min\":null,\"max\":null,\"avg\":0.0,\"sum\":0.0}"; - stats = fromJson(json, StatsAggregate.class); - - assertEquals(0, stats.count()); - assertEquals(null, stats.min()); - assertEquals(0.0, stats.avg(), 0.01); - assertEquals(null, stats.max()); - assertEquals(0.0, stats.sum(), 0.01); - - // We don't serialize null - assertEquals("{\"count\":0,\"avg\":0.0,\"sum\":0.0}", toJson(stats)); - } - - @Test - public void testNullableInt() { - StringStatsAggregate stats = StringStatsAggregate.of(b -> b - .count(1) - .minLength(2) - .avgLength(3D) - .maxLength(4) - .entropy(0D) - ); - - stats = checkJsonRoundtrip(stats, "{\"count\":1,\"min_length\":2,\"max_length\":4,\"avg_length\":3.0,\"entropy\":0.0}"); - assertEquals(2, stats.minLength()); - assertEquals(4, stats.maxLength()); - assertEquals(0, stats.entropy()); - - // Missing values - String json = "{\"count\":1,\"min_length\":null,\"max_length\":null,\"avg_length\":null,\"entropy\":null}"; - stats = fromJson(json, StringStatsAggregate.class); - assertEquals(1, stats.count()); - assertEquals(null, stats.minLength()); - assertEquals(null, stats.maxLength()); - assertEquals(null, stats.entropy()); - } - - @Test - public void testVoidDeserialization() { - String json = "{\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + - "\"hits\":{\"hits\":[{\"_index\":\"foo\",\"_id\":\"w\",\"_source\":{\"foo\": \"bar\"}}]}," + - "\"took\":42,\"timed_out\":false" + - "}"; - - SearchResponse response = fromJson(json, SearchResponse.createSearchResponseDeserializer(JsonpDeserializer.of(Void.class))); - - // Void type skips all the JSON and is serialized to null. - assertEquals(1, response.hits().hits().size()); - assertNull(response.hits().hits().get(0).source()); - assertEquals(42, response.took()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/ClassStructureTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/ClassStructureTest.java deleted file mode 100644 index 20c2aa65b..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/ClassStructureTest.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.model; - -import co.elastic.clients.elasticsearch._types.ErrorCause; -import co.elastic.clients.elasticsearch._types.SortOrder; -import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; -import co.elastic.clients.elasticsearch._types.aggregations.Aggregation; -import co.elastic.clients.elasticsearch._types.aggregations.Buckets; -import co.elastic.clients.elasticsearch._types.aggregations.CardinalityAggregate; -import co.elastic.clients.elasticsearch._types.aggregations.DateRangeAggregate; -import co.elastic.clients.elasticsearch._types.aggregations.RangeBucket; -import co.elastic.clients.elasticsearch._types.aggregations.TermsAggregation; -import co.elastic.clients.elasticsearch._types.aggregations.ValueCountAggregation; -import co.elastic.clients.elasticsearch._types.query_dsl.FieldAndFormat; -import co.elastic.clients.elasticsearch._types.query_dsl.IntervalsQuery; -import co.elastic.clients.elasticsearch.core.GetRequest; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.elasticsearch.core.search.HitsMetadata; -import co.elastic.clients.elasticsearch.core.search.TotalHits; -import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.MissingRequiredPropertyException; -import co.elastic.clients.util.NamedValue; -import co.elastic.clients.util.ObjectBuilder; -import org.junit.jupiter.api.Test; - -import javax.annotation.Nullable; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * Tests that verify common features of generated classes. - */ -public class ClassStructureTest extends ModelTestCase { - - /** - * Tests optional and required primitive types - */ - @Test - public void testPrimitiveTypes() throws Exception { - // Optional primitive should use the boxed type and be @Nullable - { - Method searchSize = SearchRequest.class.getMethod("size"); - assertNotNull(searchSize.getAnnotation(Nullable.class)); - assertEquals(Integer.class, searchSize.getReturnType()); - } - - // Builder setter for optional primitive should use the boxed type and be @Nullable - { - Method searchBuilderSize = SearchRequest.Builder.class.getMethod("size", Integer.class); - assertTrue(Arrays.stream(searchBuilderSize.getParameterAnnotations()[0]) - .anyMatch(a -> a.annotationType() == Nullable.class)); - } - - // Required primitive should use the primitive type and not be @Nullable - { - Method totalHitsValue = TotalHits.class.getMethod("value"); - assertNull(totalHitsValue.getAnnotation(Nullable.class)); - assertEquals(long.class, totalHitsValue.getReturnType()); - } - - // Builder setter for required primitive should use the primitive type and not be @Nullable - { - Method totalHitsBuilderValue = TotalHits.Builder.class.getMethod("value", long.class); - assertFalse(Arrays.stream(totalHitsBuilderValue.getParameterAnnotations()[0]) - .anyMatch(a -> a.annotationType() == Nullable.class)); - } - - // Not setting a required primitive should throw an exception - { - assertThrows(MissingRequiredPropertyException.class, () -> TotalHits.of(b -> b)); - } - } - - /** - * Tests correct initialization of inherited fields through builders and data class inheritance. - */ - @Test - public void testDataClassInheritedFieldAssignment() { - // 1 ancestor - { - CardinalityAggregate card = CardinalityAggregate.of(b -> b - .meta(Collections.singletonMap("foo", JsonData.of("bar"))) - .value(1) - ); - - assertAncestorCount(1, card); - assertEquals("bar", card.meta().get("foo").to(String.class)); - assertEquals("{\"meta\":{\"foo\":\"bar\"},\"value\":1}", toJson(card)); - } - - // 3 ancestors - { - DateRangeAggregate date = DateRangeAggregate.of(_1 -> _1 - .meta(Collections.singletonMap("foo", JsonData.of("bar"))) - .buckets(Buckets.of(b -> b.array(Collections.singletonList(RangeBucket.of(_2 -> _2.docCount(1)))))) - ); - - assertAncestorCount(3, date); - assertEquals("bar", date.meta().get("foo").to(String.class)); - assertEquals("{\"meta\":{\"foo\":\"bar\"},\"buckets\":[{\"doc_count\":1}]}", toJson(date)); - } - } - - /** - * Tests correct initialization of inherited fields for union typed. - */ - @Test - public void testUnionInheritedFieldAssignment() { - IntervalsQuery iq = IntervalsQuery.of(_1 -> _1 - .boost(2.0f) - .field("foo") - .allOf(b -> b.intervals(Collections.emptyList())) - ); - assertAncestorCount(1, iq); - assertEquals(2.0f, iq.boost(), 0.01); - assertEquals("{\"foo\":{\"boost\":2.0,\"all_of\":{\"intervals\":[]}}}", toJson(iq)); - } - - @Test - public void testUndefinedCollections() { - // Not setting a required list should throw an exception - { - MissingRequiredPropertyException ex = assertThrows(MissingRequiredPropertyException.class, - () -> HitsMetadata.of(_1 -> _1.total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)))); - assertTrue(ex.getMessage().contains(".hits")); - } - - // Unset list should be non-null, empty but not serialized - { - SearchRequest search = SearchRequest.of(b -> b); - assertNotNull(search.storedFields()); - assertEquals(0, search.storedFields().size()); - assertFalse(ApiTypeHelper.isDefined(search.storedFields())); - assertEquals("{}", toJson(search)); - } - - // Setting an empty list defines it - { - SearchRequest search = SearchRequest.of(b -> b.storedFields(Collections.emptyList())); - assertNotNull(search.storedFields()); - assertEquals(0, search.storedFields().size()); - assertTrue(ApiTypeHelper.isDefined(search.storedFields())); - assertEquals("{\"stored_fields\":[]}", toJson(search)); - } - - // Unset map should be non-null, empty but not serialized - { - CardinalityAggregate card = CardinalityAggregate.of(b -> b.value(1)); - assertNotNull(card.meta()); - assertEquals(0, card.meta().size()); - assertFalse(ApiTypeHelper.isDefined(card.meta())); - assertEquals("{\"value\":1}", toJson(card)); - } - - // Setting an empty map defines it - { - CardinalityAggregate card = CardinalityAggregate.of(b -> b - .value(1) - .meta(Collections.emptyMap()) - ); - assertNotNull(card.meta()); - assertEquals(0, card.meta().size()); - assertTrue(ApiTypeHelper.isDefined(card.meta())); - assertEquals("{\"meta\":{},\"value\":1}", toJson(card)); - } - } - - @Test - public void testListSetters() { - List fields = Arrays.asList("a", "b"); - - { - // Appending doesn't modify the original collection - SearchRequest search = SearchRequest.of(b -> b - .storedFields(fields) - .storedFields("c") - .storedFields("d", "e", "f") - ); - assertEquals(Arrays.asList("a", "b"), fields); - assertEquals(Arrays.asList("a", "b", "c", "d", "e", "f"), search.storedFields()); - } - - { - // Appending doesn't modify the original collection (appending the same list twice) - SearchRequest search = SearchRequest.of(b -> b - .storedFields(fields) - .storedFields(fields) - ); - assertEquals(Arrays.asList("a", "b"), fields); - assertEquals(Arrays.asList("a", "b", "a", "b"), search.storedFields()); - } - - - { - // List cannot be null - List nullFields = null; - assertThrows(NullPointerException.class, () -> { - SearchRequest.of(b -> b - .storedFields(nullFields) - ); - }); - } - - { - // Combine value and builder - FieldAndFormat fieldA = FieldAndFormat.of(f -> f.field("a")); - SearchRequest search = SearchRequest.of(b -> b - .docvalueFields(fieldA) - .docvalueFields(f -> f.field("b")) - .docvalueFields(f -> f.field("c")) - ); - - assertEquals(Arrays.asList("a", "b", "c"), search.docvalueFields().stream() - .map(FieldAndFormat::field).collect(Collectors.toList())); - } - } - - @Test - public void testMapSetters() { - ValueCountAggregation countA = ValueCountAggregation.of(v -> v.field("a")); - ValueCountAggregation countB = ValueCountAggregation.of(v -> v.field("b")); - ValueCountAggregation countC = ValueCountAggregation.of(v -> v.field("c")); - - Map aggs = new HashMap<>(); - aggs.put("aggA", countA._toAggregation()); - aggs.put("aggB", countB._toAggregation()); - - { - // Appending doesn't modify the original collection - SearchRequest search = SearchRequest.of(b -> b - .aggregations(aggs) - .aggregations("aggC", countC._toAggregation()) - .aggregations("aggD", a -> a.valueCount(c -> c.field("d"))) - ); - - // Original map wasn't modified - assertEquals(2, aggs.size()); - - assertEquals(4, search.aggregations().size()); - assertEquals("a", search.aggregations().get("aggA").valueCount().field()); - assertEquals("b", search.aggregations().get("aggB").valueCount().field()); - assertEquals("c", search.aggregations().get("aggC").valueCount().field()); - assertEquals("d", search.aggregations().get("aggD").valueCount().field()); - } - - { - // Map cannot be null - assertThrows(NullPointerException.class, () -> { - Map nullMap = null; - SearchRequest.of(b -> b.aggregations(nullMap)); - }); - } - } - - @Test - public void testDataClassesSingleBuilderUse() { - // no ancestor + WithJsonBase + ObjectBuilderBase - checkSingleBuilderUse(2, new ErrorCause.Builder().type("foo").reason("bar")); - - // 1 ancestor + WithJsonBase + ObjectBuilderBase - checkSingleBuilderUse(3, new CardinalityAggregate.Builder().value(0)); - - // 3 ancestors + WithJsonBase + ObjectBuilderBase - checkSingleBuilderUse(5, new DateRangeAggregate.Builder().buckets(Buckets.of(b -> b.array(Collections.emptyList())))); - } - - @Test - public void testUnionSingleBuilderUse() { - // no ancestor + ObjectBuilderBase - checkSingleBuilderUse(1, new Aggregate.Builder().cardinality(b -> b.value(0))); - - // 1 ancestor + WithJsonBase + ObjectBuilderBase - checkSingleBuilderUse(3, new IntervalsQuery.Builder().field("foo").allOf(b -> b.intervals(Collections.emptyList()))); - } - - @Test - public void testRequiredProperty() { - // All required properties present - GetRequest r = GetRequest.of(b -> b.index("foo").id("bar")); - - // Missing id property throws an exception - MissingRequiredPropertyException ex = assertThrows(MissingRequiredPropertyException.class, () -> { - GetRequest r1 = GetRequest.of(b -> b.index("foo")); - }); - assertEquals("id", ex.getPropertyName()); - - // Disable checks, missing id property is accepted. - try (ApiTypeHelper.DisabledChecksHandle h = ApiTypeHelper.DANGEROUS_disableRequiredPropertiesCheck(true)) { - GetRequest r1 = GetRequest.of(b -> b.index("foo")); - assertNull(r1.id()); - } - - // Checks are enabled again after the try block - ex = assertThrows(MissingRequiredPropertyException.class, () -> { - GetRequest r1 = GetRequest.of(b -> b.index("foo")); - }); - assertEquals("id", ex.getPropertyName()); - } - - /** - * Tests SingleKeyDictionary fields that are not transformed into a behavior. - */ - @Test - public void testNamedValue() { - TermsAggregation termsAgg = TermsAggregation.of(ta -> ta - .order(NamedValue.of("a", SortOrder.Asc)) - .order(NamedValue.of("b", SortOrder.Desc)) - ); - - checkJsonRoundtrip(termsAgg, "{\"order\":[{\"a\":\"asc\"},{\"b\":\"desc\"}]}"); - } - - private void assertAncestorCount(int count, Object obj) { - Class clazz = obj.getClass(); - while(count-- >= 0) { - clazz = clazz.getSuperclass(); - } - assertEquals(Object.class, clazz); - } - - private void checkSingleBuilderUse(int count, ObjectBuilder builder) { - assertAncestorCount(count, builder); - - // Building once should succeed - builder.build(); - - // Building twice should fail - IllegalStateException ex = assertThrows(IllegalStateException.class, builder::build); - assertEquals("Object builders can only be used once", ex.getMessage()); - - // One more for good measure - ex = assertThrows(IllegalStateException.class, builder::build); - assertEquals("Object builders can only be used once", ex.getMessage()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/CodeAdditionsTests.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/CodeAdditionsTests.java deleted file mode 100644 index 3fd26aade..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/CodeAdditionsTests.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.model; - -import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery; -import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class CodeAdditionsTests extends Assertions { - - @Test - public void testHasClauses() { - - { - BoolQuery.Builder builder = new BoolQuery.Builder(); - assertFalse(builder.hasClauses()); - - BoolQuery query = builder.build(); - assertFalse(query.hasClauses()); - } - - { - BoolQuery.Builder builder = new BoolQuery.Builder(); - builder.must(QueryBuilders.matchAll(b -> b)); - assertTrue(builder.hasClauses()); - - BoolQuery query = builder.build(); - assertTrue(query.hasClauses()); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EndpointTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EndpointTest.java deleted file mode 100644 index 67c32dff3..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EndpointTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.model; - -import co.elastic.clients.elasticsearch._types.ExpandWildcard; -import co.elastic.clients.elasticsearch.core.ExistsRequest; -import co.elastic.clients.elasticsearch.core.InfoRequest; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.elasticsearch.indices.RefreshRequest; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class EndpointTest extends Assertions { - - @Test - public void testArrayPathParameter() { - RefreshRequest req; - - req = RefreshRequest.of(b -> b); - assertNotNull(req.index()); - assertEquals("/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); - - req = RefreshRequest.of(b -> b.index("a")); - assertEquals("/a/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); - - req = RefreshRequest.of(b -> b.index("a", "b")); - assertEquals("/a,b/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); - - req = RefreshRequest.of(b -> b.index("a", "b", "c")); - assertEquals("/a,b,c/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); - } - - @Test - public void testPathEncoding() { - RefreshRequest req; - - req = RefreshRequest.of(b -> b.index("a/b")); - assertEquals("/a%2Fb/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); - - req = RefreshRequest.of(b -> b.index("a/b", "c/d")); - assertEquals("/a%2Fb,c%2Fd/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); - - } - - @Test - public void testArrayQueryParameter() { - RefreshRequest req; - - req = RefreshRequest.of(b -> b); - assertNotNull(req.expandWildcards()); // undefined list - assertNull(RefreshRequest._ENDPOINT.queryParameters(req).get("expand_wildcards")); - - req = RefreshRequest.of(b -> b.expandWildcards(ExpandWildcard.All)); - // Also tests query encoding of enums - assertEquals("all", RefreshRequest._ENDPOINT.queryParameters(req).get("expand_wildcards")); - - req = RefreshRequest.of(b -> b.expandWildcards(ExpandWildcard.All, ExpandWildcard.Closed)); - assertEquals("all,closed", RefreshRequest._ENDPOINT.queryParameters(req).get("expand_wildcards")); - } - - @Test - public void testRequestToString() { - // Simple path, no parameters, no body - assertEquals("InfoRequest: GET /", InfoRequest._INSTANCE.toString()); - - // Complex path, parameters, no body - assertEquals( - "ExistsRequest: HEAD /idx/_doc/id1?preference=foo&refresh=true", - ExistsRequest.of(b -> b.index("idx").id("id1").preference("foo").refresh(true)).toString() - ); - - assertEquals( - "SearchRequest: POST /idx/_search?typed_keys=true {\"size\":10}", - SearchRequest.of(s -> s.index("idx").size(10)).toString() - ); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EnumTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EnumTest.java deleted file mode 100644 index 7eaeab4fc..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/EnumTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.model; - -import co.elastic.clients.elasticsearch._types.Bytes; -import co.elastic.clients.elasticsearch._types.Refresh; -import co.elastic.clients.elasticsearch._types.mapping.GeoOrientation; -import co.elastic.clients.testkit.ModelTestCase; -import org.junit.jupiter.api.Test; - -import java.util.Arrays; - -public class EnumTest extends ModelTestCase { - - @Test - public void testSimpleEnum() { - assertNull(Bytes.GigaBytes.aliases()); - assertEquals(Bytes.GigaBytes, Bytes._DESERIALIZER.parse("gb")); - } - - @Test - public void testEnumWithAliases() { - assertEquals("left", GeoOrientation.Left.jsonValue()); - assertNotNull(GeoOrientation.Left.aliases()); - - Arrays.asList("right", "RIGHT", "counterclockwise", "ccw").forEach(alias -> { - assertEquals(GeoOrientation.Right, GeoOrientation._DESERIALIZER.parse(alias)); - }); - } - - @Test - public void testBooleanEnum() { - // Quoted value - assertEquals(Refresh.WaitFor, checkJsonRoundtrip(Refresh.WaitFor, "\"wait_for\"")); - - // Unquoted boolean values - assertEquals(Refresh.True, checkJsonRoundtrip(Refresh.True, "true")); - assertEquals(Refresh.False, checkJsonRoundtrip(Refresh.False, "false")); - - // true/false as strings - assertEquals(Refresh.True, fromJson("\"true\"", Refresh.class)); - assertEquals(Refresh.False, fromJson("\"false\"", Refresh.class)); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/RequestEncodingTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/RequestEncodingTest.java deleted file mode 100644 index 5333f90ee..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/RequestEncodingTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.model; - -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import co.elastic.clients.testkit.ModelTestCase; -import org.junit.jupiter.api.Test; - -public class RequestEncodingTest extends ModelTestCase { - - @Test - public void testParametersNotInJson() { - - // This checks that path parameters ("q") are not serialized as json - // and variant containers ser/deser - - SearchRequest request = new SearchRequest.Builder() - .q("blah") - .query(b1 -> b1 - .type(b2 -> b2 - .value("foo")) - ) - .aggregations( - "myagg", b2 -> b2 - .avg(b3 -> b3.field("foo")) - ) - .build(); - - JsonbJsonpMapper mapper = new JsonbJsonpMapper(); - String str = toJson(request, mapper); - - assertEquals("{\"aggregations\":{\"myagg\":{\"avg\":{\"field\":\"foo\"}}},\"query\":{\"type\":{\"value\":\"foo\"}}}", str); - - request = fromJson(str, SearchRequest.class, mapper); - - assertTrue(request.query().isType()); - assertEquals("foo", request.query().type().value()); - assertNull(request.q()); - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/SerializationTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/SerializationTest.java deleted file mode 100644 index 3cb76ac1c..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/SerializationTest.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.model; - -import co.elastic.clients.elasticsearch.cat.NodesResponse; -import co.elastic.clients.elasticsearch.core.GetSourceResponse; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapperBase; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.testkit.ModelTestCase; -import io.github.classgraph.ClassGraph; -import io.github.classgraph.ClassInfo; -import io.github.classgraph.ClassInfoList; -import io.github.classgraph.ScanResult; -import jakarta.json.Json; -import jakarta.json.JsonValue; -import jakarta.json.stream.JsonParser; -import jakarta.json.stream.JsonParsingException; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; - -public class SerializationTest extends ModelTestCase { - - @Test - public void loadAllDeserializers() throws Exception { - - ScanResult scan = new ClassGraph() - .acceptPackages("co.elastic.clients") - .enableAnnotationInfo() - .enableFieldInfo() - .scan(); - - ClassInfoList withAnnotation = scan.getClassesWithAnnotation(JsonpDeserializable.class.getName()); - - assertFalse(withAnnotation.isEmpty(), "No JsonpDeserializable classes"); - - for (ClassInfo info: withAnnotation) { - Class clazz = Class.forName(info.getName()); - JsonpDeserializer deserializer = JsonpMapperBase.findDeserializer(clazz); - assertNotNull(deserializer); - - // Deserialize something dummy to resolve lazy deserializers - JsonParser parser = mapper.jsonProvider().createParser(new StringReader("-")); - assertThrows(JsonParsingException.class, () -> deserializer.deserialize(parser, mapper), info.getName()); - } - - // Check that all classes that have a _DESERIALIZER field also have the annotation - ClassInfoList withDeserializer = scan.getAllClasses().filter((c) -> c.hasDeclaredField("_DESERIALIZER")); - assertFalse(withDeserializer.isEmpty(), "No classes with a _DESERIALIZER field"); - -// Disabled for now, empty response classes still need a deserializer object -// e.g. ExistsIndexTemplateResponse, PingResponse, ExistsResponse, ExistsAliasResponse -// -// Set annotationNames = withAnnotation.stream().map(c -> c.getName()).collect(Collectors.toSet()); -// Set withFieldNames = withDeserializer.stream().map(c -> c.getName()).collect(Collectors.toSet()); -// -// withFieldNames.removeAll(annotationNames); -// -// assertFalse( -// withFieldNames.size() + " classes with the field but not the annotation: " + withFieldNames, -// !withFieldNames.isEmpty() -// ); - - } - - @Test - public void testArrayValueBody() { - - NodesResponse nr = NodesResponse.of(_0 -> _0 - .valueBody(_1 -> _1.bulkTotalOperations("1")) - .valueBody(_1 -> _1.bulkTotalOperations("2")) - ); - - checkJsonRoundtrip(nr, "[{\"bulk.total_operations\":\"1\"},{\"bulk.total_operations\":\"2\"}]"); - - assertEquals(2, nr.valueBody().size()); - assertEquals("1", nr.valueBody().get(0).bulkTotalOperations()); - assertEquals("2", nr.valueBody().get(1).bulkTotalOperations()); - } - - @Test - public void testGenericValueBody() { - - GetSourceResponse r = GetSourceResponse.of(_0 -> _0 - .valueBody("The value") - ); - - String json = toJson(r); - assertEquals("\"The value\"", json); - - JsonpDeserializer> deserializer = - GetSourceResponse.createGetSourceResponseDeserializer(JsonpDeserializer.stringDeserializer()); - - r = deserializer.deserialize(mapper.jsonProvider().createParser(new StringReader(json)), mapper); - - assertEquals("The value", r.valueBody()); - - } - - @Test - public void testJsonpValuesToString() { - - assertEquals("foo", JsonpUtils.toString(Json.createValue("foo"))); - assertEquals("42", JsonpUtils.toString(Json.createValue(42))); - assertEquals("42.1337", JsonpUtils.toString(Json.createValue(42.1337))); - assertEquals("true", JsonpUtils.toString(JsonValue.TRUE)); - assertEquals("false", JsonpUtils.toString(JsonValue.FALSE)); - assertEquals("null", JsonpUtils.toString(JsonValue.NULL)); - assertEquals("a,b,c", JsonpUtils.toString(Json.createArrayBuilder().add("a").add("b").add("c").build())); - - assertThrows(IllegalArgumentException.class, () -> { - JsonpUtils.toString(Json.createObjectBuilder().build()); - }); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/TypedKeysTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/TypedKeysTest.java deleted file mode 100644 index ea98bc10f..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/TypedKeysTest.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.model; - -import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; -import co.elastic.clients.elasticsearch._types.aggregations.AvgAggregate; -import co.elastic.clients.elasticsearch._types.aggregations.StringTermsAggregate; -import co.elastic.clients.elasticsearch._types.aggregations.StringTermsBucket; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpMapperFeatures; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.util.ListBuilder; -import co.elastic.clients.util.MapBuilder; -import jakarta.json.spi.JsonProvider; -import jakarta.json.stream.JsonGenerator; -import org.junit.jupiter.api.Test; - -import java.io.StringWriter; -import java.util.Collections; - -public class TypedKeysTest extends ModelTestCase { - - @Test - public void testMapProperty() { - - SearchResponse resp = new SearchResponse.Builder() - .aggregations( - "foo", _2 -> _2 - .avg(_3 -> _3.value(3.14)) - ) - // Required properties on a SearchResponse - .took(1) - .shards(_1 -> _1.successful(1).failed(0).total(1)) - .hits(_1 -> _1 - .total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)) - .hits(Collections.emptyList()) - ) - .timedOut(false) - .build(); - - String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + - "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]},\"aggregations\":{\"avg#foo\":{\"value\":3.14}}}"; - - assertEquals(json, toJson(resp)); - - resp = fromJson(json, SearchResponse.createSearchResponseDeserializer(JsonpDeserializer.voidDeserializer())); - - assertEquals(1, resp.took()); - assertEquals(3.14, resp.aggregations().get("foo").avg().value(), 0.001); - - } - - @Test - public void testMapPropertyWithoutTypedKeys() { - - SearchResponse resp = new SearchResponse.Builder() - .aggregations( - "foo", _2 -> _2 - .avg(_3 -> _3.value(3.14)) - ) - // Required properties on a SearchResponse - .took(1) - .shards(_1 -> _1.successful(1).failed(0).total(1)) - .hits(_1 -> _1 - .total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)) - .hits(Collections.emptyList()) - ) - .timedOut(false) - .build(); - - // Note "foo" and not "avg#foo" below - String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + - "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]},\"aggregations\":{\"foo\":{\"value\":3.14}}}"; - - JsonpMapper newMapper = mapper.withAttribute(JsonpMapperFeatures.SERIALIZE_TYPED_KEYS, false); - - assertEquals(json, toJson(resp, newMapper)); - } - - - @Test - public void testAdditionalProperties() { - - Aggregate avg1 = AvgAggregate.of(_1 -> _1.value(1.0))._toAggregate(); - Aggregate avg2 = AvgAggregate.of(_1 -> _1.value(2.0))._toAggregate(); - - Aggregate aggregate = StringTermsAggregate.of(_0 -> _0 - .sumOtherDocCount(1L) - .buckets(b -> b.array( - ListBuilder.of(StringTermsBucket.Builder::new) - .add(_1 -> _1 - .key("key_1") - .docCount(1) - .aggregations(MapBuilder.of("bar", avg1)) - ) - .add(_1 -> _1 - .key("key_2") - .docCount(2) - .aggregations(MapBuilder.of("bar", avg2)) - ) - .build() - )) - ) - ._toAggregate(); - - SearchResponse resp = new SearchResponse.Builder() - .aggregations("foo", aggregate) - // Required properties on a SearchResponse - .took(1) - .shards(_1 -> _1.successful(1).failed(0).total(1)) - .hits(_1 -> _1 - .total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)) - .hits(Collections.emptyList()) - ) - .timedOut(false) - .build(); - - - String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + - "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]}," + - "\"aggregations\":{\"sterms#foo\":{\"buckets\":[" + - "{\"avg#bar\":{\"value\":1.0},\"doc_count\":1,\"key\":\"key_1\"}," + - "{\"avg#bar\":{\"value\":2.0},\"doc_count\":2,\"key\":\"key_2\"}" + - "],\"sum_other_doc_count\":1}}}"; - - assertEquals(json, toJson(resp)); - resp = fromJson(json, SearchResponse.createSearchResponseDeserializer(JsonpDeserializer.voidDeserializer())); - - StringTermsAggregate foo = resp.aggregations().get("foo").sterms(); - assertEquals(1, foo.sumOtherDocCount()); - assertEquals(1, foo.buckets().array().get(0).docCount()); - assertEquals("key_1", foo.buckets().array().get(0).key().stringValue()); - assertEquals(1.0, foo.buckets().array().get(0).aggregations().get("bar").avg().value(), 0.01); - assertEquals("key_2", foo.buckets().array().get(1).key().stringValue()); - assertEquals(2.0, foo.buckets().array().get(1).aggregations().get("bar").avg().value(), 0.01); - } - - // Example taken from - // https://www.elastic.co/guide/en/elasticsearch/reference/8.2/search-aggregations-bucket-reverse-nested-aggregation.html - private static final String nestedJsonWithTypedKeys = "{\n" + - " \"took\": 0," + - " \"timed_out\": false," + - " \"_shards\": {\n" + - " \"successful\": 1,\n" + - " \"failed\": 0,\n" + - " \"skipped\": 0,\n" + - " \"total\": 1\n" + - " },\n" + - " \"hits\": {\n" + - " \"hits\": [],\n" + - " \"total\": {\n" + - " \"relation\": \"eq\",\n" + - " \"value\": 5\n" + - " },\n" + - " \"max_score\": null\n" + - " }," + - " \"aggregations\" : {\n" + - " \"nested#comments\" : {\n" + - " \"doc_count\" : 3,\n" + - " \"sterms#top_usernames\" : {\n" + - " \"doc_count_error_upper_bound\" : 0,\n" + - " \"sum_other_doc_count\" : 0,\n" + - " \"buckets\" : [\n" + - " {\n" + - " \"key\" : \"dan\",\n" + - " \"doc_count\" : 3,\n" + - " \"reverse_nested#comment_to_issue\" : {\n" + - " \"doc_count\" : 1,\n" + - " \"sterms#top_tags_per_comment\" : {\n" + - " \"doc_count_error_upper_bound\" : 0,\n" + - " \"sum_other_doc_count\" : 0,\n" + - " \"buckets\" : [\n" + - " {\n" + - " \"key\" : \"tag1\",\n" + - " \"doc_count\" : 1\n" + - " },\n" + - " {\n" + - " \"key\" : \"tag2\",\n" + - " \"doc_count\" : 1\n" + - " }\n" + - " ]\n" + - " }\n" + - " }\n" + - " }\n" + - " ]\n" + - " }\n" + - " }\n" + - " }\n" + - "}"; - - @Test - public void testSerializeNested() { - - SearchResponse response = fromJson(nestedJsonWithTypedKeys, SearchResponse.class); - - // Check some deeply nested properties - StringTermsBucket bucket = response - .aggregations().get("comments").nested() - .aggregations().get("top_usernames").sterms() - .buckets().array().get(0) - .aggregations().get("comment_to_issue").reverseNested() - .aggregations().get("top_tags_per_comment").sterms() - .buckets().array().get(0); - - assertEquals("tag1", bucket.key().stringValue()); - assertEquals(1, bucket.docCount()); - - // Check that it's typed_keys encoded - String serialized = toJson(response); - assertTrue(serialized.contains("nested#comments")); - assertTrue(serialized.contains("sterms#top_usernames")); - assertTrue(serialized.contains("reverse_nested#comment_to_issue")); - assertTrue(serialized.contains("sterms#top_tags_per_comment")); - - { - // Test direct serialization - JsonProvider jsonProvider = mapper.jsonProvider(); - StringWriter stringWriter = new StringWriter(); - JsonGenerator generator = jsonProvider.createGenerator(stringWriter); - response.serialize(generator, mapper); - generator.close(); - - String directSerialized = stringWriter.toString(); - assertTrue(directSerialized.contains("nested#comments")); - assertTrue(directSerialized.contains("sterms#top_usernames")); - assertTrue(directSerialized.contains("reverse_nested#comment_to_issue")); - assertTrue(directSerialized.contains("sterms#top_tags_per_comment")); - - } - - // Re-parse and re-check - response = fromJson(serialized, SearchResponse.class); - - bucket = response - .aggregations().get("comments").nested() - .aggregations().get("top_usernames").sterms() - .buckets().array().get(0) - .aggregations().get("comment_to_issue").reverseNested() - .aggregations().get("top_tags_per_comment").sterms() - .buckets().array().get(0); - - assertEquals("tag1", bucket.key().stringValue()); - assertEquals(1, bucket.docCount()); - - - JsonProvider jsonProvider = mapper.jsonProvider(); - StringWriter stringWriter = new StringWriter(); - JsonGenerator generator = jsonProvider.createGenerator(stringWriter); - response.serialize(generator, mapper); - generator.close(); - - System.out.println(stringWriter.toString()); - } - - @Test - public void testSerializeNestedWithoutTypedKeys() { - - SearchResponse response = fromJson(nestedJsonWithTypedKeys, SearchResponse.class); - - // Check that it's typed_keys encoded - String serialized = toJson(response); - assertTrue(serialized.contains("nested#comments")); - assertTrue(serialized.contains("sterms#top_usernames")); - assertTrue(serialized.contains("reverse_nested#comment_to_issue")); - assertTrue(serialized.contains("sterms#top_tags_per_comment")); - - // Build the non-typed_keys version (replace 'type#' with 'type#name') - serialized = serialized.replaceAll("\"[^\"]*#", "\""); - assertFalse(serialized.contains("nested#comments")); - assertFalse(serialized.contains("sterms#top_usernames")); - assertFalse(serialized.contains("reverse_nested#comment_to_issue")); - assertFalse(serialized.contains("sterms#top_tags_per_comment")); - - // Serialize without typed keys - JsonpMapper newMapper = mapper.withAttribute(JsonpMapperFeatures.SERIALIZE_TYPED_KEYS, false); - assertEquals(serialized, toJson(response, newMapper)); - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/UnionTests.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/UnionTests.java deleted file mode 100644 index 7dd6296d0..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/UnionTests.java +++ /dev/null @@ -1,354 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.model; - -import co.elastic.clients.elasticsearch._types.GeoLocation; -import co.elastic.clients.elasticsearch._types.LatLonGeoLocation; -import co.elastic.clients.elasticsearch._types.Script; -import co.elastic.clients.elasticsearch._types.Time; -import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; -import co.elastic.clients.elasticsearch._types.mapping.Property; -import co.elastic.clients.elasticsearch._types.query_dsl.DistanceFeatureQuery; -import co.elastic.clients.elasticsearch._types.query_dsl.MultiValueMode; -import co.elastic.clients.elasticsearch._types.query_dsl.Query; -import co.elastic.clients.elasticsearch._types.query_dsl.RangeRelation; -import co.elastic.clients.elasticsearch._types.query_dsl.TermRangeQuery; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.testkit.ModelTestCase; -import jakarta.json.Json; -import jakarta.json.JsonObject; -import jakarta.json.stream.JsonParser; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; - -public class UnionTests extends ModelTestCase { - - @Test - public void testScriptDeserializer() { - // A union discriminated by its field names (source -> inline, id -> stored) - { - Script s = Script.of(_1 -> _1 - .source("a script") - ); - s = checkJsonRoundtrip(s, "{\"source\":\"a script\"}"); - assertEquals("a script", s.source()); - } - - { - Script s = Script.of(_1 -> _1 - .id("script_id") - ); - s = checkJsonRoundtrip(s, "{\"id\":\"script_id\"}"); - assertEquals("script_id", s.id()); - } - - { - // Test shortcut property - Script s = fromJson("\"a script\"", Script.class); - assertEquals("a script", s.source()); - } - } - - @Test - public void testOpenContainer() { - String json = "{\"foo\":{\"bar\":42}}"; - - JsonParser parser = Json.createParser(new StringReader("{ \"bar\": 42 }")); - parser.next(); - JsonObject value = parser.getObject(); - - Query obj = Query.of(b -> b._custom("foo", value)); - assertEquals(json, toJson(obj)); - - obj = checkJsonRoundtrip(obj, json); - - assertEquals(Query.Kind._Custom, obj._kind()); - assertEquals("foo", obj._customKind()); - assertEquals(42, obj._custom().toJson().asJsonObject().getInt("bar")); - } - - @Test - public void testOpenInternalUnion() { - String json = "{\"type\":\"foo\",\"bar\":42}"; - - JsonParser parser = Json.createParser(new StringReader(json)); - parser.next(); - JsonObject value = parser.getObject(); - - Property obj = Property.of(b -> b._custom("foo", value)); - assertEquals(json, toJson(obj)); - - obj = checkJsonRoundtrip(obj, json); - - assertEquals(Property.Kind._Custom, obj._kind()); - assertEquals("foo", obj._customKind()); - assertEquals(42, obj._custom().toJson().asJsonObject().getInt("bar")); - } - - @Test - public void testOpenTypedKeysUnion() { - String requiredFields = - "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + - "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]}}"; - - String customAgg = "{\"bar\":42}"; - - JsonParser parser = Json.createParser(new StringReader(customAgg)); - parser.next(); - JsonObject value = parser.getObject(); - - SearchResponse obj = SearchResponse.of(b -> b - .withJson(new StringReader(requiredFields)) - .aggregations("custom-agg", a -> a._custom("foo", value)) - ); - - String json = toJson(obj); - System.out.println(json); - assertTrue(json.contains("\"aggregations\":{\"foo#custom-agg\":{\"bar\":42}}")); - - @SuppressWarnings("unchecked") - SearchResponse obj2 = fromJson(json, SearchResponse.class); - - Aggregate aggregate = obj2.aggregations().get("custom-agg"); - assertEquals(Aggregate.Kind._Custom, aggregate._kind()); - assertEquals("foo", aggregate._customKind()); - assertEquals(42, aggregate._custom().toJson().asJsonObject().getInt("bar")); - - - } - - @Test - public void testUntaggedUnion() { - // Range queries - Query numberRangeQuery = Query.of(q -> q.range(r -> r - .number(n -> n - .field("age") - .gte(10D) - .lte(20D) - .boost(1.0F) - .relation(RangeRelation.Contains)))); - - String expectedNumberRangeQuery = "{\"range\":{\"age\":{\"boost\":1.0,\"relation\":\"contains\"," + - "\"gte\":10.0,\"lte\":20.0}}}"; - - assertEquals(expectedNumberRangeQuery, toJson(numberRangeQuery)); - - Query dateRangeQuery = Query.of(q -> q.range(r -> r - .date(d -> d - .field("day") - .gte("20-06-24") - .lte("20-07-24") - .boost(1.0F) - .format("some-format") - .relation(RangeRelation.Contains)))); - - String expectedDateRangeQuery = "{\"range\":{\"day\":{\"boost\":1.0,\"relation\":\"contains\"," + - "\"gte\":\"20-06-24\",\"lte\":\"20-07-24\",\"format\":\"some-format\"}}}"; - - assertEquals(expectedDateRangeQuery, toJson(dateRangeQuery)); - - Query termRangeQuery = Query.of(q -> q.range(r -> r - .term(d -> d - .field("word") - .gte("some") - .lte("word") - .boost(1.0F) - .relation(RangeRelation.Contains)))); - - String expectedTermRangeQuery = "{\"range\":{\"word\":{\"boost\":1.0,\"relation\":\"contains\"," + - "\"gte\":\"some\",\"lte\":\"word\"}}}"; - - assertEquals(expectedTermRangeQuery, toJson(termRangeQuery)); - - String jsonNumberRangeQuery = "{\n" + - " \"range\": {\n" + - " \"age\": {\n" + - " \"gte\": 10,\n" + - " \"lte\": 20,\n" + - " \"boost\": 1.0,\n" + - " \"relation\": \"contains\"\n" + - " }\n" + - " }\n" + - " }"; - - Query numberRangeQueryFromJson = Query.of(q -> q.withJson(new StringReader(jsonNumberRangeQuery))); - - assertTrue(numberRangeQueryFromJson.range().isUntyped()); - assertEquals(10, numberRangeQueryFromJson.range().untyped().gte().to(Integer.class)); - assertEquals(20, numberRangeQueryFromJson.range().untyped().lte().to(Integer.class)); - assertEquals(RangeRelation.Contains, numberRangeQueryFromJson.range().untyped().relation()); - - Query converted = - TermRangeQuery.of(trq -> trq.field("a").gte("b").lte("c"))._toRangeQuery()._toQuery(); - assertTrue(converted.isRange()); - - // Distance feature queries - - Query geoDistanceFeatureQuery = Query.of(q -> q.bool(b -> b - .must(m -> m.matchAll(mm -> mm)) - .should(sh -> sh.distanceFeature(df -> df - .geo(g -> g - .field("location") - .pivot("1000m") - .origin(GeoLocation.of(gl -> gl.latlon(LatLonGeoLocation.of(ll -> ll.lon(-71.3).lat(41.15)))))))))); - - String expectedGeoDistFeatQuery = "{\"bool\":{\"must\":[{\"match_all\":{}}]," + - "\"should\":[{\"distance_feature\":{\"origin\":{\"lat\":41.15,\"lon\":-71.3}," + - "\"pivot\":\"1000m\",\"field\":\"location\"}}]}}"; - assertEquals(expectedGeoDistFeatQuery, toJson(geoDistanceFeatureQuery)); - - - Query dateDistanceFeatureQuery = Query.of(q -> q.bool(b -> b - .must(m -> m.matchAll(mm -> mm)) - .should(sh -> sh.distanceFeature(df -> df - .date(d -> d - .field("date") - .pivot(Time.of(t -> t.time("7d"))) - .origin("now")))))); - - String expectedDateDistFeatQuery = "{\"bool\":{\"must\":[{\"match_all\":{}}]," + - "\"should\":[{\"distance_feature\":{\"origin\":\"now\",\"pivot\":\"7d\",\"field\":\"date\"}}]}}"; - assertEquals(expectedDateDistFeatQuery, toJson(dateDistanceFeatureQuery)); - - String distDateQuery = "{\n" + - " \"bool\": {\n" + - " \"must\": {\n" + - " \"match_all\": {}\n" + - " },\n" + - " \"should\": {\n" + - " \"distance_feature\": {\n" + - " \"field\": \"date\",\n" + - " \"pivot\": \"7d\",\n" + - " \"origin\": \"now\"\n" + - " }\n" + - " }\n" + - " }\n" + - " }"; - - Query distDateQueryFromJson = Query.of(q -> q.withJson(new StringReader(distDateQuery))); - assertTrue(distDateQueryFromJson.bool().should().get(0).distanceFeature().isUntyped()); - assertEquals("7d", - distDateQueryFromJson.bool().should().get(0).distanceFeature().untyped().pivot().to(String.class)); - assertEquals("date", - distDateQueryFromJson.bool().should().get(0).distanceFeature().untyped().field().toString()); - - - String distGeoQuery = "{\n" + - " \"bool\": {\n" + - " \"must\": {\n" + - " \"match_all\": {}\n" + - " },\n" + - " \"should\": {\n" + - " \"distance_feature\": {\n" + - " \"field\": \"location\",\n" + - " \"pivot\": \"1000m\",\n" + - " \"origin\": [-71.3, 41.15]\n" + - " }\n" + - " }\n" + - " }\n" + - " }"; - - Query distGeoQueryFromJson = Query.of(q -> q.withJson(new StringReader(distGeoQuery))); - assertTrue(distGeoQueryFromJson.bool().should().get(0).distanceFeature().isUntyped()); - assertEquals("1000m", - distGeoQueryFromJson.bool().should().get(0).distanceFeature().untyped().pivot().to(String.class)); - assertEquals("location", - distGeoQueryFromJson.bool().should().get(0).distanceFeature().untyped().field()); - - - Query convertedDist = DistanceFeatureQuery.of(dfq -> dfq.date(d -> d - .field("date") - .pivot(Time.of(t -> t.time("7d"))) - .origin("now")))._toQuery(); - - assertTrue(convertedDist.isDistanceFeature()); - - //Decay Function / Function Score queries - - Query functionScoreQueryGaussDate = Query.of(q -> q.functionScore(fs -> fs - .functions(fn -> fn - .gauss(g -> g - .date(d -> d.field("date").placement(pl -> pl - .origin("2013-09-17") - .scale(Time.of(t -> t.time("10d"))) - .offset(Time.of(t -> t.time("5d"))) - .decay(0.5D))))))); - - String expectedFunctionScoreQueryGaussDate = "{\"function_score\":{\"functions\":[{\"gauss" + - "\":{\"date\":{\"decay\":0.5,\"offset\":\"5d\",\"scale\":\"10d\",\"origin\":\"2013-09-17\"}}}]}}"; - assertEquals(expectedFunctionScoreQueryGaussDate, toJson(functionScoreQueryGaussDate)); - - Query functionScoreQueryExpGeo = Query.of(q -> q.functionScore(fs -> fs - .functions(fn -> fn - .exp(g -> g - .geo(d -> d.field("location").placement(pl -> pl - .origin(GeoLocation.of(gl -> gl.latlon(LatLonGeoLocation.of(ll -> ll.lon(-71.3).lat(41.15))))) - .scale("1km") - .offset("2km") - .decay(0.5D))))))); - - String expectedFunctionScoreQueryExpGeo = "{\"function_score\":{\"functions\":[{\"exp\":{\"location" + - "\":{\"decay\":0.5,\"offset\":\"2km\",\"scale\":\"1km\",\"origin\":{\"lat\":41.15,\"lon\":-71" + - ".3}}}}]}}"; - assertEquals(expectedFunctionScoreQueryExpGeo, toJson(functionScoreQueryExpGeo)); - - Query functionScoreQueryLinearNumeric = Query.of(q -> q.functionScore(fs -> fs - .functions(fn -> fn - .linear(g -> g - .numeric(d -> d.field("nums").placement(pl -> pl - .origin(2D) - .scale(3D) - .offset(4D) - .decay(0.5D))))))); - - String expectedFunctionScoreQueryLinearNumeric = "{\"function_score\":{\"functions\":[{\"linear" + - "\":{\"nums\":{\"decay\":0.5,\"offset\":4.0,\"scale\":3.0,\"origin\":2.0}}}]}}"; - assertEquals(expectedFunctionScoreQueryLinearNumeric, toJson(functionScoreQueryLinearNumeric)); - - String funScoreQuery = - " {\n" + - "\"function_score\": {\n" + - " \"functions\": [\n" + - "{\n" + - " \"gauss\": {\n" + - "\"date\": {\n" + - " \"origin\": \"2013-09-17\",\n" + - " \"scale\": \"10d\",\n" + - " \"offset\": \"5d\",\n" + - " \"decay\": 0.5\n" + - "},\n" + - "\"multi_value_mode\": \"avg\"\n" + - " }\n" + - "}\n" + - " ]\n" + - "}\n" + - " }"; - - Query funScoreQueryFromJson = Query.of(q -> q.withJson(new StringReader(funScoreQuery))); - assertTrue(funScoreQueryFromJson.functionScore().functions().get(0).gauss().isUntyped()); - assertEquals("2013-09-17", - funScoreQueryFromJson.functionScore().functions().get(0).gauss().untyped().placement().origin().to(String.class)); - assertEquals(MultiValueMode.Avg, - funScoreQueryFromJson.functionScore().functions().get(0).gauss().untyped().multiValueMode()); - - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/VariantsTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/VariantsTest.java deleted file mode 100644 index 1e699a898..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/VariantsTest.java +++ /dev/null @@ -1,351 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.model; - -import co.elastic.clients.elasticsearch._types.analysis.Analyzer; -import co.elastic.clients.elasticsearch._types.mapping.Property; -import co.elastic.clients.elasticsearch._types.mapping.TypeMapping; -import co.elastic.clients.elasticsearch._types.query_dsl.FunctionScore; -import co.elastic.clients.elasticsearch._types.query_dsl.Query; -import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.elasticsearch.ilm.ExplainLifecycleResponse; -import co.elastic.clients.elasticsearch.ilm.explain_lifecycle.LifecycleExplainManaged; -import co.elastic.clients.elasticsearch.ilm.explain_lifecycle.LifecycleExplainUnmanaged; -import co.elastic.clients.elasticsearch.indices.GetMappingResponse; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.testkit.ModelTestCase; -import org.junit.jupiter.api.Test; - -import java.util.function.Consumer; - -public class VariantsTest extends ModelTestCase { - - @Test - public void testNested() { - // nested containers: query > intervals > interval - // intervals is a single key dictionary - // query has container properties - - Query q = Query.of(_0 -> _0 - .intervals(_1 -> _1 - .queryName("my-query") - .field("a_field") - .anyOf(_2 -> _2 - .intervals(_3 -> _3 - .match( - _5 -> _5 - .query("match-query") - .analyzer("lowercase") - ) - ) - ) - ) - ); - - assertEquals(Query.Kind.Intervals, q._kind()); - assertNotNull(q.intervals()); - assertEquals("a_field", q.intervals().field()); - assertEquals(1, q.intervals().anyOf().intervals().size()); - assertEquals("lowercase", q.intervals().anyOf().intervals().get(0).match().analyzer()); - - String json = toJson(q); - - assertEquals("{\"intervals\":{\"a_field\":{\"_name\":\"my-query\"," + - "\"any_of\":{\"intervals\":[{\"match\":{\"analyzer\":\"lowercase\",\"query\":\"match-query\"}}]}}}}", json); - - Query q2 = fromJson(json, Query.class); - assertEquals(json, toJson(q2)); - - assertEquals(Query.Kind.Intervals, q2._kind()); - assertNotNull(q2.intervals()); - assertEquals("a_field", q2.intervals().field()); - assertEquals(1, q2.intervals().anyOf().intervals().size()); - assertEquals("lowercase", q2.intervals().anyOf().intervals().get(0).match().analyzer()); - - } - - @Test - public void testInternalTag() { - String expected = "{\"type\":\"ip\",\"fields\":{\"a-field\":{\"type\":\"float\",\"coerce\":true}},\"boost\":1" + - ".0,\"index\":true}"; - - Property p = Property.of(_0 -> _0 - .ip(_1 -> _1 - .index(true) - .boost(1.0) - .fields( - "a-field", _3 -> _3 - .float_(_4 -> _4 - .coerce(true) - ) - ) - ) - ); - - assertEquals(expected, toJson(p)); - - Property property = fromJson(expected, Property.class); - assertTrue(property.ip().index()); - assertEquals(1.0, property.ip().boost().doubleValue(), 0.09); - - assertTrue(property.ip().fields().get("a-field").float_().coerce()); - } - - @Test - public void testDefaultInternalTag() { - - Consumer test = s -> { - Analyzer a = fromJson(s, Analyzer.class); - assertEquals(Analyzer.Kind.Custom, a._kind()); - assertEquals("some-filter", a.custom().filter().get(0)); - assertTrue(a.custom().charFilter().isEmpty()); - assertEquals("some-tokenizer", a.custom().tokenizer()); - }; - - // Explicit type - test.accept("{\"type\":\"custom\",\"filter\":[\"some-filter\"],\"tokenizer\":\"some-tokenizer\"}"); - - // Default type - test.accept("{\"filter\":[\"some-filter\"],\"tokenizer\":\"some-tokenizer\"}"); - } - - @Test - public void testBuilders() { - String json = "{\"exists\":{\"field\":\"foo\"}}"; - Query q; - - q = new Query(QueryBuilders.exists().field("foo").build()); - assertEquals(json, toJson(q)); - - q = QueryBuilders.exists(e -> e.field("foo")); - assertEquals(json, toJson(q)); - } - - - @Test - public void testNestedTaggedUnionWithDefaultTag() { - // https://github.com/elastic/elasticsearch-java/issues/45 - - // Object fields don't really exist in ES and are based on a naming convention where field names - // are dot-separated paths. The hierarchy is rebuilt from these names and ES doesn't send back - // "type": "object" for object properties. - // See https://www.elastic.co/guide/en/elasticsearch/reference/current/object.html - // - // Mappings are therefore a hierarchy of internally-tagged unions based on the "type" property - // with a default "object" tag value if the "type" property is missing. - - String json = - "{\n" + - " \"testindex\" : {\n" + - " \"mappings\" : {\n" + - " \"properties\" : {\n" + - " \"id\" : {\n" + - " \"type\" : \"text\",\n" + - " \"fields\" : {\n" + - " \"keyword\" : {\n" + - " \"type\" : \"keyword\",\n" + - " \"ignore_above\" : 256\n" + - " }\n" + - " }\n" + - " },\n" + - " \"name\" : {\n" + - " \"properties\" : {\n" + - " \"first\" : {\n" + - " \"type\" : \"text\",\n" + - " \"fields\" : {\n" + - " \"keyword\" : {\n" + - " \"type\" : \"keyword\",\n" + - " \"ignore_above\" : 256\n" + - " }\n" + - " }\n" + - " },\n" + - " \"last\" : {\n" + - " \"type\" : \"text\",\n" + - " \"fields\" : {\n" + - " \"keyword\" : {\n" + - " \"type\" : \"keyword\",\n" + - " \"ignore_above\" : 256\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - "}"; - - GetMappingResponse response = fromJson(json, GetMappingResponse.class); - - TypeMapping mappings = response.get("testindex").mappings(); - assertTrue(mappings.properties().get("name").isObject()); - - assertEquals(256, mappings - .properties().get("name").object() - .properties().get("first").text() - .fields().get("keyword").keyword(). - ignoreAbove().longValue() - ); - - assertTrue(mappings.properties().get("id").isText()); - - assertEquals(256, mappings.properties().get("id").text().fields().get("keyword").keyword().ignoreAbove().longValue()); - } - - @Test - public void testEmptyProperty() { - // Edge case where we have a property with no fields and no type - String json = "{}"; - Property property = fromJson(json, Property.class); - assertEquals(Property.Kind.Object, property._kind()); - } - - @Test - public void testNestedVariantsWithContainerProperties() { - - SearchRequest search = SearchRequest.of(s -> s - .aggregations( - "agg1", a -> a - .meta("m1", JsonData.of("m1 value")) - // Here we can choose any aggregation type, but build() isn't accessible - .valueCount(v -> v.field("f")) - // Here we can only set container properties (meta and (sub)aggregations) or build() - .meta("m2", JsonData.of("m2 value")) - ) - ); - - assertEquals("m1 value", search.aggregations().get("agg1").meta().get("m1").to(String.class)); - assertEquals("m2 value", search.aggregations().get("agg1").meta().get("m2").to(String.class)); - } - - @Test - public void testContainerWithOptionalVariants() { - // FunctionScore is the only occurrence of this - - Query q = QueryBuilders.term(t -> t.field("foo").value("bar")); - - // No variant - { - Query fsq = QueryBuilders.functionScore(fs -> fs - .query(q) - .functions(f -> f.weight(1.0)) - ); - - String json = "{\"function_score\":{\"functions\":[{\"weight\":1.0}]," + - "\"query\":{\"term\":{\"foo\":{\"value\":\"bar\"}}}}}"; - assertEquals(json, toJson(fsq)); - - Query fsq2 = checkJsonRoundtrip(fsq, json); - - assertNull(fsq2.functionScore().functions().get(0)._kind()); - assertEquals(1.0, fsq2.functionScore().functions().get(0).weight(), 0.001); - } - - // With a variant - { - Query fsq = QueryBuilders.functionScore(fs -> fs - .query(q) - .functions(f -> f - .weight(1.0) - .linear(l -> l - .numeric(n -> n - .field("foo") - .placement(p -> p.decay(2.0)) - ) - ) - )); - - String json = "{\"function_score\":{\"functions\":[{\"weight\":1.0,\"linear\":{\"foo\":{\"decay\":2.0}}}]," + - "\"query\":{\"term\":{\"foo\":{\"value\":\"bar\"}}}}}"; - assertEquals(json, toJson(fsq)); - - Query fsq2 = checkJsonRoundtrip(fsq, json); - - assertEquals(FunctionScore.Kind.Linear, fsq2.functionScore().functions().get(0)._kind()); - assertEquals(1.0, fsq2.functionScore().functions().get(0).weight(), 0.001); - assertEquals(2.0, fsq2.functionScore().functions().get(0).linear().untyped().placement().decay(), 0.001); - } - } - - @Test - public void testBooleanVariantTag() { - - String jsonT = "{\n" + - " \"indices\": {\n" + - " \"test\": {\n" + - " \"index\": \"test\",\n" + - " \"managed\": true,\n" + - " \"policy\": \"my_policy\",\n" + - " \"index_creation_date_millis\": 1736785235558,\n" + - " \"time_since_index_creation\": \"27.75d\",\n" + - " \"lifecycle_date_millis\": 1736785235558,\n" + - " \"age\": \"27.75d\",\n" + - " \"phase\": \"warm\",\n" + - " \"phase_time_millis\": 1739183166898,\n" + - " \"action\": \"migrate\",\n" + - " \"action_time_millis\": 1739183166898,\n" + - " \"step\": \"check-migration\",\n" + - " \"step_time_millis\": 1739183166898,\n" + - " \"step_info\": {\n" + - " \"message\": \"Waiting for all shard copies to be active\",\n" + - " \"shards_left_to_allocate\": -1,\n" + - " \"all_shards_active\": false,\n" + - " \"number_of_replicas\": 1\n" + - " },\n" + - " \"phase_execution\": {\n" + - " \"policy\": \"my_policy\",\n" + - " \"phase_definition\": {\n" + - " \"min_age\": \"10d\",\n" + - " \"actions\": {\n" + - " \"forcemerge\": {\n" + - " \"max_num_segments\": 1\n" + - " }\n" + - " }\n" + - " },\n" + - " \"version\": 1,\n" + - " \"modified_date_in_millis\": 1739183005443\n" + - " }\n" + - " }\n" + - " }\n" + - "}"; - - ExplainLifecycleResponse respT = fromJson(jsonT,ExplainLifecycleResponse.class); - - // if managed is "true" then the variant class must be Managed - assertTrue(respT.indices().get("test").isTrue()); - assertTrue(respT.indices().get("test")._get().getClass().equals(LifecycleExplainManaged.class)); - - String jsonF = "{\n" + - " \"indices\": {\n" + - " \"test\": {\n" + - " \"index\": \"test\",\n" + - " \"managed\": false\n" + - " }\n" + - " }\n" + - "}"; - - ExplainLifecycleResponse respF = fromJson(jsonF,ExplainLifecycleResponse.class); - - // if managed is "false" then the variant class must be Unmanaged - assertTrue(respF.indices().get("test").isFalse()); - assertTrue(respF.indices().get("test")._get().getClass().equals(LifecycleExplainUnmanaged.class)); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/package-info.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/package-info.java deleted file mode 100644 index 034f71bcd..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/model/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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. - */ - -/** - * Tests that verify correct types and serialization/deserialization of the API specification model using API - * structures that cover the various model features - */ -package co.elastic.clients.rest5_client.elasticsearch.model; diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/spec_issues/SpecIssuesTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/spec_issues/SpecIssuesTest.java deleted file mode 100644 index 7f4d1a648..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/elasticsearch/spec_issues/SpecIssuesTest.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.elasticsearch.spec_issues; - -import co.elastic.clients.documentation.usage.Product; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.ElasticsearchTestServer; -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.elasticsearch._types.Script; -import co.elastic.clients.elasticsearch._types.analysis.LimitTokenCountTokenFilter; -import co.elastic.clients.elasticsearch._types.mapping.Property; -import co.elastic.clients.elasticsearch._types.mapping.RuntimeField; -import co.elastic.clients.elasticsearch._types.mapping.RuntimeFieldType; -import co.elastic.clients.elasticsearch.cluster.ClusterStatsResponse; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.core.search.Suggester; -import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; -import co.elastic.clients.elasticsearch.indices.GetFieldMappingRequest; -import co.elastic.clients.elasticsearch.indices.GetFieldMappingResponse; -import co.elastic.clients.elasticsearch.indices.IndexSettings; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.elasticsearch.snapshot.RestoreResponse; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.json.JsonpDeserializer; -import jakarta.json.stream.JsonParser; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.io.InputStream; -import java.io.StringReader; - -/** - * Test issues related to the API specifications. - * - * Depending on the feedback provided, this may involve either loading a JSON file or sending requests to an ES server. - */ -public class SpecIssuesTest extends ModelTestCase { - - @Test - public void i0328_charFilter() throws Exception { - // Both mappings and mappings_path are optional - String json = - "{\n" + - " \"analysis\": { \n" + - " \"char_filter\": {\n" + - " \"multi_char_filter\": {\n" + - " \"type\": \"mapping\",\n" + -// " \"mappings\": [\n" + -// " \"xyz => xyz\"\n" + -// " ],\n" + - " \"mappings_path\": \"analysis/multi-char-replacement.txt\"\n" + - " }\n" + - " }\n" + - " }\n" + - "}"; - - IndexSettings.of(b -> b.withJson(new StringReader(json))); - } - - @Disabled("Not fixed yet") - @Test - public void i0201_restoreResponse() throws Exception { - RestoreResponse restoreResponse = fromJson("{\"acknowledged\":true}", RestoreResponse.class); - } - - @Test - public void i0298_runtimeMappings() throws Exception { - ElasticsearchClient client = ElasticsearchTestServer.global().client(); - - String index = "i0298"; - - Product p = new Product("p1", "p2", 42.0); - - client.index(ir -> ir - .index(index) - .document(p)); - - client.indices().flush(f -> f.index(index)); - - RuntimeField runtimeField = RuntimeField.of(rf -> rf - .type(RuntimeFieldType.Double) - .script(Script.of(s -> s - .source("emit(doc['price'].value * 1.19)") - )) - ); - - client.search(sr -> sr - .index(index) - .runtimeMappings("priceWithTax", runtimeField), // NOTE: the builder accepts only lists here - Product.class); - } - - @Test - public void i0297_mappingSettings() { - - CreateIndexRequest request = CreateIndexRequest.of(r -> r - .index("i0297") - .settings(s -> s - // This is "mapping" and not "mappings" - .mapping(m -> m.totalFields(totalFields -> totalFields.limit("1001"))) - .otherSettings("foo", JsonData.of("bar")) - ) - ); - - assertEquals("{\"settings\":{\"foo\":\"bar\",\"mapping\":{\"total_fields\":{\"limit\":\"1001\"}}}}", toJson(request)); - } - - @Test - public void i0295_mappingSettings() { - String json = "{\n" + - " \"mappings\": {\n" + - " \"properties\": {\n" + - " \"myfield\": {\n" + - " \"type\": \"text\"\n" + - " }\n" + - " }\n" + - " },\n" + - " \"settings\": {\n" + - " \"index\": {\n" + - " \"max_result_window\": 1000000,\n" + - " \"mapping\": {\n" + - " \"nested_objects\": {\n" + - " \"limit\": 10000\n" + - " }\n" + - " },\n" + - " \"requests\": {\n" + - " \"cache\": {\n" + - " \"enable\": true\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - "}"; - - CreateIndexRequest request = CreateIndexRequest.of(r -> r - .index("i0295") - .withJson(new StringReader(json)) - ); - } - - @Test - public void i0254_suggesterTest() throws Exception { - new Suggester.Builder().suggesters("song-suggest", s -> s.completion(c->c.field("suggest"))).build(); - } - - @Disabled("Stable version 9 not yet available") - @Test - // update: icu_collation_keyword has been released and added to the spec - public void i0249_variantKind() throws Exception { - try (ElasticsearchTestServer server = new ElasticsearchTestServer("analysis-icu").start()) { - - ElasticsearchClient esClient = server.client(); - - esClient.indices().create(r -> r - .index("i0249") - .withJson(new StringReader("{\n" + - " \"mappings\": {\n" + - " \"properties\": {\n" + - " \"name\": { \n" + - " \"type\": \"text\",\n" + - " \"fields\": {\n" + - " \"sort\": { \n" + - " \"type\": \"icu_collation_keyword\",\n" + - " \"index\": false,\n" + - " \"language\": \"de\",\n" + - " \"country\": \"DE\",\n" + - " \"variant\": \"@collation=phonebook\"\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - "}\n")) - ); - - GetFieldMappingResponse fm = esClient.indices().getFieldMapping(b -> b - .index("i0249") - .fields("*") - ); - - Property property = fm.get("i0249").mappings().get("name").mapping().get("name").text().fields().get("sort"); - - assertFalse(property._isCustom()); - assertEquals(Property.Kind.IcuCollationKeyword, property._kind()); - } - } - - @Test - public void i0199_consumeAllTokensOptional() { - // https://github.com/elastic/elasticsearch-java/issues/199 - // Most filter properties are optional - LimitTokenCountTokenFilter filter = LimitTokenCountTokenFilter.of(b -> b); - } - - @Test - public void i0166_multiFieldMapping() throws Exception { - // https://github.com/elastic/elasticsearch-java/issues/166 - ElasticsearchClient client = ElasticsearchTestServer.global().client(); - - String indexName = "i0166_multi_field_mapping"; - - client.index(r -> r - .index(indexName) - .withJson(new StringReader("{\"a\":1,\"b\":2}")) - ); - - GetFieldMappingRequest gfmRequest = GetFieldMappingRequest.of (b -> b - .index(indexName) - .fields("a", "b") - ); - - GetFieldMappingResponse gfmResponse = client.indices().getFieldMapping(gfmRequest); - - assertEquals(2, gfmResponse.get(indexName).mappings().size()); - assertEquals("a", gfmResponse.get(indexName).mappings().get("a").fullName()); - assertEquals("b", gfmResponse.get(indexName).mappings().get("b").fullName()); - } - - @Test - public void i0107_rangeBucketKey() { - // https://github.com/elastic/elasticsearch-java/issues/107 - loadRsrc("issue-0107-response.json", SearchResponse.createSearchResponseDeserializer(JsonData._DESERIALIZER)); - } - - @Test - public void i0088_clusterStats() { - // https://github.com/elastic/elasticsearch-java/issues/88 - loadRsrc("issue-0088-response.json", ClusterStatsResponse._DESERIALIZER); - } - - @Test - public void i0087_filterAggSubAggregation() { - // https://github.com/elastic/elasticsearch-java/issues/87 - SearchResponse resp = loadRsrc("issue-0087-response.json", - SearchResponse.createSearchResponseDeserializer(JsonData._DESERIALIZER)); - - assertEquals( - "cnn.com", - resp.aggregations().get("login_filter").filter() - .aggregations().get("to_domain").sterms() - .buckets().array().get(0).key().stringValue()); - } - - @Test - public void i0080_simpleError() { - // https://github.com/elastic/elasticsearch-java/issues/80 - // When requesting a missing index, the error response in compact format. - // Fixed by adding ErrorCause.reason as a shortcut property - String json = "{\"error\":\"alias [not-existing-alias] missing\",\"status\":404}"; - ErrorResponse err = fromJson(json, ErrorResponse.class); - - assertEquals("alias [not-existing-alias] missing", err.error().reason()); - } - - @Test - public void i0078_deserializeSearchRequest() { - // https://github.com/elastic/elasticsearch-java/issues/78 - loadRsrc("issue-0078.json", SearchRequest._DESERIALIZER); - } - - @Test - public void i0057_suggestDeserialization() { - // https://github.com/elastic/elasticsearch-java/issues/57 - // Note: the _type properties have been removed so that the test works in 8.x too. - SearchResponse resp = loadRsrc("issue-0057-response.json", - SearchResponse.createSearchResponseDeserializer(JsonData._DESERIALIZER)); - - assertEquals(1, resp.suggest().get("completion:completion1").size()); - assertEquals("hash", resp.suggest().get("completion:completion1").get(0).completion().text()); - assertEquals("HashMap-Complete1", resp.suggest().get("completion:completion1").get(0).completion().options().get(0).text()); - } - - @Test - public void i0056_hitsMetadataTotal() throws Exception { - // https://github.com/elastic/elasticsearch-java/issues/56 - SearchResponse res = ElasticsearchTestServer.global().client() - .search(srb -> srb - .trackTotalHits(thb -> thb.enabled(false)), JsonData.class); - } - - @Test - public void gettingVersionFromNodes() throws Exception { - ElasticsearchTestServer.global().client() - .nodes().info().nodes().entrySet().forEach(node -> - assertNotNull(node.getValue().version())); - } - - private T loadRsrc(String res, JsonpDeserializer deser) { - InputStream is = this.getClass().getResourceAsStream(res); - assertNotNull(is, "Resource not found: " + res); - JsonParser parser = mapper.jsonProvider().createParser(is); - return deser.deserialize(parser, mapper); - } - - private T loadRsrc(String res, Class clazz) { - return loadRsrc(res, JsonpDeserializer.of(clazz)); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BinaryEndpointTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BinaryEndpointTest.java deleted file mode 100644 index 1dad3b44a..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BinaryEndpointTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.transport.endpoints; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.ElasticsearchTestServer; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.json.SimpleJsonpMapper; -import co.elastic.clients.transport.TransportOptions; -import co.elastic.clients.transport.endpoints.BinaryEndpoint; -import co.elastic.clients.transport.endpoints.BinaryResponse; -import co.elastic.clients.transport.rest_client.RestClientTransport; -import com.sun.net.httpserver.HttpServer; -import org.apache.commons.io.IOUtils; -import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.RestClient; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; - -public class BinaryEndpointTest extends Assertions { - - /** Collected headers by test name */ - private static HttpServer httpServer; - - @BeforeAll - public static void setup() throws IOException { - httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); - - // Register a handler on the core.exists("capture-handler/{name}") endpoint that will capture request headers. - httpServer.createContext("/foo/_mvt/bar/1/0/0", exchange -> { - // Reply with an empty 200 response - exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); - exchange.getResponseHeaders().set("Content-Type", "application/vnd.hello-world"); - exchange.sendResponseHeaders(200, 0); - exchange.getResponseBody().write("Hello world".getBytes(StandardCharsets.UTF_8)); - exchange.close(); - }); - - httpServer.start(); - } - - @AfterAll - public static void cleanup() { - httpServer.stop(0); - httpServer = null; - } - - @Test - public void testMvtSearch() throws IOException { - RestClient llrc = RestClient.builder( - new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) - ).build(); - - RestClientTransport transport = new RestClientTransport(llrc, new SimpleJsonpMapper()); - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - BinaryResponse resp = esClient.searchMvt(s -> s - .index("foo") - .field("bar") - .x(0) - .y(0) - .zoom(1) - ); - - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buffer = new byte[256]; - - try(InputStream input = resp.content()) { - int len; - while ((len = input.read(buffer)) > 0) { - baos.write(buffer, 0, len); - } - } - - assertEquals("application/vnd.hello-world", resp.contentType()); - assertEquals("Hello world", baos.toString(StandardCharsets.UTF_8.name())); - } - - @Test - public void convertJsonToBinaryEndpoint() throws IOException { - - ElasticsearchClient esClient = ElasticsearchTestServer.global().client(); - - // Create the search request - SearchRequest request = SearchRequest.of(b -> b); - - // Create a binary endpoint from the regular search endpoint. It will not deserialize - // the response and instead will just return the raw response input stream. - BinaryEndpoint binarySearchEndpoint = SearchRequest._ENDPOINT.withBinaryResponse(); - - // Force typed_keys to false, so that aggregations names do not hold type information - TransportOptions options = esClient._transportOptions().toBuilder() - .setParameter("typed_keys", "false") - .build(); - - // Call Elasticsearch by providing the transport the request and endpoint - BinaryResponse binaryResponse = esClient._transport().performRequest(request, binarySearchEndpoint, options); - - // Do something with the response - String response = IOUtils.toString(binaryResponse.content(), StandardCharsets.UTF_8); - assertTrue(response.matches("\\{\"took\":\\d+,\"timed_out\":false.*")); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BooleanEndpointTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BooleanEndpointTest.java deleted file mode 100644 index 47e94c889..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/BooleanEndpointTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.transport.endpoints; - -import co.elastic.clients.elasticsearch.core.ExistsRequest; -import co.elastic.clients.elasticsearch.security.SamlCompleteLogoutRequest; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class BooleanEndpointTest extends Assertions { - - @Test - public void testHasRequestBody() { - ExistsRequest er = ExistsRequest.of(r -> r.index("foo").id("1")); - assertNull(ExistsRequest._ENDPOINT.body(er)); - - SamlCompleteLogoutRequest sclr = SamlCompleteLogoutRequest.of(r -> r.ids("1").realm("r")); - assertNotNull(SamlCompleteLogoutRequest._ENDPOINT.body(sclr)); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/EndpointBaseTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/EndpointBaseTest.java deleted file mode 100644 index 0d82c9dbc..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/EndpointBaseTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.transport.endpoints; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.elasticsearch.core.PingRequest; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.endpoints.BooleanResponse; -import co.elastic.clients.transport.endpoints.EndpointBase; -import org.junit.jupiter.api.Test; - -public class EndpointBaseTest extends ModelTestCase { - - @Test - public void testPathEncoding() { - assertEquals("abCD12;-_*", pathEncode("abCD12;-_*")); - assertEquals("XYZ%5B", pathEncode("XYZ[")); - assertEquals("xyz%7B", pathEncode("xyz{")); - assertEquals("foo%2Fbar", pathEncode("foo/bar")); - assertEquals("foo%20bar", pathEncode("foo bar")); - assertEquals("f%C3%AAl%C3%A9", pathEncode("fêlé")); - } - - private String pathEncode(String s) { - StringBuilder sb = new StringBuilder(); - EndpointBase.pathEncode(s, sb); - return sb.toString(); - } - - @Test - public void testErrorDecoding() { - Endpoint endpoint = PingRequest._ENDPOINT; - - { - String json = "{\"error\":\"some error\"}"; - - ErrorResponse response = fromJson(json, endpoint.errorDeserializer(404)); - assertEquals(404, response.status()); - assertEquals("some error", response.error().reason()); - assertEquals("http_status_404", response.error().type()); - } - - { - String json = "{\"status\":401,\"error\":{\"type\":\"the_error_type\",\"reason\":\"some error\"}}"; - - ErrorResponse response = fromJson(json, endpoint.errorDeserializer(404)); - assertEquals(401, response.status()); // value in response body has precedence - assertEquals("some error", response.error().reason()); - assertEquals("the_error_type", response.error().type()); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/SimpleEndpointTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/SimpleEndpointTest.java deleted file mode 100644 index ed0b77c50..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/endpoints/SimpleEndpointTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.transport.endpoints; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.core.CountResponse; -import co.elastic.clients.testkit.MockHttpClient; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.ElasticsearchTransportBase; -import co.elastic.clients.transport.TransportOptions; -import co.elastic.clients.transport.http.TransportHttpClient; -import org.jetbrains.annotations.Nullable; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -public class SimpleEndpointTest extends ModelTestCase { - - @Test - public void testNoBodyForEmptyObject() throws Exception { - - List requests = new ArrayList<>(); - - MockHttpClient httpClient = new MockHttpClient() { - @Override - public Response performRequest( - String endpointId, @Nullable Node node, Request request, TransportOptions option - ) throws IOException { - requests.add(request); - return super.performRequest(endpointId, node, request, option); - } - }; - - httpClient.add("/_count", "application/json", toJson( - CountResponse.of(c -> c - .count(1) - .shards(s -> s.successful(1).failed(0).total(1)) - ))); - - ElasticsearchTransport transport = new ElasticsearchTransportBase(httpClient, null, mapper) {}; - ElasticsearchClient client = new ElasticsearchClient(transport, null); - - client.count(); - client.count(c -> c.q("foo:bar")); - client.count(c -> c.query(q -> q.term(t -> t.field("foo").value("bar")))); - - assertNull(requests.get(0).body()); - assertNull(requests.get(1).body()); - assertNotNull(requests.get(2).body()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/http/HeaderMapTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/http/HeaderMapTest.java deleted file mode 100644 index 8143d0079..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/http/HeaderMapTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.transport.http; - -import co.elastic.clients.transport.http.HeaderMap; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.util.Iterator; -import java.util.Map; - -class HeaderMapTest extends Assertions { - - @Test - public void testCaseSensitivity() { - HeaderMap headers = new HeaderMap(); - - headers.put("Foo", "bar"); - assertEquals("bar", headers.get("Foo")); - assertEquals("bar", headers.get("foo")); - assertEquals("bar", headers.get("fOO")); - - headers.put("foo", "baz"); - assertEquals("baz", headers.get("Foo")); - assertEquals("baz", headers.get("foo")); - assertEquals("baz", headers.get("fOO")); - } - - @Test - public void testLock() { - HeaderMap headers = new HeaderMap(); - - headers.put("foo", "bar"); - - HeaderMap locked = headers.locked(); - assertEquals("bar", headers.get("Foo")); - - assertThrows(UnsupportedOperationException.class, () -> { - locked.put("foo", "baz"); - }); - - assertThrows(UnsupportedOperationException.class, () -> { - Iterator> iterator = locked.entrySet().iterator(); - assertEquals("bar", iterator.next().getValue()); - iterator.remove(); - }); - - headers.put("foo", "baz"); - assertEquals("baz", headers.get("Foo")); - assertEquals("bar", locked.get("Foo")); - } - - @Test - public void testAdd() { - HeaderMap headers = new HeaderMap(); - - headers.add("Foo", "bar"); - headers.add("foo", "baz"); - - assertEquals("bar; baz", headers.get("Foo")); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/instrumentation/OpenTelemetryForElasticsearchTest.java b/java-client/src/test/java/co/elastic/clients/rest5_client/transport/instrumentation/OpenTelemetryForElasticsearchTest.java deleted file mode 100644 index d0866cae8..000000000 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/instrumentation/OpenTelemetryForElasticsearchTest.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.rest5_client.transport.instrumentation; - -import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._types.query_dsl.Query; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.instrumentation.Instrumentation; -import co.elastic.clients.transport.instrumentation.OpenTelemetryForElasticsearch; -import co.elastic.clients.transport.rest_client.RestClientTransport; -import com.sun.net.httpserver.HttpServer; -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.common.AttributeKey; -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.sdk.OpenTelemetrySdk; -import io.opentelemetry.sdk.common.CompletableResultCode; -import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.opentelemetry.sdk.trace.data.SpanData; -import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; -import io.opentelemetry.sdk.trace.export.SpanExporter; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; -import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; -import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.RestClient; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -public class OpenTelemetryForElasticsearchTest { - private static final String INDEX = "test-index"; - private static final String DOC_ID = "1234567"; - private static final String DOC_RESPONSE = "{\n" + - " \"_index\": \"" + INDEX + "\",\n" + - " \"_id\": \"" + DOC_ID + "\",\n" + - " \"_version\": 1,\n" + - " \"_seq_no\": 0,\n" + - " \"_primary_term\": 1,\n" + - " \"found\": true,\n" + - " \"_source\": {\n" + - " \"@timestamp\": \"2099-11-15T14:12:12\",\n" + - " \"message\": \"GET /search HTTP/1.1 200 1070000\"\n" + - " }\n" + - "}"; - private static final String SEARCH_RESPONSE = "{\n" + - " \"took\": 5,\n" + - " \"timed_out\": false,\n" + - " \"_shards\": {\n" + - " \"total\": 1,\n" + - " \"successful\": 1,\n" + - " \"skipped\": 0,\n" + - " \"failed\": 0\n" + - " },\n" + - " \"hits\": {\n" + - " \"total\": {\n" + - " \"value\": 1,\n" + - " \"relation\": \"eq\"\n" + - " },\n" + - " \"max_score\": 1.3862942,\n" + - " \"hits\": [\n" + - " {\n" + - " \"_index\": \"" + INDEX + "\",\n" + - " \"_id\": \"" + DOC_ID + "\",\n" + - " \"_score\": 1.3862942,\n" + - " \"_source\": {\n" + - " \"@timestamp\": \"2099-11-15T14:12:12\",\n" + - " \"message\": \"GET /search HTTP/1.1 200 1070000\"\n" + - " }\n" + - " }\n" + - " ]\n" + - " }\n" + - "}"; - public static final String DB_OPERATION = "db.operation"; - public static final String URL_FULL = "url.full"; - public static final String SERVER_ADDRESS = "server.address"; - public static final String SERVER_PORT = "server.port"; - // has been renamed in 1.21 from http.method - see https://github.com/open-telemetry/semantic-conventions/blob/main/schemas/1.21.0 - public static final String HTTP_REQUEST_METHOD = "http.request.method"; - private static HttpServer httpServer; - private static MockSpanExporter spanExporter; - private static OpenTelemetry openTelemetry; - private static RestClient restClient; - private static RestClientTransport transport; - private static ElasticsearchClient client; - private static ElasticsearchAsyncClient asyncClient; - - @BeforeAll - public static void setup() throws IOException { - setupOTel(); - setupHttpServer(); - setupClient(); - } - - @AfterAll - public static void cleanUp() throws IOException { - httpServer.stop(0); - transport.close(); - } - - private static void setupClient() { - restClient = - RestClient.builder(new HttpHost(httpServer.getAddress().getAddress(), httpServer.getAddress().getPort())).build(); - - Instrumentation instrumentation = new OpenTelemetryForElasticsearch(openTelemetry, false); - - transport = new RestClientTransport(restClient, new JacksonJsonpMapper(), null, instrumentation); - - client = new ElasticsearchClient(transport); - asyncClient = new ElasticsearchAsyncClient(transport); - } - - private static void setupHttpServer() throws IOException { - httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); - - // handler for GetRequest - httpServer.createContext("/" + INDEX + "/_doc/" + DOC_ID, exchange -> { - exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); - exchange.getResponseHeaders().set("Content-Type", "application/json"); - exchange.sendResponseHeaders(200, 0); - exchange.getResponseBody().write(DOC_RESPONSE.getBytes()); - exchange.close(); - }); - - // handler for SearchRequest - httpServer.createContext("/" + INDEX + "/_search", exchange -> { - exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); - exchange.getResponseHeaders().set("Content-Type", "application/json"); - exchange.sendResponseHeaders(200, 0); - exchange.getResponseBody().write(SEARCH_RESPONSE.getBytes()); - exchange.close(); - }); - - httpServer.start(); - } - - private static void setupOTel() { - Resource resource = Resource.getDefault() - .merge(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, "es-api-test"))); - - spanExporter = new MockSpanExporter(); - - SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() - .addSpanProcessor(SimpleSpanProcessor.create(spanExporter)) - .setResource(resource) - .build(); - - openTelemetry = OpenTelemetrySdk.builder() - .setTracerProvider(sdkTracerProvider) - .build(); - } - - @BeforeEach - public void reset() { - spanExporter.reset(); - } - - @Test - public void testGetRequest() throws IOException, InterruptedException { - client.get(r -> r.index(INDEX).id(DOC_ID).refresh(true), Object.class); - Assertions.assertEquals(spanExporter.getSpans().size(), 1); - SpanData span = spanExporter.getSpans().get(0); - Assertions.assertEquals("get", span.getName()); - Assertions.assertEquals("get", span.getAttributes().get(AttributeKey.stringKey(DB_OPERATION))); - Assertions.assertEquals("GET", span.getAttributes().get(AttributeKey.stringKey(HTTP_REQUEST_METHOD))); - Assertions.assertEquals("elasticsearch", span.getAttributes().get(SemanticAttributes.DB_SYSTEM)); - - String url = "http://" + httpServer.getAddress().getHostName() + ":" + httpServer.getAddress().getPort() + - "/" + INDEX + "/_doc/" + DOC_ID + "?refresh=true"; - Assertions.assertEquals(url, span.getAttributes().get(AttributeKey.stringKey(URL_FULL))); - Assertions.assertEquals(httpServer.getAddress().getHostName(), span.getAttributes().get(AttributeKey.stringKey(SERVER_ADDRESS))); - Assertions.assertEquals(httpServer.getAddress().getPort(), span.getAttributes().get(AttributeKey.longKey(SERVER_PORT))); - - // Path parts - Assertions.assertEquals(DOC_ID, span.getAttributes().get(AttributeKey.stringKey("db.elasticsearch.path_parts.id"))); - } - - @Test - public void testSearchRequest() throws IOException, InterruptedException { - // A client that will capture requests - ElasticsearchClient client = new ElasticsearchClient(new RestClientTransport( - restClient, this.client._jsonpMapper(), null, new OpenTelemetryForElasticsearch(openTelemetry, true)) - ); - SearchRequest req = SearchRequest.of(r -> r.index(INDEX).query(q -> q.term(t -> t.field("x").value("y")))); - String queryAsString = JsonpUtils.toJsonString(req, client._jsonpMapper()); - client.search(req, Object.class); - Assertions.assertEquals(spanExporter.getSpans().size(), 1); - SpanData span = spanExporter.getSpans().get(0); - Assertions.assertEquals("search", span.getName()); - Assertions.assertEquals(queryAsString, span.getAttributes().get(SemanticAttributes.DB_STATEMENT)); - } - - @Test - public void testAsyncSearchRequest() throws IOException, InterruptedException, TimeoutException, ExecutionException { - Query query = Query.of(q -> q.term(t -> t.field("x").value("y"))); - Future future = asyncClient.search(r -> r.index(INDEX).query(query), Object.class); - future.get(2, TimeUnit.SECONDS); - spanExporter.awaitNumSpans(1, 2000); - Assertions.assertEquals(spanExporter.getSpans().size(), 1); - SpanData span = spanExporter.getSpans().get(0); - Assertions.assertEquals("search", span.getName()); - - // We're not capturing bodies by default - Assertions.assertNull(span.getAttributes().get(SemanticAttributes.DB_STATEMENT)); - } - - private static class MockSpanExporter implements SpanExporter { - - private final List spans = new ArrayList(); - - @Override - public CompletableResultCode export(Collection spans) { - this.spans.addAll(spans); - synchronized (this) { - notifyAll(); - } - return CompletableResultCode.ofSuccess(); - } - - @Override - public CompletableResultCode flush() { - return CompletableResultCode.ofSuccess(); - } - - @Override - public CompletableResultCode shutdown() { - spans.clear(); - return CompletableResultCode.ofSuccess(); - } - - public List getSpans() { - return spans; - } - - public void reset() { - spans.clear(); - } - - public synchronized void awaitNumSpans(int num, long timeoutMillis) throws InterruptedException { - while(spans.size() < num){ - wait(timeoutMillis); - } - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java b/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java index c7927f980..85eef55d7 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java @@ -43,10 +43,13 @@ import java.util.Map; import java.util.Properties; +/** + * Request options tests independent of the transport implementation. + */ public class RequestOptionsTest extends Assertions { private static HttpServer httpServer; - private static RestClient restClient; + private static RestClient restClient; // TODO: pick a random implementation @BeforeEach public void classSetup() throws IOException { diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/MultiBufferEntityTest.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/MultiBufferEntityTest.java similarity index 88% rename from java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/MultiBufferEntityTest.java rename to java-client/src/test/java/co/elastic/clients/transport/rest5_client/MultiBufferEntityTest.java index 8d2e27075..62d4c2ce7 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/MultiBufferEntityTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/MultiBufferEntityTest.java @@ -17,16 +17,15 @@ * under the License. */ -package co.elastic.clients.rest5_client.transport.rest_client; +package co.elastic.clients.transport.rest5_client; import co.elastic.clients.elasticsearch.core.BulkRequest; import co.elastic.clients.json.jackson.JacksonJsonpMapper; import co.elastic.clients.transport.endpoints.BinaryResponse; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; import com.sun.net.httpserver.HttpServer; import org.apache.commons.io.IOUtils; import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -52,8 +51,8 @@ public void testBulkRequest() throws IOException { httpServer.start(); - RestClient restClient = - RestClient.builder(new HttpHost(httpServer.getAddress().getAddress(), httpServer.getAddress().getPort())).build(); + Rest5Client restClient = + Rest5Client.builder(new HttpHost(httpServer.getAddress().getAddress(), httpServer.getAddress().getPort())).build(); BulkRequest req = BulkRequest.of(_0 -> _0 .operations(_1 -> _1 @@ -78,7 +77,7 @@ public void testBulkRequest() throws IOException { ) ) ); - RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); + Rest5ClientTransport transport = new Rest5ClientTransport(restClient, new JacksonJsonpMapper()); BinaryResponse binaryResponse = transport.performRequest(req, BulkRequest._ENDPOINT.withBinaryResponse(), null); diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/RequestOptionsTest.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/RequestOptionsTest.java similarity index 87% rename from java-client/src/test/java/co/elastic/clients/rest5_client/transport/RequestOptionsTest.java rename to java-client/src/test/java/co/elastic/clients/transport/rest5_client/RequestOptionsTest.java index 7a02763c5..f4a1d1d1d 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/RequestOptionsTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/RequestOptionsTest.java @@ -17,19 +17,18 @@ * under the License. */ -package co.elastic.clients.rest5_client.transport; +package co.elastic.clients.transport.rest5_client; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.jsonb.JsonbJsonpMapper; import co.elastic.clients.transport.TransportException; import co.elastic.clients.transport.Version; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.rest5_client.low_level.ResponseException; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; import com.sun.net.httpserver.HttpServer; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.NameValuePair; import org.apache.hc.core5.net.URLEncodedUtils; -import org.elasticsearch.client.ResponseException; -import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -48,7 +47,7 @@ public class RequestOptionsTest extends Assertions { private static HttpServer httpServer; - private static RestClient restClient; + private static Rest5Client restClient; @BeforeEach public void classSetup() throws IOException { @@ -83,7 +82,7 @@ public void classSetup() throws IOException { }); httpServer.start(); - restClient = RestClient.builder(new HttpHost("http",httpServer.getAddress().getHostString(), + restClient = Rest5Client.builder(new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort())).build(); } @@ -103,7 +102,7 @@ private Properties getProps(ElasticsearchClient client) throws IOException { @Test public void testNonNullClientOptions() { - final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); + final Rest5ClientTransport trsp = new Rest5ClientTransport(restClient, new JsonbJsonpMapper()); final ElasticsearchClient client = new ElasticsearchClient(trsp); assertNotNull(client._transportOptions()); @@ -112,7 +111,7 @@ public void testNonNullClientOptions() { @Test public void testDefaultHeaders() throws IOException { - final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); + final Rest5ClientTransport trsp = new Rest5ClientTransport(restClient, new JsonbJsonpMapper()); final ElasticsearchClient client = new ElasticsearchClient(trsp); Properties props = getProps(client); @@ -128,7 +127,7 @@ public void testDefaultHeaders() throws IOException { @Test public void testClientHeader() throws IOException { - final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); + final Rest5ClientTransport trsp = new Rest5ClientTransport(restClient, new JsonbJsonpMapper()); final ElasticsearchClient client = new ElasticsearchClient(trsp) .withTransportOptions(b -> b .addHeader("X-Foo", "Bar") @@ -142,7 +141,7 @@ public void testClientHeader() throws IOException { @Test public void testQueryParameter() throws IOException { - final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); + final Rest5ClientTransport trsp = new Rest5ClientTransport(restClient, new JsonbJsonpMapper()); final ElasticsearchClient client = new ElasticsearchClient(trsp) .withTransportOptions(trsp.options().with( b -> b.setParameter("format", "pretty") @@ -155,7 +154,7 @@ public void testQueryParameter() throws IOException { @Test public void testMissingProductHeader() { - final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); + final Rest5ClientTransport trsp = new Rest5ClientTransport(restClient, new JsonbJsonpMapper()); final ElasticsearchClient client = new ElasticsearchClient(trsp); final TransportException ex = assertThrows(TransportException.class, client::ping); diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/RestClientOptionsTest.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/Rest5ClientOptionsTest.java similarity index 76% rename from java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/RestClientOptionsTest.java rename to java-client/src/test/java/co/elastic/clients/transport/rest5_client/Rest5ClientOptionsTest.java index ecdbdaa97..439acc08e 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/rest_client/RestClientOptionsTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/Rest5ClientOptionsTest.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.rest5_client.transport.rest_client; +package co.elastic.clients.transport.rest5_client; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.JsonpMapper; @@ -25,13 +25,11 @@ import co.elastic.clients.transport.ElasticsearchTransport; import co.elastic.clients.transport.Version; import co.elastic.clients.transport.endpoints.BooleanResponse; -import co.elastic.clients.transport.rest_client.RestClientOptions; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.rest5_client.low_level.RequestOptions; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; import com.sun.net.httpserver.Headers; import com.sun.net.httpserver.HttpServer; import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -45,7 +43,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; -class RestClientOptionsTest extends Assertions { +class Rest5ClientOptionsTest extends Assertions { /** Collected headers by test name */ private static Map collectedHeaders; @@ -81,14 +79,14 @@ public static void cleanup() { httpServer = null; collectedHeaders = null; } - - private ElasticsearchTransport newRestClientTransport(RestClient restClient, JsonpMapper mapper) { - return newRestClientTransport(restClient, mapper, null); + + private ElasticsearchTransport newRest5ClientTransport(Rest5Client Rest5Client, JsonpMapper mapper) { + return new Rest5ClientTransport(Rest5Client, mapper, null); } - private ElasticsearchTransport newRestClientTransport(RestClient restClient, JsonpMapper mapper, RestClientOptions options) { - return new RestClientTransport(restClient, mapper, options); - //return new RestClientMonolithTransport(restClient, mapper, options); + private ElasticsearchTransport newRest5ClientTransport(Rest5Client Rest5Client, JsonpMapper mapper, Rest5ClientOptions options) { + return new Rest5ClientTransport(Rest5Client, mapper, options); + //return new Rest5ClientMonolithTransport(Rest5Client, mapper, options); } /** @@ -105,7 +103,7 @@ private String checkHeaders(ElasticsearchClient esClient) throws IOException { assertNotNull(headers, "No headers collected for test " + testName); assertNotNull(headers.get("X-elastic-client-meta"), "Missing client meta header"); - assertEquals(RestClientOptions.CLIENT_META_VALUE, headers.get("X-elastic-client-meta").get(0)); + assertEquals(Rest5ClientOptions.CLIENT_META_VALUE, headers.get("X-elastic-client-meta").get(0)); assertNotNull(headers.get("Accept"), "Missing 'Accept' header"); assertEquals(MIME_TYPE, headers.get("Accept").get(0)); @@ -125,54 +123,54 @@ private void checkUserAgent(String testName, String value) { @Test void testNoRequestOptions() throws Exception { - RestClient llrc = RestClient.builder( + Rest5Client llrc = Rest5Client.builder( new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) ).build(); - ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper()); + ElasticsearchTransport transport = newRest5ClientTransport(llrc, new SimpleJsonpMapper()); ElasticsearchClient esClient = new ElasticsearchClient(transport); String id = checkHeaders(esClient); - checkUserAgent(id, RestClientOptions.USER_AGENT_VALUE); + checkUserAgent(id, Rest5ClientOptions.USER_AGENT_VALUE); } @Test void testTransportRequestOptions() throws Exception { - RestClient llrc = RestClient.builder( + Rest5Client llrc = Rest5Client.builder( new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) ).build(); - ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper(), - new RestClientOptions.Builder(RequestOptions.DEFAULT.toBuilder()).build() + ElasticsearchTransport transport = newRest5ClientTransport(llrc, new SimpleJsonpMapper(), + new Rest5ClientOptions.Builder(RequestOptions.DEFAULT.toBuilder()).build() ); ElasticsearchClient esClient = new ElasticsearchClient(transport); String id = checkHeaders(esClient); - checkUserAgent(id, RestClientOptions.USER_AGENT_VALUE); + checkUserAgent(id, Rest5ClientOptions.USER_AGENT_VALUE); } @Test void testClientRequestOptions() throws Exception { - RestClient llrc = RestClient.builder( + Rest5Client llrc = Rest5Client.builder( new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) ).build(); - ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper()); + ElasticsearchTransport transport = newRest5ClientTransport(llrc, new SimpleJsonpMapper()); ElasticsearchClient esClient = new ElasticsearchClient(transport).withTransportOptions( - new RestClientOptions.Builder(RequestOptions.DEFAULT.toBuilder()).build() + new Rest5ClientOptions.Builder(RequestOptions.DEFAULT.toBuilder()).build() ); String id = checkHeaders(esClient); - checkUserAgent(id, RestClientOptions.USER_AGENT_VALUE); + checkUserAgent(id, Rest5ClientOptions.USER_AGENT_VALUE); } @Test void testLambdaOptionsBuilder() throws Exception { - RestClient llrc = RestClient.builder( + Rest5Client llrc = Rest5Client.builder( new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) ).build(); - ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper()); + ElasticsearchTransport transport = newRest5ClientTransport(llrc, new SimpleJsonpMapper()); ElasticsearchClient esClient = new ElasticsearchClient(transport) .withTransportOptions(o -> o .addHeader("Foo", "bar") @@ -180,7 +178,7 @@ void testLambdaOptionsBuilder() throws Exception { ); String id = checkHeaders(esClient); - checkUserAgent(id, RestClientOptions.USER_AGENT_VALUE); + checkUserAgent(id, Rest5ClientOptions.USER_AGENT_VALUE); } @Test @@ -190,11 +188,11 @@ void testRequestOptionsOverridingBuiltin() throws Exception { .addHeader("x-elastic-client-meta", "foo-bar-client") .build(); - RestClient llrc = RestClient.builder( + Rest5Client llrc = Rest5Client.builder( new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) ).build(); - ElasticsearchTransport transport = newRestClientTransport(llrc, new SimpleJsonpMapper(), new RestClientOptions(options,false)); + ElasticsearchTransport transport = newRest5ClientTransport(llrc, new SimpleJsonpMapper(), new Rest5ClientOptions(options,false)); ElasticsearchClient esClient = new ElasticsearchClient(transport); // Should not override client meta String id = checkHeaders(esClient); diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportTest.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/TransportTest.java similarity index 88% rename from java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportTest.java rename to java-client/src/test/java/co/elastic/clients/transport/rest5_client/TransportTest.java index 3cda2671b..526967f54 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/TransportTest.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.rest5_client.transport; +package co.elastic.clients.transport.rest5_client; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.jackson.JacksonJsonpMapper; @@ -25,14 +25,12 @@ import co.elastic.clients.transport.TransportException; import co.elastic.clients.transport.http.RepeatableBodyResponse; import co.elastic.clients.transport.http.TransportHttpClient; -import co.elastic.clients.transport.rest_client.RestClientOptions; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.rest5_client.low_level.ESResponse; +import co.elastic.clients.transport.rest5_client.low_level.RequestOptions; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; import co.elastic.clients.util.BinaryData; import com.sun.net.httpserver.HttpServer; import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -65,11 +63,11 @@ public void testXMLResponse() throws Exception { httpServer.start(); InetSocketAddress address = httpServer.getAddress(); - RestClient restClient = RestClient + Rest5Client restClient = Rest5Client .builder(new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort())) .build(); - ElasticsearchClient esClient = new ElasticsearchClient(new RestClientTransport(restClient, + ElasticsearchClient esClient = new ElasticsearchClient(new Rest5ClientTransport(restClient, new JacksonJsonpMapper())); TransportException ex = Assertions.assertThrows( @@ -83,7 +81,7 @@ public void testXMLResponse() throws Exception { assertEquals("es/cat.indices", ex.endpointId()); // Original response is transport-dependent - Response restClientResponse = (Response) ex.response().originalResponse(); + ESResponse restClientResponse = (ESResponse) ex.response().originalResponse(); assertEquals(401, restClientResponse.getStatusCode()); } @@ -107,12 +105,12 @@ public void testOriginalJsonBodyRetrievalException() throws Exception { httpServer.start(); - RestClient restClient = RestClient + Rest5Client restClient = Rest5Client .builder(new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort())) .build(); // no transport options, response is not RepeatableBodyResponse, original body cannot be retrieved - ElasticsearchClient esClient = new ElasticsearchClient(new RestClientTransport(restClient, + ElasticsearchClient esClient = new ElasticsearchClient(new Rest5ClientTransport(restClient, new JacksonJsonpMapper())); TransportException ex = Assertions.assertThrows( @@ -124,9 +122,9 @@ public void testOriginalJsonBodyRetrievalException() throws Exception { assertNotEquals(RepeatableBodyResponse.class, ex.response().getClass()); // setting transport option - RestClientOptions options = new RestClientOptions(RequestOptions.DEFAULT, true); + Rest5ClientOptions options = new Rest5ClientOptions(RequestOptions.DEFAULT, true); - ElasticsearchTransport transport = new RestClientTransport( + ElasticsearchTransport transport = new Rest5ClientTransport( restClient, new JacksonJsonpMapper(), options); ElasticsearchClient esClientOptions = new ElasticsearchClient(transport); diff --git a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportUtilsTest.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/TransportUtilsTest.java similarity index 89% rename from java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportUtilsTest.java rename to java-client/src/test/java/co/elastic/clients/transport/rest5_client/TransportUtilsTest.java index c66b986a2..42efc5d88 100644 --- a/java-client/src/test/java/co/elastic/clients/rest5_client/transport/TransportUtilsTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/TransportUtilsTest.java @@ -17,14 +17,13 @@ * under the License. */ -package co.elastic.clients.rest5_client.transport; +package co.elastic.clients.transport.rest5_client; import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.rest5_client.elasticsearch.ElasticsearchTestServer; +import co.elastic.clients.elasticsearch.ElasticsearchTestServer; import co.elastic.clients.json.SimpleJsonpMapper; import co.elastic.clients.transport.TransportUtils; -import co.elastic.clients.transport.rest5_client.low_level.RestClient; -import co.elastic.clients.transport.rest5_client.RestClientTransport; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.message.BasicHeader; @@ -92,14 +91,14 @@ private void checkConnection(SSLContext sslContext) throws Exception { var creds = Base64.getEncoder().encodeToString("elastic:changeme".getBytes()); - RestClient restClient = RestClient.builder(new HttpHost("https", "localhost", + Rest5Client restClient = Rest5Client.builder(new HttpHost("https", "localhost", container.getMappedPort(9200))) .setSslContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())) .setDefaultHeaders(new Header[]{ new BasicHeader("Authorization", "Basic " + creds) }).build(); - RestClientTransport transport = new RestClientTransport(restClient, SimpleJsonpMapper.INSTANCE); + Rest5ClientTransport transport = new Rest5ClientTransport(restClient, SimpleJsonpMapper.INSTANCE); ElasticsearchClient esClient = new ElasticsearchClient(transport); assertNotNull(esClient.info()); From 8d86780029ab14afc0d83d69b810209cd3e99125 Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Wed, 26 Mar 2025 11:52:04 +0100 Subject: [PATCH 12/38] naming refactor --- .../rest5_client/ElasticsearchClientBuilder.java | 2 +- .../rest5_client/low_level/ResponseException.java | 4 ++-- .../rest5_client/low_level/Rest5Client.java | 8 ++++---- .../rest5_client/low_level/Rest5ClientBuilder.java | 13 ++++++------- .../transport/rest5_client/TransportUtilsTest.java | 2 +- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/rest5_client/ElasticsearchClientBuilder.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/rest5_client/ElasticsearchClientBuilder.java index 736758467..04f25f3b7 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/rest5_client/ElasticsearchClientBuilder.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/rest5_client/ElasticsearchClientBuilder.java @@ -115,7 +115,7 @@ public ElasticsearchClient build() { } try { - restClientBuilder.setSslContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())); + restClientBuilder.setSSLContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseException.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseException.java index 3fa18cb96..019028018 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseException.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseException.java @@ -62,8 +62,8 @@ static String buildMessage(ESResponse response) throws IOException { } try { message += "\n" + EntityUtils.toString(entity); - } catch (ParseException e) { // TODO 99% sure this will never get thrown. can suppress? - throw new RuntimeException("Could not parse headers: " + e); + } catch (ParseException e) { + throw new IOException("Could not parse headers: " + e); } } return message; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java index ec5c9bce7..052c611d7 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java @@ -349,8 +349,8 @@ private ResponseOrResponseException convertResponse(InternalRequest request, Nod Header encoding = null; try { encoding = httpResponse.getHeader(CONTENT_ENCODING); - } catch (ProtocolException e) { // TODO 99% sure this will never get thrown. can suppress? - throw new RuntimeException("Couldn't retrieve content encoding: " + e); + } catch (ProtocolException e) { + throw new IOException("Couldn't retrieve content encoding: " + e); } if (encoding != null && "gzip".equals(encoding.getValue())) { // Decompress and cleanup response headers @@ -677,8 +677,8 @@ private static HttpUriRequestBase addRequestBody(HttpUriRequestBase httpRequest, } private static boolean canHaveBody(HttpRequest httpRequest) { - return httpRequest.getMethod().contains("PUT") || httpRequest.getMethod().contains("POST") || - httpRequest.getMethod().contains("PATCH") || + return httpRequest.getMethod().equals("PUT") || httpRequest.getMethod().equals("POST") || + httpRequest.getMethod().equals("PATCH") || httpRequest instanceof HttpDeleteWithEntity || httpRequest instanceof HttpGetWithEntity; } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5ClientBuilder.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5ClientBuilder.java index b6362147f..9771e5c58 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5ClientBuilder.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5ClientBuilder.java @@ -156,11 +156,12 @@ public final class Rest5ClientBuilder { /** * Advanced setting, sets the rest client that will be used to handle requests. - * The rest client has to be fully configured, as it will be used as provided. + * The rest client has to be fully configured, as it will be used as provided, + * also this will overwrite all builder setters. * * @throws NullPointerException if {@code httpAsyncClient} is {@code null}. */ - public Rest5ClientBuilder setCustomRestClient(CloseableHttpAsyncClient httpAsyncClient) { + public RestClientBuilder setHttpClient(CloseableHttpAsyncClient httpAsyncClient) { Objects.requireNonNull(httpAsyncClient, "custom rest client must not be null"); this.httpClient = httpAsyncClient; return this; @@ -171,7 +172,7 @@ public Rest5ClientBuilder setCustomRestClient(CloseableHttpAsyncClient httpAsync * * @throws NullPointerException if {@code httpAsyncClient} is {@code null}. */ - public Rest5ClientBuilder setSslContext(SSLContext sslContext) { + public RestClientBuilder setSSLContext(SSLContext sslContext) { Objects.requireNonNull(sslContext, "ssl context must not be null"); this.sslContext = sslContext; return this; @@ -344,10 +345,8 @@ private CloseableHttpAsyncClient createHttpClient() { // otherwise, creating a default instance of CloseableHttpAsyncClient // default timeouts are all infinite RequestConfig.Builder requestConfigBuilder = RequestConfig.custom() - //.setConnectionRequestTimeout() new name for socket timeout - .setConnectTimeout(Timeout.of(DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); - //.setSocketTimeout(DEFAULT_SOCKET_TIMEOUT_MILLIS); TODO needed? check discussions, which one we - // should remove + .setConnectionRequestTimeout(Timeout.of(DEFAULT_SOCKET_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) + .setConnectTimeout(Timeout.of(DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); //TODO deprecated need to change try { diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/TransportUtilsTest.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/TransportUtilsTest.java index 42efc5d88..82bbb52e3 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/TransportUtilsTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/TransportUtilsTest.java @@ -93,7 +93,7 @@ private void checkConnection(SSLContext sslContext) throws Exception { Rest5Client restClient = Rest5Client.builder(new HttpHost("https", "localhost", container.getMappedPort(9200))) - .setSslContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())) + .setSSLContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())) .setDefaultHeaders(new Header[]{ new BasicHeader("Authorization", "Basic " + creds) }).build(); From 27c73c2b218d20158139b4cd2d79503ff02824d2 Mon Sep 17 00:00:00 2001 From: Sylvain Wallez Date: Wed, 26 Mar 2025 14:29:00 +0100 Subject: [PATCH 13/38] Add ElasticsearchTestClient that randomly chooses an implementation --- .../low_level/Rest5ClientBuilder.java | 4 +- .../ElasticsearchTestClient.java | 89 +++++++++++++++++++ .../ElasticsearchTestServer.java | 68 +------------- .../spec_issues/SpecIssuesTest.java | 2 +- 4 files changed, 96 insertions(+), 67 deletions(-) create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestClient.java diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5ClientBuilder.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5ClientBuilder.java index 9771e5c58..52a0bf0e4 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5ClientBuilder.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5ClientBuilder.java @@ -161,7 +161,7 @@ public final class Rest5ClientBuilder { * * @throws NullPointerException if {@code httpAsyncClient} is {@code null}. */ - public RestClientBuilder setHttpClient(CloseableHttpAsyncClient httpAsyncClient) { + public Rest5ClientBuilder setHttpClient(CloseableHttpAsyncClient httpAsyncClient) { Objects.requireNonNull(httpAsyncClient, "custom rest client must not be null"); this.httpClient = httpAsyncClient; return this; @@ -172,7 +172,7 @@ public RestClientBuilder setHttpClient(CloseableHttpAsyncClient httpAsyncClient) * * @throws NullPointerException if {@code httpAsyncClient} is {@code null}. */ - public RestClientBuilder setSSLContext(SSLContext sslContext) { + public Rest5ClientBuilder setSSLContext(SSLContext sslContext) { Objects.requireNonNull(sslContext, "ssl context must not be null"); this.sslContext = sslContext; return this; diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestClient.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestClient.java new file mode 100644 index 000000000..2a3c9ca42 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestClient.java @@ -0,0 +1,89 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch; + +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import co.elastic.clients.transport.rest5_client.Rest5ClientTransport; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.message.BasicHeader; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.elasticsearch.client.RestClient; + +import javax.annotation.Nullable; +import javax.net.ssl.SSLContext; +import java.net.URI; +import java.util.Base64; +import java.util.Random; + +public class ElasticsearchTestClient { + + // Same value for all tests in a test run + private static final int RAND = new Random().nextInt(100); + + private static JsonpMapper mapper(JsonpMapper mapper) { + return mapper != null ? mapper : new JsonbJsonpMapper(); + } + + public static ElasticsearchClient createClient(String url, @Nullable JsonpMapper mapper, @Nullable SSLContext sslContext) { + if(RAND % 2 == 0) { + System.out.println("Using a Rest4 client"); + return createRest4Client(url, mapper, sslContext); + } else { + System.out.println("Using a Rest5 client"); + return createRest5Client(url, mapper, sslContext); + } + } + + public static ElasticsearchClient createRest4Client(String url, @Nullable JsonpMapper mapper, @Nullable SSLContext sslContext) { + BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); + credsProv.setCredentials( + AuthScope.ANY, new UsernamePasswordCredentials("elastic", "changeme") + ); + var restClient = RestClient.builder(HttpHost.create(url)) + .setHttpClientConfigCallback(hc -> hc + .setDefaultCredentialsProvider(credsProv) + .setSSLContext(sslContext) + ) + .build(); + var transport = new RestClientTransport(restClient, mapper(mapper)); + return new ElasticsearchClient(transport); + } + + public static ElasticsearchClient createRest5Client(String url, @Nullable JsonpMapper mapper, @Nullable SSLContext sslContext) { + var pwd = Base64.getEncoder().encodeToString("elastic:changeme".getBytes()); + var restClientBuilder = Rest5Client.builder(org.apache.hc.core5.http.HttpHost.create(URI.create(url))) + .setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Basic " + pwd) + }); + + if (sslContext != null) { + restClientBuilder.setSSLContext(sslContext); + } + + var transport = new Rest5ClientTransport(restClientBuilder.build(), mapper(mapper)); + return new ElasticsearchClient(transport); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java index c41e2b3bf..ae16e105c 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java @@ -22,21 +22,10 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.json.JsonData; import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import co.elastic.clients.transport.ElasticsearchTransport; import co.elastic.clients.transport.JsonEndpoint; import co.elastic.clients.transport.Version; import co.elastic.clients.transport.endpoints.DelegatingJsonEndpoint; -import co.elastic.clients.transport.rest_client.RestClientTransport; import org.apache.commons.io.FileUtils; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.message.BasicHeader; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.elasticsearch.client.RestClient; import org.testcontainers.elasticsearch.ElasticsearchContainer; import org.testcontainers.images.builder.ImageFromDockerfile; import org.testcontainers.shaded.org.apache.commons.io.IOUtils; @@ -53,13 +42,12 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Base64; -import java.util.Optional; +import java.util.Random; public class ElasticsearchTestServer implements AutoCloseable { private final String[] plugins; private volatile ElasticsearchContainer container; - private final JsonpMapper mapper = new JsonbJsonpMapper(); private ElasticsearchClient client; private static ElasticsearchTestServer global; @@ -103,55 +91,11 @@ public ElasticsearchTestServer(String... plugins) { this.plugins = plugins; } - public ElasticsearchClient createRest4Client(String url, SSLContext sslContext) { - BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); - credsProv.setCredentials( - AuthScope.ANY, new UsernamePasswordCredentials("elastic", "changeme") - ); - var restClient = RestClient.builder(HttpHost.create(url)) - .setHttpClientConfigCallback(hc -> hc - .setDefaultCredentialsProvider(credsProv) - .setSSLContext(sslContext) - ) - .build(); - var transport = new RestClientTransport(restClient, mapper); - return new ElasticsearchClient(transport); - } - -// protected void setup(String url, SSLContext sslContext) { -// try { -// org.apache.hc.core5.http.HttpHost host = org.apache.hc.core5.http.HttpHost.create(url); -// -// var pwd = Base64.getEncoder().encodeToString("elastic:changeme".getBytes()); -// -// -// restClient = Rest5Client.builder(org.apache.hc.core5.http.HttpHost.create(url)) -// .setSslContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())) -// .setDefaultHeaders(new Header[]{ -// new BasicHeader("Authorization", "Basic " + pwd) -// }) -// //.setCompressionEnabled(true) -// .build(); -// } catch (Exception e) { -// throw new RuntimeException(e); -// } -// transport = new Rest5ClientTransport(restClient, mapper); -// client = new ElasticsearchClient(transport); -// } + // Same value for all tests in a test run + private static final int RAND = new Random().nextInt(100); protected void setup(String url, SSLContext sslContext) { - BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); - credsProv.setCredentials( - AuthScope.ANY, new UsernamePasswordCredentials("elastic", "changeme") - ); - var restClient = RestClient.builder(HttpHost.create(url)) - .setHttpClientConfigCallback(hc -> hc - .setDefaultCredentialsProvider(credsProv) - .setSSLContext(sslContext) - ) - .build(); - var transport = new RestClientTransport(restClient, mapper); - client = new ElasticsearchClient(transport); + this.client = ElasticsearchTestClient.createClient(url, null, sslContext); } private Version selectLatestVersion(Version version, String info) { @@ -300,10 +244,6 @@ public ElasticsearchContainer container() { return this.container; } - public JsonpMapper mapper() { - return mapper; - } - public ElasticsearchClient client() { return client; } diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/spec_issues/SpecIssuesTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/spec_issues/SpecIssuesTest.java index 22fafd85f..f36672b8f 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/spec_issues/SpecIssuesTest.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/spec_issues/SpecIssuesTest.java @@ -302,7 +302,7 @@ public void gettingVersionFromNodes() throws Exception { .nodes().info().nodes().entrySet().forEach(node -> assertNotNull(node.getValue().version())); } - + private T loadRsrc(String res, JsonpDeserializer deser) { InputStream is = this.getClass().getResourceAsStream(res); assertNotNull(is, "Resource not found: " + res); From a37327afe42067526a4f7b88806bd965cdc68a2e Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Wed, 26 Mar 2025 14:33:27 +0100 Subject: [PATCH 14/38] regen from latest spec --- .../elasticsearch/doc-files/api-spec.html | 24 + .../ChatCompletionUnifiedRequest.java | 38 +- .../elasticsearch/inference/EisTaskType.java | 26 + .../PostEisChatCompletionRequest.java | 48 ++ .../inference/PutAlibabacloudRequest.java | 27 + .../inference/PutAmazonbedrockRequest.java | 27 + .../inference/PutAnthropicRequest.java | 27 + .../inference/PutAzureaistudioRequest.java | 27 + .../inference/PutAzureopenaiRequest.java | 27 + .../inference/PutCohereRequest.java | 27 + .../inference/PutElasticsearchRequest.java | 27 + .../inference/PutElserRequest.java | 26 + .../inference/PutGoogleaistudioRequest.java | 26 + .../inference/PutGooglevertexaiRequest.java | 27 + .../inference/PutHuggingFaceRequest.java | 26 + .../inference/PutJinaaiRequest.java | 27 + .../inference/PutMistralRequest.java | 26 + .../inference/RequestChatCompletionBase.java | 461 ++++++++++++++++++ .../AlibabaCloudServiceSettings.java | 344 +++++++++++++ .../AlibabaCloudTaskSettings.java | 218 +++++++++ .../AlibabaCloudTaskType.java | 71 +++ .../put_alibabacloud/ServiceType.java | 65 +++ .../AmazonBedrockServiceSettings.java | 371 ++++++++++++++ .../AmazonBedrockTaskSettings.java | 292 +++++++++++ .../AmazonBedrockTaskType.java | 67 +++ .../put_amazonbedrock/ServiceType.java | 65 +++ .../AnthropicServiceSettings.java | 241 +++++++++ .../put_anthropic/AnthropicTaskSettings.java | 283 +++++++++++ .../put_anthropic/AnthropicTaskType.java | 65 +++ .../inference/put_anthropic/ServiceType.java | 65 +++ .../AzureAiStudioServiceSettings.java | 353 ++++++++++++++ .../AzureAiStudioTaskSettings.java | 320 ++++++++++++ .../AzureAiStudioTaskType.java | 67 +++ .../put_azureaistudio/ServiceType.java | 65 +++ .../AzureOpenAIServiceSettings.java | 368 ++++++++++++++ .../put_azureopenai/AzureOpenAITaskType.java | 67 +++ .../put_azureopenai/ServiceType.java | 65 +++ .../put_cohere/CohereServiceSettings.java | 363 ++++++++++++++ .../put_cohere/CohereTaskSettings.java | 317 ++++++++++++ .../inference/put_cohere/CohereTaskType.java | 69 +++ .../inference/put_cohere/EmbeddingType.java | 69 +++ .../inference/put_cohere/InputType.java | 71 +++ .../inference/put_cohere/ServiceType.java | 65 +++ .../inference/put_cohere/SimilarityType.java | 69 +++ .../inference/put_cohere/TruncateType.java | 69 +++ .../AdaptiveAllocations.java | 236 +++++++++ .../ElasticsearchServiceSettings.java | 342 +++++++++++++ .../ElasticsearchTaskSettings.java | 168 +++++++ .../ElasticsearchTaskType.java | 69 +++ .../put_elasticsearch/ServiceType.java | 65 +++ .../put_elser/AdaptiveAllocations.java | 236 +++++++++ .../put_elser/ElserServiceSettings.java | 280 +++++++++++ .../inference/put_elser/ElserTaskType.java | 65 +++ .../GoogleAiStudioServiceSettings.java | 241 +++++++++ .../GoogleAiStudioTaskType.java | 67 +++ .../put_googleaistudio/ServiceType.java | 65 +++ .../GoogleVertexAIServiceSettings.java | 300 ++++++++++++ .../GoogleVertexAITaskSettings.java | 204 ++++++++ .../GoogleVertexAITaskType.java | 67 +++ .../put_googlevertexai/ServiceType.java | 65 +++ .../HuggingFaceServiceSettings.java | 252 ++++++++++ .../put_hugging_face/HuggingFaceTaskType.java | 65 +++ .../put_hugging_face/ServiceType.java | 65 +++ .../put_jinaai/JinaAIServiceSettings.java | 297 +++++++++++ .../put_jinaai/JinaAITaskSettings.java | 261 ++++++++++ .../inference/put_jinaai/JinaAITaskType.java | 67 +++ .../inference/put_jinaai/ServiceType.java | 65 +++ .../inference/put_jinaai/SimilarityType.java | 69 +++ .../put_jinaai/TextEmbeddingTask.java | 71 +++ .../put_mistral/MistralServiceSettings.java | 289 +++++++++++ .../put_mistral/MistralTaskType.java | 65 +++ .../inference/put_mistral/ServiceType.java | 65 +++ 72 files changed, 9584 insertions(+), 5 deletions(-) create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RequestChatCompletionBase.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAIServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAITaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/EmbeddingType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/InputType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/SimilarityType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/TruncateType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/AdaptiveAllocations.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/AdaptiveAllocations.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAIServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAIServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/SimilarityType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/TextEmbeddingTask.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/ServiceType.java diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/doc-files/api-spec.html b/java-client/src/main/java/co/elastic/clients/elasticsearch/doc-files/api-spec.html index 654a4dd87..b18eab292 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/doc-files/api-spec.html +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/doc-files/api-spec.html @@ -26,7 +26,11 @@ '_global.create.Request': '_global/create/CreateRequest.ts#L35-L221', '_global.create.Response': '_global/create/CreateResponse.ts#L22-L25', '_global.delete.Request': '_global/delete/DeleteRequest.ts#L34-L146', +<<<<<<< HEAD '_global.delete.Response': '_global/delete/DeleteResponse.ts#L22-L35', +======= +'_global.delete.Response': '_global/delete/DeleteResponse.ts#L22-L34', +>>>>>>> 03828daff (regen from latest spec) '_global.delete_by_query.Request': '_global/delete_by_query/DeleteByQueryRequest.ts#L36-L314', '_global.delete_by_query.Response': '_global/delete_by_query/DeleteByQueryResponse.ts#L26-L88', '_global.delete_by_query_rethrottle.Request': '_global/delete_by_query_rethrottle/DeleteByQueryRethrottleRequest.ts#L24-L55', @@ -1808,6 +1812,7 @@ 'inference._types.TextEmbeddingByteResult': 'inference/_types/Results.ts#L53-L58', 'inference._types.TextEmbeddingInferenceResult': 'inference/_types/Results.ts#L67-L75', 'inference._types.TextEmbeddingResult': 'inference/_types/Results.ts#L60-L65', +<<<<<<< HEAD 'inference._types.ToolCall': 'inference/_types/CommonTypes.ts#L112-L128', 'inference._types.ToolCallFunction': 'inference/_types/CommonTypes.ts#L98-L110', 'inference._types.VoyageAIServiceSettings': 'inference/_types/CommonTypes.ts#L1075-L1106', @@ -1819,14 +1824,33 @@ 'inference._types.WatsonxTaskType': 'inference/_types/CommonTypes.ts#L1182-L1184', 'inference.chat_completion_unified.Request': 'inference/chat_completion_unified/UnifiedRequest.ts#L24-L53', 'inference.chat_completion_unified.Response': 'inference/chat_completion_unified/UnifiedResponse.ts#L22-L25', +======= +'inference.chat_completion_unified.CompletionTool': 'inference/chat_completion_unified/UnifiedRequest.ts#L180-L192', +'inference.chat_completion_unified.CompletionToolChoice': 'inference/chat_completion_unified/UnifiedRequest.ts#L143-L155', +'inference.chat_completion_unified.CompletionToolChoiceFunction': 'inference/chat_completion_unified/UnifiedRequest.ts#L132-L141', +'inference.chat_completion_unified.CompletionToolFunction': 'inference/chat_completion_unified/UnifiedRequest.ts#L157-L178', +'inference.chat_completion_unified.CompletionToolType': 'inference/chat_completion_unified/UnifiedRequest.ts#L54-L57', +'inference.chat_completion_unified.ContentObject': 'inference/chat_completion_unified/UnifiedRequest.ts#L59-L71', +'inference.chat_completion_unified.Message': 'inference/chat_completion_unified/UnifiedRequest.ts#L110-L130', +'inference.chat_completion_unified.MessageContent': 'inference/chat_completion_unified/UnifiedRequest.ts#L105-L108', +'inference.chat_completion_unified.Request': 'inference/chat_completion_unified/UnifiedRequest.ts#L25-L52', +'inference.chat_completion_unified.Response': 'inference/chat_completion_unified/UnifiedResponse.ts#L22-L24', +'inference.chat_completion_unified.ToolCall': 'inference/chat_completion_unified/UnifiedRequest.ts#L87-L103', +'inference.chat_completion_unified.ToolCallFunction': 'inference/chat_completion_unified/UnifiedRequest.ts#L73-L85', +>>>>>>> 03828daff (regen from latest spec) 'inference.completion.Request': 'inference/completion/CompletionRequest.ts#L25-L63', 'inference.completion.Response': 'inference/completion/CompletionResponse.ts#L22-L25', 'inference.delete.Request': 'inference/delete/DeleteRequest.ts#L24-L66', 'inference.delete.Response': 'inference/delete/DeleteResponse.ts#L22-L25', 'inference.get.Request': 'inference/get/GetRequest.ts#L24-L56', 'inference.get.Response': 'inference/get/GetResponse.ts#L22-L26', +<<<<<<< HEAD 'inference.post_eis_chat_completion.Request': 'inference/post_eis_chat_completion/PostEisChatCompletionRequest.ts#L23-L48', 'inference.post_eis_chat_completion.Response': 'inference/post_eis_chat_completion/PostEisChatCompletionResponse.ts#L22-L25', +======= +'inference.post_eis_chat_completion.Request': 'inference/post_eis_chat_completion/PostEisChatCompletionRequest.ts#L23-L46', +'inference.post_eis_chat_completion.Response': 'inference/post_eis_chat_completion/PostEisChatCompletionResponse.ts#L22-L24', +>>>>>>> 03828daff (regen from latest spec) 'inference.put.Request': 'inference/put/PutRequest.ts#L25-L65', 'inference.put.Response': 'inference/put/PutResponse.ts#L22-L25', 'inference.put_alibabacloud.Request': 'inference/put_alibabacloud/PutAlibabaCloudRequest.ts#L30-L83', diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ChatCompletionUnifiedRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ChatCompletionUnifiedRequest.java index 4b2bb22e2..08dbfdc7e 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ChatCompletionUnifiedRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ChatCompletionUnifiedRequest.java @@ -20,12 +20,9 @@ package co.elastic.clients.elasticsearch.inference; import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.elasticsearch._types.RequestBase; import co.elastic.clients.elasticsearch._types.Time; import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; import co.elastic.clients.json.ObjectBuilderDeserializer; import co.elastic.clients.json.ObjectDeserializer; import co.elastic.clients.transport.Endpoint; @@ -35,7 +32,10 @@ import co.elastic.clients.util.ApiTypeHelper; import co.elastic.clients.util.ObjectBuilder; import jakarta.json.stream.JsonGenerator; +<<<<<<< HEAD import jakarta.json.stream.JsonParser; +======= +>>>>>>> 03828daff (regen from latest spec) import java.lang.String; import java.util.HashMap; import java.util.Map; @@ -68,22 +68,29 @@ * specification */ @JsonpDeserializable -public class ChatCompletionUnifiedRequest extends RequestBase implements JsonpSerializable { +public class ChatCompletionUnifiedRequest extends RequestChatCompletionBase { private final String inferenceId; @Nullable private final Time timeout; +<<<<<<< HEAD private final RequestChatCompletion chatCompletionRequest; +======= +>>>>>>> 03828daff (regen from latest spec) // --------------------------------------------------------------------------------------------- private ChatCompletionUnifiedRequest(Builder builder) { + super(builder); this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); this.timeout = builder.timeout; +<<<<<<< HEAD this.chatCompletionRequest = ApiTypeHelper.requireNonNull(builder.chatCompletionRequest, this, "chatCompletionRequest"); +======= +>>>>>>> 03828daff (regen from latest spec) } @@ -110,6 +117,7 @@ public final Time timeout() { return this.timeout; } +<<<<<<< HEAD /** * Required - Request body. */ @@ -125,13 +133,15 @@ public void serialize(JsonGenerator generator, JsonpMapper mapper) { } +======= +>>>>>>> 03828daff (regen from latest spec) // --------------------------------------------------------------------------------------------- /** * Builder for {@link ChatCompletionUnifiedRequest}. */ - public static class Builder extends RequestBase.AbstractBuilder + public static class Builder extends RequestChatCompletionBase.AbstractBuilder implements ObjectBuilder { private String inferenceId; @@ -139,8 +149,11 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private Time timeout; +<<<<<<< HEAD private RequestChatCompletion chatCompletionRequest; +======= +>>>>>>> 03828daff (regen from latest spec) /** * Required - The inference Id *

@@ -170,6 +183,7 @@ public final Builder timeout(Function> fn) { return this.timeout(fn.apply(new Time.Builder()).build()); } +<<<<<<< HEAD /** * Required - Request body. */ @@ -195,6 +209,8 @@ public Builder withJson(JsonParser parser, JsonpMapper mapper) { return this.chatCompletionRequest(value); } +======= +>>>>>>> 03828daff (regen from latest spec) @Override protected Builder self() { return this; @@ -216,7 +232,19 @@ public ChatCompletionUnifiedRequest build() { public static final JsonpDeserializer _DESERIALIZER = createChatCompletionUnifiedRequestDeserializer(); protected static JsonpDeserializer createChatCompletionUnifiedRequestDeserializer() { +<<<<<<< HEAD JsonpDeserializer valueDeserializer = RequestChatCompletion._DESERIALIZER; +======= + /** + * Json deserializer for {@link ChatCompletionUnifiedRequest} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, ChatCompletionUnifiedRequest::setupChatCompletionUnifiedRequestDeserializer); + + protected static void setupChatCompletionUnifiedRequestDeserializer( + ObjectDeserializer op) { + RequestChatCompletionBase.setupRequestChatCompletionBaseDeserializer(op); +>>>>>>> 03828daff (regen from latest spec) return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() .chatCompletionRequest(valueDeserializer.deserialize(parser, mapper, event)).build()); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java index e9f2597a9..e86fae2b4 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java @@ -17,7 +17,15 @@ * under the License. */ +<<<<<<< HEAD:java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java package co.elastic.clients.elasticsearch.inference; +======= +<<<<<<<< HEAD:java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/ServiceType.java +package co.elastic.clients.elasticsearch.inference.put_voyageai; +======== +package co.elastic.clients.elasticsearch.inference.put_openai; +>>>>>>>> c86960dc6 (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java +>>>>>>> 03828daff (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java import co.elastic.clients.json.JsonEnum; import co.elastic.clients.json.JsonpDeserializable; @@ -40,12 +48,30 @@ /** * +<<<<<<< HEAD:java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java * @see API * specification */ @JsonpDeserializable public enum EisTaskType implements JsonEnum { ChatCompletion("chat_completion"), +======= + * @see API +======== + * "../../doc-files/api-spec.html#inference.put_openai.ServiceType">API +>>>>>>>> c86960dc6 (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { +<<<<<<<< HEAD:java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/ServiceType.java + Voyageai("voyageai"), +======== + Openai("openai"), +>>>>>>>> c86960dc6 (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java +>>>>>>> 03828daff (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java ; diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PostEisChatCompletionRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PostEisChatCompletionRequest.java index ae994a764..4e9e75981 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PostEisChatCompletionRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PostEisChatCompletionRequest.java @@ -20,11 +20,16 @@ package co.elastic.clients.elasticsearch.inference; import co.elastic.clients.elasticsearch._types.ErrorResponse; +<<<<<<< HEAD import co.elastic.clients.elasticsearch._types.RequestBase; import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; import co.elastic.clients.json.JsonpSerializable; +======= +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +>>>>>>> 03828daff (regen from latest spec) import co.elastic.clients.json.ObjectBuilderDeserializer; import co.elastic.clients.json.ObjectDeserializer; import co.elastic.clients.transport.Endpoint; @@ -34,7 +39,10 @@ import co.elastic.clients.util.ApiTypeHelper; import co.elastic.clients.util.ObjectBuilder; import jakarta.json.stream.JsonGenerator; +<<<<<<< HEAD import jakarta.json.stream.JsonParser; +======= +>>>>>>> 03828daff (regen from latest spec) import java.lang.String; import java.util.Collections; import java.util.HashMap; @@ -71,6 +79,7 @@ * specification */ @JsonpDeserializable +<<<<<<< HEAD public class PostEisChatCompletionRequest extends RequestBase implements JsonpSerializable { private final String eisInferenceId; @@ -83,6 +92,17 @@ private PostEisChatCompletionRequest(Builder builder) { this.eisInferenceId = ApiTypeHelper.requireNonNull(builder.eisInferenceId, this, "eisInferenceId"); this.chatCompletionRequest = ApiTypeHelper.requireNonNull(builder.chatCompletionRequest, this, "chatCompletionRequest"); +======= +public class PostEisChatCompletionRequest extends RequestChatCompletionBase { + private final String eisInferenceId; + + // --------------------------------------------------------------------------------------------- + + private PostEisChatCompletionRequest(Builder builder) { + super(builder); + + this.eisInferenceId = ApiTypeHelper.requireNonNull(builder.eisInferenceId, this, "eisInferenceId"); +>>>>>>> 03828daff (regen from latest spec) } @@ -99,6 +119,7 @@ public final String eisInferenceId() { return this.eisInferenceId; } +<<<<<<< HEAD /** * Required - Request body. */ @@ -114,19 +135,28 @@ public void serialize(JsonGenerator generator, JsonpMapper mapper) { } +======= +>>>>>>> 03828daff (regen from latest spec) // --------------------------------------------------------------------------------------------- /** * Builder for {@link PostEisChatCompletionRequest}. */ +<<<<<<< HEAD public static class Builder extends RequestBase.AbstractBuilder +======= + public static class Builder extends RequestChatCompletionBase.AbstractBuilder +>>>>>>> 03828daff (regen from latest spec) implements ObjectBuilder { private String eisInferenceId; +<<<<<<< HEAD private RequestChatCompletion chatCompletionRequest; +======= +>>>>>>> 03828daff (regen from latest spec) /** * Required - The unique identifier of the inference endpoint. *

@@ -137,6 +167,7 @@ public final Builder eisInferenceId(String value) { return this; } +<<<<<<< HEAD /** * Required - Request body. */ @@ -162,6 +193,8 @@ public Builder withJson(JsonParser parser, JsonpMapper mapper) { return this.chatCompletionRequest(value); } +======= +>>>>>>> 03828daff (regen from latest spec) @Override protected Builder self() { return this; @@ -180,6 +213,7 @@ public PostEisChatCompletionRequest build() { } } +<<<<<<< HEAD public static final JsonpDeserializer _DESERIALIZER = createPostEisChatCompletionRequestDeserializer(); protected static JsonpDeserializer createPostEisChatCompletionRequestDeserializer() { @@ -187,6 +221,20 @@ protected static JsonpDeserializer createPostEisCh return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() .chatCompletionRequest(valueDeserializer.deserialize(parser, mapper, event)).build()); +======= + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PostEisChatCompletionRequest} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, PostEisChatCompletionRequest::setupPostEisChatCompletionRequestDeserializer); + + protected static void setupPostEisChatCompletionRequestDeserializer( + ObjectDeserializer op) { + RequestChatCompletionBase.setupRequestChatCompletionBaseDeserializer(op); + +>>>>>>> 03828daff (regen from latest spec) } // --------------------------------------------------------------------------------------------- diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudRequest.java index c0954788d..9b059126a 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudRequest.java @@ -21,6 +21,13 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_alibabacloud.AlibabaCloudServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_alibabacloud.AlibabaCloudTaskSettings; +import co.elastic.clients.elasticsearch.inference.put_alibabacloud.AlibabaCloudTaskType; +import co.elastic.clients.elasticsearch.inference.put_alibabacloud.ServiceType; +>>>>>>> 03828daff (regen from latest spec) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -84,7 +91,11 @@ public class PutAlibabacloudRequest extends RequestBase implements JsonpSerializ @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD private final AlibabaCloudServiceType service; +======= + private final ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private final AlibabaCloudServiceSettings serviceSettings; @@ -136,7 +147,11 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ +<<<<<<< HEAD public final AlibabaCloudServiceType service() { +======= + public final ServiceType service() { +>>>>>>> 03828daff (regen from latest spec) return this.service; } @@ -213,7 +228,11 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD private AlibabaCloudServiceType service; +======= + private ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private AlibabaCloudServiceSettings serviceSettings; @@ -258,7 +277,11 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(AlibabaCloudServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> 03828daff (regen from latest spec) this.service = value; return this; } @@ -347,7 +370,11 @@ protected static void setupPutAlibabacloudRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD op.add(Builder::service, AlibabaCloudServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> 03828daff (regen from latest spec) op.add(Builder::serviceSettings, AlibabaCloudServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AlibabaCloudTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockRequest.java index 55b01e4bf..abd6b0a12 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockRequest.java @@ -21,6 +21,13 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_amazonbedrock.AmazonBedrockServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_amazonbedrock.AmazonBedrockTaskSettings; +import co.elastic.clients.elasticsearch.inference.put_amazonbedrock.AmazonBedrockTaskType; +import co.elastic.clients.elasticsearch.inference.put_amazonbedrock.ServiceType; +>>>>>>> 03828daff (regen from latest spec) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -93,7 +100,11 @@ public class PutAmazonbedrockRequest extends RequestBase implements JsonpSeriali @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD private final AmazonBedrockServiceType service; +======= + private final ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private final AmazonBedrockServiceSettings serviceSettings; @@ -145,7 +156,11 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ +<<<<<<< HEAD public final AmazonBedrockServiceType service() { +======= + public final ServiceType service() { +>>>>>>> 03828daff (regen from latest spec) return this.service; } @@ -222,7 +237,11 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD private AmazonBedrockServiceType service; +======= + private ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private AmazonBedrockServiceSettings serviceSettings; @@ -267,7 +286,11 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(AmazonBedrockServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> 03828daff (regen from latest spec) this.service = value; return this; } @@ -356,7 +379,11 @@ protected static void setupPutAmazonbedrockRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD op.add(Builder::service, AmazonBedrockServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> 03828daff (regen from latest spec) op.add(Builder::serviceSettings, AmazonBedrockServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AmazonBedrockTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicRequest.java index 2d1507c5e..164826986 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicRequest.java @@ -21,6 +21,13 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_anthropic.AnthropicServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_anthropic.AnthropicTaskSettings; +import co.elastic.clients.elasticsearch.inference.put_anthropic.AnthropicTaskType; +import co.elastic.clients.elasticsearch.inference.put_anthropic.ServiceType; +>>>>>>> 03828daff (regen from latest spec) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -83,7 +90,11 @@ public class PutAnthropicRequest extends RequestBase implements JsonpSerializabl @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD private final AnthropicServiceType service; +======= + private final ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private final AnthropicServiceSettings serviceSettings; @@ -135,7 +146,11 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ +<<<<<<< HEAD public final AnthropicServiceType service() { +======= + public final ServiceType service() { +>>>>>>> 03828daff (regen from latest spec) return this.service; } @@ -213,7 +228,11 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD private AnthropicServiceType service; +======= + private ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private AnthropicServiceSettings serviceSettings; @@ -258,7 +277,11 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(AnthropicServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> 03828daff (regen from latest spec) this.service = value; return this; } @@ -347,7 +370,11 @@ public PutAnthropicRequest build() { protected static void setupPutAnthropicRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD op.add(Builder::service, AnthropicServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> 03828daff (regen from latest spec) op.add(Builder::serviceSettings, AnthropicServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AnthropicTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioRequest.java index 3a0d1ef54..df814fdc3 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioRequest.java @@ -21,6 +21,13 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_azureaistudio.AzureAiStudioServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_azureaistudio.AzureAiStudioTaskSettings; +import co.elastic.clients.elasticsearch.inference.put_azureaistudio.AzureAiStudioTaskType; +import co.elastic.clients.elasticsearch.inference.put_azureaistudio.ServiceType; +>>>>>>> 03828daff (regen from latest spec) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -84,7 +91,11 @@ public class PutAzureaistudioRequest extends RequestBase implements JsonpSeriali @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD private final AzureAiStudioServiceType service; +======= + private final ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private final AzureAiStudioServiceSettings serviceSettings; @@ -136,7 +147,11 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ +<<<<<<< HEAD public final AzureAiStudioServiceType service() { +======= + public final ServiceType service() { +>>>>>>> 03828daff (regen from latest spec) return this.service; } @@ -213,7 +228,11 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD private AzureAiStudioServiceType service; +======= + private ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private AzureAiStudioServiceSettings serviceSettings; @@ -258,7 +277,11 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(AzureAiStudioServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> 03828daff (regen from latest spec) this.service = value; return this; } @@ -347,7 +370,11 @@ protected static void setupPutAzureaistudioRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD op.add(Builder::service, AzureAiStudioServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> 03828daff (regen from latest spec) op.add(Builder::serviceSettings, AzureAiStudioServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AzureAiStudioTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiRequest.java index 9b14d99ec..7d0466626 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiRequest.java @@ -21,6 +21,13 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_azureopenai.AzureOpenAIServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_azureopenai.AzureOpenAITaskSettings; +import co.elastic.clients.elasticsearch.inference.put_azureopenai.AzureOpenAITaskType; +import co.elastic.clients.elasticsearch.inference.put_azureopenai.ServiceType; +>>>>>>> 03828daff (regen from latest spec) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -99,7 +106,11 @@ public class PutAzureopenaiRequest extends RequestBase implements JsonpSerializa @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD private final AzureOpenAIServiceType service; +======= + private final ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private final AzureOpenAIServiceSettings serviceSettings; @@ -151,7 +162,11 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ +<<<<<<< HEAD public final AzureOpenAIServiceType service() { +======= + public final ServiceType service() { +>>>>>>> 03828daff (regen from latest spec) return this.service; } @@ -230,7 +245,11 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD private AzureOpenAIServiceType service; +======= + private ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private AzureOpenAIServiceSettings serviceSettings; @@ -275,7 +294,11 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(AzureOpenAIServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> 03828daff (regen from latest spec) this.service = value; return this; } @@ -365,7 +388,11 @@ public PutAzureopenaiRequest build() { protected static void setupPutAzureopenaiRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD op.add(Builder::service, AzureOpenAIServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> 03828daff (regen from latest spec) op.add(Builder::serviceSettings, AzureOpenAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AzureOpenAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereRequest.java index 26de9cff1..1f89d910e 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereRequest.java @@ -21,6 +21,13 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_cohere.CohereServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_cohere.CohereTaskSettings; +import co.elastic.clients.elasticsearch.inference.put_cohere.CohereTaskType; +import co.elastic.clients.elasticsearch.inference.put_cohere.ServiceType; +>>>>>>> 03828daff (regen from latest spec) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -83,7 +90,11 @@ public class PutCohereRequest extends RequestBase implements JsonpSerializable { private final String cohereInferenceId; +<<<<<<< HEAD private final CohereServiceType service; +======= + private final ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private final CohereServiceSettings serviceSettings; @@ -134,7 +145,11 @@ public final String cohereInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD public final CohereServiceType service() { +======= + public final ServiceType service() { +>>>>>>> 03828daff (regen from latest spec) return this.service; } @@ -211,7 +226,11 @@ public static class Builder extends RequestBase.AbstractBuilder private String cohereInferenceId; +<<<<<<< HEAD private CohereServiceType service; +======= + private ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private CohereServiceSettings serviceSettings; @@ -256,7 +275,11 @@ public final Builder cohereInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(CohereServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> 03828daff (regen from latest spec) this.service = value; return this; } @@ -343,7 +366,11 @@ public PutCohereRequest build() { protected static void setupPutCohereRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD op.add(Builder::service, CohereServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> 03828daff (regen from latest spec) op.add(Builder::serviceSettings, CohereServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, CohereTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchRequest.java index 26747fe1a..3c58201f2 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchRequest.java @@ -21,6 +21,13 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_elasticsearch.ElasticsearchServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_elasticsearch.ElasticsearchTaskSettings; +import co.elastic.clients.elasticsearch.inference.put_elasticsearch.ElasticsearchTaskType; +import co.elastic.clients.elasticsearch.inference.put_elasticsearch.ServiceType; +>>>>>>> 03828daff (regen from latest spec) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -101,7 +108,11 @@ public class PutElasticsearchRequest extends RequestBase implements JsonpSeriali private final String elasticsearchInferenceId; +<<<<<<< HEAD private final ElasticsearchServiceType service; +======= + private final ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private final ElasticsearchServiceSettings serviceSettings; @@ -154,7 +165,11 @@ public final String elasticsearchInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD public final ElasticsearchServiceType service() { +======= + public final ServiceType service() { +>>>>>>> 03828daff (regen from latest spec) return this.service; } @@ -231,7 +246,11 @@ public static class Builder extends RequestBase.AbstractBuilder private String elasticsearchInferenceId; +<<<<<<< HEAD private ElasticsearchServiceType service; +======= + private ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private ElasticsearchServiceSettings serviceSettings; @@ -277,7 +296,11 @@ public final Builder elasticsearchInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(ElasticsearchServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> 03828daff (regen from latest spec) this.service = value; return this; } @@ -366,7 +389,11 @@ protected static void setupPutElasticsearchRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD op.add(Builder::service, ElasticsearchServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> 03828daff (regen from latest spec) op.add(Builder::serviceSettings, ElasticsearchServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, ElasticsearchTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserRequest.java index 8ead10e62..e2d8c821d 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserRequest.java @@ -21,6 +21,12 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_elser.ElserServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_elser.ElserTaskType; +import co.elastic.clients.elasticsearch.inference.put_elser.ServiceType; +>>>>>>> 03828daff (regen from latest spec) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -104,7 +110,11 @@ public class PutElserRequest extends RequestBase implements JsonpSerializable { private final String elserInferenceId; +<<<<<<< HEAD private final ElserServiceType service; +======= + private final ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private final ElserServiceSettings serviceSettings; @@ -151,7 +161,11 @@ public final String elserInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD public final ElserServiceType service() { +======= + public final ServiceType service() { +>>>>>>> 03828daff (regen from latest spec) return this.service; } @@ -209,7 +223,11 @@ public static class Builder extends RequestBase.AbstractBuilder impleme private String elserInferenceId; +<<<<<<< HEAD private ElserServiceType service; +======= + private ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private ElserServiceSettings serviceSettings; @@ -251,7 +269,11 @@ public final Builder elserInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(ElserServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> 03828daff (regen from latest spec) this.service = value; return this; } @@ -317,7 +339,11 @@ public PutElserRequest build() { protected static void setupPutElserRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD op.add(Builder::service, ElserServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> 03828daff (regen from latest spec) op.add(Builder::serviceSettings, ElserServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioRequest.java index fb2949825..e21929848 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioRequest.java @@ -21,6 +21,12 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_googleaistudio.GoogleAiStudioServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_googleaistudio.GoogleAiStudioTaskType; +import co.elastic.clients.elasticsearch.inference.put_googleaistudio.ServiceType; +>>>>>>> 03828daff (regen from latest spec) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -84,7 +90,11 @@ public class PutGoogleaistudioRequest extends RequestBase implements JsonpSerial private final String googleaistudioInferenceId; +<<<<<<< HEAD private final GoogleAiServiceType service; +======= + private final ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private final GoogleAiStudioServiceSettings serviceSettings; @@ -132,7 +142,11 @@ public final String googleaistudioInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD public final GoogleAiServiceType service() { +======= + public final ServiceType service() { +>>>>>>> 03828daff (regen from latest spec) return this.service; } @@ -192,7 +206,11 @@ public static class Builder extends RequestBase.AbstractBuilder private String googleaistudioInferenceId; +<<<<<<< HEAD private GoogleAiServiceType service; +======= + private ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private GoogleAiStudioServiceSettings serviceSettings; @@ -234,7 +252,11 @@ public final Builder googleaistudioInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(GoogleAiServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> 03828daff (regen from latest spec) this.service = value; return this; } @@ -301,7 +323,11 @@ protected static void setupPutGoogleaistudioRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD op.add(Builder::service, GoogleAiServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> 03828daff (regen from latest spec) op.add(Builder::serviceSettings, GoogleAiStudioServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiRequest.java index c491288d4..3892b1c41 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiRequest.java @@ -21,6 +21,13 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_googlevertexai.GoogleVertexAIServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_googlevertexai.GoogleVertexAITaskSettings; +import co.elastic.clients.elasticsearch.inference.put_googlevertexai.GoogleVertexAITaskType; +import co.elastic.clients.elasticsearch.inference.put_googlevertexai.ServiceType; +>>>>>>> 03828daff (regen from latest spec) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -84,7 +91,11 @@ public class PutGooglevertexaiRequest extends RequestBase implements JsonpSerial private final String googlevertexaiInferenceId; +<<<<<<< HEAD private final GoogleVertexAIServiceType service; +======= + private final ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private final GoogleVertexAIServiceSettings serviceSettings; @@ -136,7 +147,11 @@ public final String googlevertexaiInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD public final GoogleVertexAIServiceType service() { +======= + public final ServiceType service() { +>>>>>>> 03828daff (regen from latest spec) return this.service; } @@ -213,7 +228,11 @@ public static class Builder extends RequestBase.AbstractBuilder private String googlevertexaiInferenceId; +<<<<<<< HEAD private GoogleVertexAIServiceType service; +======= + private ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private GoogleVertexAIServiceSettings serviceSettings; @@ -258,7 +277,11 @@ public final Builder googlevertexaiInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(GoogleVertexAIServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> 03828daff (regen from latest spec) this.service = value; return this; } @@ -347,7 +370,11 @@ protected static void setupPutGooglevertexaiRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD op.add(Builder::service, GoogleVertexAIServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> 03828daff (regen from latest spec) op.add(Builder::serviceSettings, GoogleVertexAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, GoogleVertexAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceRequest.java index 3b081c97f..b9978e537 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceRequest.java @@ -21,6 +21,12 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_hugging_face.HuggingFaceServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_hugging_face.HuggingFaceTaskType; +import co.elastic.clients.elasticsearch.inference.put_hugging_face.ServiceType; +>>>>>>> 03828daff (regen from latest spec) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -102,7 +108,11 @@ public class PutHuggingFaceRequest extends RequestBase implements JsonpSerializa private final String huggingfaceInferenceId; +<<<<<<< HEAD private final HuggingFaceServiceType service; +======= + private final ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private final HuggingFaceServiceSettings serviceSettings; @@ -150,7 +160,11 @@ public final String huggingfaceInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD public final HuggingFaceServiceType service() { +======= + public final ServiceType service() { +>>>>>>> 03828daff (regen from latest spec) return this.service; } @@ -210,7 +224,11 @@ public static class Builder extends RequestBase.AbstractBuilder private String huggingfaceInferenceId; +<<<<<<< HEAD private HuggingFaceServiceType service; +======= + private ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private HuggingFaceServiceSettings serviceSettings; @@ -252,7 +270,11 @@ public final Builder huggingfaceInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(HuggingFaceServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> 03828daff (regen from latest spec) this.service = value; return this; } @@ -318,7 +340,11 @@ public PutHuggingFaceRequest build() { protected static void setupPutHuggingFaceRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD op.add(Builder::service, HuggingFaceServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> 03828daff (regen from latest spec) op.add(Builder::serviceSettings, HuggingFaceServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiRequest.java index ab9b47ccb..c53bd766c 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiRequest.java @@ -21,6 +21,13 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_jinaai.JinaAIServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_jinaai.JinaAITaskSettings; +import co.elastic.clients.elasticsearch.inference.put_jinaai.JinaAITaskType; +import co.elastic.clients.elasticsearch.inference.put_jinaai.ServiceType; +>>>>>>> 03828daff (regen from latest spec) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -88,7 +95,11 @@ public class PutJinaaiRequest extends RequestBase implements JsonpSerializable { private final String jinaaiInferenceId; +<<<<<<< HEAD private final JinaAIServiceType service; +======= + private final ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private final JinaAIServiceSettings serviceSettings; @@ -139,7 +150,11 @@ public final String jinaaiInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD public final JinaAIServiceType service() { +======= + public final ServiceType service() { +>>>>>>> 03828daff (regen from latest spec) return this.service; } @@ -216,7 +231,11 @@ public static class Builder extends RequestBase.AbstractBuilder private String jinaaiInferenceId; +<<<<<<< HEAD private JinaAIServiceType service; +======= + private ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private JinaAIServiceSettings serviceSettings; @@ -261,7 +280,11 @@ public final Builder jinaaiInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(JinaAIServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> 03828daff (regen from latest spec) this.service = value; return this; } @@ -348,7 +371,11 @@ public PutJinaaiRequest build() { protected static void setupPutJinaaiRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD op.add(Builder::service, JinaAIServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> 03828daff (regen from latest spec) op.add(Builder::serviceSettings, JinaAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, JinaAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralRequest.java index cde473677..ec74bfc03 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralRequest.java @@ -21,6 +21,12 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_mistral.MistralServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_mistral.MistralTaskType; +import co.elastic.clients.elasticsearch.inference.put_mistral.ServiceType; +>>>>>>> 03828daff (regen from latest spec) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -83,7 +89,11 @@ public class PutMistralRequest extends RequestBase implements JsonpSerializable private final String mistralInferenceId; +<<<<<<< HEAD private final MistralServiceType service; +======= + private final ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private final MistralServiceSettings serviceSettings; @@ -130,7 +140,11 @@ public final String mistralInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD public final MistralServiceType service() { +======= + public final ServiceType service() { +>>>>>>> 03828daff (regen from latest spec) return this.service; } @@ -191,7 +205,11 @@ public static class Builder extends RequestBase.AbstractBuilder private String mistralInferenceId; +<<<<<<< HEAD private MistralServiceType service; +======= + private ServiceType service; +>>>>>>> 03828daff (regen from latest spec) private MistralServiceSettings serviceSettings; @@ -233,7 +251,11 @@ public final Builder mistralInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(MistralServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> 03828daff (regen from latest spec) this.service = value; return this; } @@ -300,7 +322,11 @@ public PutMistralRequest build() { protected static void setupPutMistralRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD op.add(Builder::service, MistralServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> 03828daff (regen from latest spec) op.add(Builder::serviceSettings, MistralServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RequestChatCompletionBase.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RequestChatCompletionBase.java new file mode 100644 index 000000000..1941152d1 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RequestChatCompletionBase.java @@ -0,0 +1,461 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.elasticsearch._types.RequestBase; +import co.elastic.clients.elasticsearch.inference.chat_completion_unified.CompletionTool; +import co.elastic.clients.elasticsearch.inference.chat_completion_unified.CompletionToolType; +import co.elastic.clients.elasticsearch.inference.chat_completion_unified.Message; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Float; +import java.lang.Long; +import java.lang.String; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference._types.RequestChatCompletionBase + +/** + * + * @see API + * specification + */ + +public abstract class RequestChatCompletionBase extends RequestBase implements JsonpSerializable { + private final List messages; + + @Nullable + private final String model; + + @Nullable + private final Long maxCompletionTokens; + + private final List stop; + + @Nullable + private final Float temperature; + + @Nullable + private final CompletionToolType toolChoice; + + private final List tools; + + @Nullable + private final Float topP; + + // --------------------------------------------------------------------------------------------- + + protected RequestChatCompletionBase(AbstractBuilder builder) { + + this.messages = ApiTypeHelper.unmodifiableRequired(builder.messages, this, "messages"); + this.model = builder.model; + this.maxCompletionTokens = builder.maxCompletionTokens; + this.stop = ApiTypeHelper.unmodifiable(builder.stop); + this.temperature = builder.temperature; + this.toolChoice = builder.toolChoice; + this.tools = ApiTypeHelper.unmodifiable(builder.tools); + this.topP = builder.topP; + + } + + /** + * Required - A list of objects representing the conversation. + *

+ * API name: {@code messages} + */ + public final List messages() { + return this.messages; + } + + /** + * The ID of the model to use. + *

+ * API name: {@code model} + */ + @Nullable + public final String model() { + return this.model; + } + + /** + * The upper bound limit for the number of tokens that can be generated for a + * completion request. + *

+ * API name: {@code max_completion_tokens} + */ + @Nullable + public final Long maxCompletionTokens() { + return this.maxCompletionTokens; + } + + /** + * A sequence of strings to control when the model should stop generating + * additional tokens. + *

+ * API name: {@code stop} + */ + public final List stop() { + return this.stop; + } + + /** + * The sampling temperature to use. + *

+ * API name: {@code temperature} + */ + @Nullable + public final Float temperature() { + return this.temperature; + } + + /** + * Controls which tool is called by the model. + *

+ * API name: {@code tool_choice} + */ + @Nullable + public final CompletionToolType toolChoice() { + return this.toolChoice; + } + + /** + * A list of tools that the model can call. + *

+ * API name: {@code tools} + */ + public final List tools() { + return this.tools; + } + + /** + * Nucleus sampling, an alternative to sampling with temperature. + *

+ * API name: {@code top_p} + */ + @Nullable + public final Float topP() { + return this.topP; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (ApiTypeHelper.isDefined(this.messages)) { + generator.writeKey("messages"); + generator.writeStartArray(); + for (Message item0 : this.messages) { + item0.serialize(generator, mapper); + + } + generator.writeEnd(); + + } + if (this.model != null) { + generator.writeKey("model"); + generator.write(this.model); + + } + if (this.maxCompletionTokens != null) { + generator.writeKey("max_completion_tokens"); + generator.write(this.maxCompletionTokens); + + } + if (ApiTypeHelper.isDefined(this.stop)) { + generator.writeKey("stop"); + generator.writeStartArray(); + for (String item0 : this.stop) { + generator.write(item0); + + } + generator.writeEnd(); + + } + if (this.temperature != null) { + generator.writeKey("temperature"); + generator.write(this.temperature); + + } + if (this.toolChoice != null) { + generator.writeKey("tool_choice"); + this.toolChoice.serialize(generator, mapper); + + } + if (ApiTypeHelper.isDefined(this.tools)) { + generator.writeKey("tools"); + generator.writeStartArray(); + for (CompletionTool item0 : this.tools) { + item0.serialize(generator, mapper); + + } + generator.writeEnd(); + + } + if (this.topP != null) { + generator.writeKey("top_p"); + generator.write(this.topP); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + public abstract static class AbstractBuilder> + extends + RequestBase.AbstractBuilder { + private List messages; + + @Nullable + private String model; + + @Nullable + private Long maxCompletionTokens; + + @Nullable + private List stop; + + @Nullable + private Float temperature; + + @Nullable + private CompletionToolType toolChoice; + + @Nullable + private List tools; + + @Nullable + private Float topP; + + /** + * Required - A list of objects representing the conversation. + *

+ * API name: {@code messages} + *

+ * Adds all elements of list to messages. + */ + public final BuilderT messages(List list) { + this.messages = _listAddAll(this.messages, list); + return self(); + } + + /** + * Required - A list of objects representing the conversation. + *

+ * API name: {@code messages} + *

+ * Adds one or more values to messages. + */ + public final BuilderT messages(Message value, Message... values) { + this.messages = _listAdd(this.messages, value, values); + return self(); + } + + /** + * Required - A list of objects representing the conversation. + *

+ * API name: {@code messages} + *

+ * Adds a value to messages using a builder lambda. + */ + public final BuilderT messages(Function> fn) { + return messages(fn.apply(new Message.Builder()).build()); + } + + /** + * The ID of the model to use. + *

+ * API name: {@code model} + */ + public final BuilderT model(@Nullable String value) { + this.model = value; + return self(); + } + + /** + * The upper bound limit for the number of tokens that can be generated for a + * completion request. + *

+ * API name: {@code max_completion_tokens} + */ + public final BuilderT maxCompletionTokens(@Nullable Long value) { + this.maxCompletionTokens = value; + return self(); + } + + /** + * A sequence of strings to control when the model should stop generating + * additional tokens. + *

+ * API name: {@code stop} + *

+ * Adds all elements of list to stop. + */ + public final BuilderT stop(List list) { + this.stop = _listAddAll(this.stop, list); + return self(); + } + + /** + * A sequence of strings to control when the model should stop generating + * additional tokens. + *

+ * API name: {@code stop} + *

+ * Adds one or more values to stop. + */ + public final BuilderT stop(String value, String... values) { + this.stop = _listAdd(this.stop, value, values); + return self(); + } + + /** + * The sampling temperature to use. + *

+ * API name: {@code temperature} + */ + public final BuilderT temperature(@Nullable Float value) { + this.temperature = value; + return self(); + } + + /** + * Controls which tool is called by the model. + *

+ * API name: {@code tool_choice} + */ + public final BuilderT toolChoice(@Nullable CompletionToolType value) { + this.toolChoice = value; + return self(); + } + + /** + * Controls which tool is called by the model. + *

+ * API name: {@code tool_choice} + */ + public final BuilderT toolChoice(Function> fn) { + return this.toolChoice(fn.apply(new CompletionToolType.Builder()).build()); + } + + /** + * A list of tools that the model can call. + *

+ * API name: {@code tools} + *

+ * Adds all elements of list to tools. + */ + public final BuilderT tools(List list) { + this.tools = _listAddAll(this.tools, list); + return self(); + } + + /** + * A list of tools that the model can call. + *

+ * API name: {@code tools} + *

+ * Adds one or more values to tools. + */ + public final BuilderT tools(CompletionTool value, CompletionTool... values) { + this.tools = _listAdd(this.tools, value, values); + return self(); + } + + /** + * A list of tools that the model can call. + *

+ * API name: {@code tools} + *

+ * Adds a value to tools using a builder lambda. + */ + public final BuilderT tools(Function> fn) { + return tools(fn.apply(new CompletionTool.Builder()).build()); + } + + /** + * Nucleus sampling, an alternative to sampling with temperature. + *

+ * API name: {@code top_p} + */ + public final BuilderT topP(@Nullable Float value) { + this.topP = value; + return self(); + } + + protected abstract BuilderT self(); + + } + + // --------------------------------------------------------------------------------------------- + protected static > void setupRequestChatCompletionBaseDeserializer( + ObjectDeserializer op) { + + op.add(AbstractBuilder::messages, JsonpDeserializer.arrayDeserializer(Message._DESERIALIZER), "messages"); + op.add(AbstractBuilder::model, JsonpDeserializer.stringDeserializer(), "model"); + op.add(AbstractBuilder::maxCompletionTokens, JsonpDeserializer.longDeserializer(), "max_completion_tokens"); + op.add(AbstractBuilder::stop, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), + "stop"); + op.add(AbstractBuilder::temperature, JsonpDeserializer.floatDeserializer(), "temperature"); + op.add(AbstractBuilder::toolChoice, CompletionToolType._DESERIALIZER, "tool_choice"); + op.add(AbstractBuilder::tools, JsonpDeserializer.arrayDeserializer(CompletionTool._DESERIALIZER), "tools"); + op.add(AbstractBuilder::topP, JsonpDeserializer.floatDeserializer(), "top_p"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudServiceSettings.java new file mode 100644 index 000000000..55d8c7ef9 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudServiceSettings.java @@ -0,0 +1,344 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_alibabacloud; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_alibabacloud.AlibabaCloudServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AlibabaCloudServiceSettings implements JsonpSerializable { + private final String apiKey; + + private final String host; + + @Nullable + private final RateLimitSetting rateLimit; + + private final String serviceId; + + private final String workspace; + + // --------------------------------------------------------------------------------------------- + + private AlibabaCloudServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.host = ApiTypeHelper.requireNonNull(builder.host, this, "host"); + this.rateLimit = builder.rateLimit; + this.serviceId = ApiTypeHelper.requireNonNull(builder.serviceId, this, "serviceId"); + this.workspace = ApiTypeHelper.requireNonNull(builder.workspace, this, "workspace"); + + } + + public static AlibabaCloudServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid API key for the AlibabaCloud AI Search API. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * Required - The name of the host address used for the inference task. You can + * find the host address in the API keys section of the documentation. + *

+ * API name: {@code host} + */ + public final String host() { + return this.host; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * AlibabaCloud AI Search. By default, the alibabacloud-ai-search + * service sets the number of requests allowed per minute to 1000. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Required - The name of the model service to use for the inference task. The + * following service IDs are available for the completion task: + *

    + *
  • ops-qwen-turbo
  • + *
  • qwen-turbo
  • + *
  • qwen-plus
  • + *
  • qwen-max ÷ qwen-max-longcontext
  • + *
+ *

+ * The following service ID is available for the rerank task: + *

    + *
  • ops-bge-reranker-larger
  • + *
+ *

+ * The following service ID is available for the sparse_embedding + * task: + *

    + *
  • ops-text-sparse-embedding-001
  • + *
+ *

+ * The following service IDs are available for the text_embedding + * task: + *

+ * ops-text-embedding-001 ops-text-embedding-zh-001 + * ops-text-embedding-en-001 ops-text-embedding-002 + *

+ * API name: {@code service_id} + */ + public final String serviceId() { + return this.serviceId; + } + + /** + * Required - The name of the workspace used for the inference task. + *

+ * API name: {@code workspace} + */ + public final String workspace() { + return this.workspace; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + generator.writeKey("host"); + generator.write(this.host); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + generator.writeKey("service_id"); + generator.write(this.serviceId); + + generator.writeKey("workspace"); + generator.write(this.workspace); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AlibabaCloudServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + private String host; + + @Nullable + private RateLimitSetting rateLimit; + + private String serviceId; + + private String workspace; + + /** + * Required - A valid API key for the AlibabaCloud AI Search API. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * Required - The name of the host address used for the inference task. You can + * find the host address in the API keys section of the documentation. + *

+ * API name: {@code host} + */ + public final Builder host(String value) { + this.host = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * AlibabaCloud AI Search. By default, the alibabacloud-ai-search + * service sets the number of requests allowed per minute to 1000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * AlibabaCloud AI Search. By default, the alibabacloud-ai-search + * service sets the number of requests allowed per minute to 1000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * Required - The name of the model service to use for the inference task. The + * following service IDs are available for the completion task: + *

    + *
  • ops-qwen-turbo
  • + *
  • qwen-turbo
  • + *
  • qwen-plus
  • + *
  • qwen-max ÷ qwen-max-longcontext
  • + *
+ *

+ * The following service ID is available for the rerank task: + *

    + *
  • ops-bge-reranker-larger
  • + *
+ *

+ * The following service ID is available for the sparse_embedding + * task: + *

    + *
  • ops-text-sparse-embedding-001
  • + *
+ *

+ * The following service IDs are available for the text_embedding + * task: + *

+ * ops-text-embedding-001 ops-text-embedding-zh-001 + * ops-text-embedding-en-001 ops-text-embedding-002 + *

+ * API name: {@code service_id} + */ + public final Builder serviceId(String value) { + this.serviceId = value; + return this; + } + + /** + * Required - The name of the workspace used for the inference task. + *

+ * API name: {@code workspace} + */ + public final Builder workspace(String value) { + this.workspace = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AlibabaCloudServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AlibabaCloudServiceSettings build() { + _checkSingleUse(); + + return new AlibabaCloudServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AlibabaCloudServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AlibabaCloudServiceSettings::setupAlibabaCloudServiceSettingsDeserializer); + + protected static void setupAlibabaCloudServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::host, JsonpDeserializer.stringDeserializer(), "host"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::serviceId, JsonpDeserializer.stringDeserializer(), "service_id"); + op.add(Builder::workspace, JsonpDeserializer.stringDeserializer(), "workspace"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskSettings.java new file mode 100644 index 000000000..288d3e0d1 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskSettings.java @@ -0,0 +1,218 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_alibabacloud; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_alibabacloud.AlibabaCloudTaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AlibabaCloudTaskSettings implements JsonpSerializable { + @Nullable + private final String inputType; + + @Nullable + private final Boolean returnToken; + + // --------------------------------------------------------------------------------------------- + + private AlibabaCloudTaskSettings(Builder builder) { + + this.inputType = builder.inputType; + this.returnToken = builder.returnToken; + + } + + public static AlibabaCloudTaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * For a sparse_embedding or text_embedding task, + * specify the type of input passed to the model. Valid values are: + *

    + *
  • ingest for storing document embeddings in a vector + * database.
  • + *
  • search for storing embeddings of search queries run against + * a vector database to find relevant documents.
  • + *
+ *

+ * API name: {@code input_type} + */ + @Nullable + public final String inputType() { + return this.inputType; + } + + /** + * For a sparse_embedding task, it affects whether the token name + * will be returned in the response. It defaults to false, which + * means only the token ID will be returned in the response. + *

+ * API name: {@code return_token} + */ + @Nullable + public final Boolean returnToken() { + return this.returnToken; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.inputType != null) { + generator.writeKey("input_type"); + generator.write(this.inputType); + + } + if (this.returnToken != null) { + generator.writeKey("return_token"); + generator.write(this.returnToken); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AlibabaCloudTaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private String inputType; + + @Nullable + private Boolean returnToken; + + /** + * For a sparse_embedding or text_embedding task, + * specify the type of input passed to the model. Valid values are: + *

    + *
  • ingest for storing document embeddings in a vector + * database.
  • + *
  • search for storing embeddings of search queries run against + * a vector database to find relevant documents.
  • + *
+ *

+ * API name: {@code input_type} + */ + public final Builder inputType(@Nullable String value) { + this.inputType = value; + return this; + } + + /** + * For a sparse_embedding task, it affects whether the token name + * will be returned in the response. It defaults to false, which + * means only the token ID will be returned in the response. + *

+ * API name: {@code return_token} + */ + public final Builder returnToken(@Nullable Boolean value) { + this.returnToken = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AlibabaCloudTaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AlibabaCloudTaskSettings build() { + _checkSingleUse(); + + return new AlibabaCloudTaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AlibabaCloudTaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AlibabaCloudTaskSettings::setupAlibabaCloudTaskSettingsDeserializer); + + protected static void setupAlibabaCloudTaskSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::inputType, JsonpDeserializer.stringDeserializer(), "input_type"); + op.add(Builder::returnToken, JsonpDeserializer.booleanDeserializer(), "return_token"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskType.java new file mode 100644 index 000000000..8adf946a1 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskType.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_alibabacloud; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum AlibabaCloudTaskType implements JsonEnum { + Completion("completion"), + + Rerank("rerank"), + + SpaceEmbedding("space_embedding"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + AlibabaCloudTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + AlibabaCloudTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/ServiceType.java new file mode 100644 index 000000000..010f0bfdf --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_alibabacloud; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + AlibabacloudAiSearch("alibabacloud-ai-search"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockServiceSettings.java new file mode 100644 index 000000000..06417819f --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockServiceSettings.java @@ -0,0 +1,371 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_amazonbedrock; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_amazonbedrock.AmazonBedrockServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AmazonBedrockServiceSettings implements JsonpSerializable { + private final String accessKey; + + private final String model; + + @Nullable + private final String provider; + + private final String region; + + @Nullable + private final RateLimitSetting rateLimit; + + private final String secretKey; + + // --------------------------------------------------------------------------------------------- + + private AmazonBedrockServiceSettings(Builder builder) { + + this.accessKey = ApiTypeHelper.requireNonNull(builder.accessKey, this, "accessKey"); + this.model = ApiTypeHelper.requireNonNull(builder.model, this, "model"); + this.provider = builder.provider; + this.region = ApiTypeHelper.requireNonNull(builder.region, this, "region"); + this.rateLimit = builder.rateLimit; + this.secretKey = ApiTypeHelper.requireNonNull(builder.secretKey, this, "secretKey"); + + } + + public static AmazonBedrockServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid AWS access key that has permissions to use Amazon Bedrock + * and access to models for inference requests. + *

+ * API name: {@code access_key} + */ + public final String accessKey() { + return this.accessKey; + } + + /** + * Required - The base model ID or an ARN to a custom model based on a + * foundational model. The base model IDs can be found in the Amazon Bedrock + * documentation. Note that the model ID must be available for the provider + * chosen and your IAM user must have access to the model. + *

+ * API name: {@code model} + */ + public final String model() { + return this.model; + } + + /** + * The model provider for your deployment. Note that some providers may support + * only certain task types. Supported providers include: + *

    + *
  • amazontitan - available for text_embedding and + * completion task types
  • + *
  • anthropic - available for completion task type + * only
  • + *
  • ai21labs - available for completion task type + * only
  • + *
  • cohere - available for text_embedding and + * completion task types
  • + *
  • meta - available for completion task type + * only
  • + *
  • mistral - available for completion task type + * only
  • + *
+ *

+ * API name: {@code provider} + */ + @Nullable + public final String provider() { + return this.provider; + } + + /** + * Required - The region that your model or ARN is deployed in. The list of + * available regions per model can be found in the Amazon Bedrock documentation. + *

+ * API name: {@code region} + */ + public final String region() { + return this.region; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Watsonx. By default, the watsonxai service sets the number of + * requests allowed per minute to 120. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Required - A valid AWS secret key that is paired with the + * access_key. For informationg about creating and managing access + * and secret keys, refer to the AWS documentation. + *

+ * API name: {@code secret_key} + */ + public final String secretKey() { + return this.secretKey; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("access_key"); + generator.write(this.accessKey); + + generator.writeKey("model"); + generator.write(this.model); + + if (this.provider != null) { + generator.writeKey("provider"); + generator.write(this.provider); + + } + generator.writeKey("region"); + generator.write(this.region); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + generator.writeKey("secret_key"); + generator.write(this.secretKey); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AmazonBedrockServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String accessKey; + + private String model; + + @Nullable + private String provider; + + private String region; + + @Nullable + private RateLimitSetting rateLimit; + + private String secretKey; + + /** + * Required - A valid AWS access key that has permissions to use Amazon Bedrock + * and access to models for inference requests. + *

+ * API name: {@code access_key} + */ + public final Builder accessKey(String value) { + this.accessKey = value; + return this; + } + + /** + * Required - The base model ID or an ARN to a custom model based on a + * foundational model. The base model IDs can be found in the Amazon Bedrock + * documentation. Note that the model ID must be available for the provider + * chosen and your IAM user must have access to the model. + *

+ * API name: {@code model} + */ + public final Builder model(String value) { + this.model = value; + return this; + } + + /** + * The model provider for your deployment. Note that some providers may support + * only certain task types. Supported providers include: + *

    + *
  • amazontitan - available for text_embedding and + * completion task types
  • + *
  • anthropic - available for completion task type + * only
  • + *
  • ai21labs - available for completion task type + * only
  • + *
  • cohere - available for text_embedding and + * completion task types
  • + *
  • meta - available for completion task type + * only
  • + *
  • mistral - available for completion task type + * only
  • + *
+ *

+ * API name: {@code provider} + */ + public final Builder provider(@Nullable String value) { + this.provider = value; + return this; + } + + /** + * Required - The region that your model or ARN is deployed in. The list of + * available regions per model can be found in the Amazon Bedrock documentation. + *

+ * API name: {@code region} + */ + public final Builder region(String value) { + this.region = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Watsonx. By default, the watsonxai service sets the number of + * requests allowed per minute to 120. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Watsonx. By default, the watsonxai service sets the number of + * requests allowed per minute to 120. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * Required - A valid AWS secret key that is paired with the + * access_key. For informationg about creating and managing access + * and secret keys, refer to the AWS documentation. + *

+ * API name: {@code secret_key} + */ + public final Builder secretKey(String value) { + this.secretKey = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AmazonBedrockServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AmazonBedrockServiceSettings build() { + _checkSingleUse(); + + return new AmazonBedrockServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AmazonBedrockServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AmazonBedrockServiceSettings::setupAmazonBedrockServiceSettingsDeserializer); + + protected static void setupAmazonBedrockServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::accessKey, JsonpDeserializer.stringDeserializer(), "access_key"); + op.add(Builder::model, JsonpDeserializer.stringDeserializer(), "model"); + op.add(Builder::provider, JsonpDeserializer.stringDeserializer(), "provider"); + op.add(Builder::region, JsonpDeserializer.stringDeserializer(), "region"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::secretKey, JsonpDeserializer.stringDeserializer(), "secret_key"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskSettings.java new file mode 100644 index 000000000..3ada2fc38 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskSettings.java @@ -0,0 +1,292 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_amazonbedrock; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Float; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_amazonbedrock.AmazonBedrockTaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AmazonBedrockTaskSettings implements JsonpSerializable { + @Nullable + private final Integer maxNewTokens; + + @Nullable + private final Float temperature; + + @Nullable + private final Float topK; + + @Nullable + private final Float topP; + + // --------------------------------------------------------------------------------------------- + + private AmazonBedrockTaskSettings(Builder builder) { + + this.maxNewTokens = builder.maxNewTokens; + this.temperature = builder.temperature; + this.topK = builder.topK; + this.topP = builder.topP; + + } + + public static AmazonBedrockTaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * For a completion task, it sets the maximum number for the output + * tokens to be generated. + *

+ * API name: {@code max_new_tokens} + */ + @Nullable + public final Integer maxNewTokens() { + return this.maxNewTokens; + } + + /** + * For a completion task, it is a number between 0.0 and 1.0 that + * controls the apparent creativity of the results. At temperature 0.0 the model + * is most deterministic, at temperature 1.0 most random. It should not be used + * if top_p or top_k is specified. + *

+ * API name: {@code temperature} + */ + @Nullable + public final Float temperature() { + return this.temperature; + } + + /** + * For a completion task, it limits samples to the top-K most + * likely words, balancing coherence and variability. It is only available for + * anthropic, cohere, and mistral providers. It is an alternative to + * temperature; it should not be used if temperature + * is specified. + *

+ * API name: {@code top_k} + */ + @Nullable + public final Float topK() { + return this.topK; + } + + /** + * For a completion task, it is a number in the range of 0.0 to + * 1.0, to eliminate low-probability tokens. Top-p uses nucleus sampling to + * select top tokens whose sum of likelihoods does not exceed a certain value, + * ensuring both variety and coherence. It is an alternative to + * temperature; it should not be used if temperature + * is specified. + *

+ * API name: {@code top_p} + */ + @Nullable + public final Float topP() { + return this.topP; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.maxNewTokens != null) { + generator.writeKey("max_new_tokens"); + generator.write(this.maxNewTokens); + + } + if (this.temperature != null) { + generator.writeKey("temperature"); + generator.write(this.temperature); + + } + if (this.topK != null) { + generator.writeKey("top_k"); + generator.write(this.topK); + + } + if (this.topP != null) { + generator.writeKey("top_p"); + generator.write(this.topP); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AmazonBedrockTaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private Integer maxNewTokens; + + @Nullable + private Float temperature; + + @Nullable + private Float topK; + + @Nullable + private Float topP; + + /** + * For a completion task, it sets the maximum number for the output + * tokens to be generated. + *

+ * API name: {@code max_new_tokens} + */ + public final Builder maxNewTokens(@Nullable Integer value) { + this.maxNewTokens = value; + return this; + } + + /** + * For a completion task, it is a number between 0.0 and 1.0 that + * controls the apparent creativity of the results. At temperature 0.0 the model + * is most deterministic, at temperature 1.0 most random. It should not be used + * if top_p or top_k is specified. + *

+ * API name: {@code temperature} + */ + public final Builder temperature(@Nullable Float value) { + this.temperature = value; + return this; + } + + /** + * For a completion task, it limits samples to the top-K most + * likely words, balancing coherence and variability. It is only available for + * anthropic, cohere, and mistral providers. It is an alternative to + * temperature; it should not be used if temperature + * is specified. + *

+ * API name: {@code top_k} + */ + public final Builder topK(@Nullable Float value) { + this.topK = value; + return this; + } + + /** + * For a completion task, it is a number in the range of 0.0 to + * 1.0, to eliminate low-probability tokens. Top-p uses nucleus sampling to + * select top tokens whose sum of likelihoods does not exceed a certain value, + * ensuring both variety and coherence. It is an alternative to + * temperature; it should not be used if temperature + * is specified. + *

+ * API name: {@code top_p} + */ + public final Builder topP(@Nullable Float value) { + this.topP = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AmazonBedrockTaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AmazonBedrockTaskSettings build() { + _checkSingleUse(); + + return new AmazonBedrockTaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AmazonBedrockTaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AmazonBedrockTaskSettings::setupAmazonBedrockTaskSettingsDeserializer); + + protected static void setupAmazonBedrockTaskSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::maxNewTokens, JsonpDeserializer.integerDeserializer(), "max_new_tokens"); + op.add(Builder::temperature, JsonpDeserializer.floatDeserializer(), "temperature"); + op.add(Builder::topK, JsonpDeserializer.floatDeserializer(), "top_k"); + op.add(Builder::topP, JsonpDeserializer.floatDeserializer(), "top_p"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskType.java new file mode 100644 index 000000000..67d56cc4f --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskType.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_amazonbedrock; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum AmazonBedrockTaskType implements JsonEnum { + Completion("completion"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + AmazonBedrockTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + AmazonBedrockTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/ServiceType.java new file mode 100644 index 000000000..417d4e7c7 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_amazonbedrock; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Amazonbedrock("amazonbedrock"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicServiceSettings.java new file mode 100644 index 000000000..fd1133481 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicServiceSettings.java @@ -0,0 +1,241 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_anthropic; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_anthropic.AnthropicServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AnthropicServiceSettings implements JsonpSerializable { + private final String apiKey; + + private final String modelId; + + @Nullable + private final RateLimitSetting rateLimit; + + // --------------------------------------------------------------------------------------------- + + private AnthropicServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); + this.rateLimit = builder.rateLimit; + + } + + public static AnthropicServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid API key for the Anthropic API. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * Anthropic documentation for the list of supported models. + *

+ * API name: {@code model_id} + */ + public final String modelId() { + return this.modelId; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Anthropic. By default, the anthropic service sets the number of + * requests allowed per minute to 50. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + generator.writeKey("model_id"); + generator.write(this.modelId); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AnthropicServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + private String modelId; + + @Nullable + private RateLimitSetting rateLimit; + + /** + * Required - A valid API key for the Anthropic API. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * Anthropic documentation for the list of supported models. + *

+ * API name: {@code model_id} + */ + public final Builder modelId(String value) { + this.modelId = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Anthropic. By default, the anthropic service sets the number of + * requests allowed per minute to 50. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Anthropic. By default, the anthropic service sets the number of + * requests allowed per minute to 50. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AnthropicServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AnthropicServiceSettings build() { + _checkSingleUse(); + + return new AnthropicServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AnthropicServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AnthropicServiceSettings::setupAnthropicServiceSettingsDeserializer); + + protected static void setupAnthropicServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskSettings.java new file mode 100644 index 000000000..cababb804 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskSettings.java @@ -0,0 +1,283 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_anthropic; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Float; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_anthropic.AnthropicTaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AnthropicTaskSettings implements JsonpSerializable { + private final int maxTokens; + + @Nullable + private final Float temperature; + + @Nullable + private final Integer topK; + + @Nullable + private final Float topP; + + // --------------------------------------------------------------------------------------------- + + private AnthropicTaskSettings(Builder builder) { + + this.maxTokens = ApiTypeHelper.requireNonNull(builder.maxTokens, this, "maxTokens"); + this.temperature = builder.temperature; + this.topK = builder.topK; + this.topP = builder.topP; + + } + + public static AnthropicTaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - For a completion task, it is the maximum number of + * tokens to generate before stopping. + *

+ * API name: {@code max_tokens} + */ + public final int maxTokens() { + return this.maxTokens; + } + + /** + * For a completion task, it is the amount of randomness injected + * into the response. For more details about the supported range, refer to + * Anthropic documentation. + *

+ * API name: {@code temperature} + */ + @Nullable + public final Float temperature() { + return this.temperature; + } + + /** + * For a completion task, it specifies to only sample from the top + * K options for each subsequent token. It is recommended for advanced use cases + * only. You usually only need to use temperature. + *

+ * API name: {@code top_k} + */ + @Nullable + public final Integer topK() { + return this.topK; + } + + /** + * For a completion task, it specifies to use Anthropic's nucleus + * sampling. In nucleus sampling, Anthropic computes the cumulative distribution + * over all the options for each subsequent token in decreasing probability + * order and cuts it off once it reaches the specified probability. You should + * either alter temperature or top_p, but not both. It + * is recommended for advanced use cases only. You usually only need to use + * temperature. + *

+ * API name: {@code top_p} + */ + @Nullable + public final Float topP() { + return this.topP; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("max_tokens"); + generator.write(this.maxTokens); + + if (this.temperature != null) { + generator.writeKey("temperature"); + generator.write(this.temperature); + + } + if (this.topK != null) { + generator.writeKey("top_k"); + generator.write(this.topK); + + } + if (this.topP != null) { + generator.writeKey("top_p"); + generator.write(this.topP); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AnthropicTaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private Integer maxTokens; + + @Nullable + private Float temperature; + + @Nullable + private Integer topK; + + @Nullable + private Float topP; + + /** + * Required - For a completion task, it is the maximum number of + * tokens to generate before stopping. + *

+ * API name: {@code max_tokens} + */ + public final Builder maxTokens(int value) { + this.maxTokens = value; + return this; + } + + /** + * For a completion task, it is the amount of randomness injected + * into the response. For more details about the supported range, refer to + * Anthropic documentation. + *

+ * API name: {@code temperature} + */ + public final Builder temperature(@Nullable Float value) { + this.temperature = value; + return this; + } + + /** + * For a completion task, it specifies to only sample from the top + * K options for each subsequent token. It is recommended for advanced use cases + * only. You usually only need to use temperature. + *

+ * API name: {@code top_k} + */ + public final Builder topK(@Nullable Integer value) { + this.topK = value; + return this; + } + + /** + * For a completion task, it specifies to use Anthropic's nucleus + * sampling. In nucleus sampling, Anthropic computes the cumulative distribution + * over all the options for each subsequent token in decreasing probability + * order and cuts it off once it reaches the specified probability. You should + * either alter temperature or top_p, but not both. It + * is recommended for advanced use cases only. You usually only need to use + * temperature. + *

+ * API name: {@code top_p} + */ + public final Builder topP(@Nullable Float value) { + this.topP = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AnthropicTaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AnthropicTaskSettings build() { + _checkSingleUse(); + + return new AnthropicTaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AnthropicTaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AnthropicTaskSettings::setupAnthropicTaskSettingsDeserializer); + + protected static void setupAnthropicTaskSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::maxTokens, JsonpDeserializer.integerDeserializer(), "max_tokens"); + op.add(Builder::temperature, JsonpDeserializer.floatDeserializer(), "temperature"); + op.add(Builder::topK, JsonpDeserializer.integerDeserializer(), "top_k"); + op.add(Builder::topP, JsonpDeserializer.floatDeserializer(), "top_p"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskType.java new file mode 100644 index 000000000..4599e9d31 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_anthropic; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum AnthropicTaskType implements JsonEnum { + Completion("completion"), + + ; + + private final String jsonValue; + + AnthropicTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + AnthropicTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/ServiceType.java new file mode 100644 index 000000000..2d6288747 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_anthropic; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Anthropic("anthropic"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioServiceSettings.java new file mode 100644 index 000000000..a407ad66b --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioServiceSettings.java @@ -0,0 +1,353 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_azureaistudio; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_azureaistudio.AzureAiStudioServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AzureAiStudioServiceSettings implements JsonpSerializable { + private final String apiKey; + + private final String endpointType; + + private final String target; + + private final String provider; + + @Nullable + private final RateLimitSetting rateLimit; + + // --------------------------------------------------------------------------------------------- + + private AzureAiStudioServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.endpointType = ApiTypeHelper.requireNonNull(builder.endpointType, this, "endpointType"); + this.target = ApiTypeHelper.requireNonNull(builder.target, this, "target"); + this.provider = ApiTypeHelper.requireNonNull(builder.provider, this, "provider"); + this.rateLimit = builder.rateLimit; + + } + + public static AzureAiStudioServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid API key of your Azure AI Studio model deployment. This key + * can be found on the overview page for your deployment in the management + * section of your Azure AI Studio account. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * Required - The type of endpoint that is available for deployment through + * Azure AI Studio: token or realtime. The + * token endpoint type is for "pay as you go" endpoints + * that are billed per token. The realtime endpoint type is for + * "real-time" endpoints that are billed per hour of usage. + *

+ * API name: {@code endpoint_type} + */ + public final String endpointType() { + return this.endpointType; + } + + /** + * Required - The target URL of your Azure AI Studio model deployment. This can + * be found on the overview page for your deployment in the management section + * of your Azure AI Studio account. + *

+ * API name: {@code target} + */ + public final String target() { + return this.target; + } + + /** + * Required - The model provider for your deployment. Note that some providers + * may support only certain task types. Supported providers include: + *

    + *
  • cohere - available for text_embedding and + * completion task types
  • + *
  • databricks - available for completion task type + * only
  • + *
  • meta - available for completion task type + * only
  • + *
  • microsoft_phi - available for completion task + * type only
  • + *
  • mistral - available for completion task type + * only
  • + *
  • openai - available for text_embedding and + * completion task types
  • + *
+ *

+ * API name: {@code provider} + */ + public final String provider() { + return this.provider; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Azure AI Studio. By default, the azureaistudio service sets the + * number of requests allowed per minute to 240. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + generator.writeKey("endpoint_type"); + generator.write(this.endpointType); + + generator.writeKey("target"); + generator.write(this.target); + + generator.writeKey("provider"); + generator.write(this.provider); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AzureAiStudioServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + private String endpointType; + + private String target; + + private String provider; + + @Nullable + private RateLimitSetting rateLimit; + + /** + * Required - A valid API key of your Azure AI Studio model deployment. This key + * can be found on the overview page for your deployment in the management + * section of your Azure AI Studio account. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * Required - The type of endpoint that is available for deployment through + * Azure AI Studio: token or realtime. The + * token endpoint type is for "pay as you go" endpoints + * that are billed per token. The realtime endpoint type is for + * "real-time" endpoints that are billed per hour of usage. + *

+ * API name: {@code endpoint_type} + */ + public final Builder endpointType(String value) { + this.endpointType = value; + return this; + } + + /** + * Required - The target URL of your Azure AI Studio model deployment. This can + * be found on the overview page for your deployment in the management section + * of your Azure AI Studio account. + *

+ * API name: {@code target} + */ + public final Builder target(String value) { + this.target = value; + return this; + } + + /** + * Required - The model provider for your deployment. Note that some providers + * may support only certain task types. Supported providers include: + *

    + *
  • cohere - available for text_embedding and + * completion task types
  • + *
  • databricks - available for completion task type + * only
  • + *
  • meta - available for completion task type + * only
  • + *
  • microsoft_phi - available for completion task + * type only
  • + *
  • mistral - available for completion task type + * only
  • + *
  • openai - available for text_embedding and + * completion task types
  • + *
+ *

+ * API name: {@code provider} + */ + public final Builder provider(String value) { + this.provider = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Azure AI Studio. By default, the azureaistudio service sets the + * number of requests allowed per minute to 240. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Azure AI Studio. By default, the azureaistudio service sets the + * number of requests allowed per minute to 240. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AzureAiStudioServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AzureAiStudioServiceSettings build() { + _checkSingleUse(); + + return new AzureAiStudioServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AzureAiStudioServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AzureAiStudioServiceSettings::setupAzureAiStudioServiceSettingsDeserializer); + + protected static void setupAzureAiStudioServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::endpointType, JsonpDeserializer.stringDeserializer(), "endpoint_type"); + op.add(Builder::target, JsonpDeserializer.stringDeserializer(), "target"); + op.add(Builder::provider, JsonpDeserializer.stringDeserializer(), "provider"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskSettings.java new file mode 100644 index 000000000..df846c062 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskSettings.java @@ -0,0 +1,320 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_azureaistudio; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Float; +import java.lang.Integer; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_azureaistudio.AzureAiStudioTaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AzureAiStudioTaskSettings implements JsonpSerializable { + @Nullable + private final Float doSample; + + @Nullable + private final Integer maxNewTokens; + + @Nullable + private final Float temperature; + + @Nullable + private final Float topP; + + @Nullable + private final String user; + + // --------------------------------------------------------------------------------------------- + + private AzureAiStudioTaskSettings(Builder builder) { + + this.doSample = builder.doSample; + this.maxNewTokens = builder.maxNewTokens; + this.temperature = builder.temperature; + this.topP = builder.topP; + this.user = builder.user; + + } + + public static AzureAiStudioTaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * For a completion task, instruct the inference process to perform + * sampling. It has no effect unless temperature or + * top_p is specified. + *

+ * API name: {@code do_sample} + */ + @Nullable + public final Float doSample() { + return this.doSample; + } + + /** + * For a completion task, provide a hint for the maximum number of + * output tokens to be generated. + *

+ * API name: {@code max_new_tokens} + */ + @Nullable + public final Integer maxNewTokens() { + return this.maxNewTokens; + } + + /** + * For a completion task, control the apparent creativity of + * generated completions with a sampling temperature. It must be a number in the + * range of 0.0 to 2.0. It should not be used if top_p is + * specified. + *

+ * API name: {@code temperature} + */ + @Nullable + public final Float temperature() { + return this.temperature; + } + + /** + * For a completion task, make the model consider the results of + * the tokens with nucleus sampling probability. It is an alternative value to + * temperature and must be a number in the range of 0.0 to 2.0. It + * should not be used if temperature is specified. + *

+ * API name: {@code top_p} + */ + @Nullable + public final Float topP() { + return this.topP; + } + + /** + * For a text_embedding task, specify the user issuing the request. + * This information can be used for abuse detection. + *

+ * API name: {@code user} + */ + @Nullable + public final String user() { + return this.user; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.doSample != null) { + generator.writeKey("do_sample"); + generator.write(this.doSample); + + } + if (this.maxNewTokens != null) { + generator.writeKey("max_new_tokens"); + generator.write(this.maxNewTokens); + + } + if (this.temperature != null) { + generator.writeKey("temperature"); + generator.write(this.temperature); + + } + if (this.topP != null) { + generator.writeKey("top_p"); + generator.write(this.topP); + + } + if (this.user != null) { + generator.writeKey("user"); + generator.write(this.user); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AzureAiStudioTaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private Float doSample; + + @Nullable + private Integer maxNewTokens; + + @Nullable + private Float temperature; + + @Nullable + private Float topP; + + @Nullable + private String user; + + /** + * For a completion task, instruct the inference process to perform + * sampling. It has no effect unless temperature or + * top_p is specified. + *

+ * API name: {@code do_sample} + */ + public final Builder doSample(@Nullable Float value) { + this.doSample = value; + return this; + } + + /** + * For a completion task, provide a hint for the maximum number of + * output tokens to be generated. + *

+ * API name: {@code max_new_tokens} + */ + public final Builder maxNewTokens(@Nullable Integer value) { + this.maxNewTokens = value; + return this; + } + + /** + * For a completion task, control the apparent creativity of + * generated completions with a sampling temperature. It must be a number in the + * range of 0.0 to 2.0. It should not be used if top_p is + * specified. + *

+ * API name: {@code temperature} + */ + public final Builder temperature(@Nullable Float value) { + this.temperature = value; + return this; + } + + /** + * For a completion task, make the model consider the results of + * the tokens with nucleus sampling probability. It is an alternative value to + * temperature and must be a number in the range of 0.0 to 2.0. It + * should not be used if temperature is specified. + *

+ * API name: {@code top_p} + */ + public final Builder topP(@Nullable Float value) { + this.topP = value; + return this; + } + + /** + * For a text_embedding task, specify the user issuing the request. + * This information can be used for abuse detection. + *

+ * API name: {@code user} + */ + public final Builder user(@Nullable String value) { + this.user = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AzureAiStudioTaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AzureAiStudioTaskSettings build() { + _checkSingleUse(); + + return new AzureAiStudioTaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AzureAiStudioTaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AzureAiStudioTaskSettings::setupAzureAiStudioTaskSettingsDeserializer); + + protected static void setupAzureAiStudioTaskSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::doSample, JsonpDeserializer.floatDeserializer(), "do_sample"); + op.add(Builder::maxNewTokens, JsonpDeserializer.integerDeserializer(), "max_new_tokens"); + op.add(Builder::temperature, JsonpDeserializer.floatDeserializer(), "temperature"); + op.add(Builder::topP, JsonpDeserializer.floatDeserializer(), "top_p"); + op.add(Builder::user, JsonpDeserializer.stringDeserializer(), "user"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskType.java new file mode 100644 index 000000000..7a8b074fe --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskType.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_azureaistudio; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum AzureAiStudioTaskType implements JsonEnum { + Completion("completion"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + AzureAiStudioTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + AzureAiStudioTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/ServiceType.java new file mode 100644 index 000000000..5e3b80f0e --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_azureaistudio; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Azureaistudio("azureaistudio"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAIServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAIServiceSettings.java new file mode 100644 index 000000000..849f7bee6 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAIServiceSettings.java @@ -0,0 +1,368 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_azureopenai; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_azureopenai.AzureOpenAIServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AzureOpenAIServiceSettings implements JsonpSerializable { + @Nullable + private final String apiKey; + + private final String apiVersion; + + private final String deploymentId; + + @Nullable + private final String entraId; + + @Nullable + private final RateLimitSetting rateLimit; + + private final String resourceName; + + // --------------------------------------------------------------------------------------------- + + private AzureOpenAIServiceSettings(Builder builder) { + + this.apiKey = builder.apiKey; + this.apiVersion = ApiTypeHelper.requireNonNull(builder.apiVersion, this, "apiVersion"); + this.deploymentId = ApiTypeHelper.requireNonNull(builder.deploymentId, this, "deploymentId"); + this.entraId = builder.entraId; + this.rateLimit = builder.rateLimit; + this.resourceName = ApiTypeHelper.requireNonNull(builder.resourceName, this, "resourceName"); + + } + + public static AzureOpenAIServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * A valid API key for your Azure OpenAI account. You must specify either + * api_key or entra_id. If you do not provide either + * or you provide both, you will receive an error when you try to create your + * model. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + @Nullable + public final String apiKey() { + return this.apiKey; + } + + /** + * Required - The Azure API version ID to use. It is recommended to use the + * latest supported non-preview version. + *

+ * API name: {@code api_version} + */ + public final String apiVersion() { + return this.apiVersion; + } + + /** + * Required - The deployment name of your deployed models. Your Azure OpenAI + * deployments can be found though the Azure OpenAI Studio portal that is linked + * to your subscription. + *

+ * API name: {@code deployment_id} + */ + public final String deploymentId() { + return this.deploymentId; + } + + /** + * A valid Microsoft Entra token. You must specify either api_key + * or entra_id. If you do not provide either or you provide both, + * you will receive an error when you try to create your model. + *

+ * API name: {@code entra_id} + */ + @Nullable + public final String entraId() { + return this.entraId; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Azure. The azureopenai service sets a default number of requests + * allowed per minute depending on the task type. For + * text_embedding, it is set to 1440. For + * completion, it is set to 120. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Required - The name of your Azure OpenAI resource. You can find this from the + * list of resources in the Azure Portal for your subscription. + *

+ * API name: {@code resource_name} + */ + public final String resourceName() { + return this.resourceName; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.apiKey != null) { + generator.writeKey("api_key"); + generator.write(this.apiKey); + + } + generator.writeKey("api_version"); + generator.write(this.apiVersion); + + generator.writeKey("deployment_id"); + generator.write(this.deploymentId); + + if (this.entraId != null) { + generator.writeKey("entra_id"); + generator.write(this.entraId); + + } + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + generator.writeKey("resource_name"); + generator.write(this.resourceName); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AzureOpenAIServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private String apiKey; + + private String apiVersion; + + private String deploymentId; + + @Nullable + private String entraId; + + @Nullable + private RateLimitSetting rateLimit; + + private String resourceName; + + /** + * A valid API key for your Azure OpenAI account. You must specify either + * api_key or entra_id. If you do not provide either + * or you provide both, you will receive an error when you try to create your + * model. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(@Nullable String value) { + this.apiKey = value; + return this; + } + + /** + * Required - The Azure API version ID to use. It is recommended to use the + * latest supported non-preview version. + *

+ * API name: {@code api_version} + */ + public final Builder apiVersion(String value) { + this.apiVersion = value; + return this; + } + + /** + * Required - The deployment name of your deployed models. Your Azure OpenAI + * deployments can be found though the Azure OpenAI Studio portal that is linked + * to your subscription. + *

+ * API name: {@code deployment_id} + */ + public final Builder deploymentId(String value) { + this.deploymentId = value; + return this; + } + + /** + * A valid Microsoft Entra token. You must specify either api_key + * or entra_id. If you do not provide either or you provide both, + * you will receive an error when you try to create your model. + *

+ * API name: {@code entra_id} + */ + public final Builder entraId(@Nullable String value) { + this.entraId = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Azure. The azureopenai service sets a default number of requests + * allowed per minute depending on the task type. For + * text_embedding, it is set to 1440. For + * completion, it is set to 120. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Azure. The azureopenai service sets a default number of requests + * allowed per minute depending on the task type. For + * text_embedding, it is set to 1440. For + * completion, it is set to 120. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * Required - The name of your Azure OpenAI resource. You can find this from the + * list of resources in the Azure Portal for your subscription. + *

+ * API name: {@code resource_name} + */ + public final Builder resourceName(String value) { + this.resourceName = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AzureOpenAIServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AzureOpenAIServiceSettings build() { + _checkSingleUse(); + + return new AzureOpenAIServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AzureOpenAIServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AzureOpenAIServiceSettings::setupAzureOpenAIServiceSettingsDeserializer); + + protected static void setupAzureOpenAIServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::apiVersion, JsonpDeserializer.stringDeserializer(), "api_version"); + op.add(Builder::deploymentId, JsonpDeserializer.stringDeserializer(), "deployment_id"); + op.add(Builder::entraId, JsonpDeserializer.stringDeserializer(), "entra_id"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::resourceName, JsonpDeserializer.stringDeserializer(), "resource_name"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAITaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAITaskType.java new file mode 100644 index 000000000..4c6414276 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAITaskType.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_azureopenai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum AzureOpenAITaskType implements JsonEnum { + Completion("completion"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + AzureOpenAITaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + AzureOpenAITaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/ServiceType.java new file mode 100644 index 000000000..c27837b69 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_azureopenai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Azureopenai("azureopenai"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereServiceSettings.java new file mode 100644 index 000000000..86c1c9e24 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereServiceSettings.java @@ -0,0 +1,363 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_cohere; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_cohere.CohereServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class CohereServiceSettings implements JsonpSerializable { + private final String apiKey; + + @Nullable + private final EmbeddingType embeddingType; + + @Nullable + private final String modelId; + + @Nullable + private final RateLimitSetting rateLimit; + + @Nullable + private final SimilarityType similarity; + + // --------------------------------------------------------------------------------------------- + + private CohereServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.embeddingType = builder.embeddingType; + this.modelId = builder.modelId; + this.rateLimit = builder.rateLimit; + this.similarity = builder.similarity; + + } + + public static CohereServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid API key for your Cohere account. You can find or create + * your Cohere API keys on the Cohere API key settings page. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * For a text_embedding task, the types of embeddings you want to + * get back. Use byte for signed int8 embeddings (this is a synonym + * of int8). Use float for the default float + * embeddings. Use int8 for signed int8 embeddings. + *

+ * API name: {@code embedding_type} + */ + @Nullable + public final EmbeddingType embeddingType() { + return this.embeddingType; + } + + /** + * For a completion, rerank, or + * text_embedding task, the name of the model to use for the + * inference task. + *

+ *

+ * The default value for a text embedding task is + * embed-english-v2.0. + *

+ * API name: {@code model_id} + */ + @Nullable + public final String modelId() { + return this.modelId; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Cohere. By default, the cohere service sets the number of + * requests allowed per minute to 10000. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * The similarity measure. If the embedding_type is + * float, the default value is dot_product. If the + * embedding_type is int8 or byte, the + * default value is cosine. + *

+ * API name: {@code similarity} + */ + @Nullable + public final SimilarityType similarity() { + return this.similarity; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + if (this.embeddingType != null) { + generator.writeKey("embedding_type"); + this.embeddingType.serialize(generator, mapper); + } + if (this.modelId != null) { + generator.writeKey("model_id"); + generator.write(this.modelId); + + } + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + if (this.similarity != null) { + generator.writeKey("similarity"); + this.similarity.serialize(generator, mapper); + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link CohereServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + @Nullable + private EmbeddingType embeddingType; + + @Nullable + private String modelId; + + @Nullable + private RateLimitSetting rateLimit; + + @Nullable + private SimilarityType similarity; + + /** + * Required - A valid API key for your Cohere account. You can find or create + * your Cohere API keys on the Cohere API key settings page. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * For a text_embedding task, the types of embeddings you want to + * get back. Use byte for signed int8 embeddings (this is a synonym + * of int8). Use float for the default float + * embeddings. Use int8 for signed int8 embeddings. + *

+ * API name: {@code embedding_type} + */ + public final Builder embeddingType(@Nullable EmbeddingType value) { + this.embeddingType = value; + return this; + } + + /** + * For a completion, rerank, or + * text_embedding task, the name of the model to use for the + * inference task. + *

+ *

+ * The default value for a text embedding task is + * embed-english-v2.0. + *

+ * API name: {@code model_id} + */ + public final Builder modelId(@Nullable String value) { + this.modelId = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Cohere. By default, the cohere service sets the number of + * requests allowed per minute to 10000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Cohere. By default, the cohere service sets the number of + * requests allowed per minute to 10000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * The similarity measure. If the embedding_type is + * float, the default value is dot_product. If the + * embedding_type is int8 or byte, the + * default value is cosine. + *

+ * API name: {@code similarity} + */ + public final Builder similarity(@Nullable SimilarityType value) { + this.similarity = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link CohereServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public CohereServiceSettings build() { + _checkSingleUse(); + + return new CohereServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link CohereServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, CohereServiceSettings::setupCohereServiceSettingsDeserializer); + + protected static void setupCohereServiceSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::embeddingType, EmbeddingType._DESERIALIZER, "embedding_type"); + op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::similarity, SimilarityType._DESERIALIZER, "similarity"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskSettings.java new file mode 100644 index 000000000..77947b3ee --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskSettings.java @@ -0,0 +1,317 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_cohere; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_cohere.CohereTaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class CohereTaskSettings implements JsonpSerializable { + @Nullable + private final InputType inputType; + + @Nullable + private final Boolean returnDocuments; + + @Nullable + private final Integer topN; + + @Nullable + private final TruncateType truncate; + + // --------------------------------------------------------------------------------------------- + + private CohereTaskSettings(Builder builder) { + + this.inputType = builder.inputType; + this.returnDocuments = builder.returnDocuments; + this.topN = builder.topN; + this.truncate = builder.truncate; + + } + + public static CohereTaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * For a text_embedding task, the type of input passed to the + * model. Valid values are: + *

    + *
  • classification: Use it for embeddings passed through a text + * classifier.
  • + *
  • clustering: Use it for the embeddings run through a + * clustering algorithm.
  • + *
  • ingest: Use it for storing document embeddings in a vector + * database.
  • + *
  • search: Use it for storing embeddings of search queries run + * against a vector database to find relevant documents.
  • + *
+ *

+ * IMPORTANT: The input_type field is required when using embedding + * models v3 and higher. + *

+ * API name: {@code input_type} + */ + @Nullable + public final InputType inputType() { + return this.inputType; + } + + /** + * For a rerank task, return doc text within the results. + *

+ * API name: {@code return_documents} + */ + @Nullable + public final Boolean returnDocuments() { + return this.returnDocuments; + } + + /** + * For a rerank task, the number of most relevant documents to + * return. It defaults to the number of the documents. If this inference + * endpoint is used in a text_similarity_reranker retriever query + * and top_n is set, it must be greater than or equal to + * rank_window_size in the query. + *

+ * API name: {@code top_n} + */ + @Nullable + public final Integer topN() { + return this.topN; + } + + /** + * For a text_embedding task, the method to handle inputs longer + * than the maximum token length. Valid values are: + *

    + *
  • END: When the input exceeds the maximum input token length, + * the end of the input is discarded.
  • + *
  • NONE: When the input exceeds the maximum input token length, + * an error is returned.
  • + *
  • START: When the input exceeds the maximum input token + * length, the start of the input is discarded.
  • + *
+ *

+ * API name: {@code truncate} + */ + @Nullable + public final TruncateType truncate() { + return this.truncate; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.inputType != null) { + generator.writeKey("input_type"); + this.inputType.serialize(generator, mapper); + } + if (this.returnDocuments != null) { + generator.writeKey("return_documents"); + generator.write(this.returnDocuments); + + } + if (this.topN != null) { + generator.writeKey("top_n"); + generator.write(this.topN); + + } + if (this.truncate != null) { + generator.writeKey("truncate"); + this.truncate.serialize(generator, mapper); + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link CohereTaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private InputType inputType; + + @Nullable + private Boolean returnDocuments; + + @Nullable + private Integer topN; + + @Nullable + private TruncateType truncate; + + /** + * For a text_embedding task, the type of input passed to the + * model. Valid values are: + *

    + *
  • classification: Use it for embeddings passed through a text + * classifier.
  • + *
  • clustering: Use it for the embeddings run through a + * clustering algorithm.
  • + *
  • ingest: Use it for storing document embeddings in a vector + * database.
  • + *
  • search: Use it for storing embeddings of search queries run + * against a vector database to find relevant documents.
  • + *
+ *

+ * IMPORTANT: The input_type field is required when using embedding + * models v3 and higher. + *

+ * API name: {@code input_type} + */ + public final Builder inputType(@Nullable InputType value) { + this.inputType = value; + return this; + } + + /** + * For a rerank task, return doc text within the results. + *

+ * API name: {@code return_documents} + */ + public final Builder returnDocuments(@Nullable Boolean value) { + this.returnDocuments = value; + return this; + } + + /** + * For a rerank task, the number of most relevant documents to + * return. It defaults to the number of the documents. If this inference + * endpoint is used in a text_similarity_reranker retriever query + * and top_n is set, it must be greater than or equal to + * rank_window_size in the query. + *

+ * API name: {@code top_n} + */ + public final Builder topN(@Nullable Integer value) { + this.topN = value; + return this; + } + + /** + * For a text_embedding task, the method to handle inputs longer + * than the maximum token length. Valid values are: + *

    + *
  • END: When the input exceeds the maximum input token length, + * the end of the input is discarded.
  • + *
  • NONE: When the input exceeds the maximum input token length, + * an error is returned.
  • + *
  • START: When the input exceeds the maximum input token + * length, the start of the input is discarded.
  • + *
+ *

+ * API name: {@code truncate} + */ + public final Builder truncate(@Nullable TruncateType value) { + this.truncate = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link CohereTaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public CohereTaskSettings build() { + _checkSingleUse(); + + return new CohereTaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link CohereTaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, CohereTaskSettings::setupCohereTaskSettingsDeserializer); + + protected static void setupCohereTaskSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::inputType, InputType._DESERIALIZER, "input_type"); + op.add(Builder::returnDocuments, JsonpDeserializer.booleanDeserializer(), "return_documents"); + op.add(Builder::topN, JsonpDeserializer.integerDeserializer(), "top_n"); + op.add(Builder::truncate, TruncateType._DESERIALIZER, "truncate"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskType.java new file mode 100644 index 000000000..81025c4aa --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskType.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_cohere; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum CohereTaskType implements JsonEnum { + Completion("completion"), + + Rerank("rerank"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + CohereTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + CohereTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/EmbeddingType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/EmbeddingType.java new file mode 100644 index 000000000..0527144d6 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/EmbeddingType.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_cohere; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum EmbeddingType implements JsonEnum { + Byte("byte"), + + Float("float"), + + Int8("int8"), + + ; + + private final String jsonValue; + + EmbeddingType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + EmbeddingType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/InputType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/InputType.java new file mode 100644 index 000000000..e4ff40c8f --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/InputType.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_cohere; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum InputType implements JsonEnum { + Classification("classification"), + + Clustering("clustering"), + + Ingest("ingest"), + + Search("search"), + + ; + + private final String jsonValue; + + InputType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + InputType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/ServiceType.java new file mode 100644 index 000000000..ff717e85a --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_cohere; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Cohere("cohere"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/SimilarityType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/SimilarityType.java new file mode 100644 index 000000000..651346c62 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/SimilarityType.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_cohere; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum SimilarityType implements JsonEnum { + Cosine("cosine"), + + DotProduct("dot_product"), + + L2Norm("l2_norm"), + + ; + + private final String jsonValue; + + SimilarityType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + SimilarityType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/TruncateType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/TruncateType.java new file mode 100644 index 000000000..b3f7691cd --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/TruncateType.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_cohere; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum TruncateType implements JsonEnum { + End("END"), + + None("NONE"), + + Start("START"), + + ; + + private final String jsonValue; + + TruncateType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + TruncateType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/AdaptiveAllocations.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/AdaptiveAllocations.java new file mode 100644 index 000000000..b5c60a2ae --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/AdaptiveAllocations.java @@ -0,0 +1,236 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_elasticsearch; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_elasticsearch.AdaptiveAllocations + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AdaptiveAllocations implements JsonpSerializable { + @Nullable + private final Boolean enabled; + + @Nullable + private final Integer maxNumberOfAllocations; + + @Nullable + private final Integer minNumberOfAllocations; + + // --------------------------------------------------------------------------------------------- + + private AdaptiveAllocations(Builder builder) { + + this.enabled = builder.enabled; + this.maxNumberOfAllocations = builder.maxNumberOfAllocations; + this.minNumberOfAllocations = builder.minNumberOfAllocations; + + } + + public static AdaptiveAllocations of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Turn on adaptive_allocations. + *

+ * API name: {@code enabled} + */ + @Nullable + public final Boolean enabled() { + return this.enabled; + } + + /** + * The maximum number of allocations to scale to. If set, it must be greater + * than or equal to min_number_of_allocations. + *

+ * API name: {@code max_number_of_allocations} + */ + @Nullable + public final Integer maxNumberOfAllocations() { + return this.maxNumberOfAllocations; + } + + /** + * The minimum number of allocations to scale to. If set, it must be greater + * than or equal to 0. If not defined, the deployment scales to 0. + *

+ * API name: {@code min_number_of_allocations} + */ + @Nullable + public final Integer minNumberOfAllocations() { + return this.minNumberOfAllocations; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.enabled != null) { + generator.writeKey("enabled"); + generator.write(this.enabled); + + } + if (this.maxNumberOfAllocations != null) { + generator.writeKey("max_number_of_allocations"); + generator.write(this.maxNumberOfAllocations); + + } + if (this.minNumberOfAllocations != null) { + generator.writeKey("min_number_of_allocations"); + generator.write(this.minNumberOfAllocations); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AdaptiveAllocations}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private Boolean enabled; + + @Nullable + private Integer maxNumberOfAllocations; + + @Nullable + private Integer minNumberOfAllocations; + + /** + * Turn on adaptive_allocations. + *

+ * API name: {@code enabled} + */ + public final Builder enabled(@Nullable Boolean value) { + this.enabled = value; + return this; + } + + /** + * The maximum number of allocations to scale to. If set, it must be greater + * than or equal to min_number_of_allocations. + *

+ * API name: {@code max_number_of_allocations} + */ + public final Builder maxNumberOfAllocations(@Nullable Integer value) { + this.maxNumberOfAllocations = value; + return this; + } + + /** + * The minimum number of allocations to scale to. If set, it must be greater + * than or equal to 0. If not defined, the deployment scales to 0. + *

+ * API name: {@code min_number_of_allocations} + */ + public final Builder minNumberOfAllocations(@Nullable Integer value) { + this.minNumberOfAllocations = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AdaptiveAllocations}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AdaptiveAllocations build() { + _checkSingleUse(); + + return new AdaptiveAllocations(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AdaptiveAllocations} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AdaptiveAllocations::setupAdaptiveAllocationsDeserializer); + + protected static void setupAdaptiveAllocationsDeserializer(ObjectDeserializer op) { + + op.add(Builder::enabled, JsonpDeserializer.booleanDeserializer(), "enabled"); + op.add(Builder::maxNumberOfAllocations, JsonpDeserializer.integerDeserializer(), "max_number_of_allocations"); + op.add(Builder::minNumberOfAllocations, JsonpDeserializer.integerDeserializer(), "min_number_of_allocations"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchServiceSettings.java new file mode 100644 index 000000000..e9e60d46a --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchServiceSettings.java @@ -0,0 +1,342 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_elasticsearch; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Integer; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_elasticsearch.ElasticsearchServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class ElasticsearchServiceSettings implements JsonpSerializable { + @Nullable + private final AdaptiveAllocations adaptiveAllocations; + + @Nullable + private final String deploymentId; + + private final String modelId; + + @Nullable + private final Integer numAllocations; + + private final int numThreads; + + // --------------------------------------------------------------------------------------------- + + private ElasticsearchServiceSettings(Builder builder) { + + this.adaptiveAllocations = builder.adaptiveAllocations; + this.deploymentId = builder.deploymentId; + this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); + this.numAllocations = builder.numAllocations; + this.numThreads = ApiTypeHelper.requireNonNull(builder.numThreads, this, "numThreads"); + + } + + public static ElasticsearchServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Adaptive allocations configuration details. If enabled is true, + * the number of allocations of the model is set based on the current load the + * process gets. When the load is high, a new model allocation is automatically + * created, respecting the value of max_number_of_allocations if + * it's set. When the load is low, a model allocation is automatically removed, + * respecting the value of min_number_of_allocations if it's set. + * If enabled is true, do not set the number of allocations + * manually. + *

+ * API name: {@code adaptive_allocations} + */ + @Nullable + public final AdaptiveAllocations adaptiveAllocations() { + return this.adaptiveAllocations; + } + + /** + * The deployment identifier for a trained model deployment. When + * deployment_id is used the model_id is optional. + *

+ * API name: {@code deployment_id} + */ + @Nullable + public final String deploymentId() { + return this.deploymentId; + } + + /** + * Required - The name of the model to use for the inference task. It can be the + * ID of a built-in model (for example, .multilingual-e5-small for + * E5) or a text embedding model that was uploaded by using the Eland client. + *

+ * API name: {@code model_id} + */ + public final String modelId() { + return this.modelId; + } + + /** + * The total number of allocations that are assigned to the model across machine + * learning nodes. Increasing this value generally increases the throughput. If + * adaptive allocations are enabled, do not set this value because it's + * automatically set. + *

+ * API name: {@code num_allocations} + */ + @Nullable + public final Integer numAllocations() { + return this.numAllocations; + } + + /** + * Required - The number of threads used by each model allocation during + * inference. This setting generally increases the speed per inference request. + * The inference process is a compute-bound process; + * threads_per_allocations must not exceed the number of available + * allocated processors per node. The value must be a power of 2. The maximum + * value is 32. + *

+ * API name: {@code num_threads} + */ + public final int numThreads() { + return this.numThreads; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.adaptiveAllocations != null) { + generator.writeKey("adaptive_allocations"); + this.adaptiveAllocations.serialize(generator, mapper); + + } + if (this.deploymentId != null) { + generator.writeKey("deployment_id"); + generator.write(this.deploymentId); + + } + generator.writeKey("model_id"); + generator.write(this.modelId); + + if (this.numAllocations != null) { + generator.writeKey("num_allocations"); + generator.write(this.numAllocations); + + } + generator.writeKey("num_threads"); + generator.write(this.numThreads); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link ElasticsearchServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private AdaptiveAllocations adaptiveAllocations; + + @Nullable + private String deploymentId; + + private String modelId; + + @Nullable + private Integer numAllocations; + + private Integer numThreads; + + /** + * Adaptive allocations configuration details. If enabled is true, + * the number of allocations of the model is set based on the current load the + * process gets. When the load is high, a new model allocation is automatically + * created, respecting the value of max_number_of_allocations if + * it's set. When the load is low, a model allocation is automatically removed, + * respecting the value of min_number_of_allocations if it's set. + * If enabled is true, do not set the number of allocations + * manually. + *

+ * API name: {@code adaptive_allocations} + */ + public final Builder adaptiveAllocations(@Nullable AdaptiveAllocations value) { + this.adaptiveAllocations = value; + return this; + } + + /** + * Adaptive allocations configuration details. If enabled is true, + * the number of allocations of the model is set based on the current load the + * process gets. When the load is high, a new model allocation is automatically + * created, respecting the value of max_number_of_allocations if + * it's set. When the load is low, a model allocation is automatically removed, + * respecting the value of min_number_of_allocations if it's set. + * If enabled is true, do not set the number of allocations + * manually. + *

+ * API name: {@code adaptive_allocations} + */ + public final Builder adaptiveAllocations( + Function> fn) { + return this.adaptiveAllocations(fn.apply(new AdaptiveAllocations.Builder()).build()); + } + + /** + * The deployment identifier for a trained model deployment. When + * deployment_id is used the model_id is optional. + *

+ * API name: {@code deployment_id} + */ + public final Builder deploymentId(@Nullable String value) { + this.deploymentId = value; + return this; + } + + /** + * Required - The name of the model to use for the inference task. It can be the + * ID of a built-in model (for example, .multilingual-e5-small for + * E5) or a text embedding model that was uploaded by using the Eland client. + *

+ * API name: {@code model_id} + */ + public final Builder modelId(String value) { + this.modelId = value; + return this; + } + + /** + * The total number of allocations that are assigned to the model across machine + * learning nodes. Increasing this value generally increases the throughput. If + * adaptive allocations are enabled, do not set this value because it's + * automatically set. + *

+ * API name: {@code num_allocations} + */ + public final Builder numAllocations(@Nullable Integer value) { + this.numAllocations = value; + return this; + } + + /** + * Required - The number of threads used by each model allocation during + * inference. This setting generally increases the speed per inference request. + * The inference process is a compute-bound process; + * threads_per_allocations must not exceed the number of available + * allocated processors per node. The value must be a power of 2. The maximum + * value is 32. + *

+ * API name: {@code num_threads} + */ + public final Builder numThreads(int value) { + this.numThreads = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link ElasticsearchServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public ElasticsearchServiceSettings build() { + _checkSingleUse(); + + return new ElasticsearchServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link ElasticsearchServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, ElasticsearchServiceSettings::setupElasticsearchServiceSettingsDeserializer); + + protected static void setupElasticsearchServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::adaptiveAllocations, AdaptiveAllocations._DESERIALIZER, "adaptive_allocations"); + op.add(Builder::deploymentId, JsonpDeserializer.stringDeserializer(), "deployment_id"); + op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); + op.add(Builder::numAllocations, JsonpDeserializer.integerDeserializer(), "num_allocations"); + op.add(Builder::numThreads, JsonpDeserializer.integerDeserializer(), "num_threads"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskSettings.java new file mode 100644 index 000000000..085c5faad --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskSettings.java @@ -0,0 +1,168 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_elasticsearch; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_elasticsearch.ElasticsearchTaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class ElasticsearchTaskSettings implements JsonpSerializable { + @Nullable + private final Boolean returnDocuments; + + // --------------------------------------------------------------------------------------------- + + private ElasticsearchTaskSettings(Builder builder) { + + this.returnDocuments = builder.returnDocuments; + + } + + public static ElasticsearchTaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * For a rerank task, return the document instead of only the + * index. + *

+ * API name: {@code return_documents} + */ + @Nullable + public final Boolean returnDocuments() { + return this.returnDocuments; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.returnDocuments != null) { + generator.writeKey("return_documents"); + generator.write(this.returnDocuments); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link ElasticsearchTaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private Boolean returnDocuments; + + /** + * For a rerank task, return the document instead of only the + * index. + *

+ * API name: {@code return_documents} + */ + public final Builder returnDocuments(@Nullable Boolean value) { + this.returnDocuments = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link ElasticsearchTaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public ElasticsearchTaskSettings build() { + _checkSingleUse(); + + return new ElasticsearchTaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link ElasticsearchTaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, ElasticsearchTaskSettings::setupElasticsearchTaskSettingsDeserializer); + + protected static void setupElasticsearchTaskSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::returnDocuments, JsonpDeserializer.booleanDeserializer(), "return_documents"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskType.java new file mode 100644 index 000000000..bdd5a9230 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskType.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_elasticsearch; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ElasticsearchTaskType implements JsonEnum { + Rerank("rerank"), + + SparseEmbedding("sparse_embedding"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + ElasticsearchTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ElasticsearchTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ServiceType.java new file mode 100644 index 000000000..623a65181 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_elasticsearch; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Elasticsearch("elasticsearch"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/AdaptiveAllocations.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/AdaptiveAllocations.java new file mode 100644 index 000000000..3facca41b --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/AdaptiveAllocations.java @@ -0,0 +1,236 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_elser; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_elser.AdaptiveAllocations + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AdaptiveAllocations implements JsonpSerializable { + @Nullable + private final Boolean enabled; + + @Nullable + private final Integer maxNumberOfAllocations; + + @Nullable + private final Integer minNumberOfAllocations; + + // --------------------------------------------------------------------------------------------- + + private AdaptiveAllocations(Builder builder) { + + this.enabled = builder.enabled; + this.maxNumberOfAllocations = builder.maxNumberOfAllocations; + this.minNumberOfAllocations = builder.minNumberOfAllocations; + + } + + public static AdaptiveAllocations of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Turn on adaptive_allocations. + *

+ * API name: {@code enabled} + */ + @Nullable + public final Boolean enabled() { + return this.enabled; + } + + /** + * The maximum number of allocations to scale to. If set, it must be greater + * than or equal to min_number_of_allocations. + *

+ * API name: {@code max_number_of_allocations} + */ + @Nullable + public final Integer maxNumberOfAllocations() { + return this.maxNumberOfAllocations; + } + + /** + * The minimum number of allocations to scale to. If set, it must be greater + * than or equal to 0. If not defined, the deployment scales to 0. + *

+ * API name: {@code min_number_of_allocations} + */ + @Nullable + public final Integer minNumberOfAllocations() { + return this.minNumberOfAllocations; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.enabled != null) { + generator.writeKey("enabled"); + generator.write(this.enabled); + + } + if (this.maxNumberOfAllocations != null) { + generator.writeKey("max_number_of_allocations"); + generator.write(this.maxNumberOfAllocations); + + } + if (this.minNumberOfAllocations != null) { + generator.writeKey("min_number_of_allocations"); + generator.write(this.minNumberOfAllocations); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AdaptiveAllocations}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private Boolean enabled; + + @Nullable + private Integer maxNumberOfAllocations; + + @Nullable + private Integer minNumberOfAllocations; + + /** + * Turn on adaptive_allocations. + *

+ * API name: {@code enabled} + */ + public final Builder enabled(@Nullable Boolean value) { + this.enabled = value; + return this; + } + + /** + * The maximum number of allocations to scale to. If set, it must be greater + * than or equal to min_number_of_allocations. + *

+ * API name: {@code max_number_of_allocations} + */ + public final Builder maxNumberOfAllocations(@Nullable Integer value) { + this.maxNumberOfAllocations = value; + return this; + } + + /** + * The minimum number of allocations to scale to. If set, it must be greater + * than or equal to 0. If not defined, the deployment scales to 0. + *

+ * API name: {@code min_number_of_allocations} + */ + public final Builder minNumberOfAllocations(@Nullable Integer value) { + this.minNumberOfAllocations = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AdaptiveAllocations}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AdaptiveAllocations build() { + _checkSingleUse(); + + return new AdaptiveAllocations(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AdaptiveAllocations} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AdaptiveAllocations::setupAdaptiveAllocationsDeserializer); + + protected static void setupAdaptiveAllocationsDeserializer(ObjectDeserializer op) { + + op.add(Builder::enabled, JsonpDeserializer.booleanDeserializer(), "enabled"); + op.add(Builder::maxNumberOfAllocations, JsonpDeserializer.integerDeserializer(), "max_number_of_allocations"); + op.add(Builder::minNumberOfAllocations, JsonpDeserializer.integerDeserializer(), "min_number_of_allocations"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserServiceSettings.java new file mode 100644 index 000000000..5cee104ba --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserServiceSettings.java @@ -0,0 +1,280 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_elser; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_elser.ElserServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class ElserServiceSettings implements JsonpSerializable { + @Nullable + private final AdaptiveAllocations adaptiveAllocations; + + private final int numAllocations; + + private final int numThreads; + + // --------------------------------------------------------------------------------------------- + + private ElserServiceSettings(Builder builder) { + + this.adaptiveAllocations = builder.adaptiveAllocations; + this.numAllocations = ApiTypeHelper.requireNonNull(builder.numAllocations, this, "numAllocations"); + this.numThreads = ApiTypeHelper.requireNonNull(builder.numThreads, this, "numThreads"); + + } + + public static ElserServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Adaptive allocations configuration details. If enabled is true, + * the number of allocations of the model is set based on the current load the + * process gets. When the load is high, a new model allocation is automatically + * created, respecting the value of max_number_of_allocations if + * it's set. When the load is low, a model allocation is automatically removed, + * respecting the value of min_number_of_allocations if it's set. + * If enabled is true, do not set the number of allocations + * manually. + *

+ * API name: {@code adaptive_allocations} + */ + @Nullable + public final AdaptiveAllocations adaptiveAllocations() { + return this.adaptiveAllocations; + } + + /** + * Required - The total number of allocations this model is assigned across + * machine learning nodes. Increasing this value generally increases the + * throughput. If adaptive allocations is enabled, do not set this value because + * it's automatically set. + *

+ * API name: {@code num_allocations} + */ + public final int numAllocations() { + return this.numAllocations; + } + + /** + * Required - The number of threads used by each model allocation during + * inference. Increasing this value generally increases the speed per inference + * request. The inference process is a compute-bound process; + * threads_per_allocations must not exceed the number of available + * allocated processors per node. The value must be a power of 2. The maximum + * value is 32.

+ *

+ * info If you want to optimize your ELSER endpoint for ingest, set the number + * of threads to 1. If you want to optimize your ELSER endpoint for search, set + * the number of threads to greater than 1. + *

+ *
+ *

+ * API name: {@code num_threads} + */ + public final int numThreads() { + return this.numThreads; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.adaptiveAllocations != null) { + generator.writeKey("adaptive_allocations"); + this.adaptiveAllocations.serialize(generator, mapper); + + } + generator.writeKey("num_allocations"); + generator.write(this.numAllocations); + + generator.writeKey("num_threads"); + generator.write(this.numThreads); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link ElserServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private AdaptiveAllocations adaptiveAllocations; + + private Integer numAllocations; + + private Integer numThreads; + + /** + * Adaptive allocations configuration details. If enabled is true, + * the number of allocations of the model is set based on the current load the + * process gets. When the load is high, a new model allocation is automatically + * created, respecting the value of max_number_of_allocations if + * it's set. When the load is low, a model allocation is automatically removed, + * respecting the value of min_number_of_allocations if it's set. + * If enabled is true, do not set the number of allocations + * manually. + *

+ * API name: {@code adaptive_allocations} + */ + public final Builder adaptiveAllocations(@Nullable AdaptiveAllocations value) { + this.adaptiveAllocations = value; + return this; + } + + /** + * Adaptive allocations configuration details. If enabled is true, + * the number of allocations of the model is set based on the current load the + * process gets. When the load is high, a new model allocation is automatically + * created, respecting the value of max_number_of_allocations if + * it's set. When the load is low, a model allocation is automatically removed, + * respecting the value of min_number_of_allocations if it's set. + * If enabled is true, do not set the number of allocations + * manually. + *

+ * API name: {@code adaptive_allocations} + */ + public final Builder adaptiveAllocations( + Function> fn) { + return this.adaptiveAllocations(fn.apply(new AdaptiveAllocations.Builder()).build()); + } + + /** + * Required - The total number of allocations this model is assigned across + * machine learning nodes. Increasing this value generally increases the + * throughput. If adaptive allocations is enabled, do not set this value because + * it's automatically set. + *

+ * API name: {@code num_allocations} + */ + public final Builder numAllocations(int value) { + this.numAllocations = value; + return this; + } + + /** + * Required - The number of threads used by each model allocation during + * inference. Increasing this value generally increases the speed per inference + * request. The inference process is a compute-bound process; + * threads_per_allocations must not exceed the number of available + * allocated processors per node. The value must be a power of 2. The maximum + * value is 32.

+ *

+ * info If you want to optimize your ELSER endpoint for ingest, set the number + * of threads to 1. If you want to optimize your ELSER endpoint for search, set + * the number of threads to greater than 1. + *

+ *
+ *

+ * API name: {@code num_threads} + */ + public final Builder numThreads(int value) { + this.numThreads = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link ElserServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public ElserServiceSettings build() { + _checkSingleUse(); + + return new ElserServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link ElserServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, ElserServiceSettings::setupElserServiceSettingsDeserializer); + + protected static void setupElserServiceSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::adaptiveAllocations, AdaptiveAllocations._DESERIALIZER, "adaptive_allocations"); + op.add(Builder::numAllocations, JsonpDeserializer.integerDeserializer(), "num_allocations"); + op.add(Builder::numThreads, JsonpDeserializer.integerDeserializer(), "num_threads"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserTaskType.java new file mode 100644 index 000000000..b06065905 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserTaskType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_elser; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ElserTaskType implements JsonEnum { + SparseEmbedding("sparse_embedding"), + + ; + + private final String jsonValue; + + ElserTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ElserTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioServiceSettings.java new file mode 100644 index 000000000..9fa3878c5 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioServiceSettings.java @@ -0,0 +1,241 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_googleaistudio; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_googleaistudio.GoogleAiStudioServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class GoogleAiStudioServiceSettings implements JsonpSerializable { + private final String apiKey; + + private final String modelId; + + @Nullable + private final RateLimitSetting rateLimit; + + // --------------------------------------------------------------------------------------------- + + private GoogleAiStudioServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); + this.rateLimit = builder.rateLimit; + + } + + public static GoogleAiStudioServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid API key of your Google Gemini account. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * Google documentation for the list of supported models. + *

+ * API name: {@code model_id} + */ + public final String modelId() { + return this.modelId; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Google AI Studio. By default, the googleaistudio service sets + * the number of requests allowed per minute to 360. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + generator.writeKey("model_id"); + generator.write(this.modelId); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link GoogleAiStudioServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + private String modelId; + + @Nullable + private RateLimitSetting rateLimit; + + /** + * Required - A valid API key of your Google Gemini account. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * Google documentation for the list of supported models. + *

+ * API name: {@code model_id} + */ + public final Builder modelId(String value) { + this.modelId = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Google AI Studio. By default, the googleaistudio service sets + * the number of requests allowed per minute to 360. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Google AI Studio. By default, the googleaistudio service sets + * the number of requests allowed per minute to 360. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link GoogleAiStudioServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public GoogleAiStudioServiceSettings build() { + _checkSingleUse(); + + return new GoogleAiStudioServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link GoogleAiStudioServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, GoogleAiStudioServiceSettings::setupGoogleAiStudioServiceSettingsDeserializer); + + protected static void setupGoogleAiStudioServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioTaskType.java new file mode 100644 index 000000000..7c9fa04ea --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioTaskType.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_googleaistudio; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum GoogleAiStudioTaskType implements JsonEnum { + Completion("completion"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + GoogleAiStudioTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + GoogleAiStudioTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/ServiceType.java new file mode 100644 index 000000000..cc2d8aca2 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_googleaistudio; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Googleaistudio("googleaistudio"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAIServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAIServiceSettings.java new file mode 100644 index 000000000..8482cbdfa --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAIServiceSettings.java @@ -0,0 +1,300 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_googlevertexai; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_googlevertexai.GoogleVertexAIServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class GoogleVertexAIServiceSettings implements JsonpSerializable { + private final String location; + + private final String modelId; + + private final String projectId; + + @Nullable + private final RateLimitSetting rateLimit; + + private final String serviceAccountJson; + + // --------------------------------------------------------------------------------------------- + + private GoogleVertexAIServiceSettings(Builder builder) { + + this.location = ApiTypeHelper.requireNonNull(builder.location, this, "location"); + this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); + this.projectId = ApiTypeHelper.requireNonNull(builder.projectId, this, "projectId"); + this.rateLimit = builder.rateLimit; + this.serviceAccountJson = ApiTypeHelper.requireNonNull(builder.serviceAccountJson, this, "serviceAccountJson"); + + } + + public static GoogleVertexAIServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The name of the location to use for the inference task. Refer to + * the Google documentation for the list of supported locations. + *

+ * API name: {@code location} + */ + public final String location() { + return this.location; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * Google documentation for the list of supported models. + *

+ * API name: {@code model_id} + */ + public final String modelId() { + return this.modelId; + } + + /** + * Required - The name of the project to use for the inference task. + *

+ * API name: {@code project_id} + */ + public final String projectId() { + return this.projectId; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Google Vertex AI. By default, the googlevertexai service sets + * the number of requests allowed per minute to 30.000. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Required - A valid service account in JSON format for the Google Vertex AI + * API. + *

+ * API name: {@code service_account_json} + */ + public final String serviceAccountJson() { + return this.serviceAccountJson; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("location"); + generator.write(this.location); + + generator.writeKey("model_id"); + generator.write(this.modelId); + + generator.writeKey("project_id"); + generator.write(this.projectId); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + generator.writeKey("service_account_json"); + generator.write(this.serviceAccountJson); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link GoogleVertexAIServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String location; + + private String modelId; + + private String projectId; + + @Nullable + private RateLimitSetting rateLimit; + + private String serviceAccountJson; + + /** + * Required - The name of the location to use for the inference task. Refer to + * the Google documentation for the list of supported locations. + *

+ * API name: {@code location} + */ + public final Builder location(String value) { + this.location = value; + return this; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * Google documentation for the list of supported models. + *

+ * API name: {@code model_id} + */ + public final Builder modelId(String value) { + this.modelId = value; + return this; + } + + /** + * Required - The name of the project to use for the inference task. + *

+ * API name: {@code project_id} + */ + public final Builder projectId(String value) { + this.projectId = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Google Vertex AI. By default, the googlevertexai service sets + * the number of requests allowed per minute to 30.000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Google Vertex AI. By default, the googlevertexai service sets + * the number of requests allowed per minute to 30.000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * Required - A valid service account in JSON format for the Google Vertex AI + * API. + *

+ * API name: {@code service_account_json} + */ + public final Builder serviceAccountJson(String value) { + this.serviceAccountJson = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link GoogleVertexAIServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public GoogleVertexAIServiceSettings build() { + _checkSingleUse(); + + return new GoogleVertexAIServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link GoogleVertexAIServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, GoogleVertexAIServiceSettings::setupGoogleVertexAIServiceSettingsDeserializer); + + protected static void setupGoogleVertexAIServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::location, JsonpDeserializer.stringDeserializer(), "location"); + op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); + op.add(Builder::projectId, JsonpDeserializer.stringDeserializer(), "project_id"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::serviceAccountJson, JsonpDeserializer.stringDeserializer(), "service_account_json"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskSettings.java new file mode 100644 index 000000000..99ea25c03 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskSettings.java @@ -0,0 +1,204 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_googlevertexai; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_googlevertexai.GoogleVertexAITaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class GoogleVertexAITaskSettings implements JsonpSerializable { + @Nullable + private final Boolean autoTruncate; + + @Nullable + private final Integer topN; + + // --------------------------------------------------------------------------------------------- + + private GoogleVertexAITaskSettings(Builder builder) { + + this.autoTruncate = builder.autoTruncate; + this.topN = builder.topN; + + } + + public static GoogleVertexAITaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * For a text_embedding task, truncate inputs longer than the + * maximum token length automatically. + *

+ * API name: {@code auto_truncate} + */ + @Nullable + public final Boolean autoTruncate() { + return this.autoTruncate; + } + + /** + * For a rerank task, the number of the top N documents that should + * be returned. + *

+ * API name: {@code top_n} + */ + @Nullable + public final Integer topN() { + return this.topN; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.autoTruncate != null) { + generator.writeKey("auto_truncate"); + generator.write(this.autoTruncate); + + } + if (this.topN != null) { + generator.writeKey("top_n"); + generator.write(this.topN); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link GoogleVertexAITaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private Boolean autoTruncate; + + @Nullable + private Integer topN; + + /** + * For a text_embedding task, truncate inputs longer than the + * maximum token length automatically. + *

+ * API name: {@code auto_truncate} + */ + public final Builder autoTruncate(@Nullable Boolean value) { + this.autoTruncate = value; + return this; + } + + /** + * For a rerank task, the number of the top N documents that should + * be returned. + *

+ * API name: {@code top_n} + */ + public final Builder topN(@Nullable Integer value) { + this.topN = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link GoogleVertexAITaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public GoogleVertexAITaskSettings build() { + _checkSingleUse(); + + return new GoogleVertexAITaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link GoogleVertexAITaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, GoogleVertexAITaskSettings::setupGoogleVertexAITaskSettingsDeserializer); + + protected static void setupGoogleVertexAITaskSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::autoTruncate, JsonpDeserializer.booleanDeserializer(), "auto_truncate"); + op.add(Builder::topN, JsonpDeserializer.integerDeserializer(), "top_n"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskType.java new file mode 100644 index 000000000..4b1859642 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskType.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_googlevertexai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum GoogleVertexAITaskType implements JsonEnum { + Rerank("rerank"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + GoogleVertexAITaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + GoogleVertexAITaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/ServiceType.java new file mode 100644 index 000000000..65b054f2e --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_googlevertexai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Googlevertexai("googlevertexai"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceServiceSettings.java new file mode 100644 index 000000000..07464ac58 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceServiceSettings.java @@ -0,0 +1,252 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_hugging_face; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_hugging_face.HuggingFaceServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class HuggingFaceServiceSettings implements JsonpSerializable { + private final String apiKey; + + @Nullable + private final RateLimitSetting rateLimit; + + private final String url; + + // --------------------------------------------------------------------------------------------- + + private HuggingFaceServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.rateLimit = builder.rateLimit; + this.url = ApiTypeHelper.requireNonNull(builder.url, this, "url"); + + } + + public static HuggingFaceServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid access token for your HuggingFace account. You can create + * or find your access tokens on the HuggingFace settings page. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Hugging Face. By default, the hugging_face service sets the + * number of requests allowed per minute to 3000. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Required - The URL endpoint to use for the requests. + *

+ * API name: {@code url} + */ + public final String url() { + return this.url; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + generator.writeKey("url"); + generator.write(this.url); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link HuggingFaceServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + @Nullable + private RateLimitSetting rateLimit; + + private String url; + + /** + * Required - A valid access token for your HuggingFace account. You can create + * or find your access tokens on the HuggingFace settings page. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Hugging Face. By default, the hugging_face service sets the + * number of requests allowed per minute to 3000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Hugging Face. By default, the hugging_face service sets the + * number of requests allowed per minute to 3000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * Required - The URL endpoint to use for the requests. + *

+ * API name: {@code url} + */ + public final Builder url(String value) { + this.url = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link HuggingFaceServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public HuggingFaceServiceSettings build() { + _checkSingleUse(); + + return new HuggingFaceServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link HuggingFaceServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, HuggingFaceServiceSettings::setupHuggingFaceServiceSettingsDeserializer); + + protected static void setupHuggingFaceServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::url, JsonpDeserializer.stringDeserializer(), "url"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceTaskType.java new file mode 100644 index 000000000..3a36ada42 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceTaskType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_hugging_face; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum HuggingFaceTaskType implements JsonEnum { + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + HuggingFaceTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + HuggingFaceTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/ServiceType.java new file mode 100644 index 000000000..870661dba --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_hugging_face; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + HuggingFace("hugging_face"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAIServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAIServiceSettings.java new file mode 100644 index 000000000..26f5e7643 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAIServiceSettings.java @@ -0,0 +1,297 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_jinaai; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_jinaai.JinaAIServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class JinaAIServiceSettings implements JsonpSerializable { + private final String apiKey; + + @Nullable + private final String modelId; + + @Nullable + private final RateLimitSetting rateLimit; + + @Nullable + private final SimilarityType similarity; + + // --------------------------------------------------------------------------------------------- + + private JinaAIServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.modelId = builder.modelId; + this.rateLimit = builder.rateLimit; + this.similarity = builder.similarity; + + } + + public static JinaAIServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid API key of your JinaAI account. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * The name of the model to use for the inference task. For a + * rerank task, it is required. For a text_embedding + * task, it is optional. + *

+ * API name: {@code model_id} + */ + @Nullable + public final String modelId() { + return this.modelId; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * JinaAI. By default, the jinaai service sets the number of + * requests allowed per minute to 2000 for all task types. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * For a text_embedding task, the similarity measure. One of + * cosine, dot_product, l2_norm. The default values varies with the embedding + * type. For example, a float embedding type uses a dot_product + * similarity measure by default. + *

+ * API name: {@code similarity} + */ + @Nullable + public final SimilarityType similarity() { + return this.similarity; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + if (this.modelId != null) { + generator.writeKey("model_id"); + generator.write(this.modelId); + + } + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + if (this.similarity != null) { + generator.writeKey("similarity"); + this.similarity.serialize(generator, mapper); + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link JinaAIServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + @Nullable + private String modelId; + + @Nullable + private RateLimitSetting rateLimit; + + @Nullable + private SimilarityType similarity; + + /** + * Required - A valid API key of your JinaAI account. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * The name of the model to use for the inference task. For a + * rerank task, it is required. For a text_embedding + * task, it is optional. + *

+ * API name: {@code model_id} + */ + public final Builder modelId(@Nullable String value) { + this.modelId = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * JinaAI. By default, the jinaai service sets the number of + * requests allowed per minute to 2000 for all task types. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * JinaAI. By default, the jinaai service sets the number of + * requests allowed per minute to 2000 for all task types. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * For a text_embedding task, the similarity measure. One of + * cosine, dot_product, l2_norm. The default values varies with the embedding + * type. For example, a float embedding type uses a dot_product + * similarity measure by default. + *

+ * API name: {@code similarity} + */ + public final Builder similarity(@Nullable SimilarityType value) { + this.similarity = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link JinaAIServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public JinaAIServiceSettings build() { + _checkSingleUse(); + + return new JinaAIServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link JinaAIServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, JinaAIServiceSettings::setupJinaAIServiceSettingsDeserializer); + + protected static void setupJinaAIServiceSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::similarity, SimilarityType._DESERIALIZER, "similarity"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskSettings.java new file mode 100644 index 000000000..25888bdce --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskSettings.java @@ -0,0 +1,261 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_jinaai; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_jinaai.JinaAITaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class JinaAITaskSettings implements JsonpSerializable { + @Nullable + private final Boolean returnDocuments; + + @Nullable + private final TextEmbeddingTask task; + + @Nullable + private final Integer topN; + + // --------------------------------------------------------------------------------------------- + + private JinaAITaskSettings(Builder builder) { + + this.returnDocuments = builder.returnDocuments; + this.task = builder.task; + this.topN = builder.topN; + + } + + public static JinaAITaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * For a rerank task, return the doc text within the results. + *

+ * API name: {@code return_documents} + */ + @Nullable + public final Boolean returnDocuments() { + return this.returnDocuments; + } + + /** + * For a text_embedding task, the task passed to the model. Valid + * values are: + *

    + *
  • classification: Use it for embeddings passed through a text + * classifier.
  • + *
  • clustering: Use it for the embeddings run through a + * clustering algorithm.
  • + *
  • ingest: Use it for storing document embeddings in a vector + * database.
  • + *
  • search: Use it for storing embeddings of search queries run + * against a vector database to find relevant documents.
  • + *
+ *

+ * API name: {@code task} + */ + @Nullable + public final TextEmbeddingTask task() { + return this.task; + } + + /** + * For a rerank task, the number of most relevant documents to + * return. It defaults to the number of the documents. If this inference + * endpoint is used in a text_similarity_reranker retriever query + * and top_n is set, it must be greater than or equal to + * rank_window_size in the query. + *

+ * API name: {@code top_n} + */ + @Nullable + public final Integer topN() { + return this.topN; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.returnDocuments != null) { + generator.writeKey("return_documents"); + generator.write(this.returnDocuments); + + } + if (this.task != null) { + generator.writeKey("task"); + this.task.serialize(generator, mapper); + } + if (this.topN != null) { + generator.writeKey("top_n"); + generator.write(this.topN); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link JinaAITaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private Boolean returnDocuments; + + @Nullable + private TextEmbeddingTask task; + + @Nullable + private Integer topN; + + /** + * For a rerank task, return the doc text within the results. + *

+ * API name: {@code return_documents} + */ + public final Builder returnDocuments(@Nullable Boolean value) { + this.returnDocuments = value; + return this; + } + + /** + * For a text_embedding task, the task passed to the model. Valid + * values are: + *

    + *
  • classification: Use it for embeddings passed through a text + * classifier.
  • + *
  • clustering: Use it for the embeddings run through a + * clustering algorithm.
  • + *
  • ingest: Use it for storing document embeddings in a vector + * database.
  • + *
  • search: Use it for storing embeddings of search queries run + * against a vector database to find relevant documents.
  • + *
+ *

+ * API name: {@code task} + */ + public final Builder task(@Nullable TextEmbeddingTask value) { + this.task = value; + return this; + } + + /** + * For a rerank task, the number of most relevant documents to + * return. It defaults to the number of the documents. If this inference + * endpoint is used in a text_similarity_reranker retriever query + * and top_n is set, it must be greater than or equal to + * rank_window_size in the query. + *

+ * API name: {@code top_n} + */ + public final Builder topN(@Nullable Integer value) { + this.topN = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link JinaAITaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public JinaAITaskSettings build() { + _checkSingleUse(); + + return new JinaAITaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link JinaAITaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, JinaAITaskSettings::setupJinaAITaskSettingsDeserializer); + + protected static void setupJinaAITaskSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::returnDocuments, JsonpDeserializer.booleanDeserializer(), "return_documents"); + op.add(Builder::task, TextEmbeddingTask._DESERIALIZER, "task"); + op.add(Builder::topN, JsonpDeserializer.integerDeserializer(), "top_n"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskType.java new file mode 100644 index 000000000..0d8771a24 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskType.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_jinaai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum JinaAITaskType implements JsonEnum { + Rerank("rerank"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + JinaAITaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + JinaAITaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/ServiceType.java new file mode 100644 index 000000000..f9df9ea40 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_jinaai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Jinaai("jinaai"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/SimilarityType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/SimilarityType.java new file mode 100644 index 000000000..970051384 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/SimilarityType.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_jinaai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum SimilarityType implements JsonEnum { + Cosine("cosine"), + + DotProduct("dot_product"), + + L2Norm("l2_norm"), + + ; + + private final String jsonValue; + + SimilarityType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + SimilarityType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/TextEmbeddingTask.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/TextEmbeddingTask.java new file mode 100644 index 000000000..1a1667667 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/TextEmbeddingTask.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_jinaai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum TextEmbeddingTask implements JsonEnum { + Classification("classification"), + + Clustering("clustering"), + + Ingest("ingest"), + + Search("search"), + + ; + + private final String jsonValue; + + TextEmbeddingTask(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + TextEmbeddingTask.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralServiceSettings.java new file mode 100644 index 000000000..fbcc888ec --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralServiceSettings.java @@ -0,0 +1,289 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_mistral; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Integer; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_mistral.MistralServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class MistralServiceSettings implements JsonpSerializable { + private final String apiKey; + + @Nullable + private final Integer maxInputTokens; + + private final String model; + + @Nullable + private final RateLimitSetting rateLimit; + + // --------------------------------------------------------------------------------------------- + + private MistralServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.maxInputTokens = builder.maxInputTokens; + this.model = ApiTypeHelper.requireNonNull(builder.model, this, "model"); + this.rateLimit = builder.rateLimit; + + } + + public static MistralServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid API key of your Mistral account. You can find your Mistral + * API keys or you can create a new one on the API Keys page. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * The maximum number of tokens per input before chunking occurs. + *

+ * API name: {@code max_input_tokens} + */ + @Nullable + public final Integer maxInputTokens() { + return this.maxInputTokens; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * Mistral models documentation for the list of available text embedding models. + *

+ * API name: {@code model} + */ + public final String model() { + return this.model; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * the Mistral API. By default, the mistral service sets the number + * of requests allowed per minute to 240. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + if (this.maxInputTokens != null) { + generator.writeKey("max_input_tokens"); + generator.write(this.maxInputTokens); + + } + generator.writeKey("model"); + generator.write(this.model); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link MistralServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + @Nullable + private Integer maxInputTokens; + + private String model; + + @Nullable + private RateLimitSetting rateLimit; + + /** + * Required - A valid API key of your Mistral account. You can find your Mistral + * API keys or you can create a new one on the API Keys page. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * The maximum number of tokens per input before chunking occurs. + *

+ * API name: {@code max_input_tokens} + */ + public final Builder maxInputTokens(@Nullable Integer value) { + this.maxInputTokens = value; + return this; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * Mistral models documentation for the list of available text embedding models. + *

+ * API name: {@code model} + */ + public final Builder model(String value) { + this.model = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * the Mistral API. By default, the mistral service sets the number + * of requests allowed per minute to 240. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * the Mistral API. By default, the mistral service sets the number + * of requests allowed per minute to 240. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link MistralServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public MistralServiceSettings build() { + _checkSingleUse(); + + return new MistralServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link MistralServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, MistralServiceSettings::setupMistralServiceSettingsDeserializer); + + protected static void setupMistralServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::maxInputTokens, JsonpDeserializer.integerDeserializer(), "max_input_tokens"); + op.add(Builder::model, JsonpDeserializer.stringDeserializer(), "model"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralTaskType.java new file mode 100644 index 000000000..94c34e12c --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralTaskType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_mistral; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum MistralTaskType implements JsonEnum { + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + MistralTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + MistralTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/ServiceType.java new file mode 100644 index 000000000..36f555841 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_mistral; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Mistral("mistral"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} From 0730514135ee46377e064b3a375e711c955be94e Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Wed, 26 Mar 2025 15:04:23 +0100 Subject: [PATCH 15/38] test fixes --- .../rest_client/RestClientOptions.java | 3 +- .../_helpers/ClientBuildersTest.java | 29 +- .../elasticsearch/model/BehaviorsTest2.java | 305 ------------------ 3 files changed, 28 insertions(+), 309 deletions(-) delete mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/BehaviorsTest2.java diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java index 707c23dcc..ba3b7f05f 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java @@ -104,8 +104,7 @@ public Function, Boolean> onWarnings() { @Override public void updateToken(String token) { - // TODO not many choices here - throw new UnsupportedOperationException("Operation unsupported, use rest5 client"); + throw new UnsupportedOperationException("Operation unsupported in the legacy client, use rest5 client"); } @Override diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java index 0c686520a..1a2297ab2 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java @@ -21,6 +21,8 @@ import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch._helpers.builders.ElasticsearchClientBuilder; +import co.elastic.clients.transport.rest5_client.Rest5ClientOptions; +import co.elastic.clients.transport.rest5_client.Rest5ClientTransport; import co.elastic.clients.transport.rest_client.RestClientOptions; import co.elastic.clients.transport.rest_client.RestClientTransport; import org.elasticsearch.client.RequestOptions; @@ -31,12 +33,13 @@ import java.net.URISyntaxException; import java.security.NoSuchAlgorithmException; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; public class ClientBuildersTest { @Test - public void build() throws IOException, URISyntaxException, NoSuchAlgorithmException { + public void buildLegacy() throws IOException, URISyntaxException, NoSuchAlgorithmException { // create client with helper ElasticsearchClient client = new ElasticsearchClientBuilder() @@ -54,7 +57,29 @@ public void build() throws IOException, URISyntaxException, NoSuchAlgorithmExcep assertTrue(client._transportOptions().keepResponseBodyOnException()); assertTrue(client._transportOptions().headers().size() == 3); - //assertTrue(client._transport().options().keepResponseBodyOnException()); TODO ? + // token update utility + ElasticsearchClient finalClient = client; + assertThrows(UnsupportedOperationException.class, () -> finalClient._transportOptions().updateToken("token")); + } + + @Test + public void buildRest5() throws IOException, URISyntaxException, NoSuchAlgorithmException { + + // create client with helper + ElasticsearchClient client = new co.elastic.clients.elasticsearch._helpers.builders.rest5_client.ElasticsearchClientBuilder() + .host("url") + .usernameAndPassword("elastic", "changeme") + .sslContext(SSLContext.getDefault()) + .build(); + + Rest5ClientOptions options = new Rest5ClientOptions(co.elastic.clients.transport.rest5_client.low_level.RequestOptions.DEFAULT, true); + + client = client.withTransportOptions(options); + + // checking options correctness + assertTrue(client._transport().getClass().equals(Rest5ClientTransport.class)); + assertTrue(client._transportOptions().keepResponseBodyOnException()); + assertTrue(client._transportOptions().headers().size() == 3); // token update utility diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/BehaviorsTest2.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/BehaviorsTest2.java deleted file mode 100644 index 0cf76cf29..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/BehaviorsTest2.java +++ /dev/null @@ -1,305 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.model; - -import co.elastic.clients.elasticsearch._types.ErrorCause; -import co.elastic.clients.elasticsearch._types.FieldSort; -import co.elastic.clients.elasticsearch._types.FieldValue; -import co.elastic.clients.elasticsearch._types.GeoLocation; -import co.elastic.clients.elasticsearch._types.GeoShapeRelation; -import co.elastic.clients.elasticsearch._types.SortOptions; -import co.elastic.clients.elasticsearch._types.SortOptionsBuilders; -import co.elastic.clients.elasticsearch._types.SortOrder; -import co.elastic.clients.elasticsearch._types.query_dsl.FunctionScoreQuery; -import co.elastic.clients.elasticsearch._types.query_dsl.MultiValueMode; -import co.elastic.clients.elasticsearch._types.query_dsl.Query; -import co.elastic.clients.elasticsearch._types.query_dsl.ShapeQuery; -import co.elastic.clients.elasticsearch._types.query_dsl.TermQuery; -import co.elastic.clients.elasticsearch.connector.UpdateIndexNameRequest; -import co.elastic.clients.elasticsearch.core.rank_eval.RankEvalQuery; -import co.elastic.clients.elasticsearch.core.search.SourceFilter; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.json.LazyDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.util.MapBuilder; -import org.junit.jupiter.api.Test; - -public class BehaviorsTest2 extends ModelTestCase { - - /** - * Test for SingleKeyDictionary transformed to a behavior. For regular fields, see NamedValue tests in {@link ClassStructureTest} - */ - @Test - public void testSingleKeyDictionary() { - TermQuery q = new TermQuery.Builder() - .queryName("query-name") - .field("field-name") - .value(FieldValue.of("some-value")) - .build(); - - q = checkJsonRoundtrip(q, "{\"field-name\":{\"_name\":\"query-name\",\"value\":\"some-value\"}}"); - - assertEquals("query-name", q.queryName()); - assertEquals("field-name", q.field()); - assertEquals("some-value", q.value().stringValue()); - } - - @Test - public void testAdditionalPropertyOnClass() { - ShapeQuery q = new ShapeQuery.Builder() - .queryName("query-name") - .field("field-name") - .shape(_0 -> _0 - .relation(GeoShapeRelation.Disjoint) - ) - .ignoreUnmapped(true) - .build(); - - q = checkJsonRoundtrip(q, - "{\"field-name\":{\"relation\":\"disjoint\"},\"_name\":\"query-name\",\"ignore_unmapped\":true}" - ); - - assertEquals("query-name", q.queryName()); - assertTrue(q.ignoreUnmapped()); - assertEquals(GeoShapeRelation.Disjoint, q.shape().relation()); - } - - @Test - public void testAdditionalPropertyOnContainer() { - // Regular variant - { - SortOptions so = SortOptions.of(_0 -> _0 - .doc(_1 -> _1.order(SortOrder.Asc)) - ); - - so = checkJsonRoundtrip(so, "{\"_doc\":{\"order\":\"asc\"}}"); - assertEquals(SortOptions.Kind.Doc, so._kind()); - assertEquals(SortOrder.Asc, so.doc().order()); - } - - // Regular variant - { - SortOptions so = SortOptionsBuilders.geoDistance() - .field("foo") - .location(GeoLocation.of(_b -> _b.text("someWKT"))) - .build() - ._toSortOptions(); - - so = checkJsonRoundtrip(so, "{\"_geo_distance\":{\"foo\":[\"someWKT\"]}}"); - assertEquals(SortOptions.Kind.GeoDistance, so._kind()); - assertEquals("foo", so.geoDistance().field()); - assertEquals("someWKT", so.geoDistance().location().get(0).text()); - } - - { - SortOptions so = SortOptions.of(_0 -> _0 - .score(_1 -> _1.order(SortOrder.Asc))); - - so = checkJsonRoundtrip(so, "{\"_score\":{\"order\":\"asc\"}}"); - assertEquals(SortOptions.Kind.Score, so._kind()); - assertEquals(SortOrder.Asc, so.score().order()); - } - - { - SortOptions so = SortOptions.of(_0 -> _0 - .script(_1 -> _1.script(_3 -> _3.source("blah"))) - ); - so = checkJsonRoundtrip(so, "{\"_script\":{\"script\":{\"source\":\"blah\"}}}"); - assertEquals("blah", so.script().script().source()); - - } - - // Additional property variant - { - SortOptions so = SortOptions.of(_0 -> _0 - .field(_1 -> _1.field("foo").order(SortOrder.Desc)) - ); - - so = checkJsonRoundtrip(so, "{\"foo\":{\"order\":\"desc\"}}"); - assertEquals(SortOptions.Kind.Field, so._kind()); - assertEquals("foo", so.field().field()); - assertEquals(SortOrder.Desc, so.field().order()); - } - } - - @Test - public void testAdditionalProperties() { - // Check that additional property map is initialized even if not set explicitly - ErrorCause err = new ErrorCause.Builder() - .reason("Foo") - .type("Bar") - .build(); - assertEquals(0, err.metadata().size()); - - err = new ErrorCause.Builder() - .reason("Some failure") - .type("Some type") - .metadata(MapBuilder.of( - "index", JsonData.of("test"), - "retries", JsonData.of(1) - )) - .build(); - - err = checkJsonRoundtrip(err, "{\"index\":\"test\",\"retries\":1,\"type\":\"Some type\",\"reason\":\"Some failure\"}"); - - assertEquals("Some failure", err.reason()); - assertEquals(1, err.metadata().get("retries").to(int.class).intValue()); - assertEquals("test", err.metadata().get("index").to(String.class)); - } - - @Test - public void testPrimitiveShortcutProperty() { - - // All-in-one: a variant, wrapping a single-key dictionary with a shortcut property - String json = "{\"term\":{\"some-field\":\"some-value\"}}"; - Query q = fromJson(json, Query.class); - - assertEquals("some-field", q.term().field()); - assertEquals("some-value", q.term().value().stringValue()); - - } - - @Test - public void testArrayShortcutProperty() { - - // Check that don't look ahead to handle the shortcut - ObjectDeserializer deser = (ObjectDeserializer) LazyDeserializer.unwrap(SourceFilter._DESERIALIZER); - assertEquals("includes", deser.shortcutProperty()); - assertFalse(deser.shortcutIsObject()); - - // Regular form - SourceFilter sf = fromJson("{\"includes\":[\"foo\",\"bar\"]}", SourceFilter.class); - assertEquals(2, sf.includes().size()); - assertEquals("foo", sf.includes().get(0)); - assertEquals("bar", sf.includes().get(1)); - - // Shortcut with an array value - sf = fromJson("[\"foo\",\"bar\"]", SourceFilter.class); - assertEquals(2, sf.includes().size()); - assertEquals("foo", sf.includes().get(0)); - assertEquals("bar", sf.includes().get(1)); - - // Shortcut with a single value (lenient array) - sf = fromJson("\"foo\"]", SourceFilter.class); - assertEquals(1, sf.includes().size()); - assertEquals("foo", sf.includes().get(0)); - } - - @Test - public void testEnumShortcutProperty() { - - // Check that we don't look ahead to handle the shortcut - ObjectDeserializer deser = (ObjectDeserializer) LazyDeserializer.unwrap(FieldSort._DESERIALIZER); - assertEquals("order", deser.shortcutProperty()); - assertFalse(deser.shortcutIsObject()); - - // We have to test on the enclosing SortOption as FieldSort is used as a single-key dict - SortOptions so = fromJson("{\"foo\":{\"order\":\"asc\"}}", SortOptions.class); - - assertEquals("foo", so.field().field()); - assertEquals(SortOrder.Asc, so.field().order()); - - so = fromJson("{\"foo\":\"asc\"}", SortOptions.class); - - assertEquals("foo", so.field().field()); - assertEquals(SortOrder.Asc, so.field().order()); - } - - @Test - public void testObjectShortcutProperty() { - - // Check that we look ahead to handle the shortcut - ObjectDeserializer deser = (ObjectDeserializer) LazyDeserializer.unwrap(RankEvalQuery._DESERIALIZER); - assertEquals("query", deser.shortcutProperty()); - assertTrue(deser.shortcutIsObject()); - - // Standard form - RankEvalQuery req = fromJson("{\"query\":{\"term\":{\"foo\":{\"value\":\"bar\"}}}}", RankEvalQuery.class); - - assertEquals("foo", req.query().term().field()); - assertEquals("bar", req.query().term().value().stringValue()); - - // Shortcut form - req = fromJson("{\"term\":{\"foo\":{\"value\":\"bar\"}}}", RankEvalQuery.class); - - assertEquals("foo", req.query().term().field()); - assertEquals("bar", req.query().term().value().stringValue()); - - // Nested shortcuts - req = fromJson("{\"term\":{\"foo\":\"bar\"}}", RankEvalQuery.class); - - assertEquals("foo", req.query().term().field()); - assertEquals("bar", req.query().term().value().stringValue()); - } - - @Test - public void testFunctionScoreQuery() { - String shortcut = - "{" + - " \"gauss\": {" + - " \"date\": {" + - " \"origin\": \"2013-09-17\", " + - " \"scale\": \"10d\"," + - " \"offset\": \"5d\", " + - " \"decay\": 0.5" + - " }," + - " \"multi_value_mode\": \"avg\"" + - " }" + - "}"; - - String full = - "{" + - " \"functions\": [" + - " {" + - " \"gauss\": {" + - " \"date\": {" + - " \"origin\": \"2013-09-17\"," + - " \"scale\": \"10d\"," + - " \"offset\": \"5d\"," + - " \"decay\": 0.5" + - " }," + - " \"multi_value_mode\": \"avg\"" + - " }" + - " }" + - " ]" + - "}"; - - FunctionScoreQuery fsq; - - fsq = fromJson(full, FunctionScoreQuery.class); - assertEquals(MultiValueMode.Avg, fsq.functions().get(0).gauss().untyped().multiValueMode()); - - fsq = fromJson(shortcut, FunctionScoreQuery.class); - assertEquals(MultiValueMode.Avg, fsq.functions().get(0).gauss().untyped().multiValueMode()); - } - - @Test - public void testWithNull() { - - String jsonValue = "{\"index_name\":\"value\"}"; - String jsonNull = "{\"index_name\":null}"; - UpdateIndexNameRequest updateValue = UpdateIndexNameRequest.of(u -> u.connectorId("connector").indexName("value")); - UpdateIndexNameRequest updateNull = UpdateIndexNameRequest.of(u -> u.connectorId("connector").indexNameWithNull()); - - assertEquals(jsonValue,toJson(updateValue)); - assertEquals(jsonNull,toJson(updateNull)); - } -} From 4343f007237363d4ba63ca78a449d3db8c7e3fcb Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Wed, 26 Mar 2025 15:26:30 +0100 Subject: [PATCH 16/38] esql test config fix --- .../esql/EsqlAdapterEndToEndTest.java | 52 ++++++++++++++----- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java index eaa413e2b..c180dfa3d 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java @@ -25,6 +25,9 @@ import co.elastic.clients.elasticsearch._helpers.esql.jdbc.ResultSetEsqlAdapter; import co.elastic.clients.elasticsearch._helpers.esql.objects.ObjectsEsqlAdapter; import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.rest5_client.Rest5ClientTransport; +import co.elastic.clients.transport.rest5_client.low_level.ESRequest; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; import co.elastic.clients.transport.rest_client.RestClientTransport; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.databind.PropertyNamingStrategies; @@ -55,18 +58,33 @@ public class EsqlAdapterEndToEndTest extends Assertions { @BeforeAll public static void setup() throws Exception { ElasticsearchClient global = ElasticsearchTestServer.global().client(); - RestClient restClient = ((RestClientTransport) global._transport()).restClient(); - esClient = new ElasticsearchClient(new RestClientTransport(restClient, new JacksonJsonpMapper())); + if (global._transport() instanceof RestClientTransport) { + RestClient restClient = ((RestClientTransport) global._transport()).restClient(); + esClient = new ElasticsearchClient(new RestClientTransport(restClient, new JacksonJsonpMapper())); - esClient.indices().delete(d -> d.index("employees").ignoreUnavailable(true)); + esClient.indices().delete(d -> d.index("employees").ignoreUnavailable(true)); - Request request = new Request("POST", "/employees/_bulk?refresh=true"); + Request request = new Request("POST", "/employees/_bulk?refresh=true"); - InputStream resourceAsStream = EsqlAdapterTest.class.getResourceAsStream("employees.ndjson"); - byte[] bytes = IOUtils.toByteArray(resourceAsStream); - request.setEntity(new ByteArrayEntity(bytes, ContentType.APPLICATION_JSON)); + InputStream resourceAsStream = EsqlAdapterTest.class.getResourceAsStream("employees.ndjson"); + byte[] bytes = IOUtils.toByteArray(resourceAsStream); + request.setEntity(new ByteArrayEntity(bytes, ContentType.APPLICATION_JSON)); - restClient.performRequest(request); + restClient.performRequest(request); + } else if (global._transport() instanceof Rest5ClientTransport) { + Rest5Client restClient = ((Rest5ClientTransport) global._transport()).restClient(); + esClient = new ElasticsearchClient(new Rest5ClientTransport(restClient, new JacksonJsonpMapper())); + + esClient.indices().delete(d -> d.index("employees").ignoreUnavailable(true)); + + ESRequest request = new ESRequest("POST", "/employees/_bulk?refresh=true"); + + InputStream resourceAsStream = EsqlAdapterTest.class.getResourceAsStream("employees.ndjson"); + byte[] bytes = IOUtils.toByteArray(resourceAsStream); + request.setEntity(new org.apache.hc.core5.http.io.entity.ByteArrayEntity(bytes, org.apache.hc.core5.http.ContentType.APPLICATION_JSON)); + + restClient.performRequest(request); + } } @Test @@ -74,7 +92,8 @@ public void resultSetTest() throws Exception { ResultSet rs = esClient.esql().query( ResultSetEsqlAdapter.INSTANCE, - "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | SORT emp_no | LIMIT 300", + "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | " + + "SORT emp_no | LIMIT 300", // Testing parameters. Note that FROM and LIMIT do not accept parameters "10042", "10002" ); @@ -116,7 +135,8 @@ public void resultSetTest() throws Exception { public void objectsTest() throws Exception { Iterable result = esClient.esql().query( ObjectsEsqlAdapter.of(EmpData.class), - "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | SORT emp_no | LIMIT 300", + "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | " + + "SORT emp_no | LIMIT 300", // Testing parameters. Note that FROM and LIMIT do not accept parameters "10042", "10002" ); @@ -152,12 +172,14 @@ public void objectsTest() throws Exception { @Test public void asyncObjects() throws Exception { - ElasticsearchAsyncClient asyncClient = new ElasticsearchAsyncClient(esClient._transport(), esClient._transportOptions()); + ElasticsearchAsyncClient asyncClient = new ElasticsearchAsyncClient(esClient._transport(), + esClient._transportOptions()); CompletableFuture> future = asyncClient.esql().query( ObjectsEsqlAdapter.of(EmpData.class), - "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | SORT emp_no | LIMIT 300", + "FROM employees | WHERE emp_no == ? or emp_no == ? | KEEP emp_no, job_positions, hire_date | " + + "SORT emp_no | LIMIT 300", // Testing parameters. Note that FROM and LIMIT do not accept parameters "10042", "10002" ); @@ -169,7 +191,8 @@ public void asyncObjects() throws Exception { EmpData emp = it.next(); assertEquals("10002", emp.empNo); List jobPositions = emp.jobPositions; - // In addition to the value, this tests that single strings are correctly deserialized as a list + // In addition to the value, this tests that single strings are correctly deserialized + // as a list assertEquals(Arrays.asList("Senior Team Lead"), emp.jobPositions); } @@ -183,7 +206,8 @@ public void asyncObjects() throws Exception { assertTrue(emp.jobPositions.contains("Junior Developer")); assertEquals("1993-03-21T00:00:00Z[UTC]", - DateTimeFormatter.ISO_DATE_TIME.format(emp.hireDate.toInstant().atZone(ZoneId.of("UTC"))) + DateTimeFormatter.ISO_DATE_TIME.format(emp.hireDate.toInstant().atZone(ZoneId.of( + "UTC"))) ); } From bab380521e168a40b1c9d0c0dcc897016d8c7572 Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Wed, 26 Mar 2025 16:31:50 +0100 Subject: [PATCH 17/38] porting low level client unit tests --- java-client/build.gradle.kts | 14 + .../rest5_client/Rest5ClientHttpClient.java | 20 +- .../rest5_client/low_level/Cancellable.java | 2 +- .../{ESRequest.java => Request.java} | 8 +- .../{ESResponse.java => Response.java} | 4 +- .../low_level/ResponseException.java | 10 +- .../low_level/ResponseListener.java | 2 +- .../rest5_client/low_level/Rest5Client.java | 22 +- .../low_level/WarningFailureException.java | 10 +- .../esql/EsqlAdapterEndToEndTest.java | 7 +- .../transport/rest5_client/TransportTest.java | 4 +- .../BasicAsyncResponseConsumerTests.java | 74 ++ .../ClientsGraalVMThreadsFilter.java | 33 + .../low_level/DeadHostStateTests.java | 133 ++++ .../FailureTrackingResponseListenerTests.java | 108 +++ .../HasAttributeNodeSelectorTests.java | 74 ++ .../HostsTrackingFailureListener.java | 61 ++ .../low_level/NodeSelectorTests.java | 126 ++++ .../rest5_client/low_level/NodeTests.java | 173 +++++ .../PreferHasAttributeNodeSelectorTests.java | 84 +++ .../low_level/RequestLoggerTests.java | 200 +++++ .../low_level/RequestOptionsTests.java | 208 ++++++ .../rest5_client/low_level/RequestTests.java | 245 +++++++ .../low_level/ResponseExceptionTests.java | 91 +++ .../RestClientBuilderIntegTests.java | 223 ++++++ .../low_level/RestClientBuilderTests.java | 266 +++++++ .../RestClientGzipCompressionTests.java | 251 +++++++ .../RestClientMultipleHostsIntegTests.java | 387 ++++++++++ .../RestClientMultipleHostsTests.java | 333 +++++++++ .../RestClientSingleHostIntegTests.java | 447 ++++++++++++ .../low_level/RestClientSingleHostTests.java | 681 ++++++++++++++++++ .../low_level/RestClientTestCase.java | 119 +++ .../low_level/RestClientTestUtil.java | 117 +++ .../low_level/RestClientTests.java | 447 ++++++++++++ .../RestClientDocumentation.java | 461 ++++++++++++ 35 files changed, 5399 insertions(+), 46 deletions(-) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/{ESRequest.java => Request.java} (97%) rename java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/{ESResponse.java => Response.java} (98%) create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncResponseConsumerTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/ClientsGraalVMThreadsFilter.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/DeadHostStateTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/FailureTrackingResponseListenerTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/HasAttributeNodeSelectorTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/HostsTrackingFailureListener.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/NodeSelectorTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/NodeTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/PreferHasAttributeNodeSelectorTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestLoggerTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptionsTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/ResponseExceptionTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderIntegTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientGzipCompressionTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientMultipleHostsIntegTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientMultipleHostsTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostIntegTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestCase.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestUtil.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/documentation/RestClientDocumentation.java diff --git a/java-client/build.gradle.kts b/java-client/build.gradle.kts index 1af0efc75..840605044 100644 --- a/java-client/build.gradle.kts +++ b/java-client/build.gradle.kts @@ -273,6 +273,20 @@ dependencies { // Apache-2.0 // https://github.com/awaitility/awaitility testImplementation("org.awaitility", "awaitility", "4.2.0") + + // MIT + // https://github.com/mockito/mockito + testImplementation("org.mockito","mockito-core","5.12.0") + + // Apache-2.0 + // https://github.com/randomizedtesting/randomizedtesting + testImplementation("com.carrotsearch.randomizedtesting","randomizedtesting-runner","2.8.1") + + // Apache-2.0 + // https://github.com/elastic/mocksocket + testImplementation("org.elasticsearch","mocksocket","1.2") + + } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java index 792434303..e7e8d1b83 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java @@ -23,8 +23,6 @@ import co.elastic.clients.transport.http.HeaderMap; import co.elastic.clients.transport.http.TransportHttpClient; import co.elastic.clients.transport.rest5_client.low_level.Cancellable; -import co.elastic.clients.transport.rest5_client.low_level.ESRequest; -import co.elastic.clients.transport.rest5_client.low_level.ESResponse; import co.elastic.clients.transport.rest5_client.low_level.ResponseListener; import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; import co.elastic.clients.util.BinaryData; @@ -91,8 +89,8 @@ public Rest5ClientOptions createOptions(@Nullable TransportOptions options) { public Response performRequest(String endpointId, @Nullable Node node, Request request, TransportOptions options) throws IOException { Rest5ClientOptions rcOptions = Rest5ClientOptions.of(options); - ESRequest restRequest = createRestRequest(request, rcOptions); - ESResponse restResponse = restClient.performRequest(restRequest); + co.elastic.clients.transport.rest5_client.low_level.Request restRequest = createRestRequest(request, rcOptions); + co.elastic.clients.transport.rest5_client.low_level.Response restResponse = restClient.performRequest(restRequest); return new RestResponse(restResponse); } @@ -102,7 +100,7 @@ public CompletableFuture performRequestAsync( ) { RequestFuture future = new RequestFuture<>(); - ESRequest restRequest; + co.elastic.clients.transport.rest5_client.low_level.Request restRequest; try { Rest5ClientOptions rcOptions = Rest5ClientOptions.of(options); @@ -115,7 +113,7 @@ public CompletableFuture performRequestAsync( future.cancellable = restClient.performRequestAsync(restRequest, new ResponseListener() { @Override - public void onSuccess(ESResponse response) { + public void onSuccess(co.elastic.clients.transport.rest5_client.low_level.Response response) { future.complete(new RestResponse(response)); } @@ -133,8 +131,8 @@ public void close() throws IOException { this.restClient.close(); } - private ESRequest createRestRequest(Request request, Rest5ClientOptions options) { - ESRequest clientReq = new ESRequest( + private co.elastic.clients.transport.rest5_client.low_level.Request createRestRequest(Request request, Rest5ClientOptions options) { + co.elastic.clients.transport.rest5_client.low_level.Request clientReq = new co.elastic.clients.transport.rest5_client.low_level.Request( request.method(), request.path() ); @@ -180,9 +178,9 @@ private ESRequest createRestRequest(Request request, Rest5ClientOptions options) } static class RestResponse implements Response { - private final ESResponse restResponse; + private final co.elastic.clients.transport.rest5_client.low_level.Response restResponse; - RestResponse(ESResponse restResponse) { + RestResponse(co.elastic.clients.transport.rest5_client.low_level.Response restResponse) { this.restResponse = restResponse; } @@ -234,7 +232,7 @@ public BinaryData body() throws IOException { @Nullable @Override - public ESResponse originalResponse() { + public co.elastic.clients.transport.rest5_client.low_level.Response originalResponse() { return this.restResponse; } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Cancellable.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Cancellable.java index 8cc8d2391..05bc7b749 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Cancellable.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Cancellable.java @@ -26,7 +26,7 @@ /** * Represents an operation that can be cancelled. * Returned when executing async requests through - * {@link Rest5Client#performRequestAsync(ESRequest, ResponseListener)}, so that the request + * {@link Rest5Client#performRequestAsync(Request, ResponseListener)}, so that the request * can be cancelled if needed. Cancelling a request will result in calling * {@link HttpUriRequestBase#abort()} on the underlying * request object, which will in turn cancel its corresponding {@link java.util.concurrent.Future}. diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ESRequest.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Request.java similarity index 97% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ESRequest.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Request.java index aa13589b9..e0d0855d3 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ESRequest.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Request.java @@ -33,7 +33,7 @@ /** * HTTP Request to Elasticsearch. */ -public final class ESRequest { +public final class Request { private final String method; private final String endpoint; private final Map parameters = new HashMap<>(); @@ -42,11 +42,11 @@ public final class ESRequest { private RequestOptions options = RequestOptions.DEFAULT; /** - * Create the {@linkplain ESRequest}. + * Create the {@linkplain Request}. * @param method the HTTP method * @param endpoint the path of the request (without scheme, host, port, or prefix) */ - public ESRequest(String method, String endpoint) { + public Request(String method, String endpoint) { this.method = Objects.requireNonNull(method, "method cannot be null"); this.endpoint = Objects.requireNonNull(endpoint, "endpoint cannot be null"); } @@ -173,7 +173,7 @@ public boolean equals(Object obj) { return true; } - ESRequest other = (ESRequest) obj; + Request other = (Request) obj; return method.equals(other.method) && endpoint.equals(other.endpoint) && parameters.equals(other.parameters) diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ESResponse.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Response.java similarity index 98% rename from java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ESResponse.java rename to java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Response.java index caf55dc81..ce9c9afa7 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ESResponse.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Response.java @@ -37,13 +37,13 @@ * Holds an elasticsearch response. It wraps the {@link BasicClassicHttpResponse} returned and associates * it with its corresponding {@link RequestLine} and {@link HttpHost}. */ -public class ESResponse { +public class Response { private final RequestLine requestLine; private final HttpHost host; private final ClassicHttpResponse response; - ESResponse(RequestLine requestLine, HttpHost host, ClassicHttpResponse response) { + Response(RequestLine requestLine, HttpHost host, ClassicHttpResponse response) { Objects.requireNonNull(requestLine, "requestLine cannot be null"); Objects.requireNonNull(host, "host cannot be null"); Objects.requireNonNull(response, "response cannot be null"); diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseException.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseException.java index 019028018..f02b9803a 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseException.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseException.java @@ -33,14 +33,14 @@ */ public final class ResponseException extends IOException { - private final ESResponse response; + private final Response response; - public ResponseException(ESResponse response) throws IOException { + public ResponseException(Response response) throws IOException { super(buildMessage(response)); this.response = response; } - static String buildMessage(ESResponse response) throws IOException { + static String buildMessage(Response response) throws IOException { String message = String.format( Locale.ROOT, "method [%s], host [%s], URI [%s], status line [%s]", @@ -70,9 +70,9 @@ static String buildMessage(ESResponse response) throws IOException { } /** - * Returns the {@link ESResponse} that caused this exception to be thrown. + * Returns the {@link Response} that caused this exception to be thrown. */ - public ESResponse getResponse() { + public Response getResponse() { return response; } } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseListener.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseListener.java index 079a50405..0ee20741f 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseListener.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/ResponseListener.java @@ -33,7 +33,7 @@ public interface ResponseListener { /** * Method invoked if the request yielded a successful response */ - void onSuccess(ESResponse response); + void onSuccess(Response response); /** * Method invoked if the request failed. There are two main categories of failures: connection failures (usually diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java index 052c611d7..1843ae004 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java @@ -95,7 +95,7 @@ * The hosts that are part of the cluster need to be provided at creation time, but can also be replaced later * by calling {@link #setNodes(Collection)}. *

- * The method {@link #performRequest(ESRequest)} allows to send a request to the cluster. When + * The method {@link #performRequest(Request)} allows to send a request to the cluster. When * sending a request, a host gets selected out of the provided ones in a round-robin fashion. Failing hosts * are marked dead and * retried after a certain amount of time (minimum 1 minute, maximum 30 minutes), depending on how many @@ -296,13 +296,13 @@ public boolean isRunning() { * @throws ResponseException in case Elasticsearch responded with a status code that indicated an * error */ - public ESResponse performRequest(ESRequest request) throws IOException { + public Response performRequest(Request request) throws IOException { InternalRequest internalRequest = new InternalRequest(request); return performRequest(nextNodes(), internalRequest, null); } - private ESResponse performRequest(final Iterator nodes, final InternalRequest request, - Exception previousException) + private Response performRequest(final Iterator nodes, final InternalRequest request, + Exception previousException) throws IOException { RequestContext context = request.createContextForNextAttempt(nodes.next()); ClassicHttpResponse httpResponse; @@ -360,7 +360,7 @@ private ResponseOrResponseException convertResponse(InternalRequest request, Nod } } - ESResponse response = new ESResponse(new RequestLine(request.httpRequest), node.getHost(), httpResponse); + Response response = new Response(new RequestLine(request.httpRequest), node.getHost(), httpResponse); if (isCorrectServerResponse(statusCode)) { onResponse(node); if (request.warningsHandler.warningsShouldFailRequest(response.getWarnings())) { @@ -395,7 +395,7 @@ private ResponseOrResponseException convertResponse(InternalRequest request, Nod * @param responseListener the {@link ResponseListener} to notify when the * request is completed or fails */ - public Cancellable performRequestAsync(ESRequest request, ResponseListener responseListener) { + public Cancellable performRequestAsync(Request request, ResponseListener responseListener) { try { FailureTrackingResponseListener failureTrackingResponseListener = new FailureTrackingResponseListener(responseListener); @@ -726,7 +726,7 @@ static class FailureTrackingResponseListener { /** * Notifies the caller of a response through the wrapped listener */ - void onSuccess(ESResponse response) { + void onSuccess(Response response) { responseListener.onSuccess(response); } @@ -812,12 +812,12 @@ public void remove() { } private class InternalRequest { - private final ESRequest request; + private final Request request; private final HttpUriRequestBase httpRequest; private final Cancellable cancellable; private final WarningsHandler warningsHandler; - InternalRequest(ESRequest request) { + InternalRequest(Request request) { this.request = request; Map params = new HashMap<>(request.getParameters()); params.putAll(request.getOptions().getParameters()); @@ -897,10 +897,10 @@ private static class RequestContext { } private static class ResponseOrResponseException { - private final ESResponse response; + private final Response response; private final ResponseException responseException; - ResponseOrResponseException(ESResponse response) { + ResponseOrResponseException(Response response) { this.response = Objects.requireNonNull(response); this.responseException = null; } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/WarningFailureException.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/WarningFailureException.java index b50f083aa..706b8f586 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/WarningFailureException.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/WarningFailureException.java @@ -24,7 +24,7 @@ import static co.elastic.clients.transport.rest5_client.low_level.ResponseException.buildMessage; /** - * This exception is used to indicate that one or more {@link ESResponse#getWarnings()} exist + * This exception is used to indicate that one or more {@link Response#getWarnings()} exist * and is typically used when the {@link Rest5Client} is set to fail by setting * {@link Rest5ClientBuilder#setStrictDeprecationMode(boolean)} to `true`. */ @@ -32,9 +32,9 @@ // if the exception is not of type ElasticsearchException or RuntimeException it will be wrapped in a UncategorizedExecutionException public final class WarningFailureException extends RuntimeException { - private final ESResponse response; + private final Response response; - public WarningFailureException(ESResponse response) throws IOException { + public WarningFailureException(Response response) throws IOException { super(buildMessage(response)); this.response = response; } @@ -50,9 +50,9 @@ public WarningFailureException(ESResponse response) throws IOException { } /** - * Returns the {@link ESResponse} that caused this exception to be thrown. + * Returns the {@link Response} that caused this exception to be thrown. */ - public ESResponse getResponse() { + public Response getResponse() { return response; } } diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java index c180dfa3d..232e4e238 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java @@ -26,7 +26,7 @@ import co.elastic.clients.elasticsearch._helpers.esql.objects.ObjectsEsqlAdapter; import co.elastic.clients.json.jackson.JacksonJsonpMapper; import co.elastic.clients.transport.rest5_client.Rest5ClientTransport; -import co.elastic.clients.transport.rest5_client.low_level.ESRequest; +import co.elastic.clients.transport.rest5_client.low_level.Request; import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; import co.elastic.clients.transport.rest_client.RestClientTransport; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -35,7 +35,6 @@ import org.apache.commons.io.IOUtils; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.ContentType; -import org.elasticsearch.client.Request; import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -64,7 +63,7 @@ public static void setup() throws Exception { esClient.indices().delete(d -> d.index("employees").ignoreUnavailable(true)); - Request request = new Request("POST", "/employees/_bulk?refresh=true"); + org.elasticsearch.client.Request request = new org.elasticsearch.client.Request("POST", "/employees/_bulk?refresh=true"); InputStream resourceAsStream = EsqlAdapterTest.class.getResourceAsStream("employees.ndjson"); byte[] bytes = IOUtils.toByteArray(resourceAsStream); @@ -77,7 +76,7 @@ public static void setup() throws Exception { esClient.indices().delete(d -> d.index("employees").ignoreUnavailable(true)); - ESRequest request = new ESRequest("POST", "/employees/_bulk?refresh=true"); + Request request = new Request("POST", "/employees/_bulk?refresh=true"); InputStream resourceAsStream = EsqlAdapterTest.class.getResourceAsStream("employees.ndjson"); byte[] bytes = IOUtils.toByteArray(resourceAsStream); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/TransportTest.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/TransportTest.java index 526967f54..26d314e5c 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/TransportTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/TransportTest.java @@ -25,7 +25,7 @@ import co.elastic.clients.transport.TransportException; import co.elastic.clients.transport.http.RepeatableBodyResponse; import co.elastic.clients.transport.http.TransportHttpClient; -import co.elastic.clients.transport.rest5_client.low_level.ESResponse; +import co.elastic.clients.transport.rest5_client.low_level.Response; import co.elastic.clients.transport.rest5_client.low_level.RequestOptions; import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; import co.elastic.clients.util.BinaryData; @@ -81,7 +81,7 @@ public void testXMLResponse() throws Exception { assertEquals("es/cat.indices", ex.endpointId()); // Original response is transport-dependent - ESResponse restClientResponse = (ESResponse) ex.response().originalResponse(); + Response restClientResponse = (Response) ex.response().originalResponse(); assertEquals(401, restClientResponse.getStatusCode()); } diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncResponseConsumerTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncResponseConsumerTests.java new file mode 100644 index 000000000..311296b98 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncResponseConsumerTests.java @@ -0,0 +1,74 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.ContentTooLongException; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.io.entity.ByteArrayEntity; +import org.apache.hc.core5.http.message.BasicClassicHttpResponse; +import org.apache.hc.core5.http.nio.AsyncResponseConsumer; +import org.apache.hc.core5.http.nio.ContentDecoder; +import org.apache.hc.core5.http.protocol.HttpContext; +import org.junit.Assert; + +import java.nio.ByteBuffer; + +import static org.mockito.Mockito.mock; + +public class BasicAsyncResponseConsumerTests extends RestClientTestCase { + + // maximum buffer that this test ends up allocating is 50MB + private static final int MAX_TEST_BUFFER_SIZE = 50 * 1024 * 1024; + + public void testResponseProcessing() throws Exception { + ContentDecoder contentDecoder = mock(ContentDecoder.class); + HttpContext httpContext = mock(HttpContext.class); + + AsyncResponseConsumer consumer = + new HttpAsyncResponseConsumerFactory.BasicAsyncResponseConsumerFactory(MAX_TEST_BUFFER_SIZE) + .createHttpAsyncResponseConsumer(); + + BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(200, "OK"); + ByteArrayEntity entity = new ByteArrayEntity("test".getBytes(), ContentType.APPLICATION_JSON); + httpResponse.setEntity(entity); + + // everything goes well, no exception thrown + consumer.consumeResponse(httpResponse, entity, httpContext, null); + consumer.consume(ByteBuffer.wrap("test".getBytes())); + } + + public void testBufferLimit() throws Exception { + HttpContext httpContext = mock(HttpContext.class); + + AsyncResponseConsumer consumer = + new HttpAsyncResponseConsumerFactory.BasicAsyncResponseConsumerFactory(MAX_TEST_BUFFER_SIZE) + .createHttpAsyncResponseConsumer(); + + ByteArrayEntity entity = new ByteArrayEntity("test".getBytes(), ContentType.APPLICATION_JSON); + BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(200, "OK"); + httpResponse.setEntity(entity); + + // should throw exception + consumer.consumeResponse(httpResponse, entity, httpContext, null); + Assert.assertThrows(ContentTooLongException.class, + () -> consumer.consume(ByteBuffer.allocate(MAX_TEST_BUFFER_SIZE + 1))); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/ClientsGraalVMThreadsFilter.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/ClientsGraalVMThreadsFilter.java new file mode 100644 index 000000000..362c08657 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/ClientsGraalVMThreadsFilter.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import com.carrotsearch.randomizedtesting.ThreadFilter; + +/** + * The GraalVM spawns extra threads, which causes our thread leak + * detection to fail. Filter these threads out since we can't clean them up. + */ +public class ClientsGraalVMThreadsFilter implements ThreadFilter { + @Override + public boolean reject(Thread t) { + return t.getName().startsWith("Libgraal"); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/DeadHostStateTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/DeadHostStateTests.java new file mode 100644 index 000000000..ecd1d1852 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/DeadHostStateTests.java @@ -0,0 +1,133 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.lessThan; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class DeadHostStateTests extends RestClientTestCase { + + private static long[] EXPECTED_TIMEOUTS_SECONDS = new long[]{60, 84, 120, 169, 240, 339, 480, 678, 960, + 1357, 1800}; + + public void testInitialDeadHostStateDefaultTimeSupplier() { + DeadHostState deadHostState = new DeadHostState(DeadHostState.DEFAULT_TIME_SUPPLIER); + long currentTime = System.nanoTime(); + assertThat(deadHostState.getDeadUntilNanos(), greaterThanOrEqualTo(currentTime)); + assertThat(deadHostState.getFailedAttempts(), equalTo(1)); + } + + public void testDeadHostStateFromPreviousDefaultTimeSupplier() { + DeadHostState previous = new DeadHostState(DeadHostState.DEFAULT_TIME_SUPPLIER); + int iters = randomIntBetween(5, 30); + for (int i = 0; i < iters; i++) { + DeadHostState deadHostState = new DeadHostState(previous); + assertThat(deadHostState.getDeadUntilNanos(), greaterThan(previous.getDeadUntilNanos())); + assertThat(deadHostState.getFailedAttempts(), equalTo(previous.getFailedAttempts() + 1)); + previous = deadHostState; + } + } + + public void testCompareToTimeSupplier() { + int numObjects = randomIntBetween(EXPECTED_TIMEOUTS_SECONDS.length, 30); + DeadHostState[] deadHostStates = new DeadHostState[numObjects]; + final AtomicLong time = new AtomicLong(0); + for (int i = 0; i < numObjects; i++) { + if (i == 0) { + // this test requires a strictly increasing timer. This ensures that even if we call this + // time supplier in a very tight + // loop we always notice time moving forward. This does not happen for real timer + // implementations + // (e.g. on Linux clock_gettime provides microsecond resolution). + deadHostStates[i] = new DeadHostState(time::incrementAndGet); + } else { + deadHostStates[i] = new DeadHostState(deadHostStates[i - 1]); + } + } + for (int k = 1; k < deadHostStates.length; k++) { + assertThat(deadHostStates[k - 1].getDeadUntilNanos(), + lessThan(deadHostStates[k].getDeadUntilNanos())); + assertThat(deadHostStates[k - 1], lessThan(deadHostStates[k])); + } + } + + public void testCompareToDifferingTimeSupplier() { + try { + new DeadHostState(DeadHostState.DEFAULT_TIME_SUPPLIER).compareTo(new DeadHostState(() -> 0L)); + fail("expected failure"); + } catch (IllegalArgumentException e) { + assertEquals( + "can't compare DeadHostStates holding different time suppliers as they may be based on " + + "different clocks", + e.getMessage() + ); + } + } + + public void testShallBeRetried() { + final AtomicLong time = new AtomicLong(0); + DeadHostState deadHostState = null; + for (int i = 0; i < EXPECTED_TIMEOUTS_SECONDS.length; i++) { + long expectedTimeoutSecond = EXPECTED_TIMEOUTS_SECONDS[i]; + if (i == 0) { + deadHostState = new DeadHostState(time::get); + } else { + deadHostState = new DeadHostState(deadHostState); + } + for (int j = 0; j < expectedTimeoutSecond; j++) { + time.addAndGet(TimeUnit.SECONDS.toNanos(1)); + assertThat(deadHostState.shallBeRetried(), is(false)); + } + int iters = randomIntBetween(5, 30); + for (int j = 0; j < iters; j++) { + time.addAndGet(TimeUnit.SECONDS.toNanos(1)); + assertThat(deadHostState.shallBeRetried(), is(true)); + } + } + } + + public void testDeadHostStateTimeouts() { + DeadHostState previous = new DeadHostState(() -> 0L); + for (long expectedTimeoutsSecond : EXPECTED_TIMEOUTS_SECONDS) { + assertThat(TimeUnit.NANOSECONDS.toSeconds(previous.getDeadUntilNanos()), + equalTo(expectedTimeoutsSecond)); + previous = new DeadHostState(previous); + } + // check that from here on the timeout does not increase + int iters = randomIntBetween(5, 30); + for (int i = 0; i < iters; i++) { + DeadHostState deadHostState = new DeadHostState(previous); + assertThat( + TimeUnit.NANOSECONDS.toSeconds(deadHostState.getDeadUntilNanos()), + equalTo(EXPECTED_TIMEOUTS_SECONDS[EXPECTED_TIMEOUTS_SECONDS.length - 1]) + ); + previous = deadHostState; + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/FailureTrackingResponseListenerTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/FailureTrackingResponseListenerTests.java new file mode 100644 index 000000000..23a2f3b50 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/FailureTrackingResponseListenerTests.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.ProtocolVersion; +import org.apache.hc.core5.http.message.BasicClassicHttpResponse; +import org.apache.hc.core5.http.message.RequestLine; + +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +public class FailureTrackingResponseListenerTests extends RestClientTestCase { + + public void testOnSuccess() { + MockResponseListener responseListener = new MockResponseListener(); + Rest5Client.FailureTrackingResponseListener listener = + new Rest5Client.FailureTrackingResponseListener(responseListener); + + final Response response = mockResponse(); + listener.onSuccess(response); + assertSame(response, responseListener.lastResponse.get()); + assertNull(responseListener.lastException.get()); + } + + public void testOnFailure() { + MockResponseListener responseListener = new MockResponseListener(); + Rest5Client.FailureTrackingResponseListener listener = + new Rest5Client.FailureTrackingResponseListener(responseListener); + int numIters = randomIntBetween(1, 10); + Exception[] expectedExceptions = new Exception[numIters]; + for (int i = 0; i < numIters; i++) { + RuntimeException runtimeException = new RuntimeException("test" + i); + expectedExceptions[i] = runtimeException; + listener.trackFailure(runtimeException); + assertNull(responseListener.lastResponse.get()); + assertNull(responseListener.lastException.get()); + } + + if (randomBoolean()) { + Response response = mockResponse(); + listener.onSuccess(response); + assertSame(response, responseListener.lastResponse.get()); + assertNull(responseListener.lastException.get()); + } else { + RuntimeException runtimeException = new RuntimeException("definitive"); + listener.onDefinitiveFailure(runtimeException); + assertNull(responseListener.lastResponse.get()); + Throwable exception = responseListener.lastException.get(); + assertSame(runtimeException, exception); + + int i = numIters - 1; + do { + assertNotNull(exception.getSuppressed()); + assertEquals(1, exception.getSuppressed().length); + assertSame(expectedExceptions[i--], exception.getSuppressed()[0]); + exception = exception.getSuppressed()[0]; + } while (i >= 0); + } + } + + private static class MockResponseListener implements ResponseListener { + private final AtomicReference lastResponse = new AtomicReference<>(); + private final AtomicReference lastException = new AtomicReference<>(); + + @Override + public void onSuccess(Response response) { + if (!this.lastResponse.compareAndSet(null, response)) { + throw new IllegalStateException("onSuccess was called multiple times"); + } + } + + @Override + public void onFailure(Exception exception) { + if (!this.lastException.compareAndSet(null, exception)) { + throw new IllegalStateException("onFailure was called multiple times"); + } + } + } + + private static Response mockResponse() { + ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1); + RequestLine requestLine = new RequestLine("GET", "/", protocolVersion); + BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(200, "OK"); + return new Response(requestLine, new HttpHost("localhost", 9200), httpResponse); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/HasAttributeNodeSelectorTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/HasAttributeNodeSelectorTests.java new file mode 100644 index 000000000..c84e251a0 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/HasAttributeNodeSelectorTests.java @@ -0,0 +1,74 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import org.apache.hc.core5.http.HttpHost; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; +import static org.junit.Assert.assertEquals; + +public class HasAttributeNodeSelectorTests extends RestClientTestCase { + public void testHasAttribute() { + Node hasAttributeValue = dummyNode(singletonMap("attr", singletonList("val"))); + Node hasAttributeButNotValue = dummyNode(singletonMap("attr", singletonList("notval"))); + Node hasAttributeValueInList = dummyNode(singletonMap("attr", Arrays.asList("val", "notval"))); + Node notHasAttribute = dummyNode(singletonMap("notattr", singletonList("val"))); + List nodes = new ArrayList<>(); + nodes.add(hasAttributeValue); + nodes.add(hasAttributeButNotValue); + nodes.add(hasAttributeValueInList); + nodes.add(notHasAttribute); + List expected = new ArrayList<>(); + expected.add(hasAttributeValue); + expected.add(hasAttributeValueInList); + new HasAttributeNodeSelector("attr", "val").select(nodes); + assertEquals(expected, nodes); + } + + private static Node dummyNode(Map> attributes) { + final Set roles = new TreeSet<>(); + if (randomBoolean()) { + roles.add("master"); + } + if (randomBoolean()) { + roles.add("data"); + } + if (randomBoolean()) { + roles.add("ingest"); + } + return new Node( + new HttpHost("dummy"), + Collections.emptySet(), + randomAsciiAlphanumOfLength(5), + randomAsciiAlphanumOfLength(5), + new Node.Roles(roles), + attributes + ); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/HostsTrackingFailureListener.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/HostsTrackingFailureListener.java new file mode 100644 index 000000000..eb3b350e0 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/HostsTrackingFailureListener.java @@ -0,0 +1,61 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.client.RestClient; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +/** + * {@link RestClient.FailureListener} impl that allows to track when it gets called for which host. + */ +class HostsTrackingFailureListener extends Rest5Client.FailureListener { + private volatile Set httpHosts = new HashSet<>(); + + @Override + public void onFailure(Node node) { + httpHosts.add(node.getHost()); + } + + void assertCalled(List nodes) { + HttpHost[] hosts = new HttpHost[nodes.size()]; + for (int i = 0; i < nodes.size(); i++) { + hosts[i] = nodes.get(i).getHost(); + } + assertCalled(hosts); + } + + void assertCalled(HttpHost... hosts) { + assertEquals(hosts.length, this.httpHosts.size()); + assertThat(this.httpHosts, containsInAnyOrder(hosts)); + this.httpHosts.clear(); + } + + void assertNotCalled() { + assertEquals(0, httpHosts.size()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/NodeSelectorTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/NodeSelectorTests.java new file mode 100644 index 000000000..5ff117c92 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/NodeSelectorTests.java @@ -0,0 +1,126 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import org.apache.hc.core5.http.HttpHost; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import static org.junit.Assert.assertEquals; + +public class NodeSelectorTests extends RestClientTestCase { + public void testAny() { + List nodes = new ArrayList<>(); + int size = between(2, 5); + for (int i = 0; i < size; i++) { + nodes.add(dummyNode(randomBoolean(), randomBoolean(), randomBoolean())); + } + List expected = new ArrayList<>(nodes); + NodeSelector.ANY.select(nodes); + assertEquals(expected, nodes); + } + + public void testNotMasterOnly() { + Node masterOnly = dummyNode(true, false, false); + Node all = dummyNode(true, true, true); + Node masterAndData = dummyNode(true, true, false); + Node masterAndIngest = dummyNode(true, false, true); + Node coordinatingOnly = dummyNode(false, false, false); + Node ingestOnly = dummyNode(false, false, true); + Node data = dummyNode(false, true, randomBoolean()); + Node dataContent = dummyNode(false, false, false, true, false, false, false, false); + Node dataHot = dummyNode(false, false, false, false, true, false, false, false); + Node dataWarm = dummyNode(false, false, false, false, false, true, false, false); + Node dataCold = dummyNode(false, false, false, false, false, false, true, false); + Node dataFrozen = dummyNode(false, false, false, false, false, false, false, true); + List nodes = new ArrayList<>(); + nodes.add(masterOnly); + nodes.add(all); + nodes.add(masterAndData); + nodes.add(masterAndIngest); + nodes.add(coordinatingOnly); + nodes.add(ingestOnly); + nodes.add(data); + nodes.add(dataContent); + nodes.add(dataHot); + nodes.add(dataWarm); + nodes.add(dataCold); + nodes.add(dataFrozen); + Collections.shuffle(nodes, getRandom()); + List expected = new ArrayList<>(nodes); + expected.remove(masterOnly); + NodeSelector.SKIP_DEDICATED_MASTERS.select(nodes); + assertEquals(expected, nodes); + } + + private static Node dummyNode(boolean master, boolean data, boolean ingest) { + return dummyNode(master, data, ingest, false, false, false, false, false); + } + + private static Node dummyNode( + boolean master, + boolean data, + boolean ingest, + boolean dataContent, + boolean dataHot, + boolean dataWarm, + boolean dataCold, + boolean dataFrozen + ) { + final Set roles = new TreeSet<>(); + if (master) { + roles.add("master"); + } + if (data) { + roles.add("data"); + } + if (dataContent) { + roles.add("data_content"); + } + if (dataHot) { + roles.add("data_hot"); + } + if (dataWarm) { + roles.add("data_warm"); + } + if (dataCold) { + roles.add("data_cold"); + } + if (dataFrozen) { + roles.add("data_frozen"); + } + if (ingest) { + roles.add("ingest"); + } + return new Node( + new HttpHost("dummy"), + Collections.emptySet(), + randomAsciiAlphanumOfLength(5), + randomAsciiAlphanumOfLength(5), + new Node.Roles(roles), + Collections.>emptyMap() + ); + } + +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/NodeTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/NodeTests.java new file mode 100644 index 000000000..979bb2f50 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/NodeTests.java @@ -0,0 +1,173 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import org.apache.hc.core5.http.HttpHost; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.TreeSet; + +import static java.util.Collections.singleton; +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class NodeTests extends RestClientTestCase { + public void testToString() { + Map> attributes = new HashMap<>(); + attributes.put("foo", singletonList("bar")); + attributes.put("baz", Arrays.asList("bort", "zoom")); + assertEquals("[host=http://1]", new Node(new HttpHost("1")).toString()); + assertEquals( + "[host=http://1, attributes={foo=[bar], baz=[bort, zoom]}]", + new Node(new HttpHost("1"), null, null, null, null, attributes).toString() + ); + assertEquals( + "[host=http://1, roles=data,ingest,master]", + new Node(new HttpHost("1"), null, null, null, new Node.Roles(new TreeSet<>(Arrays.asList("master", "data", "ingest"))), null) + .toString() + ); + assertEquals("[host=http://1, version=ver]", new Node(new HttpHost("1"), null, null, "ver", null, null).toString()); + assertEquals("[host=http://1, name=nam]", new Node(new HttpHost("1"), null, "nam", null, null, null).toString()); + assertEquals( + "[host=http://1, bound=[http://1, http://2]]", + new Node(new HttpHost("1"), new HashSet<>(Arrays.asList(new HttpHost("1"), new HttpHost("2"))), null, null, null, null) + .toString() + ); + assertEquals( + "[host=http://1, bound=[http://1, http://2], " + + "name=nam, version=ver, roles=master, attributes={foo=[bar], baz=[bort, zoom]}]", + new Node( + new HttpHost("1"), + new HashSet<>(Arrays.asList(new HttpHost("1"), new HttpHost("2"))), + "nam", + "ver", + new Node.Roles(Collections.singleton("master")), + attributes + ).toString() + ); + } + + public void testEqualsAndHashCode() { + HttpHost host = new HttpHost(randomAsciiAlphanumOfLength(5)); + Node node = new Node( + host, + randomBoolean() ? null : singleton(host), + randomBoolean() ? null : randomAsciiAlphanumOfLength(5), + randomBoolean() ? null : randomAsciiAlphanumOfLength(5), + randomBoolean() ? null : new Node.Roles(new TreeSet<>(Arrays.asList("master", "data", "ingest"))), + randomBoolean() ? null : singletonMap("foo", singletonList("bar")) + ); + assertFalse(node.equals(null)); + assertTrue(node.equals(node)); + assertEquals(node.hashCode(), node.hashCode()); + Node copy = new Node(host, node.getBoundHosts(), node.getName(), node.getVersion(), node.getRoles(), node.getAttributes()); + assertTrue(node.equals(copy)); + assertEquals(node.hashCode(), copy.hashCode()); + assertFalse( + node.equals( + new Node( + new HttpHost(host.toHostString() + "changed"), + node.getBoundHosts(), + node.getName(), + node.getVersion(), + node.getRoles(), + node.getAttributes() + ) + ) + ); + assertFalse( + node.equals( + new Node( + host, + new HashSet<>(Arrays.asList(host, new HttpHost(host.toHostString() + "changed"))), + node.getName(), + node.getVersion(), + node.getRoles(), + node.getAttributes() + ) + ) + ); + assertFalse( + node.equals( + new Node(host, node.getBoundHosts(), node.getName() + "changed", node.getVersion(), node.getRoles(), node.getAttributes()) + ) + ); + assertFalse( + node.equals( + new Node(host, node.getBoundHosts(), node.getName(), node.getVersion() + "changed", node.getRoles(), node.getAttributes()) + ) + ); + assertFalse( + node.equals( + new Node( + host, + node.getBoundHosts(), + node.getName(), + node.getVersion(), + new Node.Roles(Collections.emptySet()), + node.getAttributes() + ) + ) + ); + assertFalse( + node.equals( + new Node( + host, + node.getBoundHosts(), + node.getName(), + node.getVersion(), + node.getRoles(), + singletonMap("bort", singletonList("bing")) + ) + ) + ); + } + + public void testDataRole() { + Node.Roles roles = new Node.Roles(new TreeSet<>(Arrays.asList("data_hot"))); + assertTrue(roles.hasDataHotRole()); + assertTrue(roles.canContainData()); + roles = new Node.Roles(new TreeSet<>(Arrays.asList("data_warm"))); + assertTrue(roles.hasDataWarmRole()); + assertTrue(roles.canContainData()); + roles = new Node.Roles(new TreeSet<>(Arrays.asList("data_cold"))); + assertTrue(roles.hasDataColdRole()); + assertTrue(roles.canContainData()); + roles = new Node.Roles(new TreeSet<>(Arrays.asList("data_frozen"))); + assertTrue(roles.hasDataFrozenRole()); + assertTrue(roles.canContainData()); + roles = new Node.Roles(new TreeSet<>(Arrays.asList("data_content"))); + assertTrue(roles.hasDataContentRole()); + assertTrue(roles.canContainData()); + roles = new Node.Roles(new TreeSet<>(Arrays.asList("data"))); + assertTrue(roles.hasDataRole()); + assertTrue(roles.canContainData()); + roles = new Node.Roles(new TreeSet<>(Arrays.asList("data_foo"))); + assertTrue(roles.canContainData()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/PreferHasAttributeNodeSelectorTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/PreferHasAttributeNodeSelectorTests.java new file mode 100644 index 000000000..f9ab1000e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/PreferHasAttributeNodeSelectorTests.java @@ -0,0 +1,84 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import org.apache.hc.core5.http.HttpHost; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; +import static org.junit.Assert.assertEquals; + +public class PreferHasAttributeNodeSelectorTests extends RestClientTestCase { + public void testFoundPreferHasAttribute() { + Node hasAttributeValue = dummyNode(singletonMap("attr", singletonList("val"))); + Node hasAttributeButNotValue = dummyNode(singletonMap("attr", singletonList("notval"))); + Node hasAttributeValueInList = dummyNode(singletonMap("attr", Arrays.asList("val", "notval"))); + Node notHasAttribute = dummyNode(singletonMap("notattr", singletonList("val"))); + List nodes = new ArrayList<>(); + nodes.add(hasAttributeValue); + nodes.add(hasAttributeButNotValue); + nodes.add(hasAttributeValueInList); + nodes.add(notHasAttribute); + List expected = new ArrayList<>(); + expected.add(hasAttributeValue); + expected.add(hasAttributeValueInList); + new PreferHasAttributeNodeSelector("attr", "val").select(nodes); + assertEquals(expected, nodes); + } + + public void testNotFoundPreferHasAttribute() { + Node notHasAttribute = dummyNode(singletonMap("notattr", singletonList("val"))); + List nodes = new ArrayList<>(); + nodes.add(notHasAttribute); + List expected = new ArrayList<>(); + expected.add(notHasAttribute); + new PreferHasAttributeNodeSelector("attr", "val").select(nodes); + assertEquals(expected, nodes); + } + + private static Node dummyNode(Map> attributes) { + final Set roles = new TreeSet<>(); + if (randomBoolean()) { + roles.add("master"); + } + if (randomBoolean()) { + roles.add("data"); + } + if (randomBoolean()) { + roles.add("ingest"); + } + return new Node( + new HttpHost("dummy"), + Collections.emptySet(), + randomAsciiAlphanumOfLength(5), + randomAsciiAlphanumOfLength(5), + new Node.Roles(roles), + attributes + ); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestLoggerTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestLoggerTests.java new file mode 100644 index 000000000..b184cd763 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestLoggerTests.java @@ -0,0 +1,200 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + + +import org.apache.hc.client5.http.classic.methods.HttpHead; +import org.apache.hc.client5.http.classic.methods.HttpOptions; +import org.apache.hc.client5.http.classic.methods.HttpPatch; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.classic.methods.HttpPut; +import org.apache.hc.client5.http.classic.methods.HttpTrace; +import org.apache.hc.client5.http.classic.methods.HttpUriRequest; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.io.entity.ByteArrayEntity; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.entity.InputStreamEntity; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.http.message.BasicClassicHttpResponse; +import org.apache.hc.core5.http.message.BasicHeader; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestUtil.canHaveBody; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +public class RequestLoggerTests extends RestClientTestCase { + public void testTraceRequest() throws IOException, URISyntaxException, ParseException { + HttpHost host = new HttpHost(randomBoolean() ? "http" : "https", "localhost", 9200); + String expectedEndpoint = "/index/type/_api"; + URI uri; + if (randomBoolean()) { + uri = new URI(expectedEndpoint); + } else { + uri = new URI("index/type/_api"); + } + HttpUriRequest request = randomHttpRequest(uri); + String expected = "curl -iX " + request.getMethod() + " '" + host + expectedEndpoint + "'"; + boolean hasBody = canHaveBody((HttpUriRequestBase) request) && randomBoolean(); + String requestBody = "{ \"field\": \"value\" }"; + if (hasBody) { + expected += " -d '" + requestBody + "'"; + HttpEntity entity; + switch (randomIntBetween(0, 4)) { + case 0: + case 2: + entity = new StringEntity(requestBody, ContentType.APPLICATION_JSON); + break; + case 1: + entity = new InputStreamEntity( + new ByteArrayInputStream(requestBody.getBytes(StandardCharsets.UTF_8)), + ContentType.APPLICATION_JSON + ); + break; + case 3: + entity = new ByteArrayEntity(requestBody.getBytes(StandardCharsets.UTF_8), + ContentType.APPLICATION_JSON); + break; + case 4: + // Evil entity without a charset + entity = new StringEntity(requestBody, ContentType.create("application/json", + (Charset) null)); + break; + default: + throw new UnsupportedOperationException(); + } + request.setEntity(entity); + } + String traceRequest = RequestLogger.buildTraceRequest(request, host); + assertThat(traceRequest, equalTo(expected)); + if (hasBody) { + // check that the body is still readable as most entities are not repeatable + String body = EntityUtils.toString(request.getEntity(), + StandardCharsets.UTF_8); + assertThat(body, equalTo(requestBody)); + } + } + + public void testTraceResponse() throws IOException, ParseException { + int statusCode = randomIntBetween(200, 599); + String reasonPhrase = "REASON"; + BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(statusCode, reasonPhrase); + String expected = "# " + statusCode; + int numHeaders = randomIntBetween(0, 3); + for (int i = 0; i < numHeaders; i++) { + httpResponse.setHeader("header" + i, "value"); + expected += "\n# header" + i + ": value"; + } + expected += "\n#"; + boolean hasBody = getRandom().nextBoolean(); + String responseBody = "{\n \"field\": \"value\"\n}"; + if (hasBody) { + expected += "\n# {"; + expected += "\n# \"field\": \"value\""; + expected += "\n# }"; + HttpEntity entity; + switch (randomIntBetween(0, 2)) { + case 0: + entity = new StringEntity(responseBody, ContentType.APPLICATION_JSON); + break; + case 1: + // test a non repeatable entity + entity = new InputStreamEntity( + new ByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8)), + ContentType.APPLICATION_JSON + ); + break; + case 2: + // Evil entity without a charset + entity = new StringEntity(responseBody, ContentType.create("application/json", + (Charset) null)); + break; + default: + throw new UnsupportedOperationException(); + } + httpResponse.setEntity(entity); + } + String traceResponse = RequestLogger.buildTraceResponse(httpResponse); + assertThat(traceResponse, equalTo(expected)); + if (hasBody) { + // check that the body is still readable as most entities are not repeatable + String body = EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8); + assertThat(body, equalTo(responseBody)); + } + } + + public void testResponseWarnings() throws Exception { + HttpHost host = new HttpHost("localhost", 9200); + HttpUriRequest request = randomHttpRequest(new URI("/index/type/_api")); + int numWarnings = randomIntBetween(1, 5); + StringBuilder expected = new StringBuilder("request [").append(request.getMethod()) + .append(" ") + .append(host) + .append("/index/type/_api] returned ") + .append(numWarnings) + .append(" warnings: "); + Header[] warnings = new Header[numWarnings]; + for (int i = 0; i < numWarnings; i++) { + String warning = "this is warning number " + i; + warnings[i] = new BasicHeader("Warning", warning); + if (i > 0) { + expected.append(","); + } + expected.append("[").append(warning).append("]"); + } + assertEquals(expected.toString(), RequestLogger.buildWarningMessage(request, host, warnings)); + } + + private static HttpUriRequest randomHttpRequest(URI uri) { + int requestType = randomIntBetween(0, 7); + switch (requestType) { + case 0: + return new HttpGetWithEntity(uri); + case 1: + return new HttpPost(uri); + case 2: + return new HttpPut(uri); + case 3: + return new HttpDeleteWithEntity(uri); + case 4: + return new HttpHead(uri); + case 5: + return new HttpTrace(uri); + case 6: + return new HttpOptions(uri); + case 7: + return new HttpPatch(uri); + default: + throw new UnsupportedOperationException(); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptionsTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptionsTests.java new file mode 100644 index 000000000..d04431479 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptionsTests.java @@ -0,0 +1,208 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.util.Timeout; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; + +public class RequestOptionsTests extends RestClientTestCase { + public void testDefault() { + assertEquals(Collections.

emptyList(), RequestOptions.DEFAULT.getHeaders()); + assertEquals(Collections.emptyMap(), RequestOptions.DEFAULT.getParameters()); + assertEquals(HttpAsyncResponseConsumerFactory.DEFAULT, + RequestOptions.DEFAULT.getHttpAsyncResponseConsumerFactory()); + assertEquals(RequestOptions.DEFAULT, RequestOptions.DEFAULT.toBuilder().build()); + } + + public void testAddHeader() { + try { + randomBuilder().addHeader(null, randomAsciiLettersOfLengthBetween(3, 10)); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("header name cannot be null", e.getMessage()); + } + + try { + randomBuilder().addHeader(randomAsciiLettersOfLengthBetween(3, 10), null); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("header value cannot be null", e.getMessage()); + } + + RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); + int numHeaders = between(0, 5); + List
headers = new ArrayList<>(); + for (int i = 0; i < numHeaders; i++) { + Header header = new RequestOptions.ReqHeader(randomAsciiAlphanumOfLengthBetween(5, 10), + randomAsciiAlphanumOfLength(3)); + headers.add(header); + builder.addHeader(header.getName(), header.getValue()); + } + RequestOptions options = builder.build(); + assertEquals(headers, options.getHeaders()); + + try { + options.getHeaders() + .add(new RequestOptions.ReqHeader(randomAsciiAlphanumOfLengthBetween(5, 10), + randomAsciiAlphanumOfLength(3))); + fail("expected failure"); + } catch (UnsupportedOperationException e) { + assertNull(e.getMessage()); + } + } + + public void testSetHttpAsyncResponseConsumerFactory() { + try { + RequestOptions.DEFAULT.toBuilder().setHttpAsyncResponseConsumerFactory(null); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("httpAsyncResponseConsumerFactory cannot be null", e.getMessage()); + } + + HttpAsyncResponseConsumerFactory factory = mock(HttpAsyncResponseConsumerFactory.class); + RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); + builder.setHttpAsyncResponseConsumerFactory(factory); + RequestOptions options = builder.build(); + assertSame(factory, options.getHttpAsyncResponseConsumerFactory()); + } + + public void testAddParameters() { + try { + randomBuilder().addParameter(null, randomAsciiLettersOfLengthBetween(3, 10)); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("parameter key cannot be null", e.getMessage()); + } + + try { + randomBuilder().addParameter(randomAsciiLettersOfLengthBetween(3, 10), null); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("parameter value cannot be null", e.getMessage()); + } + + RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); + int numParameters = between(0, 5); + Map parameters = new HashMap<>(); + for (int i = 0; i < numParameters; i++) { + String key = randomAsciiAlphanumOfLengthBetween(5, 10); + String value = randomAsciiAlphanumOfLength(3); + + parameters.put(key, value); + builder.addParameter(key, value); + } + RequestOptions options = builder.build(); + assertEquals(parameters, options.getParameters()); + } + + public void testSetRequestBuilder() { + RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); + + RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); + int socketTimeout = 10000; + int connectTimeout = 100; + requestConfigBuilder.setConnectionRequestTimeout(Timeout.ofMilliseconds(socketTimeout)).setConnectTimeout(Timeout.ofMilliseconds(connectTimeout)); + RequestConfig requestConfig = requestConfigBuilder.build(); + + builder.setRequestConfig(requestConfig); + RequestOptions options = builder.build(); + assertSame(options.getRequestConfig(), requestConfig); + assertEquals(options.getRequestConfig().getConnectionRequestTimeout(), Timeout.ofMilliseconds(socketTimeout)); + assertEquals(options.getRequestConfig().getConnectTimeout(), Timeout.ofMilliseconds(connectTimeout)); + } + + public void testEqualsAndHashCode() { + RequestOptions request = randomBuilder().build(); + assertEquals(request, request); + + RequestOptions copy = copy(request); + assertEquals(request, copy); + assertEquals(copy, request); + assertEquals(request.hashCode(), copy.hashCode()); + + RequestOptions mutant = mutate(request); + assertNotEquals(request, mutant); + assertNotEquals(mutant, request); + } + + static RequestOptions.Builder randomBuilder() { + RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); + + if (randomBoolean()) { + int headerCount = between(1, 5); + for (int i = 0; i < headerCount; i++) { + builder.addHeader(randomAsciiAlphanumOfLength(3), randomAsciiAlphanumOfLength(3)); + } + } + + if (randomBoolean()) { + builder.setHttpAsyncResponseConsumerFactory(HttpAsyncResponseConsumerFactory.DEFAULT); + } + + if (randomBoolean()) { + builder.setWarningsHandler(randomBoolean() ? WarningsHandler.STRICT : WarningsHandler.PERMISSIVE); + } + + if (randomBoolean()) { + builder.setRequestConfig(RequestConfig.custom().build()); + } + + return builder; + } + + private static RequestOptions copy(RequestOptions options) { + return options.toBuilder().build(); + } + + private static RequestOptions mutate(RequestOptions options) { + RequestOptions.Builder mutant = options.toBuilder(); + int mutationType = between(0, 2); + switch (mutationType) { + case 0: + mutant.addHeader("extra", "m"); + return mutant.build(); + case 1: + mutant.setHttpAsyncResponseConsumerFactory(new HttpAsyncResponseConsumerFactory.BasicAsyncResponseConsumerFactory(5)); + return mutant.build(); + case 2: + mutant.setWarningsHandler(warnings -> { + fail("never called"); + return false; + }); + return mutant.build(); + default: + throw new UnsupportedOperationException("Unknown mutation type [" + mutationType + "]"); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestTests.java new file mode 100644 index 000000000..e2688bd08 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestTests.java @@ -0,0 +1,245 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.io.entity.ByteArrayEntity; +import org.apache.hc.core5.http.io.entity.StringEntity; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; + +public class RequestTests extends RestClientTestCase { + public void testConstructor() { + final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); + final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); + + try { + new Request(null, endpoint); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("method cannot be null", e.getMessage()); + } + + try { + new Request(method, null); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("endpoint cannot be null", e.getMessage()); + } + + final Request request = new Request(method, endpoint); + assertEquals(method, request.getMethod()); + assertEquals(endpoint, request.getEndpoint()); + } + + public void testAddParameters() { + final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); + final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); + int parametersCount = between(1, 3); + final Map parameters = new HashMap<>(parametersCount); + while (parameters.size() < parametersCount) { + parameters.put(randomAsciiLettersOfLength(5), randomAsciiLettersOfLength(5)); + } + Request request = new Request(method, endpoint); + + try { + request.addParameter(null, "value"); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("url parameter name cannot be null", e.getMessage()); + } + + for (Map.Entry entry : parameters.entrySet()) { + request.addParameter(entry.getKey(), entry.getValue()); + } + assertEquals(parameters, request.getParameters()); + + // Test that adding parameters with a null value is ok. + request.addParameter("is_null", null); + parameters.put("is_null", null); + assertEquals(parameters, request.getParameters()); + + // Test that adding a duplicate parameter fails + String firstValue = randomBoolean() ? null : "value"; + request.addParameter("name", firstValue); + try { + request.addParameter("name", randomBoolean() ? firstValue : "second_value"); + fail("expected failure"); + } catch (IllegalArgumentException e) { + assertEquals("url parameter [name] has already been set to [" + firstValue + "]", e.getMessage()); + } + } + + public void testSetEntity() { + final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); + final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); + final HttpEntity entity = randomBoolean() + ? new StringEntity(randomAsciiLettersOfLengthBetween(1, 100), ContentType.TEXT_PLAIN) + : null; + + Request request = new Request(method, endpoint); + request.setEntity(entity); + assertEquals(entity, request.getEntity()); + } + + public void testSetJsonEntity() throws IOException { + final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); + final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); + + Request request = new Request(method, endpoint); + assertNull(request.getEntity()); + + final String json = randomAsciiLettersOfLengthBetween(1, 100); + request.setJsonEntity(json); + assertEquals(ContentType.APPLICATION_JSON.toString(), request.getEntity().getContentType()); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + request.getEntity().writeTo(os); + assertEquals(json, new String(os.toByteArray(), ContentType.APPLICATION_JSON.getCharset())); + } + + public void testSetOptions() { + final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); + final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); + Request request = new Request(method, endpoint); + + try { + request.setOptions((RequestOptions) null); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("options cannot be null", e.getMessage()); + } + + try { + request.setOptions((RequestOptions.Builder) null); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("options cannot be null", e.getMessage()); + } + + RequestOptions.Builder builder = RequestOptionsTests.randomBuilder(); + request.setOptions(builder); + assertEquals(builder.build(), request.getOptions()); + + builder = RequestOptionsTests.randomBuilder(); + RequestOptions options = builder.build(); + request.setOptions(options); + assertSame(options, request.getOptions()); + } + + public void testEqualsAndHashCode() { + Request request = randomRequest(); + assertEquals(request, request); + + Request copy = copy(request); + assertEquals(request, copy); + assertEquals(copy, request); + assertEquals(request.hashCode(), copy.hashCode()); + + Request mutant = mutate(request); + assertNotEquals(request, mutant); + assertNotEquals(mutant, request); + } + + private static Request randomRequest() { + Request request = new Request( + randomFrom(new String[] { "GET", "PUT", "DELETE", "POST", "HEAD", "OPTIONS" }), + randomAsciiAlphanumOfLength(5) + ); + + int parameterCount = between(0, 5); + for (int i = 0; i < parameterCount; i++) { + request.addParameter(randomAsciiAlphanumOfLength(i), randomAsciiLettersOfLength(3)); + } + + if (randomBoolean()) { + if (randomBoolean()) { + request.setJsonEntity(randomAsciiAlphanumOfLength(10)); + } else { + request.setEntity( + randomFrom( + new HttpEntity[] { + new StringEntity(randomAsciiAlphanumOfLength(10), ContentType.APPLICATION_JSON), + new ByteArrayEntity(randomBytesOfLength(40), ContentType.APPLICATION_JSON) } + ) + ); + } + } + + if (randomBoolean()) { + RequestOptions.Builder options = request.getOptions().toBuilder(); + options.setHttpAsyncResponseConsumerFactory(new HttpAsyncResponseConsumerFactory.BasicAsyncResponseConsumerFactory(1)); + request.setOptions(options); + } + + return request; + } + + private static Request copy(Request request) { + Request copy = new Request(request.getMethod(), request.getEndpoint()); + copyMutables(request, copy); + return copy; + } + + private static Request mutate(Request request) { + if (randomBoolean()) { + // Mutate request or method but keep everything else constant + Request mutant = randomBoolean() + ? new Request(request.getMethod() + "m", request.getEndpoint()) + : new Request(request.getMethod(), request.getEndpoint() + "m"); + copyMutables(request, mutant); + return mutant; + } + Request mutant = copy(request); + int mutationType = between(0, 2); + switch (mutationType) { + case 0: + mutant.addParameter(randomAsciiAlphanumOfLength(mutant.getParameters().size() + 4), "extra"); + return mutant; + case 1: + mutant.setJsonEntity("mutant"); // randomRequest can't produce this value + return mutant; + case 2: + RequestOptions.Builder options = mutant.getOptions().toBuilder(); + options.addHeader("extra", "m"); + mutant.setOptions(options); + return mutant; + default: + throw new UnsupportedOperationException("Unknown mutation type [" + mutationType + "]"); + } + } + + private static void copyMutables(Request from, Request to) { + for (Map.Entry param : from.getParameters().entrySet()) { + to.addParameter(param.getKey(), param.getValue()); + } + to.setEntity(from.getEntity()); + to.setOptions(from.getOptions()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/ResponseExceptionTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/ResponseExceptionTests.java new file mode 100644 index 000000000..c6cef25d0 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/ResponseExceptionTests.java @@ -0,0 +1,91 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + + +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.ProtocolVersion; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.entity.InputStreamEntity; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.http.message.BasicClassicHttpResponse; +import org.apache.hc.core5.http.message.RequestLine; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Locale; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +public class ResponseExceptionTests extends RestClientTestCase { + + public void testResponseException() throws IOException, ParseException { + ProtocolVersion protocolVersion = new ProtocolVersion("http", 1, 1); + BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(500, "Internal Server Error"); + + String responseBody = "{\"error\":{\"root_cause\": {}}}"; + boolean hasBody = getRandom().nextBoolean(); + if (hasBody) { + HttpEntity entity; + if (getRandom().nextBoolean()) { + entity = new StringEntity(responseBody, ContentType.APPLICATION_JSON); + } else { + // test a non repeatable entity + entity = new InputStreamEntity( + new ByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8)), + ContentType.APPLICATION_JSON + ); + } + httpResponse.setEntity(entity); + } + + RequestLine requestLine = new RequestLine("GET", "/", protocolVersion); + HttpHost httpHost = new HttpHost("localhost", 9200); + Response response = new Response(requestLine, httpHost, httpResponse); + ResponseException responseException = new ResponseException(response); + + assertSame(response, responseException.getResponse()); + if (hasBody) { + assertEquals(responseBody, EntityUtils.toString(responseException.getResponse().getEntity())); + } else { + assertNull(responseException.getResponse().getEntity()); + } + + String message = String.format( + Locale.ROOT, + "method [%s], host [%s], URI [%s], status line [%s]", + response.getRequestLine().getMethod(), + response.getHost(), + response.getRequestLine().getUri(), + response.getStatusCode() + ); + + if (hasBody) { + message += "\n" + responseBody; + } + assertEquals(message, responseException.getMessage()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderIntegTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderIntegTests.java new file mode 100644 index 000000000..bc3bead5e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderIntegTests.java @@ -0,0 +1,223 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsServer; +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.mocksocket.MockHttpServer; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.TrustManagerFactory; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.KeyFactory; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.startsWith; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Integration test to validate the builder builds a client with the correct configuration + */ +public class RestClientBuilderIntegTests extends RestClientTestCase { + + private static HttpsServer httpsServer; + + @BeforeClass + public static void startHttpServer() throws Exception { + httpsServer = MockHttpServer.createHttps(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0) + , 0); + httpsServer.setHttpsConfigurator(new HttpsConfigurator(getSslContext())); + httpsServer.createContext("/", new ResponseHandler()); + httpsServer.start(); + } + + private static class ResponseHandler implements HttpHandler { + @Override + public void handle(HttpExchange httpExchange) throws IOException { + httpExchange.sendResponseHeaders(200, -1); + httpExchange.close(); + } + } + + @AfterClass + public static void stopHttpServers() throws IOException { + httpsServer.stop(0); + httpsServer = null; + } + + public void testBuilderUsesDefaultSSLContext() throws Exception { + assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm()); + final SSLContext defaultSSLContext = SSLContext.getDefault(); + try { + try (Rest5Client client = buildRestClient()) { + try { + client.performRequest(new Request("GET", "/")); + fail("connection should have been rejected due to SSL handshake"); + } catch (Exception e) { + assertThat(e, instanceOf(SSLHandshakeException.class)); + } + } + + SSLContext.setDefault(getSslContext()); + try (Rest5Client client = buildRestClient()) { + Response response = client.performRequest(new Request("GET", "/")); + assertEquals(200, response.getStatusCode()); + } + } finally { + SSLContext.setDefault(defaultSSLContext); + } + } + + public void testBuilderSetsThreadName() throws Exception { + assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm()); + final SSLContext defaultSSLContext = SSLContext.getDefault(); + try { + SSLContext.setDefault(getSslContext()); + try (Rest5Client client = buildRestClient()) { + final CountDownLatch latch = new CountDownLatch(1); + client.performRequestAsync(new Request("GET", "/"), new ResponseListener() { + @Override + public void onSuccess(Response response) { + assertThat( + Thread.currentThread().getName(), + allOf( + startsWith(Rest5ClientBuilder.THREAD_NAME_PREFIX), + containsString("elasticsearch"), + containsString("rest-client") + ) + ); + assertEquals(200, response.getStatusCode()); + latch.countDown(); + } + + @Override + public void onFailure(Exception exception) { + throw new AssertionError("unexpected", exception); + } + }); + assertTrue(latch.await(10, TimeUnit.SECONDS)); + } + } finally { + SSLContext.setDefault(defaultSSLContext); + } + } + + private Rest5Client buildRestClient() { + InetSocketAddress address = httpsServer.getAddress(); + return Rest5Client.builder(new HttpHost("https", address.getHostString(), address.getPort())).build(); + } + + private static SSLContext getSslContext() throws Exception { + SSLContext sslContext = SSLContext.getInstance(getProtocol()); + try ( + InputStream certFile = RestClientBuilderIntegTests.class.getResourceAsStream("/test.crt"); + InputStream keyStoreFile = RestClientBuilderIntegTests.class.getResourceAsStream( + "/test_truststore.jks") + ) { + // Build a keystore of default type programmatically since we can't use JKS keystores to + // init a KeyManagerFactory in FIPS 140 JVMs. + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(null, "password".toCharArray()); + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec( + Files.readAllBytes(Paths.get(RestClientBuilderIntegTests.class.getResource("/test.der").toURI())) + ); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + keyStore.setKeyEntry( + "mykey", + keyFactory.generatePrivate(privateKeySpec), + "password".toCharArray(), + new Certificate[]{certFactory.generateCertificate(certFile)} + ); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(keyStore, "password".toCharArray()); + KeyStore trustStore = KeyStore.getInstance("JKS"); + trustStore.load(keyStoreFile, "password".toCharArray()); + TrustManagerFactory tmf = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(trustStore); + sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + } + return sslContext; + } + + /** + * The {@link HttpsServer} in the JDK has issues with TLSv1.3 when running in a JDK prior to + * 12.0.1 so we pin to TLSv1.2 when running on an earlier JDK + */ + private static String getProtocol() { + String version = System.getProperty("java.version"); + String[] parts = version.split("-"); + String[] numericComponents; + if (parts.length == 1) { + numericComponents = version.split("\\."); + } else if (parts.length == 2) { + numericComponents = parts[0].split("\\."); + } else { + throw new IllegalArgumentException("Java version string [" + version + "] could not be parsed."); + } + if (numericComponents.length > 0) { + final int major = Integer.valueOf(numericComponents[0]); + if (major > 12) { + return "TLS"; + } else if (major == 12 && numericComponents.length > 2) { + final int minor = Integer.valueOf(numericComponents[1]); + if (minor > 0) { + return "TLS"; + } else { + String patch = numericComponents[2]; + final int index = patch.indexOf("_"); + if (index > -1) { + patch = patch.substring(0, index); + } + + if (Integer.valueOf(patch) >= 1) { + return "TLS"; + } + } + } + } + return "TLSv1.2"; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderTests.java new file mode 100644 index 000000000..37f104baa --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderTests.java @@ -0,0 +1,266 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.impl.async.HttpAsyncClients; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.message.BasicHeader; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; + +import java.io.IOException; +import java.util.Base64; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +public class RestClientBuilderTests extends RestClientTestCase { + + public void testBuild() throws IOException { + try { + Rest5Client.builder((HttpHost[]) null); + fail("should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("hosts must not be null nor empty", e.getMessage()); + } + + try { + Rest5Client.builder(new HttpHost[]{}); + fail("should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("hosts must not be null nor empty", e.getMessage()); + } + + try { + Rest5Client.builder((Node[]) null); + fail("should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("nodes must not be null or empty", e.getMessage()); + } + + try { + Rest5Client.builder(new Node[]{}); + fail("should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("nodes must not be null or empty", e.getMessage()); + } + + try { + Rest5Client.builder(new Node(new HttpHost("localhost", 9200)), null); + fail("should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("node cannot be null", e.getMessage()); + } + + try { + Rest5Client.builder(new HttpHost("localhost", 9200), null); + fail("should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("host cannot be null", e.getMessage()); + } + + try (Rest5Client restClient = Rest5Client.builder(new HttpHost("localhost", 9200)).build()) { + assertNotNull(restClient); + } + + try { + Rest5Client.builder(new HttpHost("localhost", 9200)).setDefaultHeaders(null); + fail("should have failed"); + } catch (NullPointerException e) { + assertEquals("defaultHeaders must not be null", e.getMessage()); + } + + try { + Rest5Client.builder(new HttpHost("localhost", 9200)).setDefaultHeaders(new Header[]{null}); + fail("should have failed"); + } catch (NullPointerException e) { + assertEquals("default header must not be null", e.getMessage()); + } + + try { + Rest5Client.builder(new HttpHost("localhost", 9200)).setFailureListener(null); + fail("should have failed"); + } catch (NullPointerException e) { + assertEquals("failureListener must not be null", e.getMessage()); + } + + try { + Rest5Client.builder(new HttpHost("localhost", 9200)).setHttpClient(null); + fail("should have failed"); + } catch (NullPointerException e) { + assertEquals("custom rest client must not be null", e.getMessage()); + } + + try { + Rest5Client.builder(new HttpHost("localhost", 9200)).setSSLContext(null); + fail("should have failed"); + } catch (NullPointerException e) { + assertEquals("ssl context must not be null", e.getMessage()); + } + + int numNodes = randomIntBetween(1, 5); + HttpHost[] hosts = new HttpHost[numNodes]; + for (int i = 0; i < numNodes; i++) { + hosts[i] = new HttpHost("localhost", 9200 + i); + } + Rest5ClientBuilder builder = Rest5Client.builder(hosts); + CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() + .build(); + if (randomBoolean()) { + builder.setHttpClient(httpclient); + } + if (randomBoolean()) { + int numHeaders = randomIntBetween(1, 5); + Header[] headers = new Header[numHeaders]; + for (int i = 0; i < numHeaders; i++) { + headers[i] = new BasicHeader("header" + i, "value"); + } + builder.setDefaultHeaders(headers); + } + if (randomBoolean()) { + String pathPrefix = (randomBoolean() ? "/" : "") + randomAsciiLettersOfLengthBetween(2, 5); + while (pathPrefix.length() < 20 && randomBoolean()) { + pathPrefix += "/" + randomAsciiLettersOfLengthBetween(3, 6); + } + builder.setPathPrefix(pathPrefix + (randomBoolean() ? "/" : "")); + } + try (Rest5Client restClient = builder.build()) { + assertNotNull(restClient); + } + } + + public void testBuildCloudId() throws IOException { + String host = "us-east-1.aws.found.io"; + String esId = "elasticsearch"; + String kibanaId = "kibana"; + String toEncode = host + "$" + esId + "$" + kibanaId; + String encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(UTF8)); + assertNotNull(Rest5Client.builder(encodedId)); + assertNotNull(Rest5Client.builder("humanReadable:" + encodedId)); + + String badId = Base64.getEncoder().encodeToString("foo$bar".getBytes(UTF8)); + try { + Rest5Client.builder(badId); + fail("should have failed"); + } catch (IllegalStateException e) { + assertEquals("cloudId " + badId + " did not decode to a cluster identifier correctly", + e.getMessage()); + } + + try { + Rest5Client.builder(badId + ":"); + fail("should have failed"); + } catch (IllegalStateException e) { + assertEquals("cloudId " + badId + ": must begin with a human readable identifier followed by a " + + "colon", e.getMessage()); + } + + Rest5Client client = Rest5Client.builder(encodedId).build(); + assertThat(client.getNodes().size(), equalTo(1)); + assertThat(client.getNodes().get(0).getHost().getHostName(), equalTo(esId + "." + host)); + assertThat(client.getNodes().get(0).getHost().getPort(), equalTo(443)); + assertThat(client.getNodes().get(0).getHost().getSchemeName(), equalTo("https")); + client.close(); + } + + public void testBuildCloudIdWithPort() throws IOException { + String host = "us-east-1.aws.found.io"; + String esId = "elasticsearch"; + String kibanaId = "kibana"; + String port = "9443"; + String toEncode = host + ":" + port + "$" + esId + "$" + kibanaId; + String encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(UTF8)); + + Rest5Client client = Rest5Client.builder("humanReadable:" + encodedId).build(); + assertThat(client.getNodes().size(), equalTo(1)); + assertThat(client.getNodes().get(0).getHost().getPort(), equalTo(9443)); + assertThat(client.getNodes().get(0).getHost().getHostName(), equalTo(esId + "." + host)); + assertThat(client.getNodes().get(0).getHost().getSchemeName(), equalTo("https")); + client.close(); + + toEncode = host + ":" + "123:foo" + "$" + esId + "$" + kibanaId; + encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(UTF8)); + + try { + Rest5Client.builder("humanReadable:" + encodedId); + fail("should have failed"); + } catch (IllegalStateException e) { + assertEquals("cloudId " + encodedId + " does not contain a valid port number", e.getMessage()); + } + } + + public void testSetPathPrefixNull() { + try { + Rest5Client.builder(new HttpHost("localhost", 9200)).setPathPrefix(null); + fail("pathPrefix set to null should fail!"); + } catch (final NullPointerException e) { + assertEquals("pathPrefix must not be null", e.getMessage()); + } + } + + public void testSetPathPrefixEmpty() { + assertSetPathPrefixThrows(""); + } + + public void testSetPathPrefixMalformed() { + assertSetPathPrefixThrows("//"); + assertSetPathPrefixThrows("base/path//"); + } + + private static void assertSetPathPrefixThrows(final String pathPrefix) { + try { + Rest5Client.builder(new HttpHost("localhost", 9200)).setPathPrefix(pathPrefix); + fail("path prefix [" + pathPrefix + "] should have failed"); + } catch (final IllegalArgumentException e) { + assertThat(e.getMessage(), containsString(pathPrefix)); + } + } + + /** + * This test verifies that we don't change the default value for the connection request timeout as that + * causes problems. + * See https://github.com/elastic/elasticsearch/issues/24069 + */ + public void testDefaultConnectionRequestTimeout() throws IOException { + Rest5ClientBuilder builder = Rest5Client.builder(new HttpHost("localhost", 9200)); + + RequestConfig requestConfig = RequestConfig.custom().build(); + assertEquals(RequestConfig.DEFAULT.getConnectionRequestTimeout(), + requestConfig.getConnectionRequestTimeout()); + // this way we get notified if the default ever changes + // TODO IT CHANGED from -1 to 3 minutes, does it mean we always need to explicitly set it? + //assertEquals(-1, requestConfig.getConnectionRequestTimeout()); + + CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() + .setDefaultRequestConfig(requestConfig) + .build(); + + try (Rest5Client restClient = builder.build()) { + assertNotNull(restClient); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientGzipCompressionTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientGzipCompressionTests.java new file mode 100644 index 000000000..195ed69c0 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientGzipCompressionTests.java @@ -0,0 +1,251 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.elasticsearch.mocksocket.MockHttpServer; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.CompletableFuture; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +import static org.apache.hc.core5.http.HttpHeaders.CONTENT_ENCODING; +import static org.apache.hc.core5.http.HttpHeaders.CONTENT_LENGTH; + +public class RestClientGzipCompressionTests extends RestClientTestCase { + + private static HttpServer httpServer; + + @BeforeClass + public static void startHttpServer() throws Exception { + httpServer = MockHttpServer.createHttp(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + httpServer.createContext("/", new GzipResponseHandler()); + httpServer.start(); + } + + @AfterClass + public static void stopHttpServers() throws IOException { + httpServer.stop(0); + httpServer = null; + } + + /** + * A response handler that accepts gzip-encoded data and replies request and response encoding values + * followed by the request body. The response is compressed if "Accept-Encoding" is "gzip". + */ + private static class GzipResponseHandler implements HttpHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + + // Decode body (if any) + String contentEncoding = exchange.getRequestHeaders().getFirst("Content-Encoding"); + InputStream body = exchange.getRequestBody(); + if ("gzip".equals(contentEncoding)) { + body = new GZIPInputStream(body); + } + byte[] bytes = readAll(body); + + boolean compress = "gzip".equals(exchange.getRequestHeaders().getFirst("Accept-Encoding")); + if (compress) { + exchange.getResponseHeaders().add("Content-Encoding", "gzip"); + } + + // Encode response if needed + ByteArrayOutputStream bao = new ByteArrayOutputStream(); + OutputStream out = bao; + if (compress) { + out = new GZIPOutputStream(out); + } + + // Outputs ## + out.write(String.valueOf(contentEncoding).getBytes(StandardCharsets.UTF_8)); + out.write('#'); + out.write((compress ? "gzip" : "null").getBytes(StandardCharsets.UTF_8)); + out.write('#'); + out.write(bytes); + out.close(); + + bytes = bao.toByteArray(); + + exchange.sendResponseHeaders(200, bytes.length); + + exchange.getResponseBody().write(bytes); + exchange.close(); + } + } + + /** + * Read all bytes of an input stream and close it. + */ + private static byte[] readAll(InputStream in) throws IOException { + byte[] buffer = new byte[1024]; + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + int len = 0; + while ((len = in.read(buffer)) > 0) { + bos.write(buffer, 0, len); + } + in.close(); + return bos.toByteArray(); + } + + private Rest5Client createClient(boolean enableCompression) { + InetSocketAddress address = httpServer.getAddress(); + return Rest5Client.builder(new HttpHost("http", address.getHostString(), address.getPort())) + .setCompressionEnabled(enableCompression) + .build(); + } + + public void testUncompressedSync() throws Exception { + Rest5Client restClient = createClient(false); + + // Send non-compressed request, expect non-compressed response + Request request = new Request("POST", "/"); + request.setEntity(new StringEntity("plain request, plain response", ContentType.TEXT_PLAIN)); + + Response response = restClient.performRequest(request); + + // Server sends a content-length which should be kept + Assert.assertTrue(response.getEntity().getContentLength() > 0); + checkResponse("null#null#plain request, plain response", response); + + restClient.close(); + } + + public void testGzipHeaderSync() throws Exception { + Rest5Client restClient = createClient(false); + + // Send non-compressed request, expect compressed response + Request request = new Request("POST", "/"); + request.setEntity(new StringEntity("plain request, gzip response", ContentType.TEXT_PLAIN)); + request.setOptions(RequestOptions.DEFAULT.toBuilder().addHeader("Accept-Encoding", "gzip").build()); + + Response response = restClient.performRequest(request); + + // Content-length is unknown because of ungzip. Do not just test -1 as it returns "a negative + // number if unknown" + Assert.assertTrue(response.getEntity().getContentLength() < 0); + checkResponse("null#gzip#plain request, gzip response", response); + + restClient.close(); + } + + public void testGzipHeaderAsync() throws Exception { + Rest5Client restClient = createClient(false); + + // Send non-compressed request, expect compressed response + Request request = new Request("POST", "/"); + request.setEntity(new StringEntity("plain request, gzip response", ContentType.TEXT_PLAIN)); + request.setOptions(RequestOptions.DEFAULT.toBuilder().addHeader("Accept-Encoding", "gzip").build()); + + FutureResponse futureResponse = new FutureResponse(); + restClient.performRequestAsync(request, futureResponse); + Response response = futureResponse.get(); + + Assert.assertTrue(response.getEntity().getContentLength() < 0); + checkResponse("null#gzip#plain request, gzip response", response); + + restClient.close(); + } + + public void testCompressingClientSync() throws Exception { + Rest5Client restClient = createClient(true); + + Request request = new Request("POST", "/"); + request.setEntity(new StringEntity("compressing client", ContentType.TEXT_PLAIN)); + + Response response = restClient.performRequest(request); + + Assert.assertTrue(response.getEntity().getContentLength() < 0); + checkResponse("gzip#gzip#compressing client", response); + + restClient.close(); + } + + public void testCompressingClientAsync() throws Exception { + InetSocketAddress address = httpServer.getAddress(); + Rest5Client restClient = Rest5Client.builder(new HttpHost("http", address.getHostString(), + address.getPort())) + .setCompressionEnabled(true) + .build(); + + Request request = new Request("POST", "/"); + request.setEntity(new StringEntity("compressing client", ContentType.TEXT_PLAIN)); + + FutureResponse futureResponse = new FutureResponse(); + restClient.performRequestAsync(request, futureResponse); + Response response = futureResponse.get(); + + // Server should report it had a compressed request and sent back a compressed response + Assert.assertTrue(response.getEntity().getContentLength() < 0); + checkResponse("gzip#gzip#compressing client", response); + + restClient.close(); + } + + public static class FutureResponse extends CompletableFuture implements ResponseListener { + @Override + public void onSuccess(Response response) { + this.complete(response); + } + + @Override + public void onFailure(Exception exception) { + this.completeExceptionally(exception); + } + } + + private static void checkResponse(String expected, Response response) throws Exception { + HttpEntity entity = response.getEntity(); + Assert.assertNotNull(entity); + + String content = new String(readAll(entity.getContent()), StandardCharsets.UTF_8); + Assert.assertEquals(expected, content); + + // Original Content-Encoding should be removed on both entity and response + Assert.assertNull(entity.getContentEncoding()); + Assert.assertNull(response.getHeader(CONTENT_ENCODING)); + + // Content-length must be consistent between entity and response + long entityContentLength = entity.getContentLength(); + String headerContentLength = response.getHeader(CONTENT_LENGTH); + + if (entityContentLength < 0) { + Assert.assertNull(headerContentLength); + } else { + Assert.assertEquals(String.valueOf(entityContentLength), headerContentLength); + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientMultipleHostsIntegTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientMultipleHostsIntegTests.java new file mode 100644 index 000000000..5ab8d7764 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientMultipleHostsIntegTests.java @@ -0,0 +1,387 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.mocksocket.MockHttpServer; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.ConnectException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestUtil.getAllStatusCodes; +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestUtil.randomErrorNoRetryStatusCode; +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestUtil.randomOkStatusCode; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Integration test to check interaction between {@link Rest5Client} and {@link org.apache.hc.client5.http.async.HttpAsyncClient}. + * Works against real http servers, multiple hosts. Also tests failover by randomly shutting down hosts. + */ +public class RestClientMultipleHostsIntegTests extends RestClientTestCase { + + private static WaitForCancelHandler waitForCancelHandler; + private static HttpServer[] httpServers; + private static HttpHost[] httpHosts; + private static boolean stoppedFirstHost = false; + private static String pathPrefixWithoutLeadingSlash; + private static String pathPrefix; + private static Rest5Client restClient; + + @BeforeClass + public static void startHttpServer() throws Exception { + if (randomBoolean()) { + pathPrefixWithoutLeadingSlash = "testPathPrefix/" + randomAsciiLettersOfLengthBetween(1, 5); + pathPrefix = "/" + pathPrefixWithoutLeadingSlash; + } else { + pathPrefix = pathPrefixWithoutLeadingSlash = ""; + } + int numHttpServers = randomIntBetween(2, 4); + httpServers = new HttpServer[numHttpServers]; + httpHosts = new HttpHost[numHttpServers]; + waitForCancelHandler = new WaitForCancelHandler(); + for (int i = 0; i < numHttpServers; i++) { + HttpServer httpServer = createHttpServer(); + httpServers[i] = httpServer; + httpHosts[i] = new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()); + } + restClient = buildRestClient(NodeSelector.ANY); + } + + private static Rest5Client buildRestClient(NodeSelector nodeSelector) { + return buildRestClient(nodeSelector, null); + } + + private static Rest5Client buildRestClient(NodeSelector nodeSelector, Rest5Client.FailureListener failureListener) { + Rest5ClientBuilder restClientBuilder = Rest5Client.builder(httpHosts); + if (pathPrefix.length() > 0) { + restClientBuilder.setPathPrefix((randomBoolean() ? "/" : "") + pathPrefixWithoutLeadingSlash); + } + if (failureListener != null) { + restClientBuilder.setFailureListener(failureListener); + } + restClientBuilder.setNodeSelector(nodeSelector); + return restClientBuilder.build(); + } + + private static HttpServer createHttpServer() throws Exception { + HttpServer httpServer = MockHttpServer.createHttp(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + httpServer.start(); + // returns a different status code depending on the path + for (int statusCode : getAllStatusCodes()) { + httpServer.createContext(pathPrefix + "/" + statusCode, new ResponseHandler(statusCode)); + } + httpServer.createContext(pathPrefix + "/20bytes", new ResponseHandlerWithContent()); + httpServer.createContext(pathPrefix + "/wait", waitForCancelHandler); + return httpServer; + } + + private static WaitForCancelHandler resetWaitHandlers() { + WaitForCancelHandler handler = new WaitForCancelHandler(); + for (HttpServer httpServer : httpServers) { + httpServer.removeContext(pathPrefix + "/wait"); + httpServer.createContext(pathPrefix + "/wait", handler); + } + return handler; + } + + private static class WaitForCancelHandler implements HttpHandler { + private final CountDownLatch requestCameInLatch = new CountDownLatch(1); + private final CountDownLatch cancelHandlerLatch = new CountDownLatch(1); + + void cancelDone() { + cancelHandlerLatch.countDown(); + } + + void awaitRequest() throws InterruptedException { + requestCameInLatch.await(); + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + requestCameInLatch.countDown(); + try { + cancelHandlerLatch.await(); + } catch (InterruptedException ignore) {} finally { + exchange.sendResponseHeaders(200, 0); + exchange.close(); + } + } + } + + private static class ResponseHandler implements HttpHandler { + private final int statusCode; + + ResponseHandler(int statusCode) { + this.statusCode = statusCode; + } + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + httpExchange.getRequestBody().close(); + httpExchange.sendResponseHeaders(statusCode, -1); + httpExchange.close(); + } + } + + private static class ResponseHandlerWithContent implements HttpHandler { + @Override + public void handle(HttpExchange httpExchange) throws IOException { + byte[] body = "01234567890123456789".getBytes(StandardCharsets.UTF_8); + httpExchange.sendResponseHeaders(200, body.length); + try (OutputStream out = httpExchange.getResponseBody()) { + out.write(body); + } + httpExchange.close(); + } + } + + @AfterClass + public static void stopHttpServers() throws IOException { + restClient.close(); + restClient = null; + for (HttpServer httpServer : httpServers) { + httpServer.stop(0); + } + httpServers = null; + } + + @Before + public void stopRandomHost() { + // verify that shutting down some hosts doesn't matter as long as one working host is left behind + if (httpServers.length > 1 && randomBoolean()) { + List updatedHttpServers = new ArrayList<>(httpServers.length - 1); + int nodeIndex = randomIntBetween(0, httpServers.length - 1); + if (0 == nodeIndex) { + stoppedFirstHost = true; + } + for (int i = 0; i < httpServers.length; i++) { + HttpServer httpServer = httpServers[i]; + if (i == nodeIndex) { + httpServer.stop(0); + } else { + updatedHttpServers.add(httpServer); + } + } + httpServers = updatedHttpServers.toArray(new HttpServer[0]); + } + } + + public void testSyncRequests() throws IOException { + int numRequests = randomIntBetween(5, 20); + for (int i = 0; i < numRequests; i++) { + final String method = RestClientTestUtil.randomHttpMethod(getRandom()); + // we don't test status codes that are subject to retries as they interfere with hosts being stopped + final int statusCode = randomBoolean() ? randomOkStatusCode(getRandom()) : randomErrorNoRetryStatusCode(getRandom()); + Response response; + try { + response = restClient.performRequest(new Request(method, "/" + statusCode)); + } catch (ResponseException responseException) { + response = responseException.getResponse(); + } + assertEquals(method, response.getRequestLine().getMethod()); + assertEquals(statusCode, response.getStatusCode()); + assertEquals((pathPrefix.length() > 0 ? pathPrefix : "") + "/" + statusCode, response.getRequestLine().getUri()); + } + } + + public void testAsyncRequests() throws Exception { + int numRequests = randomIntBetween(5, 20); + final CountDownLatch latch = new CountDownLatch(numRequests); + final List responses = new CopyOnWriteArrayList<>(); + for (int i = 0; i < numRequests; i++) { + final String method = RestClientTestUtil.randomHttpMethod(getRandom()); + // we don't test status codes that are subject to retries as they interfere with hosts being stopped + final int statusCode = randomBoolean() ? randomOkStatusCode(getRandom()) : randomErrorNoRetryStatusCode(getRandom()); + restClient.performRequestAsync(new Request(method, "/" + statusCode), new ResponseListener() { + @Override + public void onSuccess(Response response) { + responses.add(new TestResponse(method, statusCode, response)); + latch.countDown(); + } + + @Override + public void onFailure(Exception exception) { + responses.add(new TestResponse(method, statusCode, exception)); + latch.countDown(); + } + }); + } + assertTrue(latch.await(5, TimeUnit.SECONDS)); + + assertEquals(numRequests, responses.size()); + for (TestResponse testResponse : responses) { + Response response = testResponse.getResponse(); + assertEquals(testResponse.method, response.getRequestLine().getMethod()); + assertEquals(testResponse.statusCode, response.getStatusCode()); + assertEquals((pathPrefix.length() > 0 ? pathPrefix : "") + "/" + testResponse.statusCode, response.getRequestLine().getUri()); + } + } + + public void testCancelAsyncRequests() throws Exception { + int numRequests = randomIntBetween(5, 20); + final List responses = new CopyOnWriteArrayList<>(); + final List exceptions = new CopyOnWriteArrayList<>(); + for (int i = 0; i < numRequests; i++) { + CountDownLatch latch = new CountDownLatch(1); + waitForCancelHandler = resetWaitHandlers(); + Cancellable cancellable = restClient.performRequestAsync(new Request("GET", "/wait"), new ResponseListener() { + @Override + public void onSuccess(Response response) { + responses.add(response); + latch.countDown(); + } + + @Override + public void onFailure(Exception exception) { + exceptions.add(exception); + latch.countDown(); + } + }); + if (randomBoolean()) { + // we wait for the request to get to the server-side otherwise we almost always cancel + // the request artificially on the client-side before even sending it + waitForCancelHandler.awaitRequest(); + } + cancellable.cancel(); + waitForCancelHandler.cancelDone(); + assertTrue(latch.await(5, TimeUnit.SECONDS)); + } + assertEquals(0, responses.size()); + assertEquals(numRequests, exceptions.size()); + for (Exception exception : exceptions) { + assertThat(exception, instanceOf(CancellationException.class)); + } + } + + /** + * Test host selector against a real server and + * test what happens after calling + */ + public void testNodeSelector() throws Exception { + try (Rest5Client restClient = buildRestClient(firstPositionNodeSelector())) { + Request request = new Request("GET", "/200"); + int rounds = between(1, 10); + for (int i = 0; i < rounds; i++) { + /* + * Run the request more than once to verify that the + * NodeSelector overrides the round robin behavior. + */ + if (stoppedFirstHost) { + try { + RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + fail("expected to fail to connect"); + } catch (ConnectException e) { + // Windows isn't consistent here. Sometimes the message is even null! + if (false == System.getProperty("os.name").startsWith("Windows")) { + assertTrue(e.getMessage().contains("Connection refused")); + } + } + } else { + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(httpHosts[0], response.getHost()); + } + } + } + } + + @Ignore("https://github.com/elastic/elasticsearch/issues/87314") + public void testNonRetryableException() throws Exception { + RequestOptions.Builder options = RequestOptions.DEFAULT.toBuilder(); + options.setHttpAsyncResponseConsumerFactory( + // Limit to very short responses to trigger a ContentTooLongException + () -> new BasicAsyncResponseConsumer(new BufferedByteConsumer(10)) + ); + + AtomicInteger failureCount = new AtomicInteger(); + Rest5Client client = buildRestClient(NodeSelector.ANY, new Rest5Client.FailureListener() { + @Override + public void onFailure(Node node) { + failureCount.incrementAndGet(); + } + }); + + failureCount.set(0); + Request request = new Request("POST", "/20bytes"); + request.setOptions(options); + try { + RestClientSingleHostTests.performRequestSyncOrAsync(client, request); + fail("Request should not succeed"); + } catch (IOException e) { + assertEquals(stoppedFirstHost ? 2 : 1, failureCount.intValue()); + } + + client.close(); + } + + private static class TestResponse { + private final String method; + private final int statusCode; + private final Object response; + + TestResponse(String method, int statusCode, Object response) { + this.method = method; + this.statusCode = statusCode; + this.response = response; + } + + Response getResponse() { + if (response instanceof Response) { + return (Response) response; + } + if (response instanceof ResponseException) { + return ((ResponseException) response).getResponse(); + } + throw new AssertionError("unexpected response " + response.getClass()); + } + } + + private NodeSelector firstPositionNodeSelector() { + return nodes -> { + for (Iterator itr = nodes.iterator(); itr.hasNext();) { + if (httpHosts[0] != itr.next().getHost()) { + itr.remove(); + } + } + }; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientMultipleHostsTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientMultipleHostsTests.java new file mode 100644 index 000000000..d28ac4f65 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientMultipleHostsTests.java @@ -0,0 +1,333 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import com.carrotsearch.randomizedtesting.generators.RandomNumbers; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.junit.After; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestUtil.randomErrorNoRetryStatusCode; +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestUtil.randomErrorRetryStatusCode; +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestUtil.randomHttpMethod; +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestUtil.randomOkStatusCode; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Tests for {@link Rest5Client} behaviour against multiple hosts: fail-over, blacklisting etc. + * Relies on a mock http client to intercept requests and return desired responses based on request path. + */ +public class RestClientMultipleHostsTests extends RestClientTestCase { + + private ExecutorService exec = Executors.newFixedThreadPool(1); + private List nodes; + private HostsTrackingFailureListener failureListener; + + public Rest5Client createRestClient(NodeSelector nodeSelector) { + CloseableHttpAsyncClient httpClient = RestClientSingleHostTests.mockHttpClient(exec); + int numNodes = RandomNumbers.randomIntBetween(getRandom(), 2, 5); + nodes = new ArrayList<>(numNodes); + for (int i = 0; i < numNodes; i++) { + nodes.add(new Node(new HttpHost("localhost", 9200 + i))); + } + nodes = Collections.unmodifiableList(nodes); + failureListener = new HostsTrackingFailureListener(); + return new Rest5Client(httpClient, new Header[0], nodes, null, failureListener, nodeSelector, false, false, false); + } + + /** + * Shutdown the executor so we don't leak threads into other test runs. + */ + @After + public void shutdownExec() { + exec.shutdown(); + } + + public void testRoundRobinOkStatusCodes() throws Exception { + Rest5Client restClient = createRestClient(NodeSelector.ANY); + int numIters = RandomNumbers.randomIntBetween(getRandom(), 1, 5); + for (int i = 0; i < numIters; i++) { + Set hostsSet = hostsSet(); + for (int j = 0; j < nodes.size(); j++) { + int statusCode = randomOkStatusCode(getRandom()); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync( + restClient, + new Request(randomHttpMethod(getRandom()), "/" + statusCode) + ); + assertEquals(statusCode, response.getStatusCode()); + assertTrue("host not found: " + response.getHost(), hostsSet.remove(response.getHost())); + } + assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); + } + failureListener.assertNotCalled(); + } + + public void testRoundRobinNoRetryErrors() throws Exception { + Rest5Client restClient = createRestClient(NodeSelector.ANY); + int numIters = RandomNumbers.randomIntBetween(getRandom(), 1, 5); + for (int i = 0; i < numIters; i++) { + Set hostsSet = hostsSet(); + for (int j = 0; j < nodes.size(); j++) { + String method = randomHttpMethod(getRandom()); + int statusCode = randomErrorNoRetryStatusCode(getRandom()); + try { + Response response = RestClientSingleHostTests.performRequestSyncOrAsync( + restClient, + new Request(method, "/" + statusCode) + ); + if (method.equals("HEAD") && statusCode == 404) { + // no exception gets thrown although we got a 404 + assertEquals(404, response.getStatusCode()); + assertEquals(statusCode, response.getStatusCode()); + assertTrue("host not found: " + response.getHost(), hostsSet.remove(response.getHost())); + } else { + fail("request should have failed"); + } + } catch (ResponseException e) { + if (method.equals("HEAD") && statusCode == 404) { + throw e; + } + Response response = e.getResponse(); + assertEquals(statusCode, response.getStatusCode()); + assertTrue("host not found: " + response.getHost(), hostsSet.remove(response.getHost())); + assertEquals(0, e.getSuppressed().length); + } + } + assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); + } + failureListener.assertNotCalled(); + } + + public void testRoundRobinRetryErrors() throws Exception { + Rest5Client restClient = createRestClient(NodeSelector.ANY); + String retryEndpoint = randomErrorRetryEndpoint(); + try { + RestClientSingleHostTests.performRequestSyncOrAsync(restClient, new Request(randomHttpMethod(getRandom()), retryEndpoint)); + fail("request should have failed"); + } catch (ResponseException e) { + Set hostsSet = hostsSet(); + // first request causes all the hosts to be blacklisted, the returned exception holds one suppressed exception each + failureListener.assertCalled(nodes); + do { + Response response = e.getResponse(); + assertEquals(Integer.parseInt(retryEndpoint.substring(1)), response.getStatusCode()); + assertTrue( + "host [" + response.getHost() + "] not found, most likely used multiple times", + hostsSet.remove(response.getHost()) + ); + if (e.getSuppressed().length > 0) { + assertEquals(1, e.getSuppressed().length); + Throwable suppressed = e.getSuppressed()[0]; + assertThat(suppressed, instanceOf(ResponseException.class)); + e = (ResponseException) suppressed; + } else { + e = null; + } + } while (e != null); + assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); + } catch (IOException e) { + Set hostsSet = hostsSet(); + // first request causes all the hosts to be blacklisted, the returned exception holds one suppressed exception each + failureListener.assertCalled(nodes); + do { + HttpHost httpHost = HttpHost.create(e.getMessage()); + assertTrue("host [" + httpHost + "] not found, most likely used multiple times", hostsSet.remove(httpHost)); + if (e.getSuppressed().length > 0) { + assertEquals(1, e.getSuppressed().length); + Throwable suppressed = e.getSuppressed()[0]; + assertThat(suppressed, instanceOf(IOException.class)); + e = (IOException) suppressed; + } else { + e = null; + } + } while (e != null); + assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); + } + + int numIters = RandomNumbers.randomIntBetween(getRandom(), 2, 5); + for (int i = 1; i <= numIters; i++) { + // check that one different host is resurrected at each new attempt + Set hostsSet = hostsSet(); + for (int j = 0; j < nodes.size(); j++) { + retryEndpoint = randomErrorRetryEndpoint(); + try { + RestClientSingleHostTests.performRequestSyncOrAsync( + restClient, + new Request(randomHttpMethod(getRandom()), retryEndpoint) + ); + fail("request should have failed"); + } catch (ResponseException e) { + Response response = e.getResponse(); + assertThat(response.getStatusCode(), equalTo(Integer.parseInt(retryEndpoint.substring(1)))); + assertTrue( + "host [" + response.getHost() + "] not found, most likely used multiple times", + hostsSet.remove(response.getHost()) + ); + // after the first request, all hosts are blacklisted, a single one gets resurrected each time + failureListener.assertCalled(response.getHost()); + assertEquals(0, e.getSuppressed().length); + } catch (IOException e) { + HttpHost httpHost = HttpHost.create(e.getMessage()); + assertTrue("host [" + httpHost + "] not found, most likely used multiple times", hostsSet.remove(httpHost)); + // after the first request, all hosts are blacklisted, a single one gets resurrected each time + failureListener.assertCalled(httpHost); + assertEquals(0, e.getSuppressed().length); + } + } + assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); + if (getRandom().nextBoolean()) { + // mark one host back alive through a successful request and check that all requests after that are sent to it + HttpHost selectedHost = null; + int iters = RandomNumbers.randomIntBetween(getRandom(), 2, 10); + for (int y = 0; y < iters; y++) { + int statusCode = randomErrorNoRetryStatusCode(getRandom()); + Response response; + try { + response = RestClientSingleHostTests.performRequestSyncOrAsync( + restClient, + new Request(randomHttpMethod(getRandom()), "/" + statusCode) + ); + } catch (ResponseException e) { + response = e.getResponse(); + } + assertThat(response.getStatusCode(), equalTo(statusCode)); + if (selectedHost == null) { + selectedHost = response.getHost(); + } else { + assertThat(response.getHost(), equalTo(selectedHost)); + } + } + failureListener.assertNotCalled(); + // let the selected host catch up on number of failures, it gets selected a consecutive number of times as it's the one + // selected to be retried earlier (due to lower number of failures) till all the hosts have the same number of failures + for (int y = 0; y < i + 1; y++) { + retryEndpoint = randomErrorRetryEndpoint(); + try { + RestClientSingleHostTests.performRequestSyncOrAsync( + restClient, + new Request(randomHttpMethod(getRandom()), retryEndpoint) + ); + fail("request should have failed"); + } catch (ResponseException e) { + Response response = e.getResponse(); + assertThat(response.getStatusCode(), equalTo(Integer.parseInt(retryEndpoint.substring(1)))); + assertThat(response.getHost(), equalTo(selectedHost)); + failureListener.assertCalled(selectedHost); + } catch (IOException e) { + HttpHost httpHost = HttpHost.create(e.getMessage()); + assertThat(httpHost, equalTo(selectedHost)); + failureListener.assertCalled(selectedHost); + } + } + } + } + } + + public void testNodeSelector() throws Exception { + NodeSelector firstPositionOnly = restClientNodes -> { + boolean found = false; + for (Iterator itr = restClientNodes.iterator(); itr.hasNext();) { + if (nodes.get(0) == itr.next()) { + found = true; + } else { + itr.remove(); + } + } + assertTrue(found); + }; + Rest5Client restClient = createRestClient(firstPositionOnly); + int rounds = between(1, 10); + for (int i = 0; i < rounds; i++) { + /* + * Run the request more than once to verify that the + * NodeSelector overrides the round robin behavior. + */ + Request request = new Request("GET", "/200"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(nodes.get(0).getHost(), response.getHost()); + } + } + + public void testSetNodes() throws Exception { + Rest5Client restClient = createRestClient(NodeSelector.SKIP_DEDICATED_MASTERS); + List newNodes = new ArrayList<>(nodes.size()); + for (int i = 0; i < nodes.size(); i++) { + Node.Roles roles = i == 0 + ? new Node.Roles(new TreeSet<>(Arrays.asList("data", "ingest"))) + : new Node.Roles(new TreeSet<>(Arrays.asList("master"))); + newNodes.add(new Node(nodes.get(i).getHost(), null, null, null, roles, null)); + } + restClient.setNodes(newNodes); + int rounds = between(1, 10); + for (int i = 0; i < rounds; i++) { + /* + * Run the request more than once to verify that the + * NodeSelector overrides the round robin behavior. + */ + Request request = new Request("GET", "/200"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(newNodes.get(0).getHost(), response.getHost()); + } + } + + private static String randomErrorRetryEndpoint() { + switch (RandomNumbers.randomIntBetween(getRandom(), 0, 3)) { + case 0: + return "/" + randomErrorRetryStatusCode(getRandom()); + case 1: + return "/coe"; + case 2: + return "/soe"; + case 3: + return "/ioe"; + } + throw new UnsupportedOperationException(); + } + + /** + * Build a mutable {@link Set} containing all the {@link Node#getHost() hosts} + * in use by the test. + */ + private Set hostsSet() { + Set hosts = new HashSet<>(); + for (Node node : nodes) { + hosts.add(node.getHost()); + } + return hosts; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostIntegTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostIntegTests.java new file mode 100644 index 000000000..d029e81bb --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostIntegTests.java @@ -0,0 +1,447 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import org.apache.hc.client5.http.async.methods.SimpleHttpRequest; +import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; +import org.apache.hc.client5.http.impl.async.HttpAsyncClients; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.http.message.BasicHeader; +import org.elasticsearch.client.RestClientBuilder; +import org.elasticsearch.mocksocket.MockHttpServer; +import org.junit.After; +import org.junit.Before; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestUtil.getAllStatusCodes; +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestUtil.randomHttpMethod; +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestUtil.randomStatusCode; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.startsWith; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/* + * Integration test to check interaction between {@link Rest5Client} and {@link org.apache.hc.client5.http + * .async.HttpAsyncClient}. + * Works against a real http server, one single host. + */ + +public class RestClientSingleHostIntegTests extends RestClientTestCase { + + private HttpServer httpServer; + private Rest5Client restClient; + private String pathPrefix; + private Header[] defaultHeaders; + private WaitForCancelHandler waitForCancelHandler; + + @Before + public void startHttpServer() throws Exception { + // set version.properties, just for testing, version won't be updated + System.setProperty("versions.elasticsearch","8.17.0"); + pathPrefix = randomBoolean() ? "/testPathPrefix/" + randomAsciiLettersOfLengthBetween(1, 5) : ""; + httpServer = createHttpServer(); + defaultHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header-default"); + restClient = createRestClient(false, true, true); + } + + private HttpServer createHttpServer() throws Exception { + HttpServer mockServer = + MockHttpServer.createHttp(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + mockServer.start(); + // returns a different status code depending on the path + for (int statusCode : getAllStatusCodes()) { + mockServer.createContext(pathPrefix + "/" + statusCode, new ResponseHandler(statusCode)); + } + waitForCancelHandler = new WaitForCancelHandler(); + mockServer.createContext(pathPrefix + "/wait", waitForCancelHandler); + return mockServer; + } + + private static class WaitForCancelHandler implements HttpHandler { + + private final CountDownLatch cancelHandlerLatch = new CountDownLatch(1); + + void cancelDone() { + cancelHandlerLatch.countDown(); + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + cancelHandlerLatch.await(); + } catch (InterruptedException ignore) { + } finally { + exchange.sendResponseHeaders(200, 0); + exchange.close(); + } + } + } + + private static class ResponseHandler implements HttpHandler { + private final int statusCode; + + ResponseHandler(int statusCode) { + this.statusCode = statusCode; + } + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + // copy request body to response body so we can verify it was sent + StringBuilder body = new StringBuilder(); + try (InputStreamReader reader = new InputStreamReader(httpExchange.getRequestBody(), UTF_8)) { + char[] buffer = new char[256]; + int read; + while ((read = reader.read(buffer)) != -1) { + body.append(buffer, 0, read); + } + } + // copy request headers to response headers so we can verify they were sent + Headers requestHeaders = httpExchange.getRequestHeaders(); + Headers responseHeaders = httpExchange.getResponseHeaders(); + for (Map.Entry> header : requestHeaders.entrySet()) { + responseHeaders.put(header.getKey(), header.getValue()); + } + httpExchange.getRequestBody().close(); + httpExchange.sendResponseHeaders(statusCode, body.length() == 0 ? -1 : body.length()); + if (body.length() > 0) { + try (OutputStream out = httpExchange.getResponseBody()) { + out.write(body.toString().getBytes(UTF_8)); + } + } + httpExchange.close(); + } + } + + private Rest5Client createRestClient(final boolean useAuth, final boolean usePreemptiveAuth, + final boolean enableMetaHeader) { + HttpHost host = new HttpHost(httpServer.getAddress().getHostString(), + httpServer.getAddress().getPort()); + + final Rest5ClientBuilder restClientBuilder = + Rest5Client.builder(host).setDefaultHeaders(defaultHeaders); + if (pathPrefix.length() > 0) { + restClientBuilder.setPathPrefix(pathPrefix); + } + + restClientBuilder.setMetaHeaderEnabled(enableMetaHeader); + + + if (useAuth) { + // provide the username/password for every request + var creds = Base64.getEncoder().encodeToString("user:pass".getBytes()); + + HttpAsyncClientBuilder httpclientBuilder = HttpAsyncClients.custom(); + + httpclientBuilder.setDefaultHeaders(Arrays.asList(new BasicHeader("Authorization", + "Basic " + creds))); + + if (!usePreemptiveAuth) { + httpclientBuilder + .disableAuthCaching() + .setTargetAuthenticationStrategy(new DefaultAuthenticationStrategy()); + } + restClientBuilder.setHttpClient(httpclientBuilder.build()); + } + + return restClientBuilder.build(); + } + + @After + public void stopHttpServers() throws IOException { + restClient.close(); + restClient = null; + httpServer.stop(0); + httpServer = null; + } + + /* + * Tests sending a bunch of async requests works well (e.g. no TimeoutException from the leased pool) + * See https://github.com/elastic/elasticsearch/issues/24069 + */ + + public void testManyAsyncRequests() throws Exception { + int iters = randomIntBetween(500, 1000); + final CountDownLatch latch = new CountDownLatch(iters); + final List exceptions = new CopyOnWriteArrayList<>(); + for (int i = 0; i < iters; i++) { + Request request = new Request("PUT", "/200"); + request.setEntity(new StringEntity("{}", ContentType.APPLICATION_JSON)); + restClient.performRequestAsync(request, new ResponseListener() { + @Override + public void onSuccess(Response response) { + latch.countDown(); + } + + @Override + public void onFailure(Exception exception) { + exceptions.add(exception); + latch.countDown(); + } + }); + } + + assertTrue("timeout waiting for requests to be sent", latch.await(10, TimeUnit.SECONDS)); + if (exceptions.isEmpty() == false) { + AssertionError error = new AssertionError( + "expected no failures but got some. see suppressed for first 10 of [" + exceptions.size() + "] failures" + ); + for (Exception exception : exceptions.subList(0, Math.min(10, exceptions.size()))) { + error.addSuppressed(exception); + } + throw error; + } + } + + public void testCancelAsyncRequest() throws Exception { + Request request = new Request(randomHttpMethod(getRandom()), "/wait"); + CountDownLatch requestLatch = new CountDownLatch(1); + AtomicReference error = new AtomicReference<>(); + Cancellable cancellable = restClient.performRequestAsync(request, new ResponseListener() { + @Override + public void onSuccess(Response response) { + throw new AssertionError("onResponse called unexpectedly"); + } + + @Override + public void onFailure(Exception exception) { + error.set(exception); + requestLatch.countDown(); + } + }); + cancellable.cancel(); + waitForCancelHandler.cancelDone(); + assertTrue(requestLatch.await(5, TimeUnit.SECONDS)); + assertThat(error.get(), instanceOf(CancellationException.class)); + } + + /** + * This test verifies some assumptions that we rely upon around the way the async http client works + * when reusing the same request + * throughout multiple retries, and the use of the + * {@link org.apache.hc.client5.http.classic.methods.HttpUriRequestBase#abort()} method. + * In fact the low-level REST client reuses the same request instance throughout multiple retries, and + * relies on the http client + * to set the future ref to the request properly so that when abort is called, the proper future gets + * cancelled. + */ + public void testRequestResetAndAbort() throws Exception { + try (CloseableHttpAsyncClient client = HttpAsyncClientBuilder.create().build()) { + client.start(); + HttpHost httpHost = new HttpHost(httpServer.getAddress().getHostString(), + httpServer.getAddress().getPort()); + HttpGet httpGet = new HttpGet(httpHost.toURI() + pathPrefix + "/200"); + + // calling abort before the request is sent is a no-op + httpGet.abort(); + assertTrue(httpGet.isAborted()); + + { + httpGet.reset(); + assertFalse(httpGet.isAborted()); + httpGet.abort(); + Future future = client.execute(SimpleHttpRequest.copy(httpGet), null); + httpGet.setDependency((org.apache.hc.core5.concurrent.Cancellable) future); + try { + future.get(); + fail("expected cancellation exception"); + } catch (CancellationException e) { + // expected + } + assertTrue(future.isCancelled()); + } + { + httpGet.reset(); + Future future = client.execute(SimpleHttpRequest.copy(httpGet), null); + httpGet.setDependency((org.apache.hc.core5.concurrent.Cancellable) future); + + assertFalse(httpGet.isAborted()); + httpGet.abort(); + assertTrue(httpGet.isAborted()); + try { + assertTrue(future.isDone()); + future.get(); + } catch (CancellationException e) { + // expected sometimes - if the future was cancelled before executing successfully + } + } + { + httpGet.reset(); + assertFalse(httpGet.isAborted()); + Future future = client.execute(SimpleHttpRequest.copy(httpGet), null); + httpGet.setDependency((org.apache.hc.core5.concurrent.Cancellable) future); + + assertFalse(httpGet.isAborted()); + assertEquals(200, future.get().getCode()); + assertFalse(future.isCancelled()); + } + } + } + + /** + * End to end test for delete with body. We test it explicitly as it is not supported + * out of the box by {@link HttpAsyncClients}. + * Exercises the test http server ability to send back whatever body it received. + */ + public void testDeleteWithBody() throws Exception { + bodyTest("DELETE"); + } + + /** + * End to end test for get with body. We test it explicitly as it is not supported + * out of the box by {@link HttpAsyncClients}. + * Exercises the test http server ability to send back whatever body it received. + */ + public void testGetWithBody() throws Exception { + bodyTest("GET"); + } + + public void testEncodeParams() throws Exception { + { + Request request = new Request("PUT", "/200"); + request.addParameter("routing", "this/is/the/routing"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(pathPrefix + "/200?routing=this%2Fis%2Fthe%2Frouting", + response.getRequestLine().getUri()); + } + { + Request request = new Request("PUT", "/200"); + request.addParameter("routing", "this|is|the|routing"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(pathPrefix + "/200?routing=this%7Cis%7Cthe%7Crouting", + response.getRequestLine().getUri()); + } + { + Request request = new Request("PUT", "/200"); + request.addParameter("routing", "routing#1"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(pathPrefix + "/200?routing=routing%231", response.getRequestLine().getUri()); + } + { + Request request = new Request("PUT", "/200"); + request.addParameter("routing", "中文"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(pathPrefix + "/200?routing=%E4%B8%AD%E6%96%87", response.getRequestLine().getUri()); + } + { + Request request = new Request("PUT", "/200"); + request.addParameter("routing", "foo bar"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(pathPrefix + "/200?routing=foo%20bar", response.getRequestLine().getUri()); + } + { + Request request = new Request("PUT", "/200"); + request.addParameter("routing", "foo+bar"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(pathPrefix + "/200?routing=foo%2Bbar", response.getRequestLine().getUri()); + } + { + Request request = new Request("PUT", "/200"); + request.addParameter("routing", "foo/bar"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(pathPrefix + "/200?routing=foo%2Fbar", response.getRequestLine().getUri()); + } + { + Request request = new Request("PUT", "/200"); + request.addParameter("routing", "foo^bar"); + Response response = RestClientSingleHostTests.performRequestSyncOrAsync(restClient, request); + assertEquals(pathPrefix + "/200?routing=foo%5Ebar", response.getRequestLine().getUri()); + } + } + + /** + * Verify that credentials are sent on the first request with preemptive auth enabled (default when + * provided with credentials). + */ + public void testPreemptiveAuthEnabled() throws Exception { + final String[] methods = {"POST", "PUT", "GET", "DELETE"}; + + try (Rest5Client restClient = createRestClient(true, true, true)) { + for (final String method : methods) { + final Response response = bodyTest(restClient, method); + + assertThat(response.getHeader("Authorization"), startsWith("Basic")); + } + } + } + + private Response bodyTest(final String method) throws Exception { + return bodyTest(restClient, method); + } + + private Response bodyTest(final Rest5Client client, final String method) throws Exception { + int statusCode = randomStatusCode(getRandom()); + return bodyTest(client, method, statusCode, new Header[0]); + } + + private Response bodyTest(Rest5Client client, String method, int statusCode, Header[] headers) throws Exception { + String requestBody = "{ \"field\": \"value\" }"; + Request request = new Request(method, "/" + statusCode); + request.setJsonEntity(requestBody); + RequestOptions.Builder options = request.getOptions().toBuilder(); + for (Header header : headers) { + options.addHeader(header.getName(), header.getValue()); + } + request.setOptions(options); + Response esResponse; + try { + esResponse = RestClientSingleHostTests.performRequestSyncOrAsync(client, request); + } catch (ResponseException e) { + esResponse = e.getResponse(); + } + assertEquals(method, esResponse.getRequestLine().getMethod()); + assertEquals(statusCode, esResponse.getStatusCode()); + assertEquals(pathPrefix + "/" + statusCode, esResponse.getRequestLine().getUri()); + assertEquals(requestBody, EntityUtils.toString(esResponse.getEntity())); + + return esResponse; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostTests.java new file mode 100644 index 000000000..e6d99d882 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostTests.java @@ -0,0 +1,681 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hc.client5.http.ConnectTimeoutException; +import org.apache.hc.client5.http.classic.methods.HttpHead; +import org.apache.hc.client5.http.classic.methods.HttpOptions; +import org.apache.hc.client5.http.classic.methods.HttpPatch; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.classic.methods.HttpPut; +import org.apache.hc.client5.http.classic.methods.HttpTrace; +import org.apache.hc.client5.http.classic.methods.HttpUriRequest; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.core5.concurrent.FutureCallback; +import org.apache.hc.core5.http.ConnectionClosedException; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpRequest; +import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.http.message.BasicClassicHttpRequest; +import org.apache.hc.core5.http.message.BasicClassicHttpResponse; +import org.apache.hc.core5.http.nio.AsyncDataProducer; +import org.apache.hc.core5.http.nio.AsyncRequestProducer; +import org.apache.hc.core5.http.nio.AsyncResponseConsumer; +import org.apache.hc.core5.net.URIBuilder; +import org.junit.After; +import org.junit.Before; +import org.mockito.ArgumentCaptor; +import org.mockito.stubbing.Answer; + +import javax.net.ssl.SSLHandshakeException; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Field; +import java.net.SocketTimeoutException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicReference; + +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestUtil.canHaveBody; +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestUtil.getAllErrorStatusCodes; +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestUtil.getHttpMethods; +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestUtil.getOkStatusCodes; +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestUtil.randomStatusCode; +import static java.util.Collections.singletonList; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * Tests for basic functionality of {@link Rest5Client} against one single host: tests http requests being + * sent, headers, + * body, different status codes and corresponding responses/exceptions. + * Relies on a mock http client to intercept requests and return desired responses based on request path. + */ +public class RestClientSingleHostTests extends RestClientTestCase { + private static final Log logger = LogFactory.getLog(RestClientSingleHostTests.class); + + private ExecutorService exec = Executors.newFixedThreadPool(1); + private Rest5Client restClient; + private Header[] defaultHeaders; + private Node node; + private CloseableHttpAsyncClient httpClient; + private HostsTrackingFailureListener failureListener; + private boolean strictDeprecationMode; + + @Before + public void createRestClient() { + httpClient = mockHttpClient(exec); + defaultHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header-default"); + node = new Node(new HttpHost("localhost", 9200)); + failureListener = new HostsTrackingFailureListener(); + strictDeprecationMode = randomBoolean(); + restClient = new Rest5Client( + this.httpClient, + defaultHeaders, + singletonList(node), + null, + failureListener, + NodeSelector.ANY, + strictDeprecationMode, + false, + false + ); + } + + @SuppressWarnings("unchecked") + static CloseableHttpAsyncClient mockHttpClient(final ExecutorService exec) { + CloseableHttpAsyncClient httpClient = mock(CloseableHttpAsyncClient.class); + when( + httpClient.execute( + any(AsyncRequestProducer.class), + any(AsyncResponseConsumer.class), + any(HttpClientContext.class), + nullable(FutureCallback.class) + ) + ).thenAnswer((Answer>) invocationOnMock -> { + final AsyncRequestProducer requestProducer = + (AsyncRequestProducer) invocationOnMock.getArguments()[0]; + final FutureCallback futureCallback = + (FutureCallback) invocationOnMock.getArguments()[3]; + // Call the callback asynchronous to better simulate how async http client works + return exec.submit(() -> { + if (futureCallback != null) { + try { + HttpResponse httpResponse = responseOrException(requestProducer); + futureCallback.completed(httpResponse); + } catch (Exception e) { + futureCallback.failed(e); + } + return null; + } + return responseOrException(requestProducer); + }); + }); + return httpClient; + } + + private static HttpResponse responseOrException(AsyncDataProducer requestProducer) throws Exception { + // request is private in BasicRequestProducer, need to make it accessible first + Field requestField = requestProducer.getClass().getDeclaredField("request"); + requestField.setAccessible(true); + final HttpRequest request = (HttpRequest) requestField.get(requestProducer); + final HttpHost httpHost = new HttpHost(request.getAuthority().getHostName(), + request.getAuthority().getPort()); + // return the desired status code or exception depending on the path + switch (request.getPath()) { + case "/soe": + throw new SocketTimeoutException(httpHost.toString()); + case "/coe": + throw new ConnectTimeoutException(httpHost.toString()); + case "/ioe": + throw new IOException(httpHost.toString()); + case "/closed": + throw new ConnectionClosedException(); + case "/handshake": + throw new SSLHandshakeException(""); + case "/uri": + throw new URISyntaxException("", ""); + case "/runtime": + throw new RuntimeException(); + default: + int statusCode = Integer.parseInt(request.getPath().substring(1)); + + final BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(statusCode, ""); + Optional entity = retrieveEntity(requestProducer); + + // return the same body that was sent + if (entity.isPresent()) { + assertTrue("the entity is not repeatable, cannot set it to the response directly", + entity.get().isRepeatable()); + httpResponse.setEntity(entity.get()); + } + // return the same headers that were sent + httpResponse.setHeaders(request.getHeaders()); + return httpResponse; + } + } + + private static Optional retrieveEntity(AsyncDataProducer requestProducer) throws NoSuchFieldException, IllegalAccessException { + // entity is in the dataProducer field, both are private + Field dataProducerField = requestProducer.getClass().getDeclaredField("dataProducer"); + dataProducerField.setAccessible(true); + final BasicAsyncEntityProducer dataProducer = + (BasicAsyncEntityProducer) dataProducerField.get(requestProducer); + + if (dataProducer != null) { + Field entityField = dataProducer.getClass().getDeclaredField("entity"); + entityField.setAccessible(true); + return Optional.ofNullable((HttpEntity) entityField.get(dataProducer)); + } + return Optional.empty(); + } + + /** + * Shutdown the executor so we don't leak threads into other test runs. + */ + @After + public void shutdownExec() { + exec.shutdown(); + } + + /** + * Verifies the content of the {@link HttpRequest} that's internally created and passed through to the + * http client + */ + @SuppressWarnings("unchecked") + public void testInternalHttpRequest() throws Exception { + ArgumentCaptor requestArgumentCaptor = ArgumentCaptor.forClass + (AsyncRequestProducer.class); + int times = 0; + for (String httpMethod : getHttpMethods()) { + HttpRequest expectedRequest = performRandomRequest(httpMethod); + verify(httpClient, times(++times)).execute( + requestArgumentCaptor.capture(), + any(AsyncResponseConsumer.class), + any(HttpClientContext.class), + nullable(FutureCallback.class) + ); + AsyncRequestProducer requestProducer = requestArgumentCaptor.getValue(); + Field requestField = requestProducer.getClass().getDeclaredField("request"); + requestField.setAccessible(true); + final HttpRequest actualRequest = (HttpRequest) requestField.get(requestProducer); + assertEquals(expectedRequest.getRequestUri(), actualRequest.getRequestUri()); + assertArrayEquals(expectedRequest.getHeaders(), actualRequest.getHeaders()); + if (canHaveBody(expectedRequest) && expectedRequest instanceof BasicClassicHttpRequest) { + Optional actualEntity = retrieveEntity(requestProducer); + if (actualEntity.isPresent()) { + HttpEntity expectedEntity = ((BasicClassicHttpRequest) expectedRequest).getEntity(); + assertEquals(EntityUtils.toString(expectedEntity), + EntityUtils.toString(actualEntity.get())); + } + } + } + } + + /** + * End to end test for ok status codes + */ + public void testOkStatusCodes() throws Exception { + for (String method : getHttpMethods()) { + for (int okStatusCode : getOkStatusCodes()) { + Response response = performRequestSyncOrAsync(restClient, new Request(method, + "/" + okStatusCode)); + assertThat(response.getStatusCode(), equalTo(okStatusCode)); + } + } + failureListener.assertNotCalled(); + } + + /** + * End to end test for error status codes: they should cause an exception to be thrown + */ + public void testErrorStatusCodes() throws Exception { + for (String method : getHttpMethods()) { + // error status codes should cause an exception to be thrown + for (int errorStatusCode : getAllErrorStatusCodes()) { + try { + Request request = new Request(method, "/" + errorStatusCode); + Response response = restClient.performRequest(request); + fail("request should have failed"); + } catch (ResponseException e) { + assertEquals(errorStatusCode, e.getResponse().getStatusCode()); + assertExceptionStackContainsCallingMethod(e); + } + } + } + } + + public void testPerformRequestIOExceptions() throws Exception { + for (String method : getHttpMethods()) { + // IOExceptions should be let bubble up + try { + restClient.performRequest(new Request(method, "/ioe")); + fail("request should have failed"); + } catch (IOException e) { + // And we do all that so the thrown exception has our method in the stacktrace + assertExceptionStackContainsCallingMethod(e); + } + failureListener.assertCalled(singletonList(node)); + try { + restClient.performRequest(new Request(method, "/coe")); + fail("request should have failed"); + } catch (ConnectTimeoutException e) { + // And we do all that so the thrown exception has our method in the stacktrace + assertExceptionStackContainsCallingMethod(e); + } + failureListener.assertCalled(singletonList(node)); + try { + restClient.performRequest(new Request(method, "/soe")); + fail("request should have failed"); + } catch (SocketTimeoutException e) { + // And we do all that so the thrown exception has our method in the stacktrace + assertExceptionStackContainsCallingMethod(e); + } + failureListener.assertCalled(singletonList(node)); + try { + restClient.performRequest(new Request(method, "/closed")); + fail("request should have failed"); + } catch (ConnectionClosedException e) { + // And we do all that so the thrown exception has our method in the stacktrace + assertExceptionStackContainsCallingMethod(e); + } + failureListener.assertCalled(singletonList(node)); + try { + restClient.performRequest(new Request(method, "/handshake")); + fail("request should have failed"); + } catch (SSLHandshakeException e) { + // And we do all that so the thrown exception has our method in the stacktrace + assertExceptionStackContainsCallingMethod(e); + } + failureListener.assertCalled(singletonList(node)); + } + } + + public void testPerformRequestRuntimeExceptions() throws Exception { + for (String method : getHttpMethods()) { + try { + restClient.performRequest(new Request(method, "/runtime")); + fail("request should have failed"); + } catch (RuntimeException e) { + // And we do all that so the thrown exception has our method in the stacktrace + assertExceptionStackContainsCallingMethod(e); + } + failureListener.assertCalled(singletonList(node)); + } + } + + public void testPerformRequestExceptions() throws Exception { + for (String method : getHttpMethods()) { + try { + restClient.performRequest(new Request(method, "/uri")); + fail("request should have failed"); + } catch (RuntimeException e) { + assertThat(e.getCause(), instanceOf(URISyntaxException.class)); + // And we do all that so the thrown exception has our method in the stacktrace + assertExceptionStackContainsCallingMethod(e); + } + failureListener.assertCalled(singletonList(node)); + } + } + + /** + * End to end test for request and response body. Exercises the mock http client ability to send back + * whatever body it has received. + */ + public void testBody() throws Exception { + String body = "{ \"field\": \"value\" }"; + StringEntity entity = new StringEntity(body, ContentType.APPLICATION_JSON); + for (String method : Arrays.asList("DELETE", "GET", "PATCH", "POST", "PUT")) { + for (int okStatusCode : getOkStatusCodes()) { + Request request = new Request(method, "/" + okStatusCode); + request.setEntity(entity); + Response response = restClient.performRequest(request); + assertThat(response.getStatusCode(), equalTo(okStatusCode)); + assertThat(EntityUtils.toString(response.getEntity()), equalTo(body)); + } + for (int errorStatusCode : getAllErrorStatusCodes()) { + Request request = new Request(method, "/" + errorStatusCode); + request.setEntity(entity); + try { + restClient.performRequest(request); + fail("request should have failed"); + } catch (ResponseException e) { + Response response = e.getResponse(); + assertThat(response.getStatusCode(), equalTo(errorStatusCode)); + assertThat(EntityUtils.toString(response.getEntity()), equalTo(body)); + assertExceptionStackContainsCallingMethod(e); + } + } + } + for (String method : Arrays.asList("HEAD", "OPTIONS", "TRACE")) { + Request request = new Request(method, "/" + randomStatusCode(getRandom())); + request.setEntity(entity); + try { + performRequestSyncOrAsync(restClient, request); + fail("request should have failed"); + } catch (UnsupportedOperationException e) { + assertThat(e.getMessage(), equalTo(method + " with body is not supported")); + } + } + } + + /** + * End to end test for request and response headers. Exercises the mock http client ability to send back + * whatever headers it has received. + */ + public void testHeaders() throws Exception { + for (String method : getHttpMethods()) { + final Header[] requestHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header"); + final int statusCode = randomStatusCode(getRandom()); + Request request = new Request(method, "/" + statusCode); + RequestOptions.Builder options = request.getOptions().toBuilder(); + for (Header requestHeader : requestHeaders) { + options.addHeader(requestHeader.getName(), requestHeader.getValue()); + } + request.setOptions(options); + Response esResponse; + try { + esResponse = performRequestSyncOrAsync(restClient, request); + } catch (ResponseException e) { + esResponse = e.getResponse(); + } + assertThat(esResponse.getStatusCode(), equalTo(statusCode)); + assertHeaders(defaultHeaders, requestHeaders, esResponse.getHeaders(), + Collections.emptySet()); + assertFalse(esResponse.hasWarnings()); + } + } + + public void testDeprecationWarnings() throws Exception { + String chars = randomAsciiAlphanumOfLength(5); + assertDeprecationWarnings(singletonList("poorly formatted " + chars), singletonList("poorly " + + "formatted " + chars)); + assertDeprecationWarnings(singletonList(formatWarningWithoutDate(chars)), singletonList(chars)); + assertDeprecationWarnings(singletonList(formatWarning(chars)), singletonList(chars)); + assertDeprecationWarnings( + Arrays.asList(formatWarning(chars), "another one", "and another"), + Arrays.asList(chars, "another one", "and another") + ); + assertDeprecationWarnings(Arrays.asList("ignorable one", "and another"), Arrays.asList("ignorable " + + "one", "and another")); + assertDeprecationWarnings(singletonList("exact"), singletonList("exact")); + assertDeprecationWarnings(Collections.emptyList(), Collections.emptyList()); + + String proxyWarning = "112 - \"network down\" \"Sat, 25 Aug 2012 23:34:45 GMT\""; + assertDeprecationWarnings(singletonList(proxyWarning), singletonList(proxyWarning)); + } + + private enum DeprecationWarningOption { + PERMISSIVE { + protected WarningsHandler warningsHandler() { + return WarningsHandler.PERMISSIVE; + } + }, + STRICT { + protected WarningsHandler warningsHandler() { + return WarningsHandler.STRICT; + } + }, + FILTERED { + protected WarningsHandler warningsHandler() { + return new WarningsHandler() { + @Override + public boolean warningsShouldFailRequest(List warnings) { + for (String warning : warnings) { + if (false == warning.startsWith("ignorable")) { + return true; + } + } + return false; + } + }; + } + }, + EXACT { + protected WarningsHandler warningsHandler() { + return new WarningsHandler() { + @Override + public boolean warningsShouldFailRequest(List warnings) { + return false == warnings.equals(Arrays.asList("exact")); + } + }; + } + }; + + protected abstract WarningsHandler warningsHandler(); + } + + private void assertDeprecationWarnings(List warningHeaderTexts, List warningBodyTexts) throws Exception { + String method = randomFrom(getHttpMethods()); + Request request = new Request(method, "/200"); + RequestOptions.Builder options = request.getOptions().toBuilder(); + for (String warningHeaderText : warningHeaderTexts) { + options.addHeader("Warning", warningHeaderText); + } + + final boolean expectFailure; + if (randomBoolean()) { + logger.info("checking strictWarningsMode=[" + strictDeprecationMode + "] and warnings=" + warningBodyTexts); + expectFailure = strictDeprecationMode && false == warningBodyTexts.isEmpty(); + } else { + DeprecationWarningOption warningOption = randomFrom(DeprecationWarningOption.values()); + logger.info("checking warningOption=" + warningOption + " and warnings=" + warningBodyTexts); + options.setWarningsHandler(warningOption.warningsHandler()); + expectFailure = warningOption.warningsHandler().warningsShouldFailRequest(warningBodyTexts); + } + request.setOptions(options); + + Response response; + if (expectFailure) { + try { + performRequestSyncOrAsync(restClient, request); + fail("expected WarningFailureException from warnings"); + return; + } catch (WarningFailureException e) { + if (false == warningBodyTexts.isEmpty()) { + assertThat(e.getMessage(), containsString("\nWarnings: " + warningBodyTexts)); + } + response = e.getResponse(); + } + } else { + response = performRequestSyncOrAsync(restClient, request); + } + assertEquals(false == warningBodyTexts.isEmpty(), response.hasWarnings()); + assertEquals(warningBodyTexts, response.getWarnings()); + } + + /** + * Emulates Elasticsearch's HeaderWarningLogger.formatWarning in simple + * cases. We don't have that available because we're testing against 1.7. + */ + private static String formatWarningWithoutDate(String warningBody) { + final String hash = new String(new byte[40], StandardCharsets.UTF_8).replace('\0', 'e'); + return "299 Elasticsearch-1.2.2-SNAPSHOT-" + hash + " \"" + warningBody + "\""; + } + + private static String formatWarning(String warningBody) { + return formatWarningWithoutDate(warningBody) + " \"Mon, 01 Jan 2001 00:00:00 GMT\""; + } + + private HttpUriRequest performRandomRequest(String method) throws Exception { + String uriAsString = "/" + randomStatusCode(getRandom()); + Request request = new Request(method, uriAsString); + URIBuilder uriBuilder = new URIBuilder(uriAsString); + if (randomBoolean()) { + int numParams = randomIntBetween(1, 3); + for (int i = 0; i < numParams; i++) { + String name = "param-" + i; + String value = randomAsciiAlphanumOfLengthBetween(3, 10); + request.addParameter(name, value); + uriBuilder.addParameter(name, value); + } + } + URI uri = uriBuilder.build(); + + HttpUriRequestBase expectedRequest; + switch (method) { + case "DELETE": + expectedRequest = new HttpDeleteWithEntity(uri); + break; + case "GET": + expectedRequest = new HttpGetWithEntity(uri); + break; + case "HEAD": + expectedRequest = new HttpHead(uri); + break; + case "OPTIONS": + expectedRequest = new HttpOptions(uri); + break; + case "PATCH": + expectedRequest = new HttpPatch(uri); + break; + case "POST": + expectedRequest = new HttpPost(uri); + break; + case "PUT": + expectedRequest = new HttpPut(uri); + break; + case "TRACE": + expectedRequest = new HttpTrace(uri); + break; + default: + throw new UnsupportedOperationException("method not supported: " + method); + } + + if (canHaveBody(expectedRequest) && getRandom().nextBoolean()) { + HttpEntity entity = new StringEntity(randomAsciiAlphanumOfLengthBetween(10, 100), + ContentType.APPLICATION_JSON); + (expectedRequest).setEntity(entity); + request.setEntity(entity); + } + + final Set uniqueNames = new HashSet<>(); + if (randomBoolean()) { + Header[] headers = RestClientTestUtil.randomHeaders(getRandom(), "Header"); + RequestOptions.Builder options = request.getOptions().toBuilder(); + for (Header header : headers) { + options.addHeader(header.getName(), header.getValue()); + expectedRequest.addHeader(new RequestOptions.ReqHeader(header.getName(), header.getValue())); + uniqueNames.add(header.getName()); + } + request.setOptions(options); + } + for (Header defaultHeader : defaultHeaders) { + // request level headers override default headers + if (uniqueNames.contains(defaultHeader.getName()) == false) { + expectedRequest.addHeader(defaultHeader); + } + } + try { + performRequestSyncOrAsync(restClient, request); + } catch (Exception e) { + // all good + } + return expectedRequest; + } + + static Response performRequestSyncOrAsync(Rest5Client restClient, Request request) throws Exception { + // randomize between sync and async methods + if (randomBoolean()) { + return restClient.performRequest(request); + } else { + final AtomicReference exceptionRef = new AtomicReference<>(); + final AtomicReference responseRef = new AtomicReference<>(); + final CountDownLatch latch = new CountDownLatch(1); + restClient.performRequestAsync(request, new ResponseListener() { + @Override + public void onSuccess(Response response) { + responseRef.set(response); + latch.countDown(); + + } + + @Override + public void onFailure(Exception exception) { + exceptionRef.set(exception); + latch.countDown(); + } + }); + latch.await(); + if (exceptionRef.get() != null) { + throw exceptionRef.get(); + } + return responseRef.get(); + } + } + + /** + * Asserts that the provided {@linkplain Exception} contains the method + * that called this somewhere on its stack. This is + * normally the case for synchronous calls but {@link Rest5Client} performs + * synchronous calls by performing asynchronous calls and blocking the + * current thread until the call returns so it has to take special care + * to make sure that the caller shows up in the exception. We use this + * assertion to make sure that we don't break that "special care". + */ + private static void assertExceptionStackContainsCallingMethod(Throwable t) { + // 0 is getStackTrace + // 1 is this method + // 2 is the caller, what we want + StackTraceElement myMethod = Thread.currentThread().getStackTrace()[2]; + for (StackTraceElement se : t.getStackTrace()) { + if (se.getClassName().equals(myMethod.getClassName()) && se.getMethodName().equals(myMethod.getMethodName())) { + return; + } + } + StringWriter stack = new StringWriter(); + t.printStackTrace(new PrintWriter(stack)); + fail("didn't find the calling method (looks like " + myMethod + ") in:\n" + stack); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestCase.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestCase.java new file mode 100644 index 000000000..db72b558e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestCase.java @@ -0,0 +1,119 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import com.carrotsearch.randomizedtesting.JUnit3MethodProvider; +import com.carrotsearch.randomizedtesting.MixWithSuiteName; +import com.carrotsearch.randomizedtesting.RandomizedTest; +import com.carrotsearch.randomizedtesting.annotations.SeedDecorators; +import com.carrotsearch.randomizedtesting.annotations.TestMethodProviders; +import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction; +import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters; +import com.carrotsearch.randomizedtesting.annotations.ThreadLeakGroup; +import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering; +import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; +import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies; +import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite; +import org.apache.hc.core5.http.Header; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@TestMethodProviders({ JUnit3MethodProvider.class }) +@SeedDecorators({ MixWithSuiteName.class }) // See LUCENE-3995 for rationale. +@ThreadLeakScope(ThreadLeakScope.Scope.SUITE) +@ThreadLeakGroup(ThreadLeakGroup.Group.MAIN) +@ThreadLeakAction({ ThreadLeakAction.Action.WARN, ThreadLeakAction.Action.INTERRUPT }) +@ThreadLeakZombies(ThreadLeakZombies.Consequence.IGNORE_REMAINING_TESTS) +@ThreadLeakLingering(linger = 5000) // 5 sec lingering +@ThreadLeakFilters(filters = { ClientsGraalVMThreadsFilter.class }) +@TimeoutSuite(millis = 2 * 60 * 60 * 1000) +public abstract class RestClientTestCase extends RandomizedTest { + + /** + * Assert that the actual headers are the expected ones given the original default and request headers. Some headers can be ignored, + * for instance in case the http client is adding its own automatically. + * + * @param defaultHeaders the default headers set to the REST client instance + * @param requestHeaders the request headers sent with a particular request + * @param actualHeaders the actual headers as a result of the provided default and request headers + * @param ignoreHeaders header keys to be ignored as they are not part of default nor request headers, yet they + * will be part of the actual ones + */ + protected static void assertHeaders( + final Header[] defaultHeaders, + final Header[] requestHeaders, + final Header[] actualHeaders, + final Set ignoreHeaders + ) { + final Map> expectedHeaders = new HashMap<>(); + final Set requestHeaderKeys = new HashSet<>(); + for (final Header header : requestHeaders) { + final String name = header.getName(); + addValueToListEntry(expectedHeaders, name, header.getValue()); + requestHeaderKeys.add(name); + } + for (final Header defaultHeader : defaultHeaders) { + final String name = defaultHeader.getName(); + if (requestHeaderKeys.contains(name) == false) { + addValueToListEntry(expectedHeaders, name, defaultHeader.getValue()); + } + } + Set actualIgnoredHeaders = new HashSet<>(); + for (Header responseHeader : actualHeaders) { + final String name = responseHeader.getName(); + if (ignoreHeaders.contains(name)) { + expectedHeaders.remove(name); + actualIgnoredHeaders.add(name); + continue; + } + final String value = responseHeader.getValue(); + final List values = expectedHeaders.get(name); + assertNotNull("found response header [" + name + "] that wasn't originally sent: " + value, values); + assertTrue("found incorrect response header [" + name + "]: " + value, values.remove(value)); + if (values.isEmpty()) { + expectedHeaders.remove(name); + } + } + assertEquals("some headers meant to be ignored were not part of the actual headers", ignoreHeaders, actualIgnoredHeaders); + assertTrue("some headers that were sent weren't returned " + expectedHeaders, expectedHeaders.isEmpty()); + } + + private static void addValueToListEntry(final Map> map, final String name, final String value) { + List values = map.get(name); + if (values == null) { + values = new ArrayList<>(); + map.put(name, values); + } + values.add(value); + } + + public static boolean inFipsJvm() { + return Boolean.parseBoolean(System.getProperty("tests.fips.enabled")); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestUtil.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestUtil.java new file mode 100644 index 000000000..c87871ae0 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestUtil.java @@ -0,0 +1,117 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import com.carrotsearch.randomizedtesting.generators.RandomNumbers; +import com.carrotsearch.randomizedtesting.generators.RandomPicks; +import com.carrotsearch.randomizedtesting.generators.RandomStrings; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpRequest; +import org.apache.hc.core5.http.message.BasicHeader; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +final class RestClientTestUtil { + + private static final String[] HTTP_METHODS = new String[]{"DELETE", "HEAD", "GET", "OPTIONS", "PATCH", + "POST", "PUT", "TRACE"}; + private static final List ALL_STATUS_CODES; + private static final List OK_STATUS_CODES = Arrays.asList(200, 201); + private static final List ALL_ERROR_STATUS_CODES; + private static List ERROR_NO_RETRY_STATUS_CODES = Arrays.asList(500,501); + private static List ERROR_RETRY_STATUS_CODES = Arrays.asList(502, 503, 504); + + static { + ALL_ERROR_STATUS_CODES = new ArrayList<>(ERROR_RETRY_STATUS_CODES); + ALL_ERROR_STATUS_CODES.addAll(ERROR_NO_RETRY_STATUS_CODES); + ALL_STATUS_CODES = new ArrayList<>(ALL_ERROR_STATUS_CODES); + ALL_STATUS_CODES.addAll(OK_STATUS_CODES); + } + + private RestClientTestUtil() { + + } + + static boolean canHaveBody(HttpRequest httpRequest) { + return httpRequest.getMethod().contains("PUT") || httpRequest.getMethod().contains("POST") || + httpRequest.getMethod().contains("PATCH") || + httpRequest instanceof HttpDeleteWithEntity || httpRequest instanceof HttpGetWithEntity; + } + + static String[] getHttpMethods() { + return HTTP_METHODS; + } + + static String randomHttpMethod(Random random) { + return RandomPicks.randomFrom(random, HTTP_METHODS); + } + + static int randomStatusCode(Random random) { + return RandomPicks.randomFrom(random, ALL_STATUS_CODES); + } + + static int randomOkStatusCode(Random random) { + return RandomPicks.randomFrom(random, OK_STATUS_CODES); + } + + static int randomErrorNoRetryStatusCode(Random random) { + return RandomPicks.randomFrom(random, List.of(500,501)); + } + + static int randomErrorRetryStatusCode(Random random) { + return RandomPicks.randomFrom(random, ERROR_RETRY_STATUS_CODES); + } + + static List getOkStatusCodes() { + return OK_STATUS_CODES; + } + + static List getAllErrorStatusCodes() { + return ALL_ERROR_STATUS_CODES; + } + + static List getAllStatusCodes() { + return ALL_STATUS_CODES; + } + + /** + * Create a random number of {@link Header}s. + * Generated header names will either be the {@code baseName} plus its index, or exactly the provided + * {@code baseName} so that the + * we test also support for multiple headers with same key and different values. + */ + static Header[] randomHeaders(Random random, final String baseName) { + int numHeaders = RandomNumbers.randomIntBetween(random, 0, 5); + final Header[] headers = new Header[numHeaders]; + for (int i = 0; i < numHeaders; i++) { + String headerName = baseName; + // randomly exercise the code path that supports multiple headers with same key + if (random.nextBoolean()) { + headerName = headerName + i; + } + headers[i] = new BasicHeader(headerName, RandomStrings.randomAsciiLettersOfLengthBetween(random + , 3, 10)); + } + return headers; + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTests.java new file mode 100644 index 000000000..76dbe2c3e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTests.java @@ -0,0 +1,447 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level; + +import org.apache.hc.client5.http.auth.AuthCache; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.impl.auth.BasicAuthCache; +import org.apache.hc.client5.http.impl.auth.BasicScheme; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.reactor.IOReactorStatus; + +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Supplier; + +import static java.util.Collections.singletonList; +import static org.hamcrest.Matchers.instanceOf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class RestClientTests extends RestClientTestCase { + + public void testCloseIsIdempotent() throws IOException { + List nodes = singletonList(new Node(new HttpHost("localhost", 9200))); + CloseableHttpAsyncClient closeableHttpAsyncClient = mock(CloseableHttpAsyncClient.class); + Rest5Client restClient = new Rest5Client(closeableHttpAsyncClient, new Header[0], nodes, null, null, + null, false, false, false); + restClient.close(); + verify(closeableHttpAsyncClient, times(1)).close(); + restClient.close(); + verify(closeableHttpAsyncClient, times(2)).close(); + restClient.close(); + verify(closeableHttpAsyncClient, times(3)).close(); + } + + public void testPerformAsyncWithUnsupportedMethod() throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + try (Rest5Client restClient = createRestClient()) { + restClient.performRequestAsync(new Request("unsupported", randomAsciiLettersOfLength(5)), + new ResponseListener() { + @Override + public void onSuccess(Response response) { + throw new UnsupportedOperationException("onSuccess cannot be called when using a mocked" + + " http client"); + } + + @Override + public void onFailure(Exception exception) { + try { + assertThat(exception, instanceOf(UnsupportedOperationException.class)); + assertEquals("http method not supported: unsupported", exception.getMessage()); + } finally { + latch.countDown(); + } + } + }); + assertTrue("time out waiting for request to return", latch.await(1000, TimeUnit.MILLISECONDS)); + } + } + + public void testPerformAsyncWithWrongEndpoint() throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + try (Rest5Client restClient = createRestClient()) { + restClient.performRequestAsync(new Request("GET", "::http:///"), new ResponseListener() { + @Override + public void onSuccess(Response response) { + throw new UnsupportedOperationException("onSuccess cannot be called when using a mocked" + + " http client"); + } + + @Override + public void onFailure(Exception exception) { + try { + assertThat(exception, instanceOf(IllegalArgumentException.class)); + assertEquals("Expected scheme name at index 0: ::http:///", exception.getMessage()); + } finally { + latch.countDown(); + } + } + }); + assertTrue("time out waiting for request to return", latch.await(1000, TimeUnit.MILLISECONDS)); + } + } + + public void testBuildUriLeavesPathUntouched() { + final Map emptyMap = Collections.emptyMap(); + { + URI uri = Rest5Client.buildUri("/foo$bar", "/index/type/id", emptyMap); + assertEquals("/foo$bar/index/type/id", uri.getPath()); + } + { + URI uri = Rest5Client.buildUri("/", "/*", emptyMap); + assertEquals("/*", uri.getPath()); + } + { + URI uri = Rest5Client.buildUri("/", "*", emptyMap); + assertEquals("/*", uri.getPath()); + } + { + URI uri = Rest5Client.buildUri(null, "*", emptyMap); + assertEquals("*", uri.getPath()); + } + { + URI uri = Rest5Client.buildUri("", "*", emptyMap); + assertEquals("*", uri.getPath()); + } + { + URI uri = Rest5Client.buildUri(null, "/*", emptyMap); + assertEquals("/*", uri.getPath()); + } + { + URI uri = Rest5Client.buildUri(null, "/foo$bar/ty/pe/i/d", emptyMap); + assertEquals("/foo$bar/ty/pe/i/d", uri.getPath()); + } + { + URI uri = Rest5Client.buildUri(null, "/index/type/id", Collections.singletonMap("foo$bar", "x/y" + + "/z")); + assertEquals("/index/type/id", uri.getPath()); + assertEquals("foo$bar=x/y/z", uri.getQuery()); + } + } + + public void testSetNodesWrongArguments() throws IOException { + try (Rest5Client restClient = createRestClient()) { + restClient.setNodes(null); + fail("setNodes should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("node list must not be null or empty", e.getMessage()); + } + try (Rest5Client restClient = createRestClient()) { + restClient.setNodes(Collections.emptyList()); + fail("setNodes should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("node list must not be null or empty", e.getMessage()); + } + try (Rest5Client restClient = createRestClient()) { + restClient.setNodes(Collections.singletonList(null)); + fail("setNodes should have failed"); + } catch (NullPointerException e) { + assertEquals("node cannot be null", e.getMessage()); + } + try (Rest5Client restClient = createRestClient()) { + restClient.setNodes(Arrays.asList(new Node(new HttpHost("localhost", 9200)), null, + new Node(new HttpHost("localhost", 9201)))); + fail("setNodes should have failed"); + } catch (NullPointerException e) { + assertEquals("node cannot be null", e.getMessage()); + } + } + + public void testSetNodesPreservesOrdering() throws Exception { + try (Rest5Client restClient = createRestClient()) { + List nodes = randomNodes(); + restClient.setNodes(nodes); + assertEquals(nodes, restClient.getNodes()); + } + } + + private static List randomNodes() { + int numNodes = randomIntBetween(1, 10); + List nodes = new ArrayList<>(numNodes); + for (int i = 0; i < numNodes; i++) { + nodes.add(new Node(new HttpHost("host-" + i, 9200))); + } + return nodes; + } + + public void testSetNodesDuplicatedHosts() throws Exception { + try (Rest5Client restClient = createRestClient()) { + int numNodes = randomIntBetween(1, 10); + List nodes = new ArrayList<>(numNodes); + Node node = new Node(new HttpHost("host", 9200)); + for (int i = 0; i < numNodes; i++) { + nodes.add(node); + } + restClient.setNodes(nodes); + assertEquals(1, restClient.getNodes().size()); + assertEquals(node, restClient.getNodes().get(0)); + } + } + + public void testSelectHosts() throws IOException { + Node n1 = new Node(new HttpHost("1"), null, null, "1", null, null); + Node n2 = new Node(new HttpHost("2"), null, null, "2", null, null); + Node n3 = new Node(new HttpHost("3"), null, null, "3", null, null); + + NodeSelector not1 = new NodeSelector() { + @Override + public void select(Iterable nodes) { + for (Iterator itr = nodes.iterator(); itr.hasNext(); ) { + if ("1".equals(itr.next().getVersion())) { + itr.remove(); + } + } + } + + @Override + public String toString() { + return "NOT 1"; + } + }; + NodeSelector noNodes = new NodeSelector() { + @Override + public void select(Iterable nodes) { + for (Iterator itr = nodes.iterator(); itr.hasNext(); ) { + itr.next(); + itr.remove(); + } + } + + @Override + public String toString() { + return "NONE"; + } + }; + + List nodes = Arrays.asList(n1, n2, n3); + + Map emptyBlacklist = Collections.emptyMap(); + + // Normal cases where the node selector doesn't reject all living nodes + assertSelectLivingHosts(Arrays.asList(n1, n2, n3), nodes, emptyBlacklist, NodeSelector.ANY); + assertSelectLivingHosts(Arrays.asList(n2, n3), nodes, emptyBlacklist, not1); + + /* + * Try a NodeSelector that excludes all nodes. This should + * throw an exception + */ + { + String message = "NodeSelector [NONE] rejected all nodes, living: [" + + "[host=http://1, version=1], [host=http://2, version=2], " + + "[host=http://3, version=3]] and dead: null"; + assertEquals(message, assertSelectAllRejected(nodes, emptyBlacklist, noNodes)); + } + + // Mark all the nodes dead for a few test cases + { + final AtomicLong time = new AtomicLong(0L); + Supplier timeSupplier = time::get; + Map blacklist = new HashMap<>(); + blacklist.put(n1.getHost(), new DeadHostState(timeSupplier)); + blacklist.put(n2.getHost(), new DeadHostState(new DeadHostState(timeSupplier))); + blacklist.put(n3.getHost(), + new DeadHostState(new DeadHostState(new DeadHostState(timeSupplier)))); + + /* + * case when fewer nodes than blacklist, won't result in any IllegalCapacityException + */ + { + List fewerNodeTuple = Arrays.asList(n1, n2); + assertSelectLivingHosts(Arrays.asList(n1), fewerNodeTuple, blacklist, NodeSelector.ANY); + assertSelectLivingHosts(Arrays.asList(n2), fewerNodeTuple, blacklist, not1); + } + + /* + * selectHosts will revive a single host regardless of + * blacklist time. It'll revive the node that is closest + * to being revived that the NodeSelector is ok with. + */ + assertEquals(singletonList(n1), Rest5Client.selectNodes(nodes, blacklist, new AtomicInteger(), + NodeSelector.ANY)); + assertEquals(singletonList(n2), Rest5Client.selectNodes(nodes, blacklist, new AtomicInteger(), + not1)); + + /* + * Try a NodeSelector that excludes all nodes. This should + * return a failure, but a different failure than when the + * blacklist is empty so that the caller knows that all of + * their nodes are blacklisted AND blocked. + */ + String message = "NodeSelector [NONE] rejected all nodes, living: [] and dead: [" + + "[host=http://1, version=1], [host=http://2, version=2], " + + "[host=http://3, version=3]]"; + assertEquals(message, assertSelectAllRejected(nodes, blacklist, noNodes)); + + /* + * Now lets wind the clock forward, past the timeout for one of + * the dead nodes. We should return it. + */ + time.set(new DeadHostState(timeSupplier).getDeadUntilNanos()); + assertSelectLivingHosts(Arrays.asList(n1), nodes, blacklist, NodeSelector.ANY); + + /* + * But if the NodeSelector rejects that node then we'll pick the + * first on that the NodeSelector doesn't reject. + */ + assertSelectLivingHosts(Arrays.asList(n2), nodes, blacklist, not1); + + /* + * If we wind the clock way into the future, past any of the + * blacklist timeouts then we function as though the nodes aren't + * in the blacklist at all. + */ + time.addAndGet(DeadHostState.MAX_CONNECTION_TIMEOUT_NANOS); + assertSelectLivingHosts(Arrays.asList(n1, n2, n3), nodes, blacklist, NodeSelector.ANY); + assertSelectLivingHosts(Arrays.asList(n2, n3), nodes, blacklist, not1); + } + } + + private void assertSelectLivingHosts( + List expectedNodes, + List nodes, + Map blacklist, + NodeSelector nodeSelector + ) throws IOException { + int iterations = 1000; + AtomicInteger lastNodeIndex = new AtomicInteger(0); + assertEquals(expectedNodes, Rest5Client.selectNodes(nodes, blacklist, lastNodeIndex, nodeSelector)); + // Calling it again rotates the set of results + for (int i = 1; i < iterations; i++) { + Collections.rotate(expectedNodes, 1); + assertEquals("iteration " + i, expectedNodes, Rest5Client.selectNodes(nodes, blacklist, + lastNodeIndex, nodeSelector)); + } + } + + /** + * Assert that {@link Rest5Client#selectNodes} fails on the provided arguments. + * + * @return the message in the exception thrown by the failure + */ + private static String assertSelectAllRejected( + List nodes, + Map blacklist, + NodeSelector nodeSelector + ) { + try { + Rest5Client.selectNodes(nodes, blacklist, new AtomicInteger(0), nodeSelector); + throw new AssertionError("expected selectHosts to fail"); + } catch (IOException e) { + return e.getMessage(); + } + } + + private static Rest5Client createRestClient() { + List nodes = Collections.singletonList(new Node(new HttpHost("localhost", 9200))); + return new Rest5Client(mock(CloseableHttpAsyncClient.class), new Header[]{}, nodes, null, null, null + , false, false, false); + } + + public void testRoundRobin() throws IOException { + int numNodes = randomIntBetween(2, 10); + AuthCache authCache = new BasicAuthCache(); + List nodes = new ArrayList<>(numNodes); + for (int i = 0; i < numNodes; i++) { + Node node = new Node(new HttpHost("localhost", 9200 + i)); + nodes.add(node); + authCache.put(node.getHost(), new BasicScheme()); + } + + // test the transition from negative to positive values + AtomicInteger lastNodeIndex = new AtomicInteger(-numNodes); + assertNodes(nodes, lastNodeIndex, 50); + assertEquals(-numNodes + 50, lastNodeIndex.get()); + + // test the highest positive values up to MAX_VALUE + lastNodeIndex.set(Integer.MAX_VALUE - numNodes * 10); + assertNodes(nodes, lastNodeIndex, numNodes * 10); + assertEquals(Integer.MAX_VALUE, lastNodeIndex.get()); + + // test the transition from MAX_VALUE to MIN_VALUE + // this is the only time where there is most likely going to be a jump from a node + // to another one that's not necessarily the next one. + assertEquals(Integer.MIN_VALUE, lastNodeIndex.incrementAndGet()); + assertNodes(nodes, lastNodeIndex, 50); + assertEquals(Integer.MIN_VALUE + 50, lastNodeIndex.get()); + } + + public void testIsRunning() { + List nodes = Collections.singletonList(new Node(new HttpHost("localhost", 9200))); + CloseableHttpAsyncClient client = mock(CloseableHttpAsyncClient.class); + Rest5Client restClient = new Rest5Client(client, new Header[]{}, nodes, null, null, null, false, + false, false); + + when(client.getStatus()).thenReturn(IOReactorStatus.ACTIVE); + assertTrue(restClient.isRunning()); + + when(client.getStatus()).thenReturn(IOReactorStatus.INACTIVE); + assertFalse(restClient.isRunning()); + } + + private static void assertNodes(List nodes, AtomicInteger lastNodeIndex, int runs) throws IOException { + int distance = lastNodeIndex.get() % nodes.size(); + /* + * Collections.rotate is not super intuitive: distance 1 means that the last element will become + * the first and so on, + * while distance -1 means that the second element will become the first and so on. + */ + int expectedOffset = distance > 0 ? nodes.size() - distance : Math.abs(distance); + for (int i = 0; i < runs; i++) { + Iterable selectedNodes = Rest5Client.selectNodes( + nodes, + Collections.emptyMap(), + lastNodeIndex, + NodeSelector.ANY + ); + List expectedNodes = nodes; + int index = 0; + for (Node actualNode : selectedNodes) { + Node expectedNode = expectedNodes.get((index + expectedOffset) % expectedNodes.size()); + assertSame(expectedNode, actualNode); + index++; + } + expectedOffset--; + if (expectedOffset < 0) { + expectedOffset += nodes.size(); + } + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/documentation/RestClientDocumentation.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/documentation/RestClientDocumentation.java new file mode 100644 index 000000000..e9c030f7e --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/documentation/RestClientDocumentation.java @@ -0,0 +1,461 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level.documentation; + +import co.elastic.clients.transport.rest5_client.low_level.Cancellable; +import co.elastic.clients.transport.rest5_client.low_level.HttpAsyncResponseConsumerFactory; +import co.elastic.clients.transport.rest5_client.low_level.Node; +import co.elastic.clients.transport.rest5_client.low_level.NodeSelector; +import co.elastic.clients.transport.rest5_client.low_level.Request; +import co.elastic.clients.transport.rest5_client.low_level.RequestOptions; +import co.elastic.clients.transport.rest5_client.low_level.Response; +import co.elastic.clients.transport.rest5_client.low_level.ResponseListener; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; +import co.elastic.clients.transport.rest5_client.low_level.Rest5ClientBuilder; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.impl.async.HttpAsyncClients; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.http.message.BasicHeader; +import org.apache.hc.core5.http.message.RequestLine; +import org.apache.hc.core5.reactor.IOReactorConfig; +import org.apache.hc.core5.ssl.SSLContextBuilder; +import org.apache.hc.core5.ssl.SSLContexts; +import org.apache.hc.core5.util.Timeout; + +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.util.Base64; +import java.util.Iterator; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * This class is used to generate the Java low-level REST client documentation. + * You need to wrap your code between two tags like: + * // tag::example[] + * // end::example[] + *

+ * Where example is your tag name. + *

+ * Then in the documentation, you can extract what is between tag and end tags with + * ["source","java",subs="attributes,callouts,macros"] + * -------------------------------------------------- + * include-tagged::{doc-tests}/RestClientDocumentation.java[example] + * -------------------------------------------------- + *

+ * Note that this is not a test class as we are only interested in testing that docs snippets compile. We + * don't want + * to send requests to a node and we don't even have the tools to do it. + */ +@SuppressWarnings("unused") +public class RestClientDocumentation { + private static final String TOKEN = "DUMMY"; + + // tag::rest-client-options-singleton + private static final RequestOptions COMMON_OPTIONS; + + static { + RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); + builder.addHeader("Authorization", "Bearer " + TOKEN); // <1> + builder.setHttpAsyncResponseConsumerFactory( // <2> + HttpAsyncResponseConsumerFactory.DEFAULT); + COMMON_OPTIONS = builder.build(); + } + // end::rest-client-options-singleton + + @SuppressWarnings("unused") + public void usage() throws IOException, InterruptedException, ParseException { + + //tag::rest-client-init + Rest5Client restClient = Rest5Client.builder( + new HttpHost("http", "localhost", 9200), + new HttpHost("http", "localhost", 9201)).build(); + //end::rest-client-init + + //tag::rest-client-close + restClient.close(); + //end::rest-client-close + + { + //tag::rest-client-init-default-headers + Rest5ClientBuilder builder = Rest5Client.builder( + new HttpHost("http", "localhost", 9200)); + Header[] defaultHeaders = new Header[]{new BasicHeader("header", "value")}; + builder.setDefaultHeaders(defaultHeaders); // <1> + //end::rest-client-init-default-headers + } + { + //tag::rest-client-init-node-selector + Rest5ClientBuilder builder = Rest5Client.builder( + new HttpHost("http", "localhost", 9200)); + builder.setNodeSelector(NodeSelector.SKIP_DEDICATED_MASTERS); // <1> + //end::rest-client-init-node-selector + } + { + //tag::rest-client-init-allocation-aware-selector + Rest5ClientBuilder builder = Rest5Client.builder( + new HttpHost("http", "localhost", 9200)); + // <1> + builder.setNodeSelector(nodes -> { // <1> + /* + * Prefer any node that belongs to rack_one. If none is around + * we will go to another rack till it's time to try and revive + * some of the nodes that belong to rack_one. + */ + boolean foundOne = false; + for (Node node : nodes) { + String rackId = node.getAttributes().get("rack_id").get(0); + if ("rack_one".equals(rackId)) { + foundOne = true; + break; + } + } + if (foundOne) { + Iterator nodesIt = nodes.iterator(); + while (nodesIt.hasNext()) { + Node node = nodesIt.next(); + String rackId = node.getAttributes().get("rack_id").get(0); + if ("rack_one".equals(rackId) == false) { + nodesIt.remove(); + } + } + } + }); + //end::rest-client-init-allocation-aware-selector + } + { + //tag::rest-client-init-failure-listener + Rest5ClientBuilder builder = Rest5Client.builder( + new HttpHost("http", "localhost", 9200)); + builder.setFailureListener(new Rest5Client.FailureListener() { + @Override + public void onFailure(Node node) { + // <1> + } + }); + //end::rest-client-init-failure-listener + } + { + //tag::rest-client-init-request-custom-client + PoolingAsyncClientConnectionManager connectionManager = + PoolingAsyncClientConnectionManagerBuilder.create() + .setMaxConnPerRoute(5) + .build(); + + CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() + .setConnectionManager(connectionManager) + .build(); + Rest5ClientBuilder builder = Rest5Client.builder( + new HttpHost("http", "localhost", 9200)); + builder.setHttpClient(httpclient); + //end::rest-client-init-request-config-callback + } + + { + //tag::rest-client-sync + Request request = new Request( + "GET", // <1> + "/"); // <2> + Response response = restClient.performRequest(request); + //end::rest-client-sync + } + { + //tag::rest-client-async + Request request = new Request( + "GET", // <1> + "/"); // <2> + Cancellable cancellable = restClient.performRequestAsync(request, + new ResponseListener() { + @Override + public void onSuccess(Response response) { + // <3> + } + + @Override + public void onFailure(Exception exception) { + // <4> + } + }); + //end::rest-client-async + } + { + Request request = new Request("GET", "/"); + //tag::rest-client-parameters + request.addParameter("pretty", "true"); + //end::rest-client-parameters + //tag::rest-client-body + request.setEntity(new StringEntity( + "{\"json\":\"text\"}", + ContentType.APPLICATION_JSON)); + //end::rest-client-body + //tag::rest-client-body-shorter + request.setJsonEntity("{\"json\":\"text\"}"); + //end::rest-client-body-shorter + //tag::rest-client-options-set-singleton + request.setOptions(COMMON_OPTIONS); + //end::rest-client-options-set-singleton + { + //tag::rest-client-options-customize-header + RequestOptions.Builder options = COMMON_OPTIONS.toBuilder(); + options.addHeader("cats", "knock things off of other things"); + request.setOptions(options); + //end::rest-client-options-customize-header + } + } + { + HttpEntity[] documents = new HttpEntity[10]; + //tag::rest-client-async-example + final CountDownLatch latch = new CountDownLatch(documents.length); + for (int i = 0; i < documents.length; i++) { + Request request = new Request("PUT", "/posts/doc/" + i); + //let's assume that the documents are stored in an HttpEntity array + request.setEntity(documents[i]); + restClient.performRequestAsync( + request, + new ResponseListener() { + @Override + public void onSuccess(Response response) { + // <1> + latch.countDown(); + } + + @Override + public void onFailure(Exception exception) { + // <2> + latch.countDown(); + } + } + ); + } + latch.await(); + //end::rest-client-async-example + } + { + //tag::rest-client-async-cancel + Request request = new Request("GET", "/posts/_search"); + Cancellable cancellable = restClient.performRequestAsync( + request, + new ResponseListener() { + @Override + public void onSuccess(Response response) { + // <1> + } + + @Override + public void onFailure(Exception exception) { + // <2> + } + } + ); + cancellable.cancel(); + //end::rest-client-async-cancel + } + { + //tag::rest-client-response2 + Response response = restClient.performRequest(new Request("GET", "/")); + RequestLine requestLine = response.getRequestLine(); // <1> + HttpHost host = response.getHost(); // <2> + int statusCode = response.getStatusCode(); // <3> + Header[] headers = response.getHeaders(); // <4> + String responseBody = EntityUtils.toString(response.getEntity()); // <5> + //end::rest-client-response2 + } + } + + @SuppressWarnings("unused") + public void commonConfiguration() throws Exception { + { + //tag::rest-client-config-timeouts + RequestConfig.Builder requestConfigBuilder = RequestConfig.custom() + .setConnectTimeout(Timeout.of(5000, TimeUnit.MILLISECONDS)); + + CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() + .setDefaultRequestConfig(requestConfigBuilder.build()) + .build(); + + Rest5ClientBuilder builder = Rest5Client.builder( + new HttpHost("localhost", 9200)) + .setHttpClient(httpclient); + //end::rest-client-config-timeouts + } + { + //tag::rest-client-config-request-options-timeouts + RequestConfig requestConfig = RequestConfig.custom() + .setConnectTimeout(Timeout.ofMilliseconds(5000)) + .setConnectionRequestTimeout(Timeout.ofMilliseconds(60000)) + .build(); + RequestOptions options = RequestOptions.DEFAULT.toBuilder() + .setRequestConfig(requestConfig) + .build(); + //end::rest-client-config-request-options-timeouts + } + { + //tag::rest-client-config-threads + CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() + .setIOReactorConfig(IOReactorConfig.custom() + .setIoThreadCount(1).build()) + .build(); + + Rest5ClientBuilder builder = Rest5Client.builder( + new HttpHost("localhost", 9200)) + .setHttpClient(httpclient); + //end::rest-client-config-threads + } + { + //tag::rest-client-config-basic-auth + + var creds = Base64.getEncoder().encodeToString("user:test-user-password".getBytes()); + + Rest5ClientBuilder restClient = Rest5Client.builder(new HttpHost("https", "localhost", + 9200)) + .setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Basic " + creds) + }); + + //end::rest-client-config-basic-auth + } + { + //tag::rest-client-config-disable-preemptive-auth + HttpHost host = new HttpHost("http", "localhost", 9200); + + var creds = Base64.getEncoder().encodeToString("user:test-user-password".getBytes()); + + CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() + .disableAuthCaching() + .build(); + + Rest5ClientBuilder restClient = Rest5Client.builder(new HttpHost("https", "localhost", + 9200)) + .setHttpClient(httpclient) + .setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Basic " + creds) + }); + //end::rest-client-config-disable-preemptive-auth + } + { + String keyStorePass = ""; + //tag::rest-client-config-encrypted-communication + Path trustStorePath = Paths.get("/path/to/truststore.p12"); + KeyStore truststore = KeyStore.getInstance("pkcs12"); + try (InputStream is = Files.newInputStream(trustStorePath)) { + truststore.load(is, keyStorePass.toCharArray()); + } + SSLContextBuilder sslBuilder = SSLContexts.custom() + .loadTrustMaterial(truststore, null); + final SSLContext sslContext = sslBuilder.build(); + Rest5ClientBuilder builder = Rest5Client.builder( + new HttpHost("https", "localhost", + 9200)) + .setSSLContext(sslContext); + //end::rest-client-config-encrypted-communication + } + { + //tag::rest-client-config-trust-ca-pem + Path caCertificatePath = Paths.get("/path/to/ca.crt"); + CertificateFactory factory = + CertificateFactory.getInstance("X.509"); + Certificate trustedCa; + try (InputStream is = Files.newInputStream(caCertificatePath)) { + trustedCa = factory.generateCertificate(is); + } + KeyStore trustStore = KeyStore.getInstance("pkcs12"); + trustStore.load(null, null); + trustStore.setCertificateEntry("ca", trustedCa); + SSLContextBuilder sslContextBuilder = SSLContexts.custom() + .loadTrustMaterial(trustStore, null); + final SSLContext sslContext = sslContextBuilder.build(); + Rest5Client.builder( + new HttpHost("https", "localhost", + 9200)) + .setSSLContext(sslContext); + //end::rest-client-config-trust-ca-pem + } + { + String trustStorePass = ""; + String keyStorePass = ""; + //tag::rest-client-config-mutual-tls-authentication + Path trustStorePath = Paths.get("/path/to/your/truststore.p12"); + Path keyStorePath = Paths.get("/path/to/your/keystore.p12"); + KeyStore trustStore = KeyStore.getInstance("pkcs12"); + KeyStore keyStore = KeyStore.getInstance("pkcs12"); + try (InputStream is = Files.newInputStream(trustStorePath)) { + trustStore.load(is, trustStorePass.toCharArray()); + } + try (InputStream is = Files.newInputStream(keyStorePath)) { + keyStore.load(is, keyStorePass.toCharArray()); + } + SSLContextBuilder sslBuilder = SSLContexts.custom() + .loadTrustMaterial(trustStore, null) + .loadKeyMaterial(keyStore, keyStorePass.toCharArray()); + final SSLContext sslContext = sslBuilder.build(); + Rest5Client.builder( + new HttpHost("https", "localhost", + 9200)) + .setSSLContext(sslContext); + //end::rest-client-config-mutual-tls-authentication + } + { + //tag::rest-client-auth-bearer-token + Rest5ClientBuilder builder = Rest5Client.builder( + new HttpHost("https", "localhost", + 9200)); + Header[] defaultHeaders = + new Header[]{new BasicHeader("Authorization", + "Bearer u6iuAxZ0RG1Kcm5jVFI4eU4tZU9aVFEwT2F3")}; + builder.setDefaultHeaders(defaultHeaders); + //end::rest-client-auth-bearer-token + } + { + //tag::rest-client-auth-api-key + String apiKeyId = "uqlEyn8B_gQ_jlvwDIvM"; + String apiKeySecret = "HxHWk2m4RN-V_qg9cDpuX"; + String apiKeyAuth = + Base64.getEncoder().encodeToString( + (apiKeyId + ":" + apiKeySecret) + .getBytes(StandardCharsets.UTF_8)); + Rest5ClientBuilder builder = Rest5Client.builder( + new HttpHost("https", "localhost", + 9200)); + Header[] defaultHeaders = + new Header[]{new BasicHeader("Authorization", + "ApiKey " + apiKeyAuth)}; + builder.setDefaultHeaders(defaultHeaders); + //end::rest-client-auth-api-key + } + + } +} From 1652ffa3e223873db998bbf825396fc5251ee95c Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Wed, 26 Mar 2025 17:19:34 +0100 Subject: [PATCH 18/38] low level client tests to junit 5 --- java-client/build.gradle.kts | 4 - .../BasicAsyncResponseConsumerTests.java | 3 + .../ClientsGraalVMThreadsFilter.java | 33 ------- .../low_level/DeadHostStateTests.java | 8 ++ .../FailureTrackingResponseListenerTests.java | 3 + .../HasAttributeNodeSelectorTests.java | 3 + .../low_level/NodeSelectorTests.java | 9 +- .../rest5_client/low_level/NodeTests.java | 5 + .../PreferHasAttributeNodeSelectorTests.java | 4 + .../low_level/RequestLoggerTests.java | 7 +- .../low_level/RequestOptionsTests.java | 16 +++- .../rest5_client/low_level/RequestTests.java | 14 ++- .../low_level/ResponseExceptionTests.java | 7 +- .../RestClientBuilderIntegTests.java | 20 ++-- .../low_level/RestClientBuilderTests.java | 17 +++- .../RestClientGzipCompressionTests.java | 14 ++- .../RestClientMultipleHostsIntegTests.java | 32 ++++--- .../RestClientMultipleHostsTests.java | 45 +++++---- .../RestClientSingleHostIntegTests.java | 24 +++-- .../low_level/RestClientSingleHostTests.java | 32 ++++--- .../low_level/RestClientTestCase.java | 89 ++++++++++++------ .../low_level/RestClientTestUtil.java | 37 ++++---- .../low_level/RestClientTests.java | 11 +++ .../transport/rest5_client/low_level/test.crt | 24 +++++ .../transport/rest5_client/low_level/test.der | Bin 0 -> 1218 bytes .../low_level/test_truststore.jks | Bin 0 -> 1097 bytes .../rest5_client/low_level/testks.jks | Bin 0 -> 2381 bytes 27 files changed, 295 insertions(+), 166 deletions(-) delete mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/ClientsGraalVMThreadsFilter.java create mode 100644 java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/test.crt create mode 100644 java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/test.der create mode 100644 java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/test_truststore.jks create mode 100644 java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/testks.jks diff --git a/java-client/build.gradle.kts b/java-client/build.gradle.kts index 840605044..cdf63090c 100644 --- a/java-client/build.gradle.kts +++ b/java-client/build.gradle.kts @@ -278,10 +278,6 @@ dependencies { // https://github.com/mockito/mockito testImplementation("org.mockito","mockito-core","5.12.0") - // Apache-2.0 - // https://github.com/randomizedtesting/randomizedtesting - testImplementation("com.carrotsearch.randomizedtesting","randomizedtesting-runner","2.8.1") - // Apache-2.0 // https://github.com/elastic/mocksocket testImplementation("org.elasticsearch","mocksocket","1.2") diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncResponseConsumerTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncResponseConsumerTests.java index 311296b98..3b4af2931 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncResponseConsumerTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncResponseConsumerTests.java @@ -28,6 +28,7 @@ import org.apache.hc.core5.http.nio.ContentDecoder; import org.apache.hc.core5.http.protocol.HttpContext; import org.junit.Assert; +import org.junit.jupiter.api.Test; import java.nio.ByteBuffer; @@ -38,6 +39,7 @@ public class BasicAsyncResponseConsumerTests extends RestClientTestCase { // maximum buffer that this test ends up allocating is 50MB private static final int MAX_TEST_BUFFER_SIZE = 50 * 1024 * 1024; + @Test public void testResponseProcessing() throws Exception { ContentDecoder contentDecoder = mock(ContentDecoder.class); HttpContext httpContext = mock(HttpContext.class); @@ -55,6 +57,7 @@ public void testResponseProcessing() throws Exception { consumer.consume(ByteBuffer.wrap("test".getBytes())); } + @Test public void testBufferLimit() throws Exception { HttpContext httpContext = mock(HttpContext.class); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/ClientsGraalVMThreadsFilter.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/ClientsGraalVMThreadsFilter.java deleted file mode 100644 index 362c08657..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/ClientsGraalVMThreadsFilter.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport.rest5_client.low_level; - -import com.carrotsearch.randomizedtesting.ThreadFilter; - -/** - * The GraalVM spawns extra threads, which causes our thread leak - * detection to fail. Filter these threads out since we can't clean them up. - */ -public class ClientsGraalVMThreadsFilter implements ThreadFilter { - @Override - public boolean reject(Thread t) { - return t.getName().startsWith("Libgraal"); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/DeadHostStateTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/DeadHostStateTests.java index ecd1d1852..45fedefec 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/DeadHostStateTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/DeadHostStateTests.java @@ -19,6 +19,8 @@ package co.elastic.clients.transport.rest5_client.low_level; +import org.junit.jupiter.api.Test; + import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; @@ -36,6 +38,7 @@ public class DeadHostStateTests extends RestClientTestCase { private static long[] EXPECTED_TIMEOUTS_SECONDS = new long[]{60, 84, 120, 169, 240, 339, 480, 678, 960, 1357, 1800}; + @Test public void testInitialDeadHostStateDefaultTimeSupplier() { DeadHostState deadHostState = new DeadHostState(DeadHostState.DEFAULT_TIME_SUPPLIER); long currentTime = System.nanoTime(); @@ -43,6 +46,7 @@ public void testInitialDeadHostStateDefaultTimeSupplier() { assertThat(deadHostState.getFailedAttempts(), equalTo(1)); } + @Test public void testDeadHostStateFromPreviousDefaultTimeSupplier() { DeadHostState previous = new DeadHostState(DeadHostState.DEFAULT_TIME_SUPPLIER); int iters = randomIntBetween(5, 30); @@ -54,6 +58,7 @@ public void testDeadHostStateFromPreviousDefaultTimeSupplier() { } } + @Test public void testCompareToTimeSupplier() { int numObjects = randomIntBetween(EXPECTED_TIMEOUTS_SECONDS.length, 30); DeadHostState[] deadHostStates = new DeadHostState[numObjects]; @@ -77,6 +82,7 @@ public void testCompareToTimeSupplier() { } } + @Test public void testCompareToDifferingTimeSupplier() { try { new DeadHostState(DeadHostState.DEFAULT_TIME_SUPPLIER).compareTo(new DeadHostState(() -> 0L)); @@ -90,6 +96,7 @@ public void testCompareToDifferingTimeSupplier() { } } + @Test public void testShallBeRetried() { final AtomicLong time = new AtomicLong(0); DeadHostState deadHostState = null; @@ -112,6 +119,7 @@ public void testShallBeRetried() { } } + @Test public void testDeadHostStateTimeouts() { DeadHostState previous = new DeadHostState(() -> 0L); for (long expectedTimeoutsSecond : EXPECTED_TIMEOUTS_SECONDS) { diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/FailureTrackingResponseListenerTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/FailureTrackingResponseListenerTests.java index 23a2f3b50..9e3d03a6f 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/FailureTrackingResponseListenerTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/FailureTrackingResponseListenerTests.java @@ -23,6 +23,7 @@ import org.apache.hc.core5.http.ProtocolVersion; import org.apache.hc.core5.http.message.BasicClassicHttpResponse; import org.apache.hc.core5.http.message.RequestLine; +import org.junit.jupiter.api.Test; import java.util.concurrent.atomic.AtomicReference; @@ -33,6 +34,7 @@ public class FailureTrackingResponseListenerTests extends RestClientTestCase { + @Test public void testOnSuccess() { MockResponseListener responseListener = new MockResponseListener(); Rest5Client.FailureTrackingResponseListener listener = @@ -44,6 +46,7 @@ public void testOnSuccess() { assertNull(responseListener.lastException.get()); } + @Test public void testOnFailure() { MockResponseListener responseListener = new MockResponseListener(); Rest5Client.FailureTrackingResponseListener listener = diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/HasAttributeNodeSelectorTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/HasAttributeNodeSelectorTests.java index c84e251a0..4a011bb64 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/HasAttributeNodeSelectorTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/HasAttributeNodeSelectorTests.java @@ -20,6 +20,7 @@ package co.elastic.clients.transport.rest5_client.low_level; import org.apache.hc.core5.http.HttpHost; +import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.Arrays; @@ -34,6 +35,8 @@ import static org.junit.Assert.assertEquals; public class HasAttributeNodeSelectorTests extends RestClientTestCase { + + @Test public void testHasAttribute() { Node hasAttributeValue = dummyNode(singletonMap("attr", singletonList("val"))); Node hasAttributeButNotValue = dummyNode(singletonMap("attr", singletonList("notval"))); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/NodeSelectorTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/NodeSelectorTests.java index 5ff117c92..34087adb8 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/NodeSelectorTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/NodeSelectorTests.java @@ -20,19 +20,23 @@ package co.elastic.clients.transport.rest5_client.low_level; import org.apache.hc.core5.http.HttpHost; +import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Random; import java.util.Set; import java.util.TreeSet; import static org.junit.Assert.assertEquals; public class NodeSelectorTests extends RestClientTestCase { + + @Test public void testAny() { List nodes = new ArrayList<>(); - int size = between(2, 5); + int size = randomIntBetween(2, 5); for (int i = 0; i < size; i++) { nodes.add(dummyNode(randomBoolean(), randomBoolean(), randomBoolean())); } @@ -41,6 +45,7 @@ public void testAny() { assertEquals(expected, nodes); } + @Test public void testNotMasterOnly() { Node masterOnly = dummyNode(true, false, false); Node all = dummyNode(true, true, true); @@ -67,7 +72,7 @@ public void testNotMasterOnly() { nodes.add(dataWarm); nodes.add(dataCold); nodes.add(dataFrozen); - Collections.shuffle(nodes, getRandom()); + Collections.shuffle(nodes, new Random()); List expected = new ArrayList<>(nodes); expected.remove(masterOnly); NodeSelector.SKIP_DEDICATED_MASTERS.select(nodes); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/NodeTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/NodeTests.java index 979bb2f50..5cb74461d 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/NodeTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/NodeTests.java @@ -20,6 +20,7 @@ package co.elastic.clients.transport.rest5_client.low_level; import org.apache.hc.core5.http.HttpHost; +import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.Collections; @@ -37,6 +38,8 @@ import static org.junit.Assert.assertTrue; public class NodeTests extends RestClientTestCase { + + @Test public void testToString() { Map> attributes = new HashMap<>(); attributes.put("foo", singletonList("bar")); @@ -72,6 +75,7 @@ public void testToString() { ); } + @Test public void testEqualsAndHashCode() { HttpHost host = new HttpHost(randomAsciiAlphanumOfLength(5)); Node node = new Node( @@ -148,6 +152,7 @@ public void testEqualsAndHashCode() { ); } + @Test public void testDataRole() { Node.Roles roles = new Node.Roles(new TreeSet<>(Arrays.asList("data_hot"))); assertTrue(roles.hasDataHotRole()); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/PreferHasAttributeNodeSelectorTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/PreferHasAttributeNodeSelectorTests.java index f9ab1000e..c63bcf60d 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/PreferHasAttributeNodeSelectorTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/PreferHasAttributeNodeSelectorTests.java @@ -20,6 +20,7 @@ package co.elastic.clients.transport.rest5_client.low_level; import org.apache.hc.core5.http.HttpHost; +import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.Arrays; @@ -34,6 +35,8 @@ import static org.junit.Assert.assertEquals; public class PreferHasAttributeNodeSelectorTests extends RestClientTestCase { + + @Test public void testFoundPreferHasAttribute() { Node hasAttributeValue = dummyNode(singletonMap("attr", singletonList("val"))); Node hasAttributeButNotValue = dummyNode(singletonMap("attr", singletonList("notval"))); @@ -51,6 +54,7 @@ public void testFoundPreferHasAttribute() { assertEquals(expected, nodes); } + @Test public void testNotFoundPreferHasAttribute() { Node notHasAttribute = dummyNode(singletonMap("notattr", singletonList("val"))); List nodes = new ArrayList<>(); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestLoggerTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestLoggerTests.java index b184cd763..a9677aaae 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestLoggerTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestLoggerTests.java @@ -39,6 +39,7 @@ import org.apache.hc.core5.http.io.entity.StringEntity; import org.apache.hc.core5.http.message.BasicClassicHttpResponse; import org.apache.hc.core5.http.message.BasicHeader; +import org.junit.jupiter.api.Test; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -53,6 +54,8 @@ import static org.junit.Assert.assertThat; public class RequestLoggerTests extends RestClientTestCase { + + @Test public void testTraceRequest() throws IOException, URISyntaxException, ParseException { HttpHost host = new HttpHost(randomBoolean() ? "http" : "https", "localhost", 9200); String expectedEndpoint = "/index/type/_api"; @@ -104,6 +107,7 @@ public void testTraceRequest() throws IOException, URISyntaxException, ParseExce } } + @Test public void testTraceResponse() throws IOException, ParseException { int statusCode = randomIntBetween(200, 599); String reasonPhrase = "REASON"; @@ -115,7 +119,7 @@ public void testTraceResponse() throws IOException, ParseException { expected += "\n# header" + i + ": value"; } expected += "\n#"; - boolean hasBody = getRandom().nextBoolean(); + boolean hasBody = randomBoolean(); String responseBody = "{\n \"field\": \"value\"\n}"; if (hasBody) { expected += "\n# {"; @@ -152,6 +156,7 @@ public void testTraceResponse() throws IOException, ParseException { } } + @Test public void testResponseWarnings() throws Exception { HttpHost host = new HttpHost("localhost", 9200); HttpUriRequest request = randomHttpRequest(new URI("/index/type/_api")); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptionsTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptionsTests.java index d04431479..a4d7e4f4a 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptionsTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptionsTests.java @@ -22,6 +22,7 @@ import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.util.Timeout; +import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.Collections; @@ -37,6 +38,8 @@ import static org.mockito.Mockito.mock; public class RequestOptionsTests extends RestClientTestCase { + + @Test public void testDefault() { assertEquals(Collections.

emptyList(), RequestOptions.DEFAULT.getHeaders()); assertEquals(Collections.emptyMap(), RequestOptions.DEFAULT.getParameters()); @@ -45,6 +48,7 @@ public void testDefault() { assertEquals(RequestOptions.DEFAULT, RequestOptions.DEFAULT.toBuilder().build()); } + @Test public void testAddHeader() { try { randomBuilder().addHeader(null, randomAsciiLettersOfLengthBetween(3, 10)); @@ -61,7 +65,7 @@ public void testAddHeader() { } RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); - int numHeaders = between(0, 5); + int numHeaders = randomIntBetween(0, 5); List
headers = new ArrayList<>(); for (int i = 0; i < numHeaders; i++) { Header header = new RequestOptions.ReqHeader(randomAsciiAlphanumOfLengthBetween(5, 10), @@ -82,6 +86,7 @@ public void testAddHeader() { } } + @Test public void testSetHttpAsyncResponseConsumerFactory() { try { RequestOptions.DEFAULT.toBuilder().setHttpAsyncResponseConsumerFactory(null); @@ -97,6 +102,7 @@ public void testSetHttpAsyncResponseConsumerFactory() { assertSame(factory, options.getHttpAsyncResponseConsumerFactory()); } + @Test public void testAddParameters() { try { randomBuilder().addParameter(null, randomAsciiLettersOfLengthBetween(3, 10)); @@ -113,7 +119,7 @@ public void testAddParameters() { } RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); - int numParameters = between(0, 5); + int numParameters = randomIntBetween(0, 5); Map parameters = new HashMap<>(); for (int i = 0; i < numParameters; i++) { String key = randomAsciiAlphanumOfLengthBetween(5, 10); @@ -126,6 +132,7 @@ public void testAddParameters() { assertEquals(parameters, options.getParameters()); } + @Test public void testSetRequestBuilder() { RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); @@ -142,6 +149,7 @@ public void testSetRequestBuilder() { assertEquals(options.getRequestConfig().getConnectTimeout(), Timeout.ofMilliseconds(connectTimeout)); } + @Test public void testEqualsAndHashCode() { RequestOptions request = randomBuilder().build(); assertEquals(request, request); @@ -160,7 +168,7 @@ static RequestOptions.Builder randomBuilder() { RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); if (randomBoolean()) { - int headerCount = between(1, 5); + int headerCount = randomIntBetween(1, 5); for (int i = 0; i < headerCount; i++) { builder.addHeader(randomAsciiAlphanumOfLength(3), randomAsciiAlphanumOfLength(3)); } @@ -187,7 +195,7 @@ private static RequestOptions copy(RequestOptions options) { private static RequestOptions mutate(RequestOptions options) { RequestOptions.Builder mutant = options.toBuilder(); - int mutationType = between(0, 2); + int mutationType = randomIntBetween(0, 2); switch (mutationType) { case 0: mutant.addHeader("extra", "m"); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestTests.java index e2688bd08..3f0f0e76a 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestTests.java @@ -23,6 +23,7 @@ import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.io.entity.ByteArrayEntity; import org.apache.hc.core5.http.io.entity.StringEntity; +import org.junit.jupiter.api.Test; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -36,6 +37,8 @@ import static org.junit.Assert.fail; public class RequestTests extends RestClientTestCase { + + @Test public void testConstructor() { final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); @@ -59,10 +62,11 @@ public void testConstructor() { assertEquals(endpoint, request.getEndpoint()); } + @Test public void testAddParameters() { final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); - int parametersCount = between(1, 3); + int parametersCount = randomIntBetween(1, 3); final Map parameters = new HashMap<>(parametersCount); while (parameters.size() < parametersCount) { parameters.put(randomAsciiLettersOfLength(5), randomAsciiLettersOfLength(5)); @@ -97,6 +101,7 @@ public void testAddParameters() { } } + @Test public void testSetEntity() { final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); @@ -109,6 +114,7 @@ public void testSetEntity() { assertEquals(entity, request.getEntity()); } + @Test public void testSetJsonEntity() throws IOException { final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); @@ -124,6 +130,7 @@ public void testSetJsonEntity() throws IOException { assertEquals(json, new String(os.toByteArray(), ContentType.APPLICATION_JSON.getCharset())); } + @Test public void testSetOptions() { final String method = randomFrom(new String[] { "GET", "PUT", "POST", "HEAD", "DELETE" }); final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); @@ -153,6 +160,7 @@ public void testSetOptions() { assertSame(options, request.getOptions()); } + @Test public void testEqualsAndHashCode() { Request request = randomRequest(); assertEquals(request, request); @@ -173,7 +181,7 @@ private static Request randomRequest() { randomAsciiAlphanumOfLength(5) ); - int parameterCount = between(0, 5); + int parameterCount = randomIntBetween(0, 5); for (int i = 0; i < parameterCount; i++) { request.addParameter(randomAsciiAlphanumOfLength(i), randomAsciiLettersOfLength(3)); } @@ -217,7 +225,7 @@ private static Request mutate(Request request) { return mutant; } Request mutant = copy(request); - int mutationType = between(0, 2); + int mutationType = randomIntBetween(0, 2); switch (mutationType) { case 0: mutant.addParameter(randomAsciiAlphanumOfLength(mutant.getParameters().size() + 4), "extra"); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/ResponseExceptionTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/ResponseExceptionTests.java index c6cef25d0..12344c739 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/ResponseExceptionTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/ResponseExceptionTests.java @@ -30,6 +30,7 @@ import org.apache.hc.core5.http.io.entity.StringEntity; import org.apache.hc.core5.http.message.BasicClassicHttpResponse; import org.apache.hc.core5.http.message.RequestLine; +import org.junit.jupiter.api.Test; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -42,15 +43,17 @@ public class ResponseExceptionTests extends RestClientTestCase { + + @Test public void testResponseException() throws IOException, ParseException { ProtocolVersion protocolVersion = new ProtocolVersion("http", 1, 1); BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(500, "Internal Server Error"); String responseBody = "{\"error\":{\"root_cause\": {}}}"; - boolean hasBody = getRandom().nextBoolean(); + boolean hasBody = randomBoolean(); if (hasBody) { HttpEntity entity; - if (getRandom().nextBoolean()) { + if (randomBoolean()) { entity = new StringEntity(responseBody, ContentType.APPLICATION_JSON); } else { // test a non repeatable entity diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderIntegTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderIntegTests.java index bc3bead5e..e1144ccec 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderIntegTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderIntegTests.java @@ -24,10 +24,10 @@ import com.sun.net.httpserver.HttpsConfigurator; import com.sun.net.httpserver.HttpsServer; import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.RestClient; import org.elasticsearch.mocksocket.MockHttpServer; -import org.junit.AfterClass; -import org.junit.BeforeClass; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Test; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; @@ -55,6 +55,7 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.junit.Assume.assumeFalse; /** * Integration test to validate the builder builds a client with the correct configuration @@ -62,8 +63,9 @@ public class RestClientBuilderIntegTests extends RestClientTestCase { private static HttpsServer httpsServer; + private static String resourcePath = "/co/elastic/clients/transport/rest5_client/low_level"; - @BeforeClass + @BeforeAll public static void startHttpServer() throws Exception { httpsServer = MockHttpServer.createHttps(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0) , 0); @@ -80,12 +82,13 @@ public void handle(HttpExchange httpExchange) throws IOException { } } - @AfterClass + @AfterAll public static void stopHttpServers() throws IOException { httpsServer.stop(0); httpsServer = null; } + @Test public void testBuilderUsesDefaultSSLContext() throws Exception { assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm()); final SSLContext defaultSSLContext = SSLContext.getDefault(); @@ -109,6 +112,7 @@ public void testBuilderUsesDefaultSSLContext() throws Exception { } } + @Test public void testBuilderSetsThreadName() throws Exception { assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm()); final SSLContext defaultSSLContext = SSLContext.getDefault(); @@ -151,9 +155,9 @@ private Rest5Client buildRestClient() { private static SSLContext getSslContext() throws Exception { SSLContext sslContext = SSLContext.getInstance(getProtocol()); try ( - InputStream certFile = RestClientBuilderIntegTests.class.getResourceAsStream("/test.crt"); + InputStream certFile = RestClientBuilderIntegTests.class.getResourceAsStream(resourcePath + "/test.crt"); InputStream keyStoreFile = RestClientBuilderIntegTests.class.getResourceAsStream( - "/test_truststore.jks") + resourcePath + "/test_truststore.jks") ) { // Build a keystore of default type programmatically since we can't use JKS keystores to // init a KeyManagerFactory in FIPS 140 JVMs. @@ -161,7 +165,7 @@ private static SSLContext getSslContext() throws Exception { keyStore.load(null, "password".toCharArray()); CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec( - Files.readAllBytes(Paths.get(RestClientBuilderIntegTests.class.getResource("/test.der").toURI())) + Files.readAllBytes(Paths.get(RestClientBuilderIntegTests.class.getResource(resourcePath + "/test.der").toURI())) ); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); keyStore.setKeyEntry( diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderTests.java index 37f104baa..ad7a77043 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderTests.java @@ -27,8 +27,10 @@ import org.apache.hc.core5.http.message.BasicHeader; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; +import org.junit.jupiter.api.Test; import java.io.IOException; +import java.nio.charset.Charset; import java.util.Base64; import static org.hamcrest.Matchers.containsString; @@ -40,6 +42,7 @@ public class RestClientBuilderTests extends RestClientTestCase { + @Test public void testBuild() throws IOException { try { Rest5Client.builder((HttpHost[]) null); @@ -153,16 +156,17 @@ public void testBuild() throws IOException { } } + @Test public void testBuildCloudId() throws IOException { String host = "us-east-1.aws.found.io"; String esId = "elasticsearch"; String kibanaId = "kibana"; String toEncode = host + "$" + esId + "$" + kibanaId; - String encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(UTF8)); + String encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(Charset.defaultCharset())); assertNotNull(Rest5Client.builder(encodedId)); assertNotNull(Rest5Client.builder("humanReadable:" + encodedId)); - String badId = Base64.getEncoder().encodeToString("foo$bar".getBytes(UTF8)); + String badId = Base64.getEncoder().encodeToString("foo$bar".getBytes(Charset.defaultCharset())); try { Rest5Client.builder(badId); fail("should have failed"); @@ -187,13 +191,14 @@ public void testBuildCloudId() throws IOException { client.close(); } + @Test public void testBuildCloudIdWithPort() throws IOException { String host = "us-east-1.aws.found.io"; String esId = "elasticsearch"; String kibanaId = "kibana"; String port = "9443"; String toEncode = host + ":" + port + "$" + esId + "$" + kibanaId; - String encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(UTF8)); + String encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(Charset.defaultCharset())); Rest5Client client = Rest5Client.builder("humanReadable:" + encodedId).build(); assertThat(client.getNodes().size(), equalTo(1)); @@ -203,7 +208,7 @@ public void testBuildCloudIdWithPort() throws IOException { client.close(); toEncode = host + ":" + "123:foo" + "$" + esId + "$" + kibanaId; - encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(UTF8)); + encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(Charset.defaultCharset())); try { Rest5Client.builder("humanReadable:" + encodedId); @@ -213,6 +218,7 @@ public void testBuildCloudIdWithPort() throws IOException { } } + @Test public void testSetPathPrefixNull() { try { Rest5Client.builder(new HttpHost("localhost", 9200)).setPathPrefix(null); @@ -222,10 +228,12 @@ public void testSetPathPrefixNull() { } } + @Test public void testSetPathPrefixEmpty() { assertSetPathPrefixThrows(""); } + @Test public void testSetPathPrefixMalformed() { assertSetPathPrefixThrows("//"); assertSetPathPrefixThrows("base/path//"); @@ -245,6 +253,7 @@ private static void assertSetPathPrefixThrows(final String pathPrefix) { * causes problems. * See https://github.com/elastic/elasticsearch/issues/24069 */ + @Test public void testDefaultConnectionRequestTimeout() throws IOException { Rest5ClientBuilder builder = Rest5Client.builder(new HttpHost("localhost", 9200)); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientGzipCompressionTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientGzipCompressionTests.java index 195ed69c0..c1bc150ba 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientGzipCompressionTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientGzipCompressionTests.java @@ -27,9 +27,10 @@ import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.io.entity.StringEntity; import org.elasticsearch.mocksocket.MockHttpServer; -import org.junit.AfterClass; import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -49,14 +50,14 @@ public class RestClientGzipCompressionTests extends RestClientTestCase { private static HttpServer httpServer; - @BeforeClass + @BeforeAll public static void startHttpServer() throws Exception { httpServer = MockHttpServer.createHttp(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); httpServer.createContext("/", new GzipResponseHandler()); httpServer.start(); } - @AfterClass + @AfterAll public static void stopHttpServers() throws IOException { httpServer.stop(0); httpServer = null; @@ -128,6 +129,7 @@ private Rest5Client createClient(boolean enableCompression) { .build(); } + @Test public void testUncompressedSync() throws Exception { Rest5Client restClient = createClient(false); @@ -144,6 +146,7 @@ public void testUncompressedSync() throws Exception { restClient.close(); } + @Test public void testGzipHeaderSync() throws Exception { Rest5Client restClient = createClient(false); @@ -162,6 +165,7 @@ public void testGzipHeaderSync() throws Exception { restClient.close(); } + @Test public void testGzipHeaderAsync() throws Exception { Rest5Client restClient = createClient(false); @@ -180,6 +184,7 @@ public void testGzipHeaderAsync() throws Exception { restClient.close(); } + @Test public void testCompressingClientSync() throws Exception { Rest5Client restClient = createClient(true); @@ -194,6 +199,7 @@ public void testCompressingClientSync() throws Exception { restClient.close(); } + @Test public void testCompressingClientAsync() throws Exception { InetSocketAddress address = httpServer.getAddress(); Rest5Client restClient = Rest5Client.builder(new HttpHost("http", address.getHostString(), diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientMultipleHostsIntegTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientMultipleHostsIntegTests.java index 5ab8d7764..89e00f778 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientMultipleHostsIntegTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientMultipleHostsIntegTests.java @@ -24,10 +24,11 @@ import com.sun.net.httpserver.HttpServer; import org.apache.hc.core5.http.HttpHost; import org.elasticsearch.mocksocket.MockHttpServer; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Ignore; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; import java.io.IOException; import java.io.OutputStream; @@ -67,7 +68,7 @@ public class RestClientMultipleHostsIntegTests extends RestClientTestCase { private static String pathPrefix; private static Rest5Client restClient; - @BeforeClass + @BeforeAll public static void startHttpServer() throws Exception { if (randomBoolean()) { pathPrefixWithoutLeadingSlash = "testPathPrefix/" + randomAsciiLettersOfLengthBetween(1, 5); @@ -175,7 +176,7 @@ public void handle(HttpExchange httpExchange) throws IOException { } } - @AfterClass + @AfterAll public static void stopHttpServers() throws IOException { restClient.close(); restClient = null; @@ -185,7 +186,7 @@ public static void stopHttpServers() throws IOException { httpServers = null; } - @Before + @BeforeEach public void stopRandomHost() { // verify that shutting down some hosts doesn't matter as long as one working host is left behind if (httpServers.length > 1 && randomBoolean()) { @@ -206,12 +207,13 @@ public void stopRandomHost() { } } + @Test public void testSyncRequests() throws IOException { int numRequests = randomIntBetween(5, 20); for (int i = 0; i < numRequests; i++) { - final String method = RestClientTestUtil.randomHttpMethod(getRandom()); + final String method = RestClientTestUtil.randomHttpMethod(); // we don't test status codes that are subject to retries as they interfere with hosts being stopped - final int statusCode = randomBoolean() ? randomOkStatusCode(getRandom()) : randomErrorNoRetryStatusCode(getRandom()); + final int statusCode = randomBoolean() ? randomOkStatusCode() : randomErrorNoRetryStatusCode(); Response response; try { response = restClient.performRequest(new Request(method, "/" + statusCode)); @@ -224,14 +226,15 @@ public void testSyncRequests() throws IOException { } } + @Test public void testAsyncRequests() throws Exception { int numRequests = randomIntBetween(5, 20); final CountDownLatch latch = new CountDownLatch(numRequests); final List responses = new CopyOnWriteArrayList<>(); for (int i = 0; i < numRequests; i++) { - final String method = RestClientTestUtil.randomHttpMethod(getRandom()); + final String method = RestClientTestUtil.randomHttpMethod(); // we don't test status codes that are subject to retries as they interfere with hosts being stopped - final int statusCode = randomBoolean() ? randomOkStatusCode(getRandom()) : randomErrorNoRetryStatusCode(getRandom()); + final int statusCode = randomBoolean() ? randomOkStatusCode() : randomErrorNoRetryStatusCode(); restClient.performRequestAsync(new Request(method, "/" + statusCode), new ResponseListener() { @Override public void onSuccess(Response response) { @@ -257,6 +260,7 @@ public void onFailure(Exception exception) { } } + @Test public void testCancelAsyncRequests() throws Exception { int numRequests = randomIntBetween(5, 20); final List responses = new CopyOnWriteArrayList<>(); @@ -297,10 +301,11 @@ public void onFailure(Exception exception) { * Test host selector against a real server and * test what happens after calling */ + @Test public void testNodeSelector() throws Exception { try (Rest5Client restClient = buildRestClient(firstPositionNodeSelector())) { Request request = new Request("GET", "/200"); - int rounds = between(1, 10); + int rounds = randomIntBetween(1, 10); for (int i = 0; i < rounds; i++) { /* * Run the request more than once to verify that the @@ -324,7 +329,8 @@ public void testNodeSelector() throws Exception { } } - @Ignore("https://github.com/elastic/elasticsearch/issues/87314") + @Disabled("https://github.com/elastic/elasticsearch/issues/87314") + @Test public void testNonRetryableException() throws Exception { RequestOptions.Builder options = RequestOptions.DEFAULT.toBuilder(); options.setHttpAsyncResponseConsumerFactory( diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientMultipleHostsTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientMultipleHostsTests.java index d28ac4f65..71dfd014b 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientMultipleHostsTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientMultipleHostsTests.java @@ -19,11 +19,11 @@ package co.elastic.clients.transport.rest5_client.low_level; -import com.carrotsearch.randomizedtesting.generators.RandomNumbers; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpHost; import org.junit.After; +import org.junit.jupiter.api.Test; import java.io.IOException; import java.util.ArrayList; @@ -60,7 +60,7 @@ public class RestClientMultipleHostsTests extends RestClientTestCase { public Rest5Client createRestClient(NodeSelector nodeSelector) { CloseableHttpAsyncClient httpClient = RestClientSingleHostTests.mockHttpClient(exec); - int numNodes = RandomNumbers.randomIntBetween(getRandom(), 2, 5); + int numNodes = randomIntBetween(2, 5); nodes = new ArrayList<>(numNodes); for (int i = 0; i < numNodes; i++) { nodes.add(new Node(new HttpHost("localhost", 9200 + i))); @@ -78,16 +78,17 @@ public void shutdownExec() { exec.shutdown(); } + @Test public void testRoundRobinOkStatusCodes() throws Exception { Rest5Client restClient = createRestClient(NodeSelector.ANY); - int numIters = RandomNumbers.randomIntBetween(getRandom(), 1, 5); + int numIters = randomIntBetween(1, 5); for (int i = 0; i < numIters; i++) { Set hostsSet = hostsSet(); for (int j = 0; j < nodes.size(); j++) { - int statusCode = randomOkStatusCode(getRandom()); + int statusCode = randomOkStatusCode(); Response response = RestClientSingleHostTests.performRequestSyncOrAsync( restClient, - new Request(randomHttpMethod(getRandom()), "/" + statusCode) + new Request(randomHttpMethod(), "/" + statusCode) ); assertEquals(statusCode, response.getStatusCode()); assertTrue("host not found: " + response.getHost(), hostsSet.remove(response.getHost())); @@ -97,14 +98,15 @@ public void testRoundRobinOkStatusCodes() throws Exception { failureListener.assertNotCalled(); } + @Test public void testRoundRobinNoRetryErrors() throws Exception { Rest5Client restClient = createRestClient(NodeSelector.ANY); - int numIters = RandomNumbers.randomIntBetween(getRandom(), 1, 5); + int numIters = randomIntBetween(1, 5); for (int i = 0; i < numIters; i++) { Set hostsSet = hostsSet(); for (int j = 0; j < nodes.size(); j++) { - String method = randomHttpMethod(getRandom()); - int statusCode = randomErrorNoRetryStatusCode(getRandom()); + String method = randomHttpMethod(); + int statusCode = randomErrorNoRetryStatusCode(); try { Response response = RestClientSingleHostTests.performRequestSyncOrAsync( restClient, @@ -133,11 +135,12 @@ public void testRoundRobinNoRetryErrors() throws Exception { failureListener.assertNotCalled(); } + @Test public void testRoundRobinRetryErrors() throws Exception { Rest5Client restClient = createRestClient(NodeSelector.ANY); String retryEndpoint = randomErrorRetryEndpoint(); try { - RestClientSingleHostTests.performRequestSyncOrAsync(restClient, new Request(randomHttpMethod(getRandom()), retryEndpoint)); + RestClientSingleHostTests.performRequestSyncOrAsync(restClient, new Request(randomHttpMethod(), retryEndpoint)); fail("request should have failed"); } catch (ResponseException e) { Set hostsSet = hostsSet(); @@ -179,7 +182,7 @@ public void testRoundRobinRetryErrors() throws Exception { assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); } - int numIters = RandomNumbers.randomIntBetween(getRandom(), 2, 5); + int numIters = randomIntBetween(2, 5); for (int i = 1; i <= numIters; i++) { // check that one different host is resurrected at each new attempt Set hostsSet = hostsSet(); @@ -188,7 +191,7 @@ public void testRoundRobinRetryErrors() throws Exception { try { RestClientSingleHostTests.performRequestSyncOrAsync( restClient, - new Request(randomHttpMethod(getRandom()), retryEndpoint) + new Request(randomHttpMethod(), retryEndpoint) ); fail("request should have failed"); } catch (ResponseException e) { @@ -210,17 +213,17 @@ public void testRoundRobinRetryErrors() throws Exception { } } assertEquals("every host should have been used but some weren't: " + hostsSet, 0, hostsSet.size()); - if (getRandom().nextBoolean()) { + if (randomBoolean()) { // mark one host back alive through a successful request and check that all requests after that are sent to it HttpHost selectedHost = null; - int iters = RandomNumbers.randomIntBetween(getRandom(), 2, 10); + int iters = randomIntBetween(2, 10); for (int y = 0; y < iters; y++) { - int statusCode = randomErrorNoRetryStatusCode(getRandom()); + int statusCode = randomErrorNoRetryStatusCode(); Response response; try { response = RestClientSingleHostTests.performRequestSyncOrAsync( restClient, - new Request(randomHttpMethod(getRandom()), "/" + statusCode) + new Request(randomHttpMethod(), "/" + statusCode) ); } catch (ResponseException e) { response = e.getResponse(); @@ -240,7 +243,7 @@ public void testRoundRobinRetryErrors() throws Exception { try { RestClientSingleHostTests.performRequestSyncOrAsync( restClient, - new Request(randomHttpMethod(getRandom()), retryEndpoint) + new Request(randomHttpMethod(), retryEndpoint) ); fail("request should have failed"); } catch (ResponseException e) { @@ -258,6 +261,7 @@ public void testRoundRobinRetryErrors() throws Exception { } } + @Test public void testNodeSelector() throws Exception { NodeSelector firstPositionOnly = restClientNodes -> { boolean found = false; @@ -271,7 +275,7 @@ public void testNodeSelector() throws Exception { assertTrue(found); }; Rest5Client restClient = createRestClient(firstPositionOnly); - int rounds = between(1, 10); + int rounds = randomIntBetween(1, 10); for (int i = 0; i < rounds; i++) { /* * Run the request more than once to verify that the @@ -283,6 +287,7 @@ public void testNodeSelector() throws Exception { } } + @Test public void testSetNodes() throws Exception { Rest5Client restClient = createRestClient(NodeSelector.SKIP_DEDICATED_MASTERS); List newNodes = new ArrayList<>(nodes.size()); @@ -293,7 +298,7 @@ public void testSetNodes() throws Exception { newNodes.add(new Node(nodes.get(i).getHost(), null, null, null, roles, null)); } restClient.setNodes(newNodes); - int rounds = between(1, 10); + int rounds = randomIntBetween(1, 10); for (int i = 0; i < rounds; i++) { /* * Run the request more than once to verify that the @@ -306,9 +311,9 @@ public void testSetNodes() throws Exception { } private static String randomErrorRetryEndpoint() { - switch (RandomNumbers.randomIntBetween(getRandom(), 0, 3)) { + switch (randomIntBetween(0, 3)) { case 0: - return "/" + randomErrorRetryStatusCode(getRandom()); + return "/" + randomErrorRetryStatusCode(); case 1: return "/coe"; case 2: diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostIntegTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostIntegTests.java index d029e81bb..834e949f7 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostIntegTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostIntegTests.java @@ -36,10 +36,10 @@ import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.StringEntity; import org.apache.hc.core5.http.message.BasicHeader; -import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.mocksocket.MockHttpServer; -import org.junit.After; -import org.junit.Before; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import java.io.IOException; import java.io.InputStreamReader; @@ -83,13 +83,13 @@ public class RestClientSingleHostIntegTests extends RestClientTestCase { private Header[] defaultHeaders; private WaitForCancelHandler waitForCancelHandler; - @Before + @BeforeEach public void startHttpServer() throws Exception { // set version.properties, just for testing, version won't be updated System.setProperty("versions.elasticsearch","8.17.0"); pathPrefix = randomBoolean() ? "/testPathPrefix/" + randomAsciiLettersOfLengthBetween(1, 5) : ""; httpServer = createHttpServer(); - defaultHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header-default"); + defaultHeaders = RestClientTestUtil.randomHeaders("Header-default"); restClient = createRestClient(false, true, true); } @@ -195,7 +195,7 @@ private Rest5Client createRestClient(final boolean useAuth, final boolean usePre return restClientBuilder.build(); } - @After + @AfterEach public void stopHttpServers() throws IOException { restClient.close(); restClient = null; @@ -207,7 +207,7 @@ public void stopHttpServers() throws IOException { * Tests sending a bunch of async requests works well (e.g. no TimeoutException from the leased pool) * See https://github.com/elastic/elasticsearch/issues/24069 */ - + @Test public void testManyAsyncRequests() throws Exception { int iters = randomIntBetween(500, 1000); final CountDownLatch latch = new CountDownLatch(iters); @@ -241,8 +241,9 @@ public void onFailure(Exception exception) { } } + @Test public void testCancelAsyncRequest() throws Exception { - Request request = new Request(randomHttpMethod(getRandom()), "/wait"); + Request request = new Request(randomHttpMethod(), "/wait"); CountDownLatch requestLatch = new CountDownLatch(1); AtomicReference error = new AtomicReference<>(); Cancellable cancellable = restClient.performRequestAsync(request, new ResponseListener() { @@ -273,6 +274,7 @@ public void onFailure(Exception exception) { * to set the future ref to the request properly so that when abort is called, the proper future gets * cancelled. */ + @Test public void testRequestResetAndAbort() throws Exception { try (CloseableHttpAsyncClient client = HttpAsyncClientBuilder.create().build()) { client.start(); @@ -331,6 +333,7 @@ public void testRequestResetAndAbort() throws Exception { * out of the box by {@link HttpAsyncClients}. * Exercises the test http server ability to send back whatever body it received. */ + @Test public void testDeleteWithBody() throws Exception { bodyTest("DELETE"); } @@ -340,10 +343,12 @@ public void testDeleteWithBody() throws Exception { * out of the box by {@link HttpAsyncClients}. * Exercises the test http server ability to send back whatever body it received. */ + @Test public void testGetWithBody() throws Exception { bodyTest("GET"); } + @Test public void testEncodeParams() throws Exception { { Request request = new Request("PUT", "/200"); @@ -401,6 +406,7 @@ public void testEncodeParams() throws Exception { * Verify that credentials are sent on the first request with preemptive auth enabled (default when * provided with credentials). */ + @Test public void testPreemptiveAuthEnabled() throws Exception { final String[] methods = {"POST", "PUT", "GET", "DELETE"}; @@ -418,7 +424,7 @@ private Response bodyTest(final String method) throws Exception { } private Response bodyTest(final Rest5Client client, final String method) throws Exception { - int statusCode = randomStatusCode(getRandom()); + int statusCode = randomStatusCode(); return bodyTest(client, method, statusCode, new Header[0]); } diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostTests.java index e6d99d882..0bdfee300 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostTests.java @@ -48,8 +48,9 @@ import org.apache.hc.core5.http.nio.AsyncRequestProducer; import org.apache.hc.core5.http.nio.AsyncResponseConsumer; import org.apache.hc.core5.net.URIBuilder; -import org.junit.After; -import org.junit.Before; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.stubbing.Answer; @@ -113,10 +114,10 @@ public class RestClientSingleHostTests extends RestClientTestCase { private HostsTrackingFailureListener failureListener; private boolean strictDeprecationMode; - @Before + @BeforeEach public void createRestClient() { httpClient = mockHttpClient(exec); - defaultHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header-default"); + defaultHeaders = RestClientTestUtil.randomHeaders("Header-default"); node = new Node(new HttpHost("localhost", 9200)); failureListener = new HostsTrackingFailureListener(); strictDeprecationMode = randomBoolean(); @@ -224,7 +225,7 @@ private static Optional retrieveEntity(AsyncDataProducer requestProd /** * Shutdown the executor so we don't leak threads into other test runs. */ - @After + @AfterEach public void shutdownExec() { exec.shutdown(); } @@ -234,6 +235,7 @@ public void shutdownExec() { * http client */ @SuppressWarnings("unchecked") + @Test public void testInternalHttpRequest() throws Exception { ArgumentCaptor requestArgumentCaptor = ArgumentCaptor.forClass (AsyncRequestProducer.class); @@ -266,6 +268,7 @@ public void testInternalHttpRequest() throws Exception { /** * End to end test for ok status codes */ + @Test public void testOkStatusCodes() throws Exception { for (String method : getHttpMethods()) { for (int okStatusCode : getOkStatusCodes()) { @@ -280,6 +283,7 @@ public void testOkStatusCodes() throws Exception { /** * End to end test for error status codes: they should cause an exception to be thrown */ + @Test public void testErrorStatusCodes() throws Exception { for (String method : getHttpMethods()) { // error status codes should cause an exception to be thrown @@ -296,6 +300,7 @@ public void testErrorStatusCodes() throws Exception { } } + @Test public void testPerformRequestIOExceptions() throws Exception { for (String method : getHttpMethods()) { // IOExceptions should be let bubble up @@ -342,6 +347,7 @@ public void testPerformRequestIOExceptions() throws Exception { } } + @Test public void testPerformRequestRuntimeExceptions() throws Exception { for (String method : getHttpMethods()) { try { @@ -355,6 +361,7 @@ public void testPerformRequestRuntimeExceptions() throws Exception { } } + @Test public void testPerformRequestExceptions() throws Exception { for (String method : getHttpMethods()) { try { @@ -373,6 +380,7 @@ public void testPerformRequestExceptions() throws Exception { * End to end test for request and response body. Exercises the mock http client ability to send back * whatever body it has received. */ + @Test public void testBody() throws Exception { String body = "{ \"field\": \"value\" }"; StringEntity entity = new StringEntity(body, ContentType.APPLICATION_JSON); @@ -399,7 +407,7 @@ public void testBody() throws Exception { } } for (String method : Arrays.asList("HEAD", "OPTIONS", "TRACE")) { - Request request = new Request(method, "/" + randomStatusCode(getRandom())); + Request request = new Request(method, "/" + randomStatusCode()); request.setEntity(entity); try { performRequestSyncOrAsync(restClient, request); @@ -414,10 +422,11 @@ public void testBody() throws Exception { * End to end test for request and response headers. Exercises the mock http client ability to send back * whatever headers it has received. */ + @Test public void testHeaders() throws Exception { for (String method : getHttpMethods()) { - final Header[] requestHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header"); - final int statusCode = randomStatusCode(getRandom()); + final Header[] requestHeaders = RestClientTestUtil.randomHeaders( "Header"); + final int statusCode = randomStatusCode(); Request request = new Request(method, "/" + statusCode); RequestOptions.Builder options = request.getOptions().toBuilder(); for (Header requestHeader : requestHeaders) { @@ -437,6 +446,7 @@ public void testHeaders() throws Exception { } } + @Test public void testDeprecationWarnings() throws Exception { String chars = randomAsciiAlphanumOfLength(5); assertDeprecationWarnings(singletonList("poorly formatted " + chars), singletonList("poorly " + @@ -549,7 +559,7 @@ private static String formatWarning(String warningBody) { } private HttpUriRequest performRandomRequest(String method) throws Exception { - String uriAsString = "/" + randomStatusCode(getRandom()); + String uriAsString = "/" + randomStatusCode(); Request request = new Request(method, uriAsString); URIBuilder uriBuilder = new URIBuilder(uriAsString); if (randomBoolean()) { @@ -593,7 +603,7 @@ private HttpUriRequest performRandomRequest(String method) throws Exception { throw new UnsupportedOperationException("method not supported: " + method); } - if (canHaveBody(expectedRequest) && getRandom().nextBoolean()) { + if (canHaveBody(expectedRequest) && randomBoolean()) { HttpEntity entity = new StringEntity(randomAsciiAlphanumOfLengthBetween(10, 100), ContentType.APPLICATION_JSON); (expectedRequest).setEntity(entity); @@ -602,7 +612,7 @@ private HttpUriRequest performRandomRequest(String method) throws Exception { final Set uniqueNames = new HashSet<>(); if (randomBoolean()) { - Header[] headers = RestClientTestUtil.randomHeaders(getRandom(), "Header"); + Header[] headers = RestClientTestUtil.randomHeaders("Header"); RequestOptions.Builder options = request.getOptions().toBuilder(); for (Header header : headers) { options.addHeader(header.getName(), header.getValue()); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestCase.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestCase.java index db72b558e..034f63e99 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestCase.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestCase.java @@ -19,18 +19,7 @@ package co.elastic.clients.transport.rest5_client.low_level; -import com.carrotsearch.randomizedtesting.JUnit3MethodProvider; -import com.carrotsearch.randomizedtesting.MixWithSuiteName; -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.SeedDecorators; -import com.carrotsearch.randomizedtesting.annotations.TestMethodProviders; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakGroup; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies; -import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite; +import org.apache.commons.lang3.RandomStringUtils; import org.apache.hc.core5.http.Header; import java.util.ArrayList; @@ -38,32 +27,26 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Random; import java.util.Set; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -@TestMethodProviders({ JUnit3MethodProvider.class }) -@SeedDecorators({ MixWithSuiteName.class }) // See LUCENE-3995 for rationale. -@ThreadLeakScope(ThreadLeakScope.Scope.SUITE) -@ThreadLeakGroup(ThreadLeakGroup.Group.MAIN) -@ThreadLeakAction({ ThreadLeakAction.Action.WARN, ThreadLeakAction.Action.INTERRUPT }) -@ThreadLeakZombies(ThreadLeakZombies.Consequence.IGNORE_REMAINING_TESTS) -@ThreadLeakLingering(linger = 5000) // 5 sec lingering -@ThreadLeakFilters(filters = { ClientsGraalVMThreadsFilter.class }) -@TimeoutSuite(millis = 2 * 60 * 60 * 1000) -public abstract class RestClientTestCase extends RandomizedTest { +public abstract class RestClientTestCase { /** - * Assert that the actual headers are the expected ones given the original default and request headers. Some headers can be ignored, + * Assert that the actual headers are the expected ones given the original default and request headers. + * Some headers can be ignored, * for instance in case the http client is adding its own automatically. * * @param defaultHeaders the default headers set to the REST client instance * @param requestHeaders the request headers sent with a particular request - * @param actualHeaders the actual headers as a result of the provided default and request headers - * @param ignoreHeaders header keys to be ignored as they are not part of default nor request headers, yet they - * will be part of the actual ones + * @param actualHeaders the actual headers as a result of the provided default and request headers + * @param ignoreHeaders header keys to be ignored as they are not part of default nor request headers, + * yet they + * will be part of the actual ones */ protected static void assertHeaders( final Header[] defaultHeaders, @@ -94,17 +77,21 @@ protected static void assertHeaders( } final String value = responseHeader.getValue(); final List values = expectedHeaders.get(name); - assertNotNull("found response header [" + name + "] that wasn't originally sent: " + value, values); + assertNotNull("found response header [" + name + "] that wasn't originally sent: " + value, + values); assertTrue("found incorrect response header [" + name + "]: " + value, values.remove(value)); if (values.isEmpty()) { expectedHeaders.remove(name); } } - assertEquals("some headers meant to be ignored were not part of the actual headers", ignoreHeaders, actualIgnoredHeaders); - assertTrue("some headers that were sent weren't returned " + expectedHeaders, expectedHeaders.isEmpty()); + assertEquals("some headers meant to be ignored were not part of the actual headers", ignoreHeaders, + actualIgnoredHeaders); + assertTrue("some headers that were sent weren't returned " + expectedHeaders, + expectedHeaders.isEmpty()); } - private static void addValueToListEntry(final Map> map, final String name, final String value) { + private static void addValueToListEntry(final Map> map, final String name, + final String value) { List values = map.get(name); if (values == null) { values = new ArrayList<>(); @@ -116,4 +103,46 @@ private static void addValueToListEntry(final Map> map, fin public static boolean inFipsJvm() { return Boolean.parseBoolean(System.getProperty("tests.fips.enabled")); } + + public static int randomIntBetween(int min, int max) { + return new Random().ints(min, max) + .findFirst() + .getAsInt(); + } + + public static boolean randomBoolean() { + return randomIntBetween(0, 1) == 0; + } + + public static String randomAsciiAlphanumOfLength(int length) { + return RandomStringUtils.randomAlphanumeric(length); + } + + public static String randomAsciiAlphanumOfLengthBetween(int min, int max) { + return RandomStringUtils.randomAlphanumeric(min, max); + } + + public static String randomAsciiLettersOfLength(int lentgh) { + return RandomStringUtils.randomAlphabetic(lentgh); + } + + public static String randomAsciiLettersOfLengthBetween(int min, int max) { + return RandomStringUtils.randomAlphabetic(min, max); + } + + public static T randomFrom(T[] array) { + int index = randomIntBetween(0, array.length); + return array[index]; + } + + public static T randomFrom(List list) { + int index = randomIntBetween(0, list.size()); + return list.get(index); + } + + public static byte[] randomBytesOfLength(int length) { + byte[] b = new byte[length]; + new Random().nextBytes(b); + return b; + } } diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestUtil.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestUtil.java index c87871ae0..77fb04fbf 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestUtil.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestUtil.java @@ -19,9 +19,6 @@ package co.elastic.clients.transport.rest5_client.low_level; -import com.carrotsearch.randomizedtesting.generators.RandomNumbers; -import com.carrotsearch.randomizedtesting.generators.RandomPicks; -import com.carrotsearch.randomizedtesting.generators.RandomStrings; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.message.BasicHeader; @@ -31,6 +28,11 @@ import java.util.List; import java.util.Random; +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestCase.randomAsciiLettersOfLengthBetween; +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestCase.randomBoolean; +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestCase.randomFrom; +import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestCase.randomIntBetween; + final class RestClientTestUtil { private static final String[] HTTP_METHODS = new String[]{"DELETE", "HEAD", "GET", "OPTIONS", "PATCH", @@ -62,24 +64,24 @@ static String[] getHttpMethods() { return HTTP_METHODS; } - static String randomHttpMethod(Random random) { - return RandomPicks.randomFrom(random, HTTP_METHODS); + static String randomHttpMethod() { + return randomFrom(HTTP_METHODS); } - static int randomStatusCode(Random random) { - return RandomPicks.randomFrom(random, ALL_STATUS_CODES); + static int randomStatusCode() { + return randomFrom(ALL_STATUS_CODES); } - static int randomOkStatusCode(Random random) { - return RandomPicks.randomFrom(random, OK_STATUS_CODES); + static int randomOkStatusCode() { + return randomFrom(OK_STATUS_CODES); } - static int randomErrorNoRetryStatusCode(Random random) { - return RandomPicks.randomFrom(random, List.of(500,501)); + static int randomErrorNoRetryStatusCode() { + return randomFrom(List.of(500,501)); } - static int randomErrorRetryStatusCode(Random random) { - return RandomPicks.randomFrom(random, ERROR_RETRY_STATUS_CODES); + static int randomErrorRetryStatusCode() { + return randomFrom(ERROR_RETRY_STATUS_CODES); } static List getOkStatusCodes() { @@ -100,17 +102,16 @@ static List getAllStatusCodes() { * {@code baseName} so that the * we test also support for multiple headers with same key and different values. */ - static Header[] randomHeaders(Random random, final String baseName) { - int numHeaders = RandomNumbers.randomIntBetween(random, 0, 5); + static Header[] randomHeaders(final String baseName) { + int numHeaders = randomIntBetween(0, 5); final Header[] headers = new Header[numHeaders]; for (int i = 0; i < numHeaders; i++) { String headerName = baseName; // randomly exercise the code path that supports multiple headers with same key - if (random.nextBoolean()) { + if (randomBoolean()) { headerName = headerName + i; } - headers[i] = new BasicHeader(headerName, RandomStrings.randomAsciiLettersOfLengthBetween(random - , 3, 10)); + headers[i] = new BasicHeader(headerName, randomAsciiLettersOfLengthBetween(3, 10)); } return headers; } diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTests.java index 76dbe2c3e..dc12c386a 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTests.java @@ -26,6 +26,7 @@ import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.reactor.IOReactorStatus; +import org.junit.jupiter.api.Test; import java.io.IOException; import java.net.URI; @@ -57,6 +58,7 @@ public class RestClientTests extends RestClientTestCase { + @Test public void testCloseIsIdempotent() throws IOException { List nodes = singletonList(new Node(new HttpHost("localhost", 9200))); CloseableHttpAsyncClient closeableHttpAsyncClient = mock(CloseableHttpAsyncClient.class); @@ -70,6 +72,7 @@ public void testCloseIsIdempotent() throws IOException { verify(closeableHttpAsyncClient, times(3)).close(); } + @Test public void testPerformAsyncWithUnsupportedMethod() throws Exception { final CountDownLatch latch = new CountDownLatch(1); try (Rest5Client restClient = createRestClient()) { @@ -95,6 +98,7 @@ public void onFailure(Exception exception) { } } + @Test public void testPerformAsyncWithWrongEndpoint() throws Exception { final CountDownLatch latch = new CountDownLatch(1); try (Rest5Client restClient = createRestClient()) { @@ -119,6 +123,7 @@ public void onFailure(Exception exception) { } } + @Test public void testBuildUriLeavesPathUntouched() { final Map emptyMap = Collections.emptyMap(); { @@ -157,6 +162,7 @@ public void testBuildUriLeavesPathUntouched() { } } + @Test public void testSetNodesWrongArguments() throws IOException { try (Rest5Client restClient = createRestClient()) { restClient.setNodes(null); @@ -185,6 +191,7 @@ public void testSetNodesWrongArguments() throws IOException { } } + @Test public void testSetNodesPreservesOrdering() throws Exception { try (Rest5Client restClient = createRestClient()) { List nodes = randomNodes(); @@ -202,6 +209,7 @@ private static List randomNodes() { return nodes; } + @Test public void testSetNodesDuplicatedHosts() throws Exception { try (Rest5Client restClient = createRestClient()) { int numNodes = randomIntBetween(1, 10); @@ -216,6 +224,7 @@ public void testSetNodesDuplicatedHosts() throws Exception { } } + @Test public void testSelectHosts() throws IOException { Node n1 = new Node(new HttpHost("1"), null, null, "1", null, null); Node n2 = new Node(new HttpHost("2"), null, null, "2", null, null); @@ -375,6 +384,7 @@ private static Rest5Client createRestClient() { , false, false, false); } + @Test public void testRoundRobin() throws IOException { int numNodes = randomIntBetween(2, 10); AuthCache authCache = new BasicAuthCache(); @@ -403,6 +413,7 @@ public void testRoundRobin() throws IOException { assertEquals(Integer.MIN_VALUE + 50, lastNodeIndex.get()); } + @Test public void testIsRunning() { List nodes = Collections.singletonList(new Node(new HttpHost("localhost", 9200))); CloseableHttpAsyncClient client = mock(CloseableHttpAsyncClient.class); diff --git a/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/test.crt b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/test.crt new file mode 100644 index 000000000..b5edfcfa3 --- /dev/null +++ b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/test.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEATCCAumgAwIBAgIEObhDZDANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJV +UzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxEDAOBgNVBAoT +B2VsYXN0aWMxDTALBgNVBAsTBHRlc3QxEjAQBgNVBAMTCXRlc3Qgbm9kZTAeFw0x +NzA3MTcxNjEyNTZaFw0yNzA3MTUxNjEyNTZaMGcxCzAJBgNVBAYTAlVTMQswCQYD +VQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHZWxhc3Rp +YzENMAsGA1UECxMEdGVzdDESMBAGA1UEAxMJdGVzdCBub2RlMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnXtuGIgAq6vWzUD34HXkYF+0u103hb8d1h35 +kjeuNApkUhS6x/VbuNp7TpWmprfDgG5w9TourHvyiqcQMDEWrBunS6rmKo1jK1Wm +le3qA3F2l9VIZSNeeYQgezmzuElEPPmBjN8XBByIWKYjZcGd5u7DiquPUh9QLIev +itgB2jfi9D8ewyvaSbVAQuQwyIaDN9L74wKyMC8EuzzAWNSDjgIhhwcR5qg17msa +ItyM44/3hik+ObIGpMlLSxQu2V1U9bOaq48JjQBLHVg1vzC9VzGuNdEb8haFnhJN +UrdESdHymbtBSUvy30iB+kHq5R8wQ4pC+WxChQnbA2GskuFrMQIDAQABo4G0MIGx +MIGPBgNVHREEgYcwgYSHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAGCCWxvY2FsaG9z +dIIVbG9jYWxob3N0LmxvY2FsZG9tYWluggpsb2NhbGhvc3Q0ghdsb2NhbGhvc3Q0 +LmxvY2FsZG9tYWluNIIKbG9jYWxob3N0NoIXbG9jYWxob3N0Ni5sb2NhbGRvbWFp +bjYwHQYDVR0OBBYEFFwNcqIKfGBCBGo9faQJ3TsHmp0SMA0GCSqGSIb3DQEBCwUA +A4IBAQBvUJTRjSOf/+vtyS3OokwRilg1ZGF3psg0DWhjH2ehIRfNibU1Y8FVQo3I +VU8LjcIUK1cN85z+AsYqLXo/C4qmJPydQ1tGpQL7uIrPD4h+Xh3tY6A2DKRJRQFO +w2LjswPidGufMztpPbXxLREqvkvn80VkDnc44UPxYfHvZFqYwYyxZccA5mm+BhYu +IerjfvgX+8zMWIQZOd+jRq8EaVTmVK2Azwwhc5ImWfc0DA3pmGPdECzE4N0VVoIJ +N8PCVltXXP3F7K3LoT6CLSiJ3c/IDVNoVS4pRV6R6Y4oIKD9T/T1kAgAvOrUGRWY +ejWQ41GdUmkmxrqCaMbVCO4s72BC +-----END CERTIFICATE----- diff --git a/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/test.der b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/test.der new file mode 100644 index 0000000000000000000000000000000000000000..454bfd286bd97937020cb8d1535c7cb3eec43557 GIT binary patch literal 1218 zcmV;z1U>sOf&{(-0RS)!1_>&LNQUrs4#*Aqyhl|0)hbn0G)eo7>EF? ztJcjx_uzHpU|+PmT{nfl9o8NBk~gk23S?3gy2tffxY~P8m8Pb*!+>sZ^*S!Bd-95> z5HK+otQ)6Gs^%(XizNwq*i zg`N^kQny4&(ejzQK}k#U-$;S_LF(lnFhhz$`D{Xk3EKlajxI^3zY*DMf42|U+NcycGN5Ii(&fd7Vo1LaD{Jj zk^&xUtM1`nB%&;_e1ejavA5F)$JNV-kx=7#3=1 zNR_IxrXGQvev4;>7K$A&AgJXrpFZ9tBu-XU3Uf%X^y(KqMsL0Z-C#fGDTJnM2BQ?+ zKE>d@a-CM0qU0BWzEYKKBGDEJ^dka+fdITy>*NbhtzpqD5?=qK)<@mW-;493$$ORU z8{^b}t5lA~o?5U70h1-GV?nHhZXY@>$0xT2_4l9h5S-b#TRao!cqSaPrDKxeqJOjo zml{5yQNEYHnnJMOUHUBmo4Q=cM1qpnio#8Uxx~|?($N?p><9S#EFe*7KU@iKo|^)J zfdGPA6Co{I{$ZaM#M7<2E=U`i@W9cZVz3Rl(n@%p zC!K#o3d*d6FqrbI!Bq4gl1aW28R!`EhPQJRp7x7Sbl81yUf$@cT zR|0{70Hk{CRiE_&-^6Tw?fk}J`EyuV91q}E=;#|V)sX2+oC7H>FyawDL5pH3YlGNf7Lm>kJ z5SLk)6U0@>%TGx)kQ3)MG&e9eG&eLeG%_`d66ZAnaZRCI`Z=VDQ3*K^7+D#Zn;7{S z44N3Zn3@9EiBm+{dKY&Mx?Dh3UI&DWy9-kNdy3Y1&zCVq0?3+gn8M zW^BmU&9hebbM`WL%SM>)H`p6)xX$#V^e3^_c|yKH+g&^_eww-4(bN0WeUHXpj<24| z8#s44{mgM{<-Ekjav*FHySkd1LILvkfpKRps}T$r5>2Z+690q z4;e5vapvSFC+1}27nd}N!kKztR!V*@FxfP5!G%ql#1U*{H6}=k%#akBAuBR7kOeu2 zk420{B!;(W5m!xu6HAtD?Gnzr*6g$93L!@ePE8)StWekcf6T@8>!Hn2u@bR@rlREmQe3 z*E!m4Dbw#AUFZ2b>f&VICND7KS>ox+=yy2j@n+^nCE4?htut-6e$*Az+UNcJvug@p zxy3{0kBJ}Or$o&-*t0S9IK#8deQaWSimx8m{Sg0s=1fG3q~-m^ZtGbxL!O1KZ8*=P zSUgEB^1BHS@5>phh28)F literal 0 HcmV?d00001 diff --git a/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/testks.jks b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/testks.jks new file mode 100644 index 0000000000000000000000000000000000000000..cd706db5e3834f4b44493530bca17697f32d8de2 GIT binary patch literal 2381 zcmcgt`9IYA8vlOB80%QF%P^K4yYI*ll4T;A?8cHMVh&T*Y{!}zYjfo2&U*Xwz`-tYJ4{loKmp6B&EKURON0ssIz4)Cv__YA&G z3_fNKX6Ang002DBTG4J7uREh5mJ7*;DV;dAlA=s5+KPl4wULQJdoL8~Pe7D3^*Cpn+O9sr03 zISo5KN{!m#CIL0)yz>t}H?Dji7ewQeMTpah_;lIM9lfx^{MI46EY=H2Gb87zSV!L9 zBNwGc)hcRNP-{ZbigjTAb+b#asOW1;eDvzR6aB?nZ0b51o)HL=(P6?em8T=Dtimf@ zkw!zNEH-cfeLsno#O=RbxSvAmmq_5eGP;=CTVxI0y~COhkJiND1UdLS2Ol7#CcE^d zL>{Nth-L14Z4j+X`yfibe=ag4rVlxJp#US7Q|y@QX^G~`3fl?pyl5Y^R8rIQWW4Id zQ{z=r`vr-qyIpkx)5AVH*xUo_`4Nx4b(N?wT{OYbRG2-rcbCh$ubPg4`&+@r5D zzPUX@zCiejz)?}CTe3&^u7rVdbjjY6C5l@V4|cw6NVPj+>;MVdCH6G z;*UbVqziZ{8{q|$yRDA6AbU?YM#cWH7~gF>>!8r(I*ID&@IdyK9Vh)mhm9(9QprF* zTcmmB5ofTGhE^wgc6e}~gaOj0+F~@7M8SRe&>AqUy`aoNh?gL%tOLG=Z`F!b~nE6fm|g zn~sp%GU*wT?a;|Lx{14y5rz@Zi*Ei`1^Asfnk+f1QoG!rBKWDm!N)n4tjm$w;#(Ms z*y4S9lR%xR>-qfN9B<|yeOK)-bH747=ZNpA3?IQ6RWFHIE8SgO`efbu{fcV~?x(fP{fMBSHJgUi@HE~B!hGqp zOO=HE;j=bw>XQc_Lz$N7+B!oz5O}9z4>`!sl^^yX__= zt-G_fDHBHnrXd?sZVgtfT~YRfOVPRZGOfh@@i4+lcQw=8yf9tQpirKyrJ1>K}mXUYH+n6o>({TY+BG7mQ%>U&6=* z!|7mnA?}kO1}>zLcYv3_Gsz2WMIr`aIF6U>vChoJK=g3-^C!7rkPyp>!omgjC;Itg z&OjU|l#Yw(grdE?U5St|9}=SqsbW+yDi|fK%5^@Z(h0@>hyMQ(p@3qii*S4+=qMmN z08v0@7zG4@>`*WMc%Za&v|oF7I$+-EMoqJWYD_z76t$P8`b?SG)ttMjYum12Jk&V7 zsHmP6>E*Mnu22@bNiF7pFuY}Fi}583GKns-grfA-Wjf!$M+>b?2e(*eKQE{W(|_ zqzG@m_}u1gR1!=yj)8OGH|*MNL9vesbIH50(wEe#5QVStcy5LF4wl>1k4ux85&=BQ z2HOs`T4SDJht6*D#{Bb)k$L@P!=cU0W*tNP=9B^XyUy|_5eP@s-Sg0mVfsMlT$VO- z8v~;Q0kD8v1Cc8sa`JH>QJipc97K+egWo;Aws9QCLw5Rs6ebUE7iSN5Z$Ezu&)-nt zFXZa&c|0~0=D%fS3g7?mX^-+LlgcTR%4w4dggQxx4bBVawnyH{XAX1Hh2PQ)FJzj~ zV0fH;=5%9^r~A0EAmDBKU?@>M=V)d1wfsQ-HBPDx*3~(vs9PE7?jqurC(74^6*Ip;MfXd)H`2nLpdhX1nEE+M3Y~js@@+eX5olR{E5MTxf=!t-%Qh!Tb~aJm hJ4YDTZ?{bYj5Ah4y>@bn_^A>sIjjET5{u3>b{aXM4 literal 0 HcmV?d00001 From b20a8f3f1895c24ce470caff28e86a35090e9c95 Mon Sep 17 00:00:00 2001 From: Sylvain Wallez Date: Thu, 27 Mar 2025 16:52:19 +0100 Subject: [PATCH 19/38] Randomize client implementation, remove cloud-id on Rest5, add tests for overloaded methods --- .../transport/ElasticsearchTransportBase.java | 30 ++++--- .../elastic/clients/transport/Transport.java | 21 +++++ .../rest5_client/Rest5ClientTransport.java | 20 +++++ .../rest5_client/low_level/Rest5Client.java | 48 ++---------- .../rest_client/RestClientHttpClient.java | 2 +- .../rest_client/RestClientTransport.java | 21 +++++ .../documentation/DocTestsTransport.java | 2 +- .../ElasticsearchTestClient.java | 28 ++++--- .../ElasticsearchTestServer.java | 12 +++ .../esql/EsqlAdapterEndToEndTest.java | 56 +++++++------ .../elasticsearch/model/OverloadsTest.java | 78 +++++++++++++++++++ .../clients/transport/RequestOptionsTest.java | 48 +++++------- .../clients/transport/TransportTest.java | 73 +++++++---------- .../clients/transport/TransportUtilsTest.java | 28 +------ .../endpoints/BinaryEndpointTest.java | 12 +-- .../OpenTelemetryForElasticsearchTest.java | 27 +++---- .../low_level/RestClientBuilderTests.java | 68 ---------------- 17 files changed, 293 insertions(+), 281 deletions(-) create mode 100644 java-client/src/test/java/co/elastic/clients/elasticsearch/model/OverloadsTest.java diff --git a/java-client/src/main/java/co/elastic/clients/transport/ElasticsearchTransportBase.java b/java-client/src/main/java/co/elastic/clients/transport/ElasticsearchTransportBase.java index 26237501e..8d561f506 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/ElasticsearchTransportBase.java +++ b/java-client/src/main/java/co/elastic/clients/transport/ElasticsearchTransportBase.java @@ -77,15 +77,9 @@ public abstract class ElasticsearchTransportBase implements ElasticsearchTranspo } } - private final TransportHttpClient httpClient; - private final Instrumentation instrumentation; - - @Override - public void close() throws IOException { - httpClient.close(); - } - - private final JsonpMapper mapper; + protected final TransportHttpClient httpClient; + protected final Instrumentation instrumentation; + protected final JsonpMapper mapper; protected final TransportOptions transportOptions; public ElasticsearchTransportBase(TransportHttpClient httpClient, TransportOptions options, @@ -113,6 +107,20 @@ public ElasticsearchTransportBase( this.instrumentation = instrumentation; } + /** INTERNAL, used only for tests. */ + protected ElasticsearchTransportBase cloneWith( + @Nullable TransportOptions options, + @Nullable JsonpMapper mapper, + @Nullable Instrumentation instrumentation + ) { + throw new UnsupportedOperationException(); + } + + @Override + public void close() throws IOException { + httpClient.close(); + } + @Override public final JsonpMapper jsonpMapper() { return mapper; @@ -123,6 +131,10 @@ public final TransportOptions options() { return transportOptions; } + public TransportHttpClient httpClient() { + return httpClient; + } + @Override public final ResponseT performRequest( RequestT request, diff --git a/java-client/src/main/java/co/elastic/clients/transport/Transport.java b/java-client/src/main/java/co/elastic/clients/transport/Transport.java index e08263379..7a0a19e47 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/Transport.java +++ b/java-client/src/main/java/co/elastic/clients/transport/Transport.java @@ -26,6 +26,7 @@ import java.io.Closeable; import java.io.IOException; import java.util.concurrent.CompletableFuture; +import java.util.function.Function; /** * The transport layer that allows {@link ApiClient}s to send requests. @@ -51,4 +52,24 @@ CompletableFuture performRequestAsync( * {@link #performRequestAsync(Object, Endpoint, TransportOptions)}; */ TransportOptions options(); + + /** + * Clone this transport with new options. + * + * @throws UnsupportedOperationException + */ + default Transport withOptions(@Nullable TransportOptions options) { + throw new UnsupportedOperationException(); + } + + /** + * Clone this transport with additional options. The lambda expression is provided an options builder + * initialized with the transport's current options. + * + * @param fn a lambda expression that takes the current options as input + * @throws UnsupportedOperationException + */ + default Transport withOptions(Function fn) { + return withOptions(fn.apply(options().toBuilder()).build()); + } } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java index e30353d7f..72aa64602 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java @@ -21,9 +21,13 @@ import co.elastic.clients.json.JsonpMapper; import co.elastic.clients.transport.ElasticsearchTransportBase; +import co.elastic.clients.transport.Transport; +import co.elastic.clients.transport.TransportOptions; import co.elastic.clients.transport.instrumentation.Instrumentation; import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; +import javax.annotation.Nullable; + public class Rest5ClientTransport extends ElasticsearchTransportBase { private final Rest5Client restClient; @@ -45,4 +49,20 @@ public Rest5ClientTransport(Rest5Client restClient, JsonpMapper jsonpMapper, Res public Rest5Client restClient() { return this.restClient; } + + @Override + public Transport withOptions(@Nullable TransportOptions options) { + return new Rest5ClientTransport(restClient, mapper, Rest5ClientOptions.of(options), instrumentation); + } + + /** INTERNAL, used only for tests. */ + @Override + protected ElasticsearchTransportBase cloneWith(TransportOptions options, JsonpMapper mapper, Instrumentation instrumentation) { + return new Rest5ClientTransport( + restClient, + mapper != null ? mapper : this.mapper, + Rest5ClientOptions.of(options != null ? options : this.transportOptions), + instrumentation != null ? instrumentation : this.instrumentation + ); + } } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java index 1843ae004..69b47b863 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java @@ -154,50 +154,14 @@ public class Rest5Client implements Closeable { /** * Returns a new {@link Rest5ClientBuilder} to help with {@link Rest5Client} creation. - * Creates a new builder instance and sets the nodes that the client will send requests to. - * - * @param cloudId a valid elastic cloud cloudId that will route to a cluster. The cloudId is located in - * the user console https://cloud.elastic.co and will resemble a string like the following - * optionalHumanReadableName:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRlbGFzdGljc2VhcmNoJGtpYmFuYQ== + * Creates a new builder instance and sets the hosts that the client will send requests to. */ - public static Rest5ClientBuilder builder(String cloudId) { - // there is an optional first portion of the cloudId that is a human readable string, but it is not - // used. - if (cloudId.contains(":")) { - if (cloudId.indexOf(':') == cloudId.length() - 1) { - throw new IllegalStateException("cloudId " + cloudId + " must begin with a human readable " + - "identifier followed by a colon"); - } - cloudId = cloudId.substring(cloudId.indexOf(':') + 1); - } - - String decoded = new String(Base64.getDecoder().decode(cloudId), UTF_8); - // once decoded the parts are separated by a $ character. - // they are respectively domain name and optional port, elasticsearch id, kibana id - String[] decodedParts = decoded.split("\\$"); - if (decodedParts.length != 3) { - throw new IllegalStateException("cloudId " + cloudId + " did not decode to a cluster identifier" + - " correctly"); - } - - // domain name and optional port - String[] domainAndMaybePort = decodedParts[0].split(":", 2); - String domain = domainAndMaybePort[0]; - int port; - - if (domainAndMaybePort.length == 2) { - try { - port = Integer.parseInt(domainAndMaybePort[1]); - } catch (NumberFormatException nfe) { - throw new IllegalStateException("cloudId " + cloudId + " does not contain a valid port " + - "number"); - } - } else { - port = 443; + public static Rest5ClientBuilder builder(URI... uris) { + if (uris == null || uris.length == 0) { + throw new IllegalArgumentException("uris must not be null nor empty"); } - - String url = decodedParts[1] + "." + domain; - return builder(new HttpHost("https", url, port)); + List nodes = Arrays.stream(uris).map(u -> new Node(HttpHost.create(u))).toList(); + return new Rest5ClientBuilder(nodes); } /** diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java index a3afede4a..85b92c107 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java @@ -227,7 +227,7 @@ public int size() { @Override public BinaryData body() throws IOException { HttpEntity entity = restResponse.getEntity(); - return entity == null ? null : new HttpEntityBinaryData(restResponse.getEntity()); + return entity == null ? null : new HttpEntityBinaryData(entity); } @Nullable diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java index dbadfbe1a..cd7357e9c 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java @@ -21,9 +21,13 @@ import co.elastic.clients.json.JsonpMapper; import co.elastic.clients.transport.ElasticsearchTransportBase; +import co.elastic.clients.transport.Transport; +import co.elastic.clients.transport.TransportOptions; import co.elastic.clients.transport.instrumentation.Instrumentation; import org.elasticsearch.client.RestClient; +import javax.annotation.Nullable; + public class RestClientTransport extends ElasticsearchTransportBase { private final RestClient restClient; @@ -45,4 +49,21 @@ public RestClientTransport(RestClient restClient, JsonpMapper jsonpMapper, RestC public RestClient restClient() { return this.restClient; } + + + @Override + public Transport withOptions(@Nullable TransportOptions options) { + return new RestClientTransport(restClient, mapper, RestClientOptions.of(options), instrumentation); + } + + /** INTERNAL, used only for tests. */ + @Override + protected ElasticsearchTransportBase cloneWith(TransportOptions options, JsonpMapper mapper, Instrumentation instrumentation) { + return new RestClientTransport( + restClient, + mapper != null ? mapper : this.mapper, + RestClientOptions.of(options != null ? options : this.transportOptions), + instrumentation != null ? instrumentation : this.instrumentation + ); + } } diff --git a/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java b/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java index b8a71eed2..01a616c04 100644 --- a/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java +++ b/java-client/src/test/java/co/elastic/clients/documentation/DocTestsTransport.java @@ -37,7 +37,7 @@ import java.util.function.Function; /** - * A transport implementation that always returns the same result. Used for doc snippets where we can to check + * A transport implementation that always returns the same result. Used for doc snippets where we can check * compilation and do very simple tests. */ public class DocTestsTransport implements ElasticsearchTransport { diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestClient.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestClient.java index 2a3c9ca42..206a1e35c 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestClient.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestClient.java @@ -24,6 +24,7 @@ import co.elastic.clients.transport.rest5_client.Rest5ClientTransport; import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; import co.elastic.clients.transport.rest_client.RestClientTransport; +import com.sun.net.httpserver.HttpServer; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.message.BasicHeader; import org.apache.http.HttpHost; @@ -35,26 +36,35 @@ import javax.annotation.Nullable; import javax.net.ssl.SSLContext; import java.net.URI; +import java.security.SecureRandom; import java.util.Base64; -import java.util.Random; public class ElasticsearchTestClient { + protected enum ClientImpl { Rest4, Rest5 } + // Same value for all tests in a test run - private static final int RAND = new Random().nextInt(100); + private static final ClientImpl flavor; + static { + var flavors = ClientImpl.values(); + flavor = flavors[new SecureRandom().nextInt(flavors.length)]; + } private static JsonpMapper mapper(JsonpMapper mapper) { return mapper != null ? mapper : new JsonbJsonpMapper(); } public static ElasticsearchClient createClient(String url, @Nullable JsonpMapper mapper, @Nullable SSLContext sslContext) { - if(RAND % 2 == 0) { - System.out.println("Using a Rest4 client"); - return createRest4Client(url, mapper, sslContext); - } else { - System.out.println("Using a Rest5 client"); - return createRest5Client(url, mapper, sslContext); - } + System.out.println("Using a " + flavor + " client"); + return switch (flavor) { + case Rest4 -> createRest4Client(url, mapper, sslContext); + case Rest5 -> createRest5Client(url, mapper, sslContext); + }; + } + + public static ElasticsearchClient createClient(HttpServer server, @Nullable JsonpMapper mapper) { + var address = server.getAddress(); + return createClient("http://" + address.getHostString() + ":" + address.getPort(), mapper, null); } public static ElasticsearchClient createRest4Client(String url, @Nullable JsonpMapper mapper, @Nullable SSLContext sslContext) { diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java index ae16e105c..52c3f82e6 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java @@ -48,6 +48,8 @@ public class ElasticsearchTestServer implements AutoCloseable { private final String[] plugins; private volatile ElasticsearchContainer container; + private String url; + private SSLContext sslContext; private ElasticsearchClient client; private static ElasticsearchTestServer global; @@ -95,6 +97,8 @@ public ElasticsearchTestServer(String... plugins) { private static final int RAND = new Random().nextInt(100); protected void setup(String url, SSLContext sslContext) { + this.url = url; + this.sslContext = sslContext; this.client = ElasticsearchTestClient.createClient(url, null, sslContext); } @@ -244,6 +248,14 @@ public ElasticsearchContainer container() { return this.container; } + public String url() { + return url; + } + + public SSLContext sslContext() { + return sslContext; + } + public ElasticsearchClient client() { return client; } diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java index 232e4e238..c374e51bc 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/esql/EsqlAdapterEndToEndTest.java @@ -21,26 +21,23 @@ import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.ElasticsearchTestClient; import co.elastic.clients.elasticsearch.ElasticsearchTestServer; import co.elastic.clients.elasticsearch._helpers.esql.jdbc.ResultSetEsqlAdapter; import co.elastic.clients.elasticsearch._helpers.esql.objects.ObjectsEsqlAdapter; import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.rest5_client.Rest5ClientTransport; -import co.elastic.clients.transport.rest5_client.low_level.Request; -import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.ElasticsearchTransportBase; +import co.elastic.clients.transport.http.TransportHttpClient; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; -import org.apache.commons.io.IOUtils; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.entity.ContentType; -import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.sql.ResultSet; import java.sql.Timestamp; import java.time.ZoneId; @@ -48,6 +45,7 @@ import java.util.Arrays; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.concurrent.CompletableFuture; public class EsqlAdapterEndToEndTest extends Assertions { @@ -56,33 +54,31 @@ public class EsqlAdapterEndToEndTest extends Assertions { @BeforeAll public static void setup() throws Exception { - ElasticsearchClient global = ElasticsearchTestServer.global().client(); - if (global._transport() instanceof RestClientTransport) { - RestClient restClient = ((RestClientTransport) global._transport()).restClient(); - esClient = new ElasticsearchClient(new RestClientTransport(restClient, new JacksonJsonpMapper())); + var server = ElasticsearchTestServer.global(); + esClient = ElasticsearchTestClient.createClient(server.url(), new JacksonJsonpMapper(), server.sslContext()); - esClient.indices().delete(d -> d.index("employees").ignoreUnavailable(true)); + // Make sure index is empty + esClient.indices().delete(d -> d.index("employees").ignoreUnavailable(true)); - org.elasticsearch.client.Request request = new org.elasticsearch.client.Request("POST", "/employees/_bulk?refresh=true"); - - InputStream resourceAsStream = EsqlAdapterTest.class.getResourceAsStream("employees.ndjson"); - byte[] bytes = IOUtils.toByteArray(resourceAsStream); - request.setEntity(new ByteArrayEntity(bytes, ContentType.APPLICATION_JSON)); - - restClient.performRequest(request); - } else if (global._transport() instanceof Rest5ClientTransport) { - Rest5Client restClient = ((Rest5ClientTransport) global._transport()).restClient(); - esClient = new ElasticsearchClient(new Rest5ClientTransport(restClient, new JacksonJsonpMapper())); - - esClient.indices().delete(d -> d.index("employees").ignoreUnavailable(true)); + // Upload bulk data + TransportHttpClient httpClient = ((ElasticsearchTransportBase)esClient._transport()).httpClient(); + ByteBuffer body; + try (InputStream data = EsqlAdapterTest.class.getResourceAsStream("employees.ndjson")) { + body = ByteBuffer.wrap(data.readAllBytes()); + } - Request request = new Request("POST", "/employees/_bulk?refresh=true"); + TransportHttpClient.Request request = new TransportHttpClient.Request( + "POST", "/employees/_bulk", + Map.of("refresh", "true"), + Map.of("Content-Type", "application/vnd.elasticsearch+json; compatible-with=9" /*, "Accept", "application/json"*/), + List.of(body) + ); - InputStream resourceAsStream = EsqlAdapterTest.class.getResourceAsStream("employees.ndjson"); - byte[] bytes = IOUtils.toByteArray(resourceAsStream); - request.setEntity(new org.apache.hc.core5.http.io.entity.ByteArrayEntity(bytes, org.apache.hc.core5.http.ContentType.APPLICATION_JSON)); + var response = httpClient.performRequest("bulk", null, request, null); - restClient.performRequest(request); + if (response.statusCode() != 200) { + fail("Unexpected response code: " + response.statusCode() + " - " + + new String(response.body().asByteBuffer().array(), StandardCharsets.UTF_8)); } } diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/OverloadsTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/OverloadsTest.java new file mode 100644 index 000000000..573593ac1 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/OverloadsTest.java @@ -0,0 +1,78 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.model; + +import co.elastic.clients.elasticsearch._types.FieldSort; +import co.elastic.clients.elasticsearch._types.FieldValue; +import co.elastic.clients.elasticsearch._types.aggregations.TopMetrics; +import co.elastic.clients.elasticsearch._types.query_dsl.MatchAllQuery; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.testkit.ModelTestCase; +import org.junit.jupiter.api.Test; + +import java.util.List; + +public class OverloadsTest extends ModelTestCase { + + @Test + public void variantOverloads() { + // A variant can be used when a union or container is expected + MatchAllQuery maq = MatchAllQuery.of(b -> b); + + SearchRequest sr = SearchRequest.of(b -> b.query(maq)); + assertEquals(maq, sr.query().matchAll()); + } + + @Test + public void fieldValueOverloads() { + FieldSort fs = FieldSort.of(b -> b.field("field").missing(42)); + + assertTrue(fs.missing().isLong()); + assertEquals(42, fs.missing().longValue()); + } + + @Test + public void dictionaryAndArrayOverloads() { + TopMetrics tm = TopMetrics.of(b -> b + .metrics("foo", 13.37) + .sort("bar") // Required property + ); + + assertTrue(tm.metrics().get("foo").isDouble()); + assertEquals(13.37, tm.metrics().get("foo").doubleValue()); + } + + @Test + public void arrayOverloads() { + TopMetrics tm = TopMetrics.of(b -> b + .metrics("foo", 0) // Required property + .sort("bar") + .sort(42) + ); + + List sort = tm.sort(); + + assertTrue(sort.get(0).isString()); + assertEquals("bar", sort.get(0).stringValue()); + + assertTrue(sort.get(1).isLong()); + assertEquals(42, sort.get(1).longValue()); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java b/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java index 85eef55d7..4ad221c1e 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/RequestOptionsTest.java @@ -20,14 +20,10 @@ package co.elastic.clients.transport; import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.elasticsearch.ElasticsearchTestClient; import com.sun.net.httpserver.HttpServer; -import org.apache.http.HttpHost; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; -import org.elasticsearch.client.ResponseException; -import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -49,7 +45,7 @@ public class RequestOptionsTest extends Assertions { private static HttpServer httpServer; - private static RestClient restClient; // TODO: pick a random implementation + private static ElasticsearchClient client; @BeforeEach public void classSetup() throws IOException { @@ -62,9 +58,10 @@ public void classSetup() throws IOException { } // Call to info() - // Send back all request headers with a 418 that will cause an exception where we can access the LLRC response + // Send back all request headers with a non-json content type that will cause an exception where we can access the raw response + ex.getResponseHeaders().put("Content-Type", List.of("application/octet-stream")); ex.getResponseHeaders().putAll(ex.getRequestHeaders()); - ex.sendResponseHeaders(418, 0); + ex.sendResponseHeaders(200, 0); OutputStreamWriter out = new OutputStreamWriter(ex.getResponseBody(), StandardCharsets.UTF_8); for (Map.Entry> header: ex.getRequestHeaders().entrySet()) { out.write("header-"); @@ -84,29 +81,32 @@ public void classSetup() throws IOException { }); httpServer.start(); - InetSocketAddress address = httpServer.getAddress(); - restClient = RestClient.builder(new HttpHost(address.getHostString(), address.getPort(), "http")) - .build(); + client = ElasticsearchTestClient.createClient(httpServer, null); + + // We need to buffer the response body on exception to retrieve it. + var transport = (ElasticsearchTransport) client._transport() + .withOptions(opt -> opt.keepResponseBodyOnException(true)); + client = new ElasticsearchClient(transport, null); } @AfterEach public void classTearDown() throws IOException { httpServer.stop(0); - restClient.close(); + httpServer = null; + client.close(); + client = null; } private Properties getProps(ElasticsearchClient client) throws IOException { - ResponseException ex = assertThrows(ResponseException.class, client::info); - assertEquals(418, ex.getResponse().getStatusLine().getStatusCode()); + TransportException ex = assertThrows(TransportException.class, client::info); Properties result = new Properties(); - result.load(ex.getResponse().getEntity().getContent()); + result.load(ex.response().body().asInputStream()); return result; } @Test public void testNonNullClientOptions() { - final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); - final ElasticsearchClient client = new ElasticsearchClient(trsp); + final ElasticsearchTransport trsp = client._transport(); assertNotNull(client._transportOptions()); assertSame(trsp.options(), client._transportOptions()); @@ -114,9 +114,6 @@ public void testNonNullClientOptions() { @Test public void testDefaultHeaders() throws IOException { - final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); - final ElasticsearchClient client = new ElasticsearchClient(trsp); - Properties props = getProps(client); assertTrue(props.getProperty("header-user-agent").startsWith("elastic-java/" + Version.VERSION.toString())); @@ -130,21 +127,21 @@ public void testDefaultHeaders() throws IOException { @Test public void testClientHeader() throws IOException { - final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); - final ElasticsearchClient client = new ElasticsearchClient(trsp) + final ElasticsearchClient newClient = client .withTransportOptions(b -> b .addHeader("X-Foo", "Bar") .addHeader("uSer-agEnt", "MegaClient/1.2.3") ); - Properties props = getProps(client); + Properties props = getProps(newClient); assertEquals("Bar", props.getProperty("header-x-foo")); assertEquals("MegaClient/1.2.3", props.getProperty("header-user-agent")); } @Test public void testQueryParameter() throws IOException { - final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); + final ElasticsearchTransport trsp = client._transport(); + final ElasticsearchClient client = new ElasticsearchClient(trsp) .withTransportOptions(trsp.options().with( b -> b.setParameter("format", "pretty") @@ -157,9 +154,6 @@ public void testQueryParameter() throws IOException { @Test public void testMissingProductHeader() { - final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); - final ElasticsearchClient client = new ElasticsearchClient(trsp); - final TransportException ex = assertThrows(TransportException.class, client::ping); assertTrue(ex.getMessage().contains("Missing [X-Elastic-Product] header")); } diff --git a/java-client/src/test/java/co/elastic/clients/transport/TransportTest.java b/java-client/src/test/java/co/elastic/clients/transport/TransportTest.java index d25466bbd..d4f40f080 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/TransportTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/TransportTest.java @@ -20,16 +20,12 @@ package co.elastic.clients.transport; import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.elasticsearch.ElasticsearchTestClient; +import co.elastic.clients.json.JsonpMapper; import co.elastic.clients.transport.http.RepeatableBodyResponse; -import co.elastic.clients.transport.rest_client.RestClientOptions; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.instrumentation.Instrumentation; import co.elastic.clients.util.BinaryData; import com.sun.net.httpserver.HttpServer; -import org.apache.http.HttpHost; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -45,6 +41,16 @@ public class TransportTest extends Assertions { + // Make the protected method publicly visible in tests + public static ElasticsearchTransportBase cloneTransportWith( + ElasticsearchTransportBase transport, + TransportOptions options, + JsonpMapper mapper, + Instrumentation instrumentation + ) { + return transport.cloneWith(options, mapper, instrumentation); + } + @Test public void testXMLResponse() throws Exception { HttpServer httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), @@ -60,14 +66,8 @@ public void testXMLResponse() throws Exception { }); httpServer.start(); - InetSocketAddress address = httpServer.getAddress(); - RestClient restClient = RestClient - .builder(new HttpHost(address.getHostString(), address.getPort(), "http")) - .build(); - - ElasticsearchClient esClient = new ElasticsearchClient(new RestClientTransport(restClient, - new JacksonJsonpMapper())); + ElasticsearchClient esClient = ElasticsearchTestClient.createClient(httpServer, null); TransportException ex = Assertions.assertThrows( TransportException.class, @@ -78,13 +78,8 @@ public void testXMLResponse() throws Exception { assertEquals(401, ex.statusCode()); assertEquals("es/cat.indices", ex.endpointId()); - - // Original response is transport-dependent - Response restClientResponse = (Response) ex.response().originalResponse(); - assertEquals(401, restClientResponse.getStatusLine().getStatusCode()); } - @Test public void testOriginalJsonBodyRetrievalException() throws Exception { HttpServer httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), @@ -105,13 +100,7 @@ public void testOriginalJsonBodyRetrievalException() throws Exception { httpServer.start(); InetSocketAddress address = httpServer.getAddress(); - RestClient restClient = RestClient - .builder(new HttpHost(address.getHostString(), address.getPort(), "http")) - .build(); - - // no transport options, response is not RepeatableBodyResponse, original body cannot be retrieved - ElasticsearchClient esClient = new ElasticsearchClient(new RestClientTransport(restClient, - new JacksonJsonpMapper())); + var esClient = ElasticsearchTestClient.createClient(httpServer, null); TransportException ex = Assertions.assertThrows( TransportException.class, @@ -122,12 +111,8 @@ public void testOriginalJsonBodyRetrievalException() throws Exception { assertNotEquals(RepeatableBodyResponse.class, ex.response().getClass()); // setting transport option - RestClientOptions options = new RestClientOptions(RequestOptions.DEFAULT, true); - - ElasticsearchTransport transport = new RestClientTransport( - restClient, new JacksonJsonpMapper(), options); - - ElasticsearchClient esClientOptions = new ElasticsearchClient(transport); + var transport = (ElasticsearchTransport) esClient._transport().withOptions(o -> o.keepResponseBodyOnException(true)); + ElasticsearchClient esClientOptions = new ElasticsearchClient(transport, null); ex = Assertions.assertThrows( TransportException.class, @@ -137,18 +122,18 @@ public void testOriginalJsonBodyRetrievalException() throws Exception { httpServer.stop(0); assertEquals(200, ex.statusCode()); - assertEquals(RepeatableBodyResponse.class, ex.response().getClass()); - - try (RepeatableBodyResponse repeatableResponse = (RepeatableBodyResponse) ex.response()){ - BinaryData body = repeatableResponse.body(); - StringBuilder sb = new StringBuilder(); - BufferedReader br = new BufferedReader(new InputStreamReader(body.asInputStream())); - String read; - - while ((read = br.readLine()) != null) { - sb.append(read); - } - br.close(); + + try (var response = ex.response()){ + BinaryData body = response.body(); + assertTrue(body.isRepeatable()); + StringBuilder sb = new StringBuilder(); + BufferedReader br = new BufferedReader(new InputStreamReader(body.asInputStream())); + String read; + + while ((read = br.readLine()) != null) { + sb.append(read); + } + br.close(); assertEquals("definitely not json",sb.toString()); } } diff --git a/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java b/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java index 9b0ee3081..520d6a91a 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java @@ -19,18 +19,10 @@ package co.elastic.clients.transport; -import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.ElasticsearchTestClient; import co.elastic.clients.elasticsearch.ElasticsearchTestServer; -import co.elastic.clients.json.SimpleJsonpMapper; -import co.elastic.clients.transport.rest_client.RestClientTransport; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import org.testcontainers.elasticsearch.ElasticsearchContainer; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLHandshakeException; @@ -86,22 +78,8 @@ public void testCaCertificate() throws Exception { } private void checkConnection(SSLContext sslContext) throws Exception { - ElasticsearchContainer container = ElasticsearchTestServer.global().container(); - - BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); - credsProv.setCredentials( - AuthScope.ANY, new UsernamePasswordCredentials("elastic", "changeme") - ); - - RestClient restClient = RestClient.builder(new HttpHost("localhost", container.getMappedPort(9200), "https")) - .setHttpClientConfigCallback(c -> c - .setSSLContext(sslContext) - .setDefaultCredentialsProvider(credsProv) - ) - .build(); - - RestClientTransport transport = new RestClientTransport(restClient, SimpleJsonpMapper.INSTANCE); - ElasticsearchClient esClient = new ElasticsearchClient(transport); + var server = ElasticsearchTestServer.global(); + var esClient = ElasticsearchTestClient.createClient(server.url(), null, sslContext); assertNotNull(esClient.info()); } diff --git a/java-client/src/test/java/co/elastic/clients/transport/endpoints/BinaryEndpointTest.java b/java-client/src/test/java/co/elastic/clients/transport/endpoints/BinaryEndpointTest.java index de4175b3c..e0adc7ed8 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/endpoints/BinaryEndpointTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/endpoints/BinaryEndpointTest.java @@ -20,15 +20,12 @@ package co.elastic.clients.transport.endpoints; import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.ElasticsearchTestClient; import co.elastic.clients.elasticsearch.ElasticsearchTestServer; import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.json.SimpleJsonpMapper; import co.elastic.clients.transport.TransportOptions; -import co.elastic.clients.transport.rest_client.RestClientTransport; import com.sun.net.httpserver.HttpServer; import org.apache.commons.io.IOUtils; -import org.apache.http.HttpHost; -import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -71,12 +68,7 @@ public static void cleanup() { @Test public void testMvtSearch() throws IOException { - RestClient llrc = RestClient.builder( - new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort(), "http") - ).build(); - - RestClientTransport transport = new RestClientTransport(llrc, new SimpleJsonpMapper()); - ElasticsearchClient esClient = new ElasticsearchClient(transport); + var esClient = ElasticsearchTestClient.createClient(httpServer, null); BinaryResponse resp = esClient.searchMvt(s -> s .index("foo") diff --git a/java-client/src/test/java/co/elastic/clients/transport/instrumentation/OpenTelemetryForElasticsearchTest.java b/java-client/src/test/java/co/elastic/clients/transport/instrumentation/OpenTelemetryForElasticsearchTest.java index f9435165d..66879470a 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/instrumentation/OpenTelemetryForElasticsearchTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/instrumentation/OpenTelemetryForElasticsearchTest.java @@ -21,11 +21,12 @@ import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.ElasticsearchTestClient; import co.elastic.clients.elasticsearch._types.query_dsl.Query; import co.elastic.clients.elasticsearch.core.SearchRequest; import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.rest_client.RestClientTransport; +import co.elastic.clients.transport.ElasticsearchTransportBase; +import co.elastic.clients.transport.TransportTest; import com.sun.net.httpserver.HttpServer; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.common.AttributeKey; @@ -39,8 +40,6 @@ import io.opentelemetry.sdk.trace.export.SpanExporter; import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; -import org.apache.http.HttpHost; -import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -110,8 +109,6 @@ public class OpenTelemetryForElasticsearchTest { private static HttpServer httpServer; private static MockSpanExporter spanExporter; private static OpenTelemetry openTelemetry; - private static RestClient restClient; - private static RestClientTransport transport; private static ElasticsearchClient client; private static ElasticsearchAsyncClient asyncClient; @@ -125,16 +122,15 @@ public static void setup() throws IOException { @AfterAll public static void cleanUp() throws IOException { httpServer.stop(0); - transport.close(); + client.close(); } private static void setupClient() { - restClient = - RestClient.builder(new HttpHost(httpServer.getAddress().getAddress(), httpServer.getAddress().getPort())).build(); Instrumentation instrumentation = new OpenTelemetryForElasticsearch(openTelemetry, false); - transport = new RestClientTransport(restClient, new JacksonJsonpMapper(), null, instrumentation); + var transport = (ElasticsearchTransportBase) ElasticsearchTestClient.createClient(httpServer, null)._transport(); + transport = TransportTest.cloneTransportWith(transport, null, null, instrumentation); client = new ElasticsearchClient(transport); asyncClient = new ElasticsearchAsyncClient(transport); @@ -195,10 +191,10 @@ public void testGetRequest() throws IOException, InterruptedException { Assertions.assertEquals("GET", span.getAttributes().get(AttributeKey.stringKey(HTTP_REQUEST_METHOD))); Assertions.assertEquals("elasticsearch", span.getAttributes().get(SemanticAttributes.DB_SYSTEM)); - String url = "http://" + httpServer.getAddress().getHostName() + ":" + httpServer.getAddress().getPort() + + String url = "http://" + httpServer.getAddress().getHostString() + ":" + httpServer.getAddress().getPort() + "/" + INDEX + "/_doc/" + DOC_ID + "?refresh=true"; Assertions.assertEquals(url, span.getAttributes().get(AttributeKey.stringKey(URL_FULL))); - Assertions.assertEquals(httpServer.getAddress().getHostName(), span.getAttributes().get(AttributeKey.stringKey(SERVER_ADDRESS))); + Assertions.assertEquals(httpServer.getAddress().getHostString(), span.getAttributes().get(AttributeKey.stringKey(SERVER_ADDRESS))); Assertions.assertEquals(httpServer.getAddress().getPort(), span.getAttributes().get(AttributeKey.longKey(SERVER_PORT))); // Path parts @@ -208,9 +204,10 @@ public void testGetRequest() throws IOException, InterruptedException { @Test public void testSearchRequest() throws IOException, InterruptedException { // A client that will capture requests - ElasticsearchClient client = new ElasticsearchClient(new RestClientTransport( - restClient, this.client._jsonpMapper(), null, new OpenTelemetryForElasticsearch(openTelemetry, true)) - ); + var transport = (ElasticsearchTransportBase) client._transport(); + transport = TransportTest.cloneTransportWith(transport, null, null, new OpenTelemetryForElasticsearch(openTelemetry, true)); + client = new ElasticsearchClient(transport); + SearchRequest req = SearchRequest.of(r -> r.index(INDEX).query(q -> q.term(t -> t.field("x").value("y")))); String queryAsString = JsonpUtils.toJsonString(req, client._jsonpMapper()); client.search(req, Object.class); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderTests.java index ad7a77043..02f826b12 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderTests.java @@ -25,16 +25,11 @@ import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.message.BasicHeader; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; import org.junit.jupiter.api.Test; import java.io.IOException; -import java.nio.charset.Charset; -import java.util.Base64; import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; @@ -156,69 +151,6 @@ public void testBuild() throws IOException { } } - @Test - public void testBuildCloudId() throws IOException { - String host = "us-east-1.aws.found.io"; - String esId = "elasticsearch"; - String kibanaId = "kibana"; - String toEncode = host + "$" + esId + "$" + kibanaId; - String encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(Charset.defaultCharset())); - assertNotNull(Rest5Client.builder(encodedId)); - assertNotNull(Rest5Client.builder("humanReadable:" + encodedId)); - - String badId = Base64.getEncoder().encodeToString("foo$bar".getBytes(Charset.defaultCharset())); - try { - Rest5Client.builder(badId); - fail("should have failed"); - } catch (IllegalStateException e) { - assertEquals("cloudId " + badId + " did not decode to a cluster identifier correctly", - e.getMessage()); - } - - try { - Rest5Client.builder(badId + ":"); - fail("should have failed"); - } catch (IllegalStateException e) { - assertEquals("cloudId " + badId + ": must begin with a human readable identifier followed by a " + - "colon", e.getMessage()); - } - - Rest5Client client = Rest5Client.builder(encodedId).build(); - assertThat(client.getNodes().size(), equalTo(1)); - assertThat(client.getNodes().get(0).getHost().getHostName(), equalTo(esId + "." + host)); - assertThat(client.getNodes().get(0).getHost().getPort(), equalTo(443)); - assertThat(client.getNodes().get(0).getHost().getSchemeName(), equalTo("https")); - client.close(); - } - - @Test - public void testBuildCloudIdWithPort() throws IOException { - String host = "us-east-1.aws.found.io"; - String esId = "elasticsearch"; - String kibanaId = "kibana"; - String port = "9443"; - String toEncode = host + ":" + port + "$" + esId + "$" + kibanaId; - String encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(Charset.defaultCharset())); - - Rest5Client client = Rest5Client.builder("humanReadable:" + encodedId).build(); - assertThat(client.getNodes().size(), equalTo(1)); - assertThat(client.getNodes().get(0).getHost().getPort(), equalTo(9443)); - assertThat(client.getNodes().get(0).getHost().getHostName(), equalTo(esId + "." + host)); - assertThat(client.getNodes().get(0).getHost().getSchemeName(), equalTo("https")); - client.close(); - - toEncode = host + ":" + "123:foo" + "$" + esId + "$" + kibanaId; - encodedId = Base64.getEncoder().encodeToString(toEncode.getBytes(Charset.defaultCharset())); - - try { - Rest5Client.builder("humanReadable:" + encodedId); - fail("should have failed"); - } catch (IllegalStateException e) { - assertEquals("cloudId " + encodedId + " does not contain a valid port number", e.getMessage()); - } - } - - @Test public void testSetPathPrefixNull() { try { Rest5Client.builder(new HttpHost("localhost", 9200)).setPathPrefix(null); From ff4cf79d79427f7ae7cecf0c7df3b094c856092b Mon Sep 17 00:00:00 2001 From: Sylvain Wallez Date: Fri, 28 Mar 2025 12:37:49 +0100 Subject: [PATCH 20/38] Refine client builder --- .../ElasticsearchAsyncClient.java | 12 + .../elasticsearch/ElasticsearchClient.java | 11 + .../builders/ElasticsearchClientBuilder.java | 132 --------- .../ElasticsearchClientBuilderBase.java | 269 ++++++++++++++++++ .../ElasticsearchClientBuilder.java | 131 --------- .../rest5_client/Rest5ClientOptions.java | 2 +- .../rest5_client/low_level/Rest5Client.java | 17 ++ .../rest_client/RestClientOptions.java | 2 +- .../getting_started/ConnectingTest.java | 92 ++---- .../getting_started/MigrateHlrcTest.java | 3 + .../_helpers/ClientBuildersTest.java | 32 +-- 11 files changed, 343 insertions(+), 360 deletions(-) delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilderBase.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/rest5_client/ElasticsearchClientBuilder.java diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java index 88474f4c1..6f0d47d03 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java @@ -20,6 +20,7 @@ package co.elastic.clients.elasticsearch; import co.elastic.clients.ApiClient; +import co.elastic.clients.elasticsearch._helpers.builders.ElasticsearchClientBuilderBase; import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch.async_search.ElasticsearchAsyncSearchAsyncClient; import co.elastic.clients.elasticsearch.autoscaling.ElasticsearchAutoscalingAsyncClient; @@ -178,6 +179,17 @@ * Client for the namespace. */ public class ElasticsearchAsyncClient extends ApiClient { + public static class Builder extends ElasticsearchClientBuilderBase { + @Override + public ElasticsearchAsyncClient build() { + return ElasticsearchClientBuilderBase.buildAsync(this); + } + } + + public static ElasticsearchAsyncClient of( + Function fn) { + return ElasticsearchClientBuilderBase.buildAsync(fn.apply(new ElasticsearchAsyncClient.Builder())); + } public ElasticsearchAsyncClient(ElasticsearchTransport transport) { super(transport, null); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java index 3543a59d7..7e6a441bc 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java @@ -20,6 +20,7 @@ package co.elastic.clients.elasticsearch; import co.elastic.clients.ApiClient; +import co.elastic.clients.elasticsearch._helpers.builders.ElasticsearchClientBuilderBase; import co.elastic.clients.elasticsearch._types.ElasticsearchException; import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch.async_search.ElasticsearchAsyncSearchClient; @@ -179,6 +180,16 @@ * Client for the namespace. */ public class ElasticsearchClient extends ApiClient { + public static class Builder extends ElasticsearchClientBuilderBase { + @Override + public ElasticsearchClient build() { + return ElasticsearchClientBuilderBase.buildSync(this); + } + } + + public static ElasticsearchClient of(Function fn) { + return ElasticsearchClientBuilderBase.buildSync(fn.apply(new ElasticsearchClient.Builder())); + } public ElasticsearchClient(ElasticsearchTransport transport) { super(transport, null); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java deleted file mode 100644 index e225828b1..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilder.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch._helpers.builders; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.rest_client.RestClientOptions; -import co.elastic.clients.transport.rest_client.RestClientTransport; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.json.JsonMapper; -import org.apache.http.Header; -import org.apache.http.HttpHost; -import org.apache.http.message.BasicHeader; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; - -import javax.net.ssl.SSLContext; -import java.net.URISyntaxException; -import java.security.NoSuchAlgorithmException; -import java.util.Base64; -import java.util.Optional; - -// TODO do we want separate builder subclasses to make sure that only 1 auth method has been provided? -public class ElasticsearchClientBuilder { - - private HttpHost host; - private String username; - private String password; - private String token; - private String apiKey; - private SSLContext sslContext; - private JsonpMapper mapper; - private RestClientOptions transportOptions; - - public ElasticsearchClientBuilder host(String url) throws URISyntaxException { - this.host = HttpHost.create(url); - return this; - } - - public ElasticsearchClientBuilder usernameAndPassword(String username, String password) { - this.username = username; - this.password = password; - return this; - } - - public ElasticsearchClientBuilder token(String token) { - this.token = token; - return this; - } - - public ElasticsearchClientBuilder apiKey(String apiKey) { - this.apiKey = apiKey; - return this; - } - - public ElasticsearchClientBuilder sslContext(SSLContext sslContext) { - this.sslContext = sslContext; - return this; - } - - public ElasticsearchClientBuilder jsonMapper(JsonpMapper mapper) { - this.mapper = mapper; - return this; - } - - public ElasticsearchClientBuilder transportOptions(RestClientOptions transportOptions) { - this.transportOptions = transportOptions; - return this; - } - - public ElasticsearchClient build() { - - // defaulting to localhost - if (this.host == null) { - this.host = HttpHost.create("http://localhost:9200"); - } - - RestClientBuilder restClientBuilder = RestClient.builder(host); - - if (this.username != null && this.password != null) { - var cred = Base64.getEncoder().encodeToString((username + ":" + password).getBytes()); - restClientBuilder.setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "Basic " + cred) - }); - } else if (this.apiKey != null) { - restClientBuilder.setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "ApiKey " + apiKey) - }); - } else if (this.token != null) { - restClientBuilder.setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "Bearer " + token) - }); - } - - restClientBuilder.setHttpClientConfigCallback(hc -> { - try { - return hc - .setSSLContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - } - ); - - if (this.mapper == null) { - ObjectMapper mapper = JsonMapper.builder().build(); - this.mapper = new JacksonJsonpMapper(mapper); - } - - RestClientTransport transport = new RestClientTransport(restClientBuilder.build(), mapper, - transportOptions); - return new ElasticsearchClient(transport); - } -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilderBase.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilderBase.java new file mode 100644 index 000000000..06e07b666 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilderBase.java @@ -0,0 +1,269 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch._helpers.builders; + +import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.DefaultTransportOptions; +import co.elastic.clients.transport.TransportOptions; +import co.elastic.clients.transport.instrumentation.Instrumentation; +import co.elastic.clients.transport.rest5_client.Rest5ClientOptions; +import co.elastic.clients.transport.rest5_client.Rest5ClientTransport; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; +import co.elastic.clients.transport.rest5_client.low_level.Rest5ClientBuilder; +import co.elastic.clients.transport.rest_client.RestClientOptions; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.message.BasicHeader; +import org.apache.http.HttpHost; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; + +import javax.net.ssl.SSLContext; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Base64; +import java.util.List; +import java.util.function.Function; + +/** + * Base builder class for Elasticsearch sync an async clients. + * + * @see ElasticsearchClient.Builder + * @see ElasticsearchAsyncClient.Builder + */ +public abstract class ElasticsearchClientBuilderBase { + + protected List hosts; + protected String username; + protected String password; + protected String token; + protected String apiKey; + protected SSLContext sslContext; + protected JsonpMapper mapper; + protected TransportOptions transportOptions; + protected Instrumentation instrumentation; + protected boolean useLegacyTransport = false; + + public abstract T build(); + + public ElasticsearchClientBuilderBase host(String url) { + try { + this.hosts = List.of(new URI(url)); + } catch (URISyntaxException e) { + // Avoid requiring a checked exception in the builder + throw new RuntimeException(e); + } + return this; + } + + public ElasticsearchClientBuilderBase host(URI url) { + this.hosts = List.of(url); + return this; + } + + public ElasticsearchClientBuilderBase hosts(List hosts) { + this.hosts = hosts; + return this; + } + + /** + * Set the username and password to use to connect to Elasticsearch. + */ + public ElasticsearchClientBuilderBase usernameAndPassword(String username, String password) { + checkNull(this.token, "token", "username/password"); + checkNull(this.apiKey, "API key", "username/password"); + this.username = username; + this.password = password; + return this; + } + + /** + * Set the bearer token to use to authenticate to Elasticsearch. + */ + public ElasticsearchClientBuilderBase token(String token) { + checkNull(this.apiKey, "API key", "token"); + checkNull(this.username, "username", "token"); + this.token = token; + return this; + } + + /** + * Set the API key to use to authenticate to Elasticsearch. + */ + public ElasticsearchClientBuilderBase apiKey(String apiKey) { + checkNull(this.token, "token", "API key"); + checkNull(this.username, "username", "API key"); + this.apiKey = apiKey; + return this; + } + + /** + * Set the SSL context. See {@link co.elastic.clients.transport.TransportUtils} to create it + * from certificate files or fingerprint. + */ + public ElasticsearchClientBuilderBase sslContext(SSLContext sslContext) { + this.sslContext = sslContext; + return this; + } + + /** + * Set the JSON mapper. + */ + public ElasticsearchClientBuilderBase jsonMapper(JsonpMapper mapper) { + this.mapper = mapper; + return this; + } + + public ElasticsearchClientBuilderBase instrumentation(Instrumentation instrumentation) { + this.instrumentation = instrumentation; + return this; + } + + public ElasticsearchClientBuilderBase transportOptions(TransportOptions transportOptions) { + this.transportOptions = transportOptions; + return this; + } + + /** + * Sets lower level transport options. This method adds options to the ones already set, if any. + */ + public ElasticsearchClientBuilderBase transportOptions(Function fn) { + var builder = this.transportOptions == null ? new DefaultTransportOptions.Builder() : transportOptions.toBuilder(); + this.transportOptions = fn.apply(builder).build(); + return this; + } + + /** + * Should we use the legacy http implementation based on Elasticsearch's Low Level Rest Client? + */ + public ElasticsearchClientBuilderBase useLegacyTransport(boolean useLegacyTransport) { + this.useLegacyTransport = useLegacyTransport; + return this; + } + + protected ElasticsearchClient doBuild() { + if (this.hosts == null || this.hosts.isEmpty()) { + throw new IllegalArgumentException("hosts is required"); + } + + return useLegacyTransport ? buildRest4() : buildRest5(); + } + + public static ElasticsearchClient buildSync(ElasticsearchClientBuilderBase builder) { + return builder.doBuild(); + } + + public static ElasticsearchAsyncClient buildAsync(ElasticsearchClientBuilderBase builder) { + ElasticsearchClient client = builder.doBuild(); + TransportOptions clientOptions = client._transportOptions(); + if (client._transport().options() == clientOptions) { + // No options defined at the client level + clientOptions = null; + } + return new ElasticsearchAsyncClient(client._transport(), clientOptions); + } + + private ElasticsearchClient buildRest5() { + + Rest5ClientBuilder restClientBuilder = Rest5Client.builder(hosts); + + if (this.username != null && this.password != null) { + var cred = Base64.getEncoder().encodeToString((username + ":" + password).getBytes()); + restClientBuilder.setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Basic " + cred) + }); + } else if (this.apiKey != null) { + restClientBuilder.setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "ApiKey " + apiKey) + }); + } else if (this.token != null) { + restClientBuilder.setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Bearer " + token) + }); + } + + if (this.sslContext != null) { + restClientBuilder.setSSLContext(this.sslContext); + } + + if (this.mapper == null) { + ObjectMapper mapper = JsonMapper.builder().build(); + this.mapper = new JacksonJsonpMapper(mapper); + } + + Rest5ClientTransport transport = new Rest5ClientTransport( + restClientBuilder.build(), + mapper, + Rest5ClientOptions.of(transportOptions), + instrumentation + ); + return new ElasticsearchClient(transport); + } + + private ElasticsearchClient buildRest4() { + + RestClientBuilder restClientBuilder = RestClient.builder(hosts.stream() + .map(h -> HttpHost.create(h.toString())).toArray(HttpHost[]::new) + ); + + if (this.username != null && this.password != null) { + var cred = Base64.getEncoder().encodeToString((username + ":" + password).getBytes()); + restClientBuilder.setDefaultHeaders(new org.apache.http.Header[]{ + new org.apache.http.message.BasicHeader("Authorization", "Basic " + cred) + }); + } else if (this.apiKey != null) { + restClientBuilder.setDefaultHeaders(new org.apache.http.Header[]{ + new org.apache.http.message.BasicHeader("Authorization", "ApiKey " + apiKey) + }); + } else if (this.token != null) { + restClientBuilder.setDefaultHeaders(new org.apache.http.Header[]{ + new org.apache.http.message.BasicHeader("Authorization", "Bearer " + token) + }); + } + + if (sslContext != null) { + restClientBuilder.setHttpClientConfigCallback(hc -> hc.setSSLContext(sslContext)); + } + + if (this.mapper == null) { + ObjectMapper mapper = JsonMapper.builder().build(); + this.mapper = new JacksonJsonpMapper(mapper); + } + + RestClientTransport transport = new RestClientTransport( + restClientBuilder.build(), + mapper, + RestClientOptions.of(transportOptions), + instrumentation + ); + return new ElasticsearchClient(transport); + } + + private void checkNull(Object value, String name, String other) { + if (value != null) { + throw new IllegalStateException("Cannot set both " + other + " and " + name + "."); + } + } +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/rest5_client/ElasticsearchClientBuilder.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/rest5_client/ElasticsearchClientBuilder.java deleted file mode 100644 index 04f25f3b7..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/rest5_client/ElasticsearchClientBuilder.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch._helpers.builders.rest5_client; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.rest5_client.Rest5ClientOptions; -import co.elastic.clients.transport.rest5_client.Rest5ClientTransport; -import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; -import co.elastic.clients.transport.rest5_client.low_level.Rest5ClientBuilder; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.json.JsonMapper; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.message.BasicHeader; - -import javax.net.ssl.SSLContext; -import java.net.URISyntaxException; -import java.security.NoSuchAlgorithmException; -import java.util.Base64; -import java.util.Optional; - -// TODO do we want separate builder subclasses to make sure that only 1 auth method has been provided? -public class ElasticsearchClientBuilder { - - private HttpHost host; - private String username; - private String password; - private String token; - private String apiKey; - private SSLContext sslContext; - private JsonpMapper mapper; - private Rest5ClientOptions transportOptions; - - public ElasticsearchClientBuilder host(String url) throws URISyntaxException { - this.host = HttpHost.create(url); - return this; - } - - public ElasticsearchClientBuilder usernameAndPassword(String username, String password) { - this.username = username; - this.password = password; - return this; - } - - public ElasticsearchClientBuilder token(String token) { - this.token = token; - return this; - } - - public ElasticsearchClientBuilder apiKey(String apiKey) { - this.apiKey = apiKey; - return this; - } - - public ElasticsearchClientBuilder sslContext(SSLContext sslContext) { - this.sslContext = sslContext; - return this; - } - - public ElasticsearchClientBuilder jsonMapper(JsonpMapper mapper) { - this.mapper = mapper; - return this; - } - - public ElasticsearchClientBuilder transportOptions(Rest5ClientOptions transportOptions) { - this.transportOptions = transportOptions; - return this; - } - - public ElasticsearchClient build() { - - // defaulting to localhost - if (this.host == null) { - try { - this.host = HttpHost.create("http://localhost:9200"); - } catch (URISyntaxException e) { - // can't throw - } - } - - Rest5ClientBuilder restClientBuilder = Rest5Client.builder(host); - - if (this.username != null && this.password != null) { - var cred = Base64.getEncoder().encodeToString((username + ":" + password).getBytes()); - restClientBuilder.setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "Basic " + cred) - }); - } else if (this.apiKey != null) { - restClientBuilder.setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "ApiKey " + apiKey) - }); - } else if (this.token != null) { - restClientBuilder.setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "Bearer " + token) - }); - } - - try { - restClientBuilder.setSSLContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - - if (this.mapper == null) { - ObjectMapper mapper = JsonMapper.builder().build(); - this.mapper = new JacksonJsonpMapper(mapper); - } - - Rest5ClientTransport transport = new Rest5ClientTransport(restClientBuilder.build(), mapper, transportOptions); - return new ElasticsearchClient(transport); - } -} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientOptions.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientOptions.java index 713357e03..0e553088a 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientOptions.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientOptions.java @@ -49,7 +49,7 @@ public class Rest5ClientOptions implements TransportOptions { @VisibleForTesting static final String USER_AGENT_VALUE = getUserAgent(); - static Rest5ClientOptions of(@Nullable TransportOptions options) { + public static Rest5ClientOptions of(@Nullable TransportOptions options) { if (options == null) { return initialOptions(); } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java index 69b47b863..12d904365 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java @@ -164,6 +164,23 @@ public static Rest5ClientBuilder builder(URI... uris) { return new Rest5ClientBuilder(nodes); } + /** + * Returns a new {@link Rest5ClientBuilder} to help with {@link Rest5Client} creation. + * Creates a new builder instance and sets the hosts that the client will send requests to. + */ + public static Rest5ClientBuilder builder(List uris) { + if (uris == null || uris.isEmpty()) { + throw new IllegalArgumentException("uris must not be null nor empty"); + } + List nodes = uris.stream().map(u -> { + if (!u.isAbsolute()) { + throw new IllegalArgumentException("Expecting an absolute url: [" + u + "]"); + } + return new Node(HttpHost.create(u)); + }).toList(); + return new Rest5ClientBuilder(nodes); + } + /** * Returns a new {@link Rest5ClientBuilder} to help with {@link Rest5Client} creation. * Creates a new builder instance and sets the hosts that the client will send requests to. diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java index ba3b7f05f..de1658e26 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientOptions.java @@ -49,7 +49,7 @@ public class RestClientOptions implements TransportOptions { @VisibleForTesting static final String USER_AGENT_VALUE = getUserAgent(); - static RestClientOptions of(@Nullable TransportOptions options) { + public static RestClientOptions of(@Nullable TransportOptions options) { if (options == null) { return initialOptions(); } diff --git a/java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java b/java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java index a97a2ac8e..b8fef1ecf 100644 --- a/java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java +++ b/java-client/src/test/java/co/elastic/clients/documentation/getting_started/ConnectingTest.java @@ -24,19 +24,10 @@ import co.elastic.clients.elasticsearch.core.SearchResponse; import co.elastic.clients.elasticsearch.core.search.Hit; import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.ElasticsearchTransport; import co.elastic.clients.transport.TransportUtils; import co.elastic.clients.transport.instrumentation.OpenTelemetryForElasticsearch; -import co.elastic.clients.transport.rest_client.RestClientTransport; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.sdk.OpenTelemetrySdk; -import org.apache.http.Header; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.message.BasicHeader; -import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -53,20 +44,12 @@ public void createClient() throws Exception { String serverUrl = "https://localhost:9200"; String apiKey = "VnVhQ2ZHY0JDZGJrU..."; - // Create the low-level client - RestClient restClient = RestClient - .builder(HttpHost.create(serverUrl)) - .setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "ApiKey " + apiKey) - }) - .build(); - - // Create the transport with a Jackson mapper - ElasticsearchTransport transport = new RestClientTransport( - restClient, new JacksonJsonpMapper()); - - // And create the API client - ElasticsearchClient esClient = new ElasticsearchClient(transport); + ElasticsearchClient esClient = ElasticsearchClient.of(b -> b + .host(serverUrl) + .apiKey(apiKey) + // Use the Jackson mapper to deserialize JSON to application objects + .jsonMapper(new JacksonJsonpMapper()) + ); // Use the client... @@ -98,13 +81,6 @@ public void createClientWithOpenTelemetry() throws Exception { String serverUrl = "https://localhost:9200"; String apiKey = "VnVhQ2ZHY0JDZGJrU..."; - // Create the low-level client - RestClient restClient = RestClient - .builder(HttpHost.create(serverUrl)) - .setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "ApiKey " + apiKey) - }) - .build(); // Create and configure custom OpenTelemetry instance OpenTelemetry customOtel = OpenTelemetrySdk.builder().build(); @@ -113,14 +89,12 @@ public void createClientWithOpenTelemetry() throws Exception { OpenTelemetryForElasticsearch esOtelInstrumentation = new OpenTelemetryForElasticsearch(customOtel, false); - // Create the transport with the custom Instrumentation instance - ElasticsearchTransport transport = new RestClientTransport( - restClient, new JacksonJsonpMapper(), null, esOtelInstrumentation + ElasticsearchClient esClient = ElasticsearchClient.of(b -> b + .host(serverUrl) + .apiKey(apiKey) + .instrumentation(esOtelInstrumentation) ); - // And create the API client - ElasticsearchClient esClient = new ElasticsearchClient(transport); - // Use the client... // Close the client, also closing the underlying transport object and network connections. @@ -132,9 +106,7 @@ restClient, new JacksonJsonpMapper(), null, esOtelInstrumentation @Test public void createSecureClientCert() throws Exception { - // Create the low-level client - String host = "localhost"; - int port = 9200; + String url = "https://localhost:9200"; String login = "elastic"; String password = "changeme"; @@ -144,23 +116,12 @@ public void createSecureClientCert() throws Exception { SSLContext sslContext = TransportUtils .sslContextFromHttpCaCrt(certFile); // <1> - BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); // <2> - credsProv.setCredentials( - AuthScope.ANY, new UsernamePasswordCredentials(login, password) + ElasticsearchClient esClient = ElasticsearchClient.of(b -> b + .host(url) // <3> + .usernameAndPassword(login, password) // <2> + .sslContext(sslContext) // <4> ); - RestClient restClient = RestClient - .builder(new HttpHost(host, port, "https")) // <3> - .setHttpClientConfigCallback(hc -> hc - .setSSLContext(sslContext) // <4> - .setDefaultCredentialsProvider(credsProv) - ) - .build(); - - // Create the transport and the API client - ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); - ElasticsearchClient esClient = new ElasticsearchClient(transport); - // Use the client... // Close the client, also closing the underlying transport object and network connections. @@ -172,9 +133,7 @@ AuthScope.ANY, new UsernamePasswordCredentials(login, password) @Test public void createSecureClientFingerPrint() throws Exception { - // Create the low-level client - String host = "localhost"; - int port = 9200; + String url = "https://localhost:9200"; String login = "elastic"; String password = "changeme"; @@ -184,23 +143,12 @@ public void createSecureClientFingerPrint() throws Exception { SSLContext sslContext = TransportUtils .sslContextFromCaFingerprint(fingerprint); // <1> - BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); // <2> - credsProv.setCredentials( - AuthScope.ANY, new UsernamePasswordCredentials(login, password) + ElasticsearchClient esClient = ElasticsearchClient.of(b -> b + .host(url) // <3> + .usernameAndPassword(login, password) // <2> + .sslContext(sslContext) // <4> ); - RestClient restClient = RestClient - .builder(new HttpHost(host, port, "https")) // <3> - .setHttpClientConfigCallback(hc -> hc - .setSSLContext(sslContext) // <4> - .setDefaultCredentialsProvider(credsProv) - ) - .build(); - - // Create the transport and the API client - ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); - ElasticsearchClient esClient = new ElasticsearchClient(transport); - // Use the client... // Close the client, also closing the underlying transport object and network connections. diff --git a/java-client/src/test/java/co/elastic/clients/documentation/getting_started/MigrateHlrcTest.java b/java-client/src/test/java/co/elastic/clients/documentation/getting_started/MigrateHlrcTest.java index e857188b7..ef903cf27 100644 --- a/java-client/src/test/java/co/elastic/clients/documentation/getting_started/MigrateHlrcTest.java +++ b/java-client/src/test/java/co/elastic/clients/documentation/getting_started/MigrateHlrcTest.java @@ -49,6 +49,9 @@ public RestHighLevelClient build() { @Test public void migrate() { + // Note: we keep the legacy client on purpose here since this is to illustrate + // the co-existence of HLRC and the Java client + //tag::migrate // Create the low-level client RestClient httpClient = RestClient.builder( diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java index 1a2297ab2..66a9212ea 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java @@ -20,7 +20,6 @@ package co.elastic.clients.elasticsearch._helpers; import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._helpers.builders.ElasticsearchClientBuilder; import co.elastic.clients.transport.rest5_client.Rest5ClientOptions; import co.elastic.clients.transport.rest5_client.Rest5ClientTransport; import co.elastic.clients.transport.rest_client.RestClientOptions; @@ -28,24 +27,19 @@ import org.elasticsearch.client.RequestOptions; import org.junit.jupiter.api.Test; -import javax.net.ssl.SSLContext; -import java.io.IOException; -import java.net.URISyntaxException; -import java.security.NoSuchAlgorithmException; - import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; public class ClientBuildersTest { @Test - public void buildLegacy() throws IOException, URISyntaxException, NoSuchAlgorithmException { + public void buildLegacy() { // create client with helper - ElasticsearchClient client = new ElasticsearchClientBuilder() - .host("url") + ElasticsearchClient client = new ElasticsearchClient.Builder() + .host("http://example.com") .usernameAndPassword("elastic", "changeme") - .sslContext(SSLContext.getDefault()) + .useLegacyTransport(true) .build(); RestClientOptions options = new RestClientOptions(RequestOptions.DEFAULT, true); @@ -57,19 +51,18 @@ public void buildLegacy() throws IOException, URISyntaxException, NoSuchAlgorith assertTrue(client._transportOptions().keepResponseBodyOnException()); assertTrue(client._transportOptions().headers().size() == 3); - // token update utility + // token update utility: not supported on legacy transport ElasticsearchClient finalClient = client; assertThrows(UnsupportedOperationException.class, () -> finalClient._transportOptions().updateToken("token")); } @Test - public void buildRest5() throws IOException, URISyntaxException, NoSuchAlgorithmException { + public void buildRest5() { // create client with helper - ElasticsearchClient client = new co.elastic.clients.elasticsearch._helpers.builders.rest5_client.ElasticsearchClientBuilder() - .host("url") + ElasticsearchClient client = new ElasticsearchClient.Builder() + .host("http://example.com") .usernameAndPassword("elastic", "changeme") - .sslContext(SSLContext.getDefault()) .build(); Rest5ClientOptions options = new Rest5ClientOptions(co.elastic.clients.transport.rest5_client.low_level.RequestOptions.DEFAULT, true); @@ -81,17 +74,10 @@ public void buildRest5() throws IOException, URISyntaxException, NoSuchAlgorithm assertTrue(client._transportOptions().keepResponseBodyOnException()); assertTrue(client._transportOptions().headers().size() == 3); - // token update utility - + // token update utility: supported on new transport client._transportOptions().updateToken("token"); assertTrue(client._transportOptions().headers().size() == 4); assertTrue(client._transportOptions().headers().stream().anyMatch(h -> h.getKey().equals( "Authorization"))); } - - @Test - public void altSearchBuild() { - // Standard search - - } } From a2229b0e2a0dddc69688289abaa1794922ed2def Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Fri, 28 Mar 2025 12:16:36 +0100 Subject: [PATCH 21/38] todos and timeouts fix --- .../low_level/BufferedByteConsumer.java | 2 +- .../rest5_client/low_level/Rest5Client.java | 5 ++--- .../low_level/Rest5ClientBuilder.java | 16 ++++++++++++---- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BufferedByteConsumer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BufferedByteConsumer.java index debd8f9bc..278d04ec5 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BufferedByteConsumer.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BufferedByteConsumer.java @@ -55,7 +55,7 @@ protected int capacityIncrement() { @Override protected void data(final ByteBuffer src, final boolean endOfStream) throws ContentTooLongException { - if (src.capacity() > limit) { //TODO why though? the server already has a 100MB limit. also, this method is called multiple times. check if should be src.capacity + buffer.length + if (src.capacity() > limit) { throw new ContentTooLongException( "entity content is too long [" + src.capacity() + "] for the configured buffer limit [" + limit + "]" ); diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java index 12d904365..8d4b9fb5d 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java @@ -219,7 +219,7 @@ public HttpAsyncClient getHttpClient() { /** * Replaces the nodes with which the client communicates. */ - public synchronized void setNodes(Collection nodes) { // TODO why the whole method synchronized? + public synchronized void setNodes(Collection nodes) { if (nodes == null || nodes.isEmpty()) { throw new IllegalArgumentException("node list must not be null or empty"); } @@ -227,8 +227,7 @@ public synchronized void setNodes(Collection nodes) { // TODO why the whol Map nodesByHost = new LinkedHashMap<>(); for (Node node : nodes) { Objects.requireNonNull(node, "node cannot be null"); - nodesByHost.put(node.getHost(), node); // TODO same host twice will be overwritten. should - // throw exception? + nodesByHost.put(node.getHost(), node); } this.nodes = new ArrayList<>(nodesByHost.values()); this.blacklist.clear(); diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5ClientBuilder.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5ClientBuilder.java index 52a0bf0e4..4df40f375 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5ClientBuilder.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5ClientBuilder.java @@ -20,6 +20,7 @@ package co.elastic.clients.transport.rest5_client.low_level; +import org.apache.hc.client5.http.config.ConnectionConfig; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; @@ -55,6 +56,7 @@ public final class Rest5ClientBuilder { public static final int DEFAULT_CONNECT_TIMEOUT_MILLIS = 1000; public static final int DEFAULT_SOCKET_TIMEOUT_MILLIS = 30000; + public static final int DEFAULT_RESPONSE_TIMEOUT_MILLIS = 0; // meaning infinite public static final int DEFAULT_MAX_CONN_PER_ROUTE = 10; public static final int DEFAULT_MAX_CONN_TOTAL = 30; @@ -343,24 +345,30 @@ private CloseableHttpAsyncClient createHttpClient() { return this.httpClient; } // otherwise, creating a default instance of CloseableHttpAsyncClient - // default timeouts are all infinite - RequestConfig.Builder requestConfigBuilder = RequestConfig.custom() + // default timeouts are all 3 mins + RequestConfig requestConfigBuilder = RequestConfig.custom() .setConnectionRequestTimeout(Timeout.of(DEFAULT_SOCKET_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) - .setConnectTimeout(Timeout.of(DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); //TODO deprecated need to change + .setResponseTimeout(Timeout.of(DEFAULT_RESPONSE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) + .build(); try { SSLContext sslContext = this.sslContext != null ? this.sslContext : SSLContext.getDefault(); + ConnectionConfig connectionConfig = ConnectionConfig.custom() + .setConnectTimeout(Timeout.of(DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) + .build(); + PoolingAsyncClientConnectionManager defaultConnectionManager = PoolingAsyncClientConnectionManagerBuilder.create() + .setDefaultConnectionConfig(connectionConfig) .setMaxConnPerRoute(DEFAULT_MAX_CONN_PER_ROUTE) .setMaxConnTotal(DEFAULT_MAX_CONN_TOTAL) .setTlsStrategy(new BasicClientTlsStrategy(sslContext)) .build(); HttpAsyncClientBuilder httpClientBuilder = HttpAsyncClientBuilder.create() - .setDefaultRequestConfig(requestConfigBuilder.build()) + .setDefaultRequestConfig(requestConfigBuilder) .setConnectionManager(defaultConnectionManager) .setUserAgent(USER_AGENT_HEADER_VALUE) .setTargetAuthenticationStrategy(new DefaultAuthenticationStrategy()) From cb707cb02f9ea42565a18e9291a5060ee53fad1a Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Fri, 28 Mar 2025 12:44:30 +0100 Subject: [PATCH 22/38] checkstyle fixes --- .../rest5_client/Rest5ClientHttpClient.java | 5 ++--- .../rest5_client/Rest5ClientTransport.java | 3 ++- .../low_level/BasicAsyncEntityProducer.java | 19 +++++++++++++++++++ .../rest5_client/low_level/Constants.java | 19 +++++++++++++++++++ .../low_level/HttpDeleteWithEntity.java | 2 +- .../low_level/HttpGetWithEntity.java | 2 +- .../rest5_client/low_level/Rest5Client.java | 2 -- .../_helpers/ClientBuildersTest.java | 3 ++- .../low_level/RequestOptionsTests.java | 3 ++- .../low_level/RestClientSingleHostTests.java | 3 ++- .../low_level/RestClientTestCase.java | 2 +- .../low_level/RestClientTestUtil.java | 1 - 12 files changed, 51 insertions(+), 13 deletions(-) diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java index e7e8d1b83..a8649fe65 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java @@ -132,9 +132,8 @@ public void close() throws IOException { } private co.elastic.clients.transport.rest5_client.low_level.Request createRestRequest(Request request, Rest5ClientOptions options) { - co.elastic.clients.transport.rest5_client.low_level.Request clientReq = new co.elastic.clients.transport.rest5_client.low_level.Request( - request.method(), request.path() - ); + co.elastic.clients.transport.rest5_client.low_level.Request clientReq = + new co.elastic.clients.transport.rest5_client.low_level.Request(request.method(), request.path()); Iterable body = request.body(); diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java index 72aa64602..fecf4071f 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java @@ -41,7 +41,8 @@ public Rest5ClientTransport(Rest5Client restClient, JsonpMapper jsonpMapper, Res this.restClient = restClient; } - public Rest5ClientTransport(Rest5Client restClient, JsonpMapper jsonpMapper, Rest5ClientOptions options, Instrumentation instrumentation) { + public Rest5ClientTransport(Rest5Client restClient, JsonpMapper jsonpMapper, Rest5ClientOptions options, + Instrumentation instrumentation) { super(new Rest5ClientHttpClient(restClient), options, jsonpMapper, instrumentation); this.restClient = restClient; } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncEntityProducer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncEntityProducer.java index 8fdd297a4..312111903 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncEntityProducer.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncEntityProducer.java @@ -1,3 +1,22 @@ +/* + * 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. + */ + package co.elastic.clients.transport.rest5_client.low_level; import org.apache.hc.core5.http.HttpEntity; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Constants.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Constants.java index ec8962151..6c2e18e1a 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Constants.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Constants.java @@ -1,3 +1,22 @@ +/* + * 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. + */ + package co.elastic.clients.transport.rest5_client.low_level; public class Constants { diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpDeleteWithEntity.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpDeleteWithEntity.java index 761bd0c6f..ba8253219 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpDeleteWithEntity.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpDeleteWithEntity.java @@ -30,7 +30,7 @@ final class HttpDeleteWithEntity extends HttpUriRequestBase { static final String METHOD_NAME = HttpDelete.METHOD_NAME; - public HttpDeleteWithEntity(URI requestUri) { + HttpDeleteWithEntity(URI requestUri) { super(METHOD_NAME, requestUri); } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpGetWithEntity.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpGetWithEntity.java index 05fb654d4..93f28d443 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpGetWithEntity.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/HttpGetWithEntity.java @@ -30,7 +30,7 @@ final class HttpGetWithEntity extends HttpUriRequestBase { static final String METHOD_NAME = HttpGet.METHOD_NAME; - public HttpGetWithEntity(URI requestUri) { + HttpGetWithEntity(URI requestUri) { super(METHOD_NAME, requestUri); } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java index 8d4b9fb5d..790004e87 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Rest5Client.java @@ -63,7 +63,6 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; -import java.util.Base64; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -82,7 +81,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; -import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Collections.singletonList; import static org.apache.hc.core5.http.HttpHeaders.CONTENT_ENCODING; import static org.apache.hc.core5.http.HttpHeaders.CONTENT_LENGTH; diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java index 66a9212ea..024464c2e 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java @@ -65,7 +65,8 @@ public void buildRest5() { .usernameAndPassword("elastic", "changeme") .build(); - Rest5ClientOptions options = new Rest5ClientOptions(co.elastic.clients.transport.rest5_client.low_level.RequestOptions.DEFAULT, true); + Rest5ClientOptions options = new Rest5ClientOptions(co.elastic.clients.transport.rest5_client.low_level.RequestOptions.DEFAULT, + true); client = client.withTransportOptions(options); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptionsTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptionsTests.java index a4d7e4f4a..a94e23436 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptionsTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RequestOptionsTests.java @@ -139,7 +139,8 @@ public void testSetRequestBuilder() { RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); int socketTimeout = 10000; int connectTimeout = 100; - requestConfigBuilder.setConnectionRequestTimeout(Timeout.ofMilliseconds(socketTimeout)).setConnectTimeout(Timeout.ofMilliseconds(connectTimeout)); + requestConfigBuilder.setConnectionRequestTimeout(Timeout.ofMilliseconds(socketTimeout)) + .setConnectTimeout(Timeout.ofMilliseconds(connectTimeout)); RequestConfig requestConfig = requestConfigBuilder.build(); builder.setRequestConfig(requestConfig); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostTests.java index 0bdfee300..89f90f913 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientSingleHostTests.java @@ -207,7 +207,8 @@ private static HttpResponse responseOrException(AsyncDataProducer requestProduce } } - private static Optional retrieveEntity(AsyncDataProducer requestProducer) throws NoSuchFieldException, IllegalAccessException { + private static Optional retrieveEntity(AsyncDataProducer requestProducer) + throws NoSuchFieldException, IllegalAccessException { // entity is in the dataProducer field, both are private Field dataProducerField = requestProducer.getClass().getDeclaredField("dataProducer"); dataProducerField.setAccessible(true); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestCase.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestCase.java index 034f63e99..db982ed19 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestCase.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestCase.java @@ -7,7 +7,7 @@ * 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 + * 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 diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestUtil.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestUtil.java index 77fb04fbf..13c2822ac 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestUtil.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestUtil.java @@ -26,7 +26,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Random; import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestCase.randomAsciiLettersOfLengthBetween; import static co.elastic.clients.transport.rest5_client.low_level.RestClientTestCase.randomBoolean; From f5a6e0aaef3e75548a471a35d331a57ac13b4c9d Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Fri, 28 Mar 2025 14:40:44 +0100 Subject: [PATCH 23/38] remove maven local + remove legacy test --- .../low_level/RestClientBuilderTests.java | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderTests.java index 02f826b12..956bb303f 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientBuilderTests.java @@ -19,7 +19,6 @@ package co.elastic.clients.transport.rest5_client.low_level; -import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; import org.apache.hc.client5.http.impl.async.HttpAsyncClients; import org.apache.hc.core5.http.Header; @@ -179,29 +178,4 @@ private static void assertSetPathPrefixThrows(final String pathPrefix) { assertThat(e.getMessage(), containsString(pathPrefix)); } } - - /** - * This test verifies that we don't change the default value for the connection request timeout as that - * causes problems. - * See https://github.com/elastic/elasticsearch/issues/24069 - */ - @Test - public void testDefaultConnectionRequestTimeout() throws IOException { - Rest5ClientBuilder builder = Rest5Client.builder(new HttpHost("localhost", 9200)); - - RequestConfig requestConfig = RequestConfig.custom().build(); - assertEquals(RequestConfig.DEFAULT.getConnectionRequestTimeout(), - requestConfig.getConnectionRequestTimeout()); - // this way we get notified if the default ever changes - // TODO IT CHANGED from -1 to 3 minutes, does it mean we always need to explicitly set it? - //assertEquals(-1, requestConfig.getConnectionRequestTimeout()); - - CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom() - .setDefaultRequestConfig(requestConfig) - .build(); - - try (Rest5Client restClient = builder.build()) { - assertNotNull(restClient); - } - } } From df29a4b66921932ee4fd8ad6b7938c4894bf5af0 Mon Sep 17 00:00:00 2001 From: Sylvain Wallez Date: Fri, 28 Mar 2025 16:05:57 +0100 Subject: [PATCH 24/38] Add insecure SSLContext --- .../ElasticsearchClientBuilderBase.java | 9 ++++- .../clients/transport/TransportUtils.java | 37 +++++++++++++++++++ .../clients/transport/TransportUtilsTest.java | 4 ++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilderBase.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilderBase.java index 06e07b666..9eae9f2bb 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilderBase.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilderBase.java @@ -121,13 +121,20 @@ public ElasticsearchClientBuilderBase apiKey(String apiKey) { /** * Set the SSL context. See {@link co.elastic.clients.transport.TransportUtils} to create it - * from certificate files or fingerprint. + * from certificate files or a certificate fingerprint. + * + * @see co.elastic.clients.transport.TransportUtils */ public ElasticsearchClientBuilderBase sslContext(SSLContext sslContext) { this.sslContext = sslContext; return this; } + public ElasticsearchClientBuilderBase setHosts(List hosts) { + this.hosts = hosts; + return this; + } + /** * Set the JSON mapper. */ diff --git a/java-client/src/main/java/co/elastic/clients/transport/TransportUtils.java b/java-client/src/main/java/co/elastic/clients/transport/TransportUtils.java index 72e6832cb..add9e1157 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/TransportUtils.java +++ b/java-client/src/main/java/co/elastic/clients/transport/TransportUtils.java @@ -26,6 +26,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.security.GeneralSecurityException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; @@ -144,4 +145,40 @@ public X509Certificate[] getAcceptedIssuers() { throw new RuntimeException(e); } } + + /** + * Returns an insecure SSLContext that will accept any server certificate. + *

+ * Use with care as it allows man-in-the-middle attacks. + */ + public static SSLContext insecureSSLContext() { + SSLContext result; + + X509TrustManager trustManager = new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) { + // Accept anything + } + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) { + // Accept anything + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + }; + + try { + result = SSLContext.getInstance("SSL"); + result.init(null, new X509TrustManager[] { trustManager }, null); + } catch (GeneralSecurityException e) { + // An exception here means SSL is not supported, which is unlikely + throw new RuntimeException(e); + } + + return result; + } } diff --git a/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java b/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java index 520d6a91a..468cfaa7f 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/TransportUtilsTest.java @@ -77,6 +77,10 @@ public void testCaCertificate() throws Exception { ); } + @Test void testInsecureContext() throws Exception { + checkConnection(TransportUtils.insecureSSLContext()); + } + private void checkConnection(SSLContext sslContext) throws Exception { var server = ElasticsearchTestServer.global(); var esClient = ElasticsearchTestClient.createClient(server.url(), null, sslContext); From 3267e118426a0076e5994177d7635c0a9299b39d Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Fri, 28 Mar 2025 16:22:40 +0100 Subject: [PATCH 25/38] temp rebase fix --- .../ElasticsearchAsyncClient.java | 5 - .../elasticsearch/ElasticsearchClient.java | 5 - .../inference/CompletionInferenceResult.java | 157 ------ .../inference/CompletionRequest.java | 335 ------------- .../inference/CompletionResponse.java | 106 ---- .../inference/CompletionResult.java | 155 ------ .../DeleteInferenceEndpointResult.java | 134 ----- .../inference/DeleteInferenceRequest.java | 292 ----------- .../inference/DeleteInferenceResponse.java | 107 ---- .../inference/GetInferenceRequest.java | 238 --------- .../inference/GetInferenceResponse.java | 186 ------- .../inference/InferenceChunkingSettings.java | 279 ----------- .../inference/InferenceEndpoint.java | 275 ----------- .../inference/InferenceEndpointInfo.java | 182 ------- .../inference/PutAlibabacloudResponse.java | 108 ---- .../inference/PutAmazonbedrockResponse.java | 108 ---- .../inference/PutAnthropicResponse.java | 107 ---- .../inference/PutAzureaistudioResponse.java | 108 ---- .../inference/PutAzureopenaiResponse.java | 108 ---- .../inference/PutCohereResponse.java | 106 ---- .../inference/PutEisResponse.java | 106 ---- .../inference/PutElasticsearchResponse.java | 108 ---- .../inference/PutElserResponse.java | 106 ---- .../inference/PutGoogleaistudioResponse.java | 108 ---- .../inference/PutGooglevertexaiResponse.java | 108 ---- .../inference/PutHuggingFaceResponse.java | 108 ---- .../inference/PutJinaaiResponse.java | 106 ---- .../inference/PutMistralResponse.java | 106 ---- .../inference/PutOpenaiResponse.java | 106 ---- .../elasticsearch/inference/PutRequest.java | 298 ----------- .../elasticsearch/inference/PutResponse.java | 106 ---- .../inference/PutVoyageaiResponse.java | 106 ---- .../inference/PutWatsonxResponse.java | 106 ---- .../inference/RankedDocument.java | 213 -------- .../inference/RateLimitSetting.java | 163 ------- .../inference/RequestChatCompletionBase.java | 461 ------------------ .../inference/RerankRequest.java | 383 --------------- .../inference/RerankResponse.java | 106 ---- .../inference/RerankedInferenceResult.java | 156 ------ .../SparseEmbeddingInferenceResult.java | 158 ------ .../inference/SparseEmbeddingRequest.java | 337 ------------- .../inference/SparseEmbeddingResponse.java | 108 ---- .../inference/SparseEmbeddingResult.java | 180 ------- .../inference/StreamCompletionRequest.java | 327 ------------- .../elasticsearch/inference/TaskType.java | 71 --- .../inference/TextEmbeddingByteResult.java | 180 ------- .../TextEmbeddingInferenceResult.java | 284 ----------- .../TextEmbeddingInferenceResultBuilders.java | 53 -- .../TextEmbeddingInferenceResultVariant.java | 48 -- .../inference/TextEmbeddingRequest.java | 336 ------------- .../inference/TextEmbeddingResult.java | 179 ------- .../inference/UpdateInferenceRequest.java | 298 ----------- .../inference/UpdateInferenceResponse.java | 107 ---- .../AlibabaCloudServiceSettings.java | 344 ------------- .../AlibabaCloudTaskSettings.java | 218 --------- .../AlibabaCloudTaskType.java | 71 --- .../put_alibabacloud/ServiceType.java | 65 --- .../AmazonBedrockServiceSettings.java | 371 -------------- .../AmazonBedrockTaskSettings.java | 292 ----------- .../AmazonBedrockTaskType.java | 67 --- .../put_amazonbedrock/ServiceType.java | 65 --- .../AnthropicServiceSettings.java | 241 --------- .../put_anthropic/AnthropicTaskSettings.java | 283 ----------- .../put_anthropic/AnthropicTaskType.java | 65 --- .../inference/put_anthropic/ServiceType.java | 65 --- .../AzureAiStudioServiceSettings.java | 353 -------------- .../AzureAiStudioTaskSettings.java | 320 ------------ .../AzureAiStudioTaskType.java | 67 --- .../put_azureaistudio/ServiceType.java | 65 --- .../AzureOpenAIServiceSettings.java | 368 -------------- .../put_azureopenai/AzureOpenAITaskType.java | 67 --- .../put_azureopenai/ServiceType.java | 65 --- .../put_cohere/CohereServiceSettings.java | 363 -------------- .../put_cohere/CohereTaskSettings.java | 317 ------------ .../inference/put_cohere/CohereTaskType.java | 69 --- .../inference/put_cohere/EmbeddingType.java | 69 --- .../inference/put_cohere/InputType.java | 71 --- .../inference/put_cohere/ServiceType.java | 65 --- .../inference/put_cohere/SimilarityType.java | 69 --- .../inference/put_cohere/TruncateType.java | 69 --- .../AdaptiveAllocations.java | 236 --------- .../ElasticsearchServiceSettings.java | 342 ------------- .../ElasticsearchTaskSettings.java | 168 ------- .../ElasticsearchTaskType.java | 69 --- .../put_elasticsearch/ServiceType.java | 65 --- .../put_elser/AdaptiveAllocations.java | 236 --------- .../put_elser/ElserServiceSettings.java | 280 ----------- .../inference/put_elser/ElserTaskType.java | 65 --- .../GoogleAiStudioServiceSettings.java | 241 --------- .../GoogleAiStudioTaskType.java | 67 --- .../put_googleaistudio/ServiceType.java | 65 --- .../GoogleVertexAIServiceSettings.java | 300 ------------ .../GoogleVertexAITaskSettings.java | 204 -------- .../GoogleVertexAITaskType.java | 67 --- .../put_googlevertexai/ServiceType.java | 65 --- .../HuggingFaceServiceSettings.java | 252 ---------- .../put_hugging_face/HuggingFaceTaskType.java | 65 --- .../put_hugging_face/ServiceType.java | 65 --- .../put_jinaai/JinaAIServiceSettings.java | 297 ----------- .../put_jinaai/JinaAITaskSettings.java | 261 ---------- .../inference/put_jinaai/JinaAITaskType.java | 67 --- .../inference/put_jinaai/ServiceType.java | 65 --- .../inference/put_jinaai/SimilarityType.java | 69 --- .../put_jinaai/TextEmbeddingTask.java | 71 --- .../put_mistral/MistralServiceSettings.java | 289 ----------- .../put_mistral/MistralTaskType.java | 65 --- .../inference/put_mistral/ServiceType.java | 65 --- 107 files changed, 17472 deletions(-) delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionInferenceResult.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionRequest.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionResult.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceEndpointResult.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceRequest.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/GetInferenceRequest.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/GetInferenceResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceChunkingSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceEndpoint.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceEndpointInfo.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutRequest.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RankedDocument.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RateLimitSetting.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RequestChatCompletionBase.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankRequest.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankedInferenceResult.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingInferenceResult.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingRequest.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingResult.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/StreamCompletionRequest.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingByteResult.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResult.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResultBuilders.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResultVariant.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingRequest.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResult.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/UpdateInferenceRequest.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/UpdateInferenceResponse.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAIServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAITaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/EmbeddingType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/InputType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/SimilarityType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/TruncateType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/AdaptiveAllocations.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/AdaptiveAllocations.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAIServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAIServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/SimilarityType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/TextEmbeddingTask.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/ServiceType.java diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java index 6f0d47d03..0c61095bf 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java @@ -121,7 +121,6 @@ import co.elastic.clients.elasticsearch.graph.ElasticsearchGraphAsyncClient; import co.elastic.clients.elasticsearch.ilm.ElasticsearchIlmAsyncClient; import co.elastic.clients.elasticsearch.indices.ElasticsearchIndicesAsyncClient; -import co.elastic.clients.elasticsearch.inference.ElasticsearchInferenceAsyncClient; import co.elastic.clients.elasticsearch.ingest.ElasticsearchIngestAsyncClient; import co.elastic.clients.elasticsearch.license.ElasticsearchLicenseAsyncClient; import co.elastic.clients.elasticsearch.logstash.ElasticsearchLogstashAsyncClient; @@ -266,10 +265,6 @@ public ElasticsearchIndicesAsyncClient indices() { return new ElasticsearchIndicesAsyncClient(this.transport, this.transportOptions); } - public ElasticsearchInferenceAsyncClient inference() { - return new ElasticsearchInferenceAsyncClient(this.transport, this.transportOptions); - } - public ElasticsearchIngestAsyncClient ingest() { return new ElasticsearchIngestAsyncClient(this.transport, this.transportOptions); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java index 7e6a441bc..4550a4bf3 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java @@ -122,7 +122,6 @@ import co.elastic.clients.elasticsearch.graph.ElasticsearchGraphClient; import co.elastic.clients.elasticsearch.ilm.ElasticsearchIlmClient; import co.elastic.clients.elasticsearch.indices.ElasticsearchIndicesClient; -import co.elastic.clients.elasticsearch.inference.ElasticsearchInferenceClient; import co.elastic.clients.elasticsearch.ingest.ElasticsearchIngestClient; import co.elastic.clients.elasticsearch.license.ElasticsearchLicenseClient; import co.elastic.clients.elasticsearch.logstash.ElasticsearchLogstashClient; @@ -266,10 +265,6 @@ public ElasticsearchIndicesClient indices() { return new ElasticsearchIndicesClient(this.transport, this.transportOptions); } - public ElasticsearchInferenceClient inference() { - return new ElasticsearchInferenceClient(this.transport, this.transportOptions); - } - public ElasticsearchIngestClient ingest() { return new ElasticsearchIngestClient(this.transport, this.transportOptions); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionInferenceResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionInferenceResult.java deleted file mode 100644 index 145e988f7..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionInferenceResult.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference._types.CompletionInferenceResult - -/** - * Defines the completion result. - * - * @see API - * specification - */ - -public abstract class CompletionInferenceResult implements JsonpSerializable { - private final List completion; - - // --------------------------------------------------------------------------------------------- - - protected CompletionInferenceResult(AbstractBuilder builder) { - - this.completion = ApiTypeHelper.unmodifiableRequired(builder.completion, this, "completion"); - - } - - /** - * Required - API name: {@code completion} - */ - public final List completion() { - return this.completion; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (ApiTypeHelper.isDefined(this.completion)) { - generator.writeKey("completion"); - generator.writeStartArray(); - for (CompletionResult item0 : this.completion) { - item0.serialize(generator, mapper); - - } - generator.writeEnd(); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - public abstract static class AbstractBuilder> - extends - WithJsonObjectBuilderBase { - private List completion; - - /** - * Required - API name: {@code completion} - *

- * Adds all elements of list to completion. - */ - public final BuilderT completion(List list) { - this.completion = _listAddAll(this.completion, list); - return self(); - } - - /** - * Required - API name: {@code completion} - *

- * Adds one or more values to completion. - */ - public final BuilderT completion(CompletionResult value, CompletionResult... values) { - this.completion = _listAdd(this.completion, value, values); - return self(); - } - - /** - * Required - API name: {@code completion} - *

- * Adds a value to completion using a builder lambda. - */ - public final BuilderT completion(Function> fn) { - return completion(fn.apply(new CompletionResult.Builder()).build()); - } - - protected abstract BuilderT self(); - - } - - // --------------------------------------------------------------------------------------------- - protected static > void setupCompletionInferenceResultDeserializer( - ObjectDeserializer op) { - - op.add(AbstractBuilder::completion, JsonpDeserializer.arrayDeserializer(CompletionResult._DESERIALIZER), - "completion"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionRequest.java deleted file mode 100644 index 93201e360..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionRequest.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.elasticsearch._types.RequestBase; -import co.elastic.clients.elasticsearch._types.Time; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.endpoints.SimpleEndpoint; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.completion.Request - -/** - * Perform completion inference on the service - * - * @see API - * specification - */ -@JsonpDeserializable -public class CompletionRequest extends RequestBase implements JsonpSerializable { - private final String inferenceId; - - private final List input; - - @Nullable - private final JsonData taskSettings; - - @Nullable - private final Time timeout; - - // --------------------------------------------------------------------------------------------- - - private CompletionRequest(Builder builder) { - - this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); - this.input = ApiTypeHelper.unmodifiableRequired(builder.input, this, "input"); - this.taskSettings = builder.taskSettings; - this.timeout = builder.timeout; - - } - - public static CompletionRequest of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The inference Id - *

- * API name: {@code inference_id} - */ - public final String inferenceId() { - return this.inferenceId; - } - - /** - * Required - Inference input. Either a string or an array of strings. - *

- * API name: {@code input} - */ - public final List input() { - return this.input; - } - - /** - * Optional task settings - *

- * API name: {@code task_settings} - */ - @Nullable - public final JsonData taskSettings() { - return this.taskSettings; - } - - /** - * Specifies the amount of time to wait for the inference request to complete. - *

- * API name: {@code timeout} - */ - @Nullable - public final Time timeout() { - return this.timeout; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (ApiTypeHelper.isDefined(this.input)) { - generator.writeKey("input"); - generator.writeStartArray(); - for (String item0 : this.input) { - generator.write(item0); - - } - generator.writeEnd(); - - } - if (this.taskSettings != null) { - generator.writeKey("task_settings"); - this.taskSettings.serialize(generator, mapper); - - } - - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link CompletionRequest}. - */ - - public static class Builder extends RequestBase.AbstractBuilder - implements - ObjectBuilder { - private String inferenceId; - - private List input; - - @Nullable - private JsonData taskSettings; - - @Nullable - private Time timeout; - - /** - * Required - The inference Id - *

- * API name: {@code inference_id} - */ - public final Builder inferenceId(String value) { - this.inferenceId = value; - return this; - } - - /** - * Required - Inference input. Either a string or an array of strings. - *

- * API name: {@code input} - *

- * Adds all elements of list to input. - */ - public final Builder input(List list) { - this.input = _listAddAll(this.input, list); - return this; - } - - /** - * Required - Inference input. Either a string or an array of strings. - *

- * API name: {@code input} - *

- * Adds one or more values to input. - */ - public final Builder input(String value, String... values) { - this.input = _listAdd(this.input, value, values); - return this; - } - - /** - * Optional task settings - *

- * API name: {@code task_settings} - */ - public final Builder taskSettings(@Nullable JsonData value) { - this.taskSettings = value; - return this; - } - - /** - * Specifies the amount of time to wait for the inference request to complete. - *

- * API name: {@code timeout} - */ - public final Builder timeout(@Nullable Time value) { - this.timeout = value; - return this; - } - - /** - * Specifies the amount of time to wait for the inference request to complete. - *

- * API name: {@code timeout} - */ - public final Builder timeout(Function> fn) { - return this.timeout(fn.apply(new Time.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link CompletionRequest}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public CompletionRequest build() { - _checkSingleUse(); - - return new CompletionRequest(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link CompletionRequest} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, CompletionRequest::setupCompletionRequestDeserializer); - - protected static void setupCompletionRequestDeserializer(ObjectDeserializer op) { - - op.add(Builder::input, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), "input"); - op.add(Builder::taskSettings, JsonData._DESERIALIZER, "task_settings"); - - } - - // --------------------------------------------------------------------------------------------- - - /** - * Endpoint "{@code inference.completion}". - */ - public static final Endpoint _ENDPOINT = new SimpleEndpoint<>( - "es/inference.completion", - - // Request method - request -> { - return "POST"; - - }, - - // Request path - request -> { - final int _inferenceId = 1 << 0; - - int propsSet = 0; - - propsSet |= _inferenceId; - - if (propsSet == (_inferenceId)) { - StringBuilder buf = new StringBuilder(); - buf.append("/_inference"); - buf.append("/completion"); - buf.append("/"); - SimpleEndpoint.pathEncode(request.inferenceId, buf); - return buf.toString(); - } - throw SimpleEndpoint.noPathTemplateFound("path"); - - }, - - // Path parameters - request -> { - Map params = new HashMap<>(); - final int _inferenceId = 1 << 0; - - int propsSet = 0; - - propsSet |= _inferenceId; - - if (propsSet == (_inferenceId)) { - params.put("inferenceId", request.inferenceId); - } - return params; - }, - - // Request parameters - request -> { - Map params = new HashMap<>(); - if (request.timeout != null) { - params.put("timeout", request.timeout._toJsonString()); - } - return params; - - }, SimpleEndpoint.emptyMap(), true, CompletionResponse._DESERIALIZER); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionResponse.java deleted file mode 100644 index bc21e2246..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionResponse.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.completion.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class CompletionResponse extends CompletionInferenceResult { - // --------------------------------------------------------------------------------------------- - - private CompletionResponse(Builder builder) { - super(builder); - - } - - public static CompletionResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link CompletionResponse}. - */ - - public static class Builder extends CompletionInferenceResult.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link CompletionResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public CompletionResponse build() { - _checkSingleUse(); - - return new CompletionResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link CompletionResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, CompletionResponse::setupCompletionResponseDeserializer); - - protected static void setupCompletionResponseDeserializer(ObjectDeserializer op) { - CompletionInferenceResult.setupCompletionInferenceResultDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionResult.java deleted file mode 100644 index 345149456..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionResult.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference._types.CompletionResult - -/** - * The completion result object - * - * @see API - * specification - */ -@JsonpDeserializable -public class CompletionResult implements JsonpSerializable { - private final String result; - - // --------------------------------------------------------------------------------------------- - - private CompletionResult(Builder builder) { - - this.result = ApiTypeHelper.requireNonNull(builder.result, this, "result"); - - } - - public static CompletionResult of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - API name: {@code result} - */ - public final String result() { - return this.result; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("result"); - generator.write(this.result); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link CompletionResult}. - */ - - public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { - private String result; - - /** - * Required - API name: {@code result} - */ - public final Builder result(String value) { - this.result = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link CompletionResult}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public CompletionResult build() { - _checkSingleUse(); - - return new CompletionResult(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link CompletionResult} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, - CompletionResult::setupCompletionResultDeserializer); - - protected static void setupCompletionResultDeserializer(ObjectDeserializer op) { - - op.add(Builder::result, JsonpDeserializer.stringDeserializer(), "result"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceEndpointResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceEndpointResult.java deleted file mode 100644 index 345a060f3..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceEndpointResult.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.elasticsearch._types.AcknowledgedResponseBase; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.List; -import java.util.Objects; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference._types.DeleteInferenceEndpointResult - -/** - * Acknowledged response. For dry_run, contains the list of pipelines which - * reference the inference endpoint - * - * @see API - * specification - */ - -public abstract class DeleteInferenceEndpointResult extends AcknowledgedResponseBase { - private final List pipelines; - - // --------------------------------------------------------------------------------------------- - - protected DeleteInferenceEndpointResult(AbstractBuilder builder) { - super(builder); - - this.pipelines = ApiTypeHelper.unmodifiableRequired(builder.pipelines, this, "pipelines"); - - } - - /** - * Required - API name: {@code pipelines} - */ - public final List pipelines() { - return this.pipelines; - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - super.serializeInternal(generator, mapper); - if (ApiTypeHelper.isDefined(this.pipelines)) { - generator.writeKey("pipelines"); - generator.writeStartArray(); - for (String item0 : this.pipelines) { - generator.write(item0); - - } - generator.writeEnd(); - - } - - } - - public abstract static class AbstractBuilder> - extends - AcknowledgedResponseBase.AbstractBuilder { - private List pipelines; - - /** - * Required - API name: {@code pipelines} - *

- * Adds all elements of list to pipelines. - */ - public final BuilderT pipelines(List list) { - this.pipelines = _listAddAll(this.pipelines, list); - return self(); - } - - /** - * Required - API name: {@code pipelines} - *

- * Adds one or more values to pipelines. - */ - public final BuilderT pipelines(String value, String... values) { - this.pipelines = _listAdd(this.pipelines, value, values); - return self(); - } - - } - - // --------------------------------------------------------------------------------------------- - protected static > void setupDeleteInferenceEndpointResultDeserializer( - ObjectDeserializer op) { - AcknowledgedResponseBase.setupAcknowledgedResponseBaseDeserializer(op); - op.add(AbstractBuilder::pipelines, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), - "pipelines"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceRequest.java deleted file mode 100644 index 96d1ed6f8..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceRequest.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.elasticsearch._types.RequestBase; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.endpoints.SimpleEndpoint; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.lang.String; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.delete.Request - -/** - * Delete an inference endpoint - * - * @see API - * specification - */ - -public class DeleteInferenceRequest extends RequestBase { - @Nullable - private final Boolean dryRun; - - @Nullable - private final Boolean force; - - private final String inferenceId; - - @Nullable - private final TaskType taskType; - - // --------------------------------------------------------------------------------------------- - - private DeleteInferenceRequest(Builder builder) { - - this.dryRun = builder.dryRun; - this.force = builder.force; - this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); - this.taskType = builder.taskType; - - } - - public static DeleteInferenceRequest of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * When true, the endpoint is not deleted and a list of ingest processors which - * reference this endpoint is returned. - *

- * API name: {@code dry_run} - */ - @Nullable - public final Boolean dryRun() { - return this.dryRun; - } - - /** - * When true, the inference endpoint is forcefully deleted even if it is still - * being used by ingest processors or semantic text fields. - *

- * API name: {@code force} - */ - @Nullable - public final Boolean force() { - return this.force; - } - - /** - * Required - The inference identifier. - *

- * API name: {@code inference_id} - */ - public final String inferenceId() { - return this.inferenceId; - } - - /** - * The task type - *

- * API name: {@code task_type} - */ - @Nullable - public final TaskType taskType() { - return this.taskType; - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link DeleteInferenceRequest}. - */ - - public static class Builder extends RequestBase.AbstractBuilder - implements - ObjectBuilder { - @Nullable - private Boolean dryRun; - - @Nullable - private Boolean force; - - private String inferenceId; - - @Nullable - private TaskType taskType; - - /** - * When true, the endpoint is not deleted and a list of ingest processors which - * reference this endpoint is returned. - *

- * API name: {@code dry_run} - */ - public final Builder dryRun(@Nullable Boolean value) { - this.dryRun = value; - return this; - } - - /** - * When true, the inference endpoint is forcefully deleted even if it is still - * being used by ingest processors or semantic text fields. - *

- * API name: {@code force} - */ - public final Builder force(@Nullable Boolean value) { - this.force = value; - return this; - } - - /** - * Required - The inference identifier. - *

- * API name: {@code inference_id} - */ - public final Builder inferenceId(String value) { - this.inferenceId = value; - return this; - } - - /** - * The task type - *

- * API name: {@code task_type} - */ - public final Builder taskType(@Nullable TaskType value) { - this.taskType = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link DeleteInferenceRequest}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public DeleteInferenceRequest build() { - _checkSingleUse(); - - return new DeleteInferenceRequest(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Endpoint "{@code inference.delete}". - */ - public static final Endpoint _ENDPOINT = new SimpleEndpoint<>( - "es/inference.delete", - - // Request method - request -> { - return "DELETE"; - - }, - - // Request path - request -> { - final int _inferenceId = 1 << 0; - final int _taskType = 1 << 1; - - int propsSet = 0; - - propsSet |= _inferenceId; - if (request.taskType() != null) - propsSet |= _taskType; - - if (propsSet == (_inferenceId)) { - StringBuilder buf = new StringBuilder(); - buf.append("/_inference"); - buf.append("/"); - SimpleEndpoint.pathEncode(request.inferenceId, buf); - return buf.toString(); - } - if (propsSet == (_taskType | _inferenceId)) { - StringBuilder buf = new StringBuilder(); - buf.append("/_inference"); - buf.append("/"); - SimpleEndpoint.pathEncode(request.taskType.jsonValue(), buf); - buf.append("/"); - SimpleEndpoint.pathEncode(request.inferenceId, buf); - return buf.toString(); - } - throw SimpleEndpoint.noPathTemplateFound("path"); - - }, - - // Path parameters - request -> { - Map params = new HashMap<>(); - final int _inferenceId = 1 << 0; - final int _taskType = 1 << 1; - - int propsSet = 0; - - propsSet |= _inferenceId; - if (request.taskType() != null) - propsSet |= _taskType; - - if (propsSet == (_inferenceId)) { - params.put("inferenceId", request.inferenceId); - } - if (propsSet == (_taskType | _inferenceId)) { - params.put("taskType", request.taskType.jsonValue()); - params.put("inferenceId", request.inferenceId); - } - return params; - }, - - // Request parameters - request -> { - Map params = new HashMap<>(); - if (request.dryRun != null) { - params.put("dry_run", String.valueOf(request.dryRun)); - } - if (request.force != null) { - params.put("force", String.valueOf(request.force)); - } - return params; - - }, SimpleEndpoint.emptyMap(), false, DeleteInferenceResponse._DESERIALIZER); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceResponse.java deleted file mode 100644 index 1ddee6c97..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceResponse.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.delete.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class DeleteInferenceResponse extends DeleteInferenceEndpointResult { - // --------------------------------------------------------------------------------------------- - - private DeleteInferenceResponse(Builder builder) { - super(builder); - - } - - public static DeleteInferenceResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link DeleteInferenceResponse}. - */ - - public static class Builder extends DeleteInferenceEndpointResult.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link DeleteInferenceResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public DeleteInferenceResponse build() { - _checkSingleUse(); - - return new DeleteInferenceResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link DeleteInferenceResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, DeleteInferenceResponse::setupDeleteInferenceResponseDeserializer); - - protected static void setupDeleteInferenceResponseDeserializer( - ObjectDeserializer op) { - DeleteInferenceEndpointResult.setupDeleteInferenceEndpointResultDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/GetInferenceRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/GetInferenceRequest.java deleted file mode 100644 index 8a167a202..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/GetInferenceRequest.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.elasticsearch._types.RequestBase; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.endpoints.SimpleEndpoint; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.get.Request - -/** - * Get an inference endpoint - * - * @see API - * specification - */ - -public class GetInferenceRequest extends RequestBase { - @Nullable - private final String inferenceId; - - @Nullable - private final TaskType taskType; - - // --------------------------------------------------------------------------------------------- - - private GetInferenceRequest(Builder builder) { - - this.inferenceId = builder.inferenceId; - this.taskType = builder.taskType; - - } - - public static GetInferenceRequest of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * The inference Id - *

- * API name: {@code inference_id} - */ - @Nullable - public final String inferenceId() { - return this.inferenceId; - } - - /** - * The task type - *

- * API name: {@code task_type} - */ - @Nullable - public final TaskType taskType() { - return this.taskType; - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link GetInferenceRequest}. - */ - - public static class Builder extends RequestBase.AbstractBuilder - implements - ObjectBuilder { - @Nullable - private String inferenceId; - - @Nullable - private TaskType taskType; - - /** - * The inference Id - *

- * API name: {@code inference_id} - */ - public final Builder inferenceId(@Nullable String value) { - this.inferenceId = value; - return this; - } - - /** - * The task type - *

- * API name: {@code task_type} - */ - public final Builder taskType(@Nullable TaskType value) { - this.taskType = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link GetInferenceRequest}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public GetInferenceRequest build() { - _checkSingleUse(); - - return new GetInferenceRequest(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Endpoint "{@code inference.get}". - */ - public static final Endpoint _ENDPOINT = new SimpleEndpoint<>( - "es/inference.get", - - // Request method - request -> { - return "GET"; - - }, - - // Request path - request -> { - final int _inferenceId = 1 << 0; - final int _taskType = 1 << 1; - - int propsSet = 0; - - if (request.inferenceId() != null) - propsSet |= _inferenceId; - if (request.taskType() != null) - propsSet |= _taskType; - - if (propsSet == 0) { - StringBuilder buf = new StringBuilder(); - buf.append("/_inference"); - return buf.toString(); - } - if (propsSet == (_inferenceId)) { - StringBuilder buf = new StringBuilder(); - buf.append("/_inference"); - buf.append("/"); - SimpleEndpoint.pathEncode(request.inferenceId, buf); - return buf.toString(); - } - if (propsSet == (_taskType | _inferenceId)) { - StringBuilder buf = new StringBuilder(); - buf.append("/_inference"); - buf.append("/"); - SimpleEndpoint.pathEncode(request.taskType.jsonValue(), buf); - buf.append("/"); - SimpleEndpoint.pathEncode(request.inferenceId, buf); - return buf.toString(); - } - throw SimpleEndpoint.noPathTemplateFound("path"); - - }, - - // Path parameters - request -> { - Map params = new HashMap<>(); - final int _inferenceId = 1 << 0; - final int _taskType = 1 << 1; - - int propsSet = 0; - - if (request.inferenceId() != null) - propsSet |= _inferenceId; - if (request.taskType() != null) - propsSet |= _taskType; - - if (propsSet == 0) { - } - if (propsSet == (_inferenceId)) { - params.put("inferenceId", request.inferenceId); - } - if (propsSet == (_taskType | _inferenceId)) { - params.put("taskType", request.taskType.jsonValue()); - params.put("inferenceId", request.inferenceId); - } - return params; - }, - - // Request parameters - request -> { - return Collections.emptyMap(); - - }, SimpleEndpoint.emptyMap(), false, GetInferenceResponse._DESERIALIZER); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/GetInferenceResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/GetInferenceResponse.java deleted file mode 100644 index 17a5d4458..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/GetInferenceResponse.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.get.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class GetInferenceResponse implements JsonpSerializable { - private final List endpoints; - - // --------------------------------------------------------------------------------------------- - - private GetInferenceResponse(Builder builder) { - - this.endpoints = ApiTypeHelper.unmodifiableRequired(builder.endpoints, this, "endpoints"); - - } - - public static GetInferenceResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - API name: {@code endpoints} - */ - public final List endpoints() { - return this.endpoints; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (ApiTypeHelper.isDefined(this.endpoints)) { - generator.writeKey("endpoints"); - generator.writeStartArray(); - for (InferenceEndpointInfo item0 : this.endpoints) { - item0.serialize(generator, mapper); - - } - generator.writeEnd(); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link GetInferenceResponse}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private List endpoints; - - /** - * Required - API name: {@code endpoints} - *

- * Adds all elements of list to endpoints. - */ - public final Builder endpoints(List list) { - this.endpoints = _listAddAll(this.endpoints, list); - return this; - } - - /** - * Required - API name: {@code endpoints} - *

- * Adds one or more values to endpoints. - */ - public final Builder endpoints(InferenceEndpointInfo value, InferenceEndpointInfo... values) { - this.endpoints = _listAdd(this.endpoints, value, values); - return this; - } - - /** - * Required - API name: {@code endpoints} - *

- * Adds a value to endpoints using a builder lambda. - */ - public final Builder endpoints( - Function> fn) { - return endpoints(fn.apply(new InferenceEndpointInfo.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link GetInferenceResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public GetInferenceResponse build() { - _checkSingleUse(); - - return new GetInferenceResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link GetInferenceResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, GetInferenceResponse::setupGetInferenceResponseDeserializer); - - protected static void setupGetInferenceResponseDeserializer(ObjectDeserializer op) { - - op.add(Builder::endpoints, JsonpDeserializer.arrayDeserializer(InferenceEndpointInfo._DESERIALIZER), - "endpoints"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceChunkingSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceChunkingSettings.java deleted file mode 100644 index 7f85053c3..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceChunkingSettings.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Integer; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference._types.InferenceChunkingSettings - -/** - * Chunking configuration object - * - * @see API - * specification - */ -@JsonpDeserializable -public class InferenceChunkingSettings implements JsonpSerializable { - @Nullable - private final Integer maxChunkSize; - - @Nullable - private final Integer overlap; - - @Nullable - private final Integer sentenceOverlap; - - @Nullable - private final String strategy; - - // --------------------------------------------------------------------------------------------- - - private InferenceChunkingSettings(Builder builder) { - - this.maxChunkSize = builder.maxChunkSize; - this.overlap = builder.overlap; - this.sentenceOverlap = builder.sentenceOverlap; - this.strategy = builder.strategy; - - } - - public static InferenceChunkingSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * The maximum size of a chunk in words. This value cannot be higher than - * 300 or lower than 20 (for sentence - * strategy) or 10 (for word strategy). - *

- * API name: {@code max_chunk_size} - */ - @Nullable - public final Integer maxChunkSize() { - return this.maxChunkSize; - } - - /** - * The number of overlapping words for chunks. It is applicable only to a - * word chunking strategy. This value cannot be higher than half - * the max_chunk_size value. - *

- * API name: {@code overlap} - */ - @Nullable - public final Integer overlap() { - return this.overlap; - } - - /** - * The number of overlapping sentences for chunks. It is applicable only for a - * sentence chunking strategy. It can be either 1 or - * 0. - *

- * API name: {@code sentence_overlap} - */ - @Nullable - public final Integer sentenceOverlap() { - return this.sentenceOverlap; - } - - /** - * The chunking strategy: sentence or word. - *

- * API name: {@code strategy} - */ - @Nullable - public final String strategy() { - return this.strategy; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.maxChunkSize != null) { - generator.writeKey("max_chunk_size"); - generator.write(this.maxChunkSize); - - } - if (this.overlap != null) { - generator.writeKey("overlap"); - generator.write(this.overlap); - - } - if (this.sentenceOverlap != null) { - generator.writeKey("sentence_overlap"); - generator.write(this.sentenceOverlap); - - } - if (this.strategy != null) { - generator.writeKey("strategy"); - generator.write(this.strategy); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link InferenceChunkingSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private Integer maxChunkSize; - - @Nullable - private Integer overlap; - - @Nullable - private Integer sentenceOverlap; - - @Nullable - private String strategy; - - /** - * The maximum size of a chunk in words. This value cannot be higher than - * 300 or lower than 20 (for sentence - * strategy) or 10 (for word strategy). - *

- * API name: {@code max_chunk_size} - */ - public final Builder maxChunkSize(@Nullable Integer value) { - this.maxChunkSize = value; - return this; - } - - /** - * The number of overlapping words for chunks. It is applicable only to a - * word chunking strategy. This value cannot be higher than half - * the max_chunk_size value. - *

- * API name: {@code overlap} - */ - public final Builder overlap(@Nullable Integer value) { - this.overlap = value; - return this; - } - - /** - * The number of overlapping sentences for chunks. It is applicable only for a - * sentence chunking strategy. It can be either 1 or - * 0. - *

- * API name: {@code sentence_overlap} - */ - public final Builder sentenceOverlap(@Nullable Integer value) { - this.sentenceOverlap = value; - return this; - } - - /** - * The chunking strategy: sentence or word. - *

- * API name: {@code strategy} - */ - public final Builder strategy(@Nullable String value) { - this.strategy = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link InferenceChunkingSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public InferenceChunkingSettings build() { - _checkSingleUse(); - - return new InferenceChunkingSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link InferenceChunkingSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, InferenceChunkingSettings::setupInferenceChunkingSettingsDeserializer); - - protected static void setupInferenceChunkingSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::maxChunkSize, JsonpDeserializer.integerDeserializer(), "max_chunk_size"); - op.add(Builder::overlap, JsonpDeserializer.integerDeserializer(), "overlap"); - op.add(Builder::sentenceOverlap, JsonpDeserializer.integerDeserializer(), "sentence_overlap"); - op.add(Builder::strategy, JsonpDeserializer.stringDeserializer(), "strategy"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceEndpoint.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceEndpoint.java deleted file mode 100644 index 458cd09a8..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceEndpoint.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonData; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference._types.InferenceEndpoint - -/** - * Configuration options when storing the inference endpoint - * - * @see API - * specification - */ -@JsonpDeserializable -public class InferenceEndpoint implements JsonpSerializable { - @Nullable - private final InferenceChunkingSettings chunkingSettings; - - private final String service; - - private final JsonData serviceSettings; - - @Nullable - private final JsonData taskSettings; - - // --------------------------------------------------------------------------------------------- - - protected InferenceEndpoint(AbstractBuilder builder) { - - this.chunkingSettings = builder.chunkingSettings; - this.service = ApiTypeHelper.requireNonNull(builder.service, this, "service"); - this.serviceSettings = ApiTypeHelper.requireNonNull(builder.serviceSettings, this, "serviceSettings"); - this.taskSettings = builder.taskSettings; - - } - - public static InferenceEndpoint inferenceEndpointOf(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Chunking configuration object - *

- * API name: {@code chunking_settings} - */ - @Nullable - public final InferenceChunkingSettings chunkingSettings() { - return this.chunkingSettings; - } - - /** - * Required - The service type - *

- * API name: {@code service} - */ - public final String service() { - return this.service; - } - - /** - * Required - Settings specific to the service - *

- * API name: {@code service_settings} - */ - public final JsonData serviceSettings() { - return this.serviceSettings; - } - - /** - * Task settings specific to the service and task type - *

- * API name: {@code task_settings} - */ - @Nullable - public final JsonData taskSettings() { - return this.taskSettings; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.chunkingSettings != null) { - generator.writeKey("chunking_settings"); - this.chunkingSettings.serialize(generator, mapper); - - } - generator.writeKey("service"); - generator.write(this.service); - - generator.writeKey("service_settings"); - this.serviceSettings.serialize(generator, mapper); - - if (this.taskSettings != null) { - generator.writeKey("task_settings"); - this.taskSettings.serialize(generator, mapper); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link InferenceEndpoint}. - */ - - public static class Builder extends InferenceEndpoint.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link InferenceEndpoint}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public InferenceEndpoint build() { - _checkSingleUse(); - - return new InferenceEndpoint(this); - } - } - - public abstract static class AbstractBuilder> - extends - WithJsonObjectBuilderBase { - @Nullable - private InferenceChunkingSettings chunkingSettings; - - private String service; - - private JsonData serviceSettings; - - @Nullable - private JsonData taskSettings; - - /** - * Chunking configuration object - *

- * API name: {@code chunking_settings} - */ - public final BuilderT chunkingSettings(@Nullable InferenceChunkingSettings value) { - this.chunkingSettings = value; - return self(); - } - - /** - * Chunking configuration object - *

- * API name: {@code chunking_settings} - */ - public final BuilderT chunkingSettings( - Function> fn) { - return this.chunkingSettings(fn.apply(new InferenceChunkingSettings.Builder()).build()); - } - - /** - * Required - The service type - *

- * API name: {@code service} - */ - public final BuilderT service(String value) { - this.service = value; - return self(); - } - - /** - * Required - Settings specific to the service - *

- * API name: {@code service_settings} - */ - public final BuilderT serviceSettings(JsonData value) { - this.serviceSettings = value; - return self(); - } - - /** - * Task settings specific to the service and task type - *

- * API name: {@code task_settings} - */ - public final BuilderT taskSettings(@Nullable JsonData value) { - this.taskSettings = value; - return self(); - } - - protected abstract BuilderT self(); - - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link InferenceEndpoint} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, InferenceEndpoint::setupInferenceEndpointDeserializer); - - protected static > void setupInferenceEndpointDeserializer( - ObjectDeserializer op) { - - op.add(AbstractBuilder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); - op.add(AbstractBuilder::service, JsonpDeserializer.stringDeserializer(), "service"); - op.add(AbstractBuilder::serviceSettings, JsonData._DESERIALIZER, "service_settings"); - op.add(AbstractBuilder::taskSettings, JsonData._DESERIALIZER, "task_settings"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceEndpointInfo.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceEndpointInfo.java deleted file mode 100644 index 9ec75b927..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceEndpointInfo.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference._types.InferenceEndpointInfo - -/** - * Represents an inference endpoint as returned by the GET API - * - * @see API - * specification - */ -@JsonpDeserializable -public class InferenceEndpointInfo extends InferenceEndpoint { - private final String inferenceId; - - private final TaskType taskType; - - // --------------------------------------------------------------------------------------------- - - protected InferenceEndpointInfo(AbstractBuilder builder) { - super(builder); - - this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); - this.taskType = ApiTypeHelper.requireNonNull(builder.taskType, this, "taskType"); - - } - - public static InferenceEndpointInfo inferenceEndpointInfoOf( - Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The inference Id - *

- * API name: {@code inference_id} - */ - public final String inferenceId() { - return this.inferenceId; - } - - /** - * Required - The task type - *

- * API name: {@code task_type} - */ - public final TaskType taskType() { - return this.taskType; - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - super.serializeInternal(generator, mapper); - generator.writeKey("inference_id"); - generator.write(this.inferenceId); - - generator.writeKey("task_type"); - this.taskType.serialize(generator, mapper); - - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link InferenceEndpointInfo}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link InferenceEndpointInfo}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public InferenceEndpointInfo build() { - _checkSingleUse(); - - return new InferenceEndpointInfo(this); - } - } - - public abstract static class AbstractBuilder> - extends - InferenceEndpoint.AbstractBuilder { - private String inferenceId; - - private TaskType taskType; - - /** - * Required - The inference Id - *

- * API name: {@code inference_id} - */ - public final BuilderT inferenceId(String value) { - this.inferenceId = value; - return self(); - } - - /** - * Required - The task type - *

- * API name: {@code task_type} - */ - public final BuilderT taskType(TaskType value) { - this.taskType = value; - return self(); - } - - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link InferenceEndpointInfo} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, InferenceEndpointInfo::setupInferenceEndpointInfoDeserializer); - - protected static > void setupInferenceEndpointInfoDeserializer( - ObjectDeserializer op) { - InferenceEndpoint.setupInferenceEndpointDeserializer(op); - op.add(AbstractBuilder::inferenceId, JsonpDeserializer.stringDeserializer(), "inference_id"); - op.add(AbstractBuilder::taskType, TaskType._DESERIALIZER, "task_type"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudResponse.java deleted file mode 100644 index b6c1d6132..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudResponse.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_alibabacloud.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutAlibabacloudResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutAlibabacloudResponse(Builder builder) { - super(builder); - - } - - public static PutAlibabacloudResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutAlibabacloudResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutAlibabacloudResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutAlibabacloudResponse build() { - _checkSingleUse(); - - return new PutAlibabacloudResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutAlibabacloudResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, PutAlibabacloudResponse::setupPutAlibabacloudResponseDeserializer); - - protected static void setupPutAlibabacloudResponseDeserializer( - ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockResponse.java deleted file mode 100644 index 2d0bc5d53..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockResponse.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_amazonbedrock.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutAmazonbedrockResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutAmazonbedrockResponse(Builder builder) { - super(builder); - - } - - public static PutAmazonbedrockResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutAmazonbedrockResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutAmazonbedrockResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutAmazonbedrockResponse build() { - _checkSingleUse(); - - return new PutAmazonbedrockResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutAmazonbedrockResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, PutAmazonbedrockResponse::setupPutAmazonbedrockResponseDeserializer); - - protected static void setupPutAmazonbedrockResponseDeserializer( - ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicResponse.java deleted file mode 100644 index ecf53c22a..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicResponse.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_anthropic.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutAnthropicResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutAnthropicResponse(Builder builder) { - super(builder); - - } - - public static PutAnthropicResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutAnthropicResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutAnthropicResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutAnthropicResponse build() { - _checkSingleUse(); - - return new PutAnthropicResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutAnthropicResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, PutAnthropicResponse::setupPutAnthropicResponseDeserializer); - - protected static void setupPutAnthropicResponseDeserializer(ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioResponse.java deleted file mode 100644 index 1edb52050..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioResponse.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_azureaistudio.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutAzureaistudioResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutAzureaistudioResponse(Builder builder) { - super(builder); - - } - - public static PutAzureaistudioResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutAzureaistudioResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutAzureaistudioResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutAzureaistudioResponse build() { - _checkSingleUse(); - - return new PutAzureaistudioResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutAzureaistudioResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, PutAzureaistudioResponse::setupPutAzureaistudioResponseDeserializer); - - protected static void setupPutAzureaistudioResponseDeserializer( - ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiResponse.java deleted file mode 100644 index 3674a08b7..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiResponse.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_azureopenai.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutAzureopenaiResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutAzureopenaiResponse(Builder builder) { - super(builder); - - } - - public static PutAzureopenaiResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutAzureopenaiResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutAzureopenaiResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutAzureopenaiResponse build() { - _checkSingleUse(); - - return new PutAzureopenaiResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutAzureopenaiResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, PutAzureopenaiResponse::setupPutAzureopenaiResponseDeserializer); - - protected static void setupPutAzureopenaiResponseDeserializer( - ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereResponse.java deleted file mode 100644 index 8a3dbffeb..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereResponse.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_cohere.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutCohereResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutCohereResponse(Builder builder) { - super(builder); - - } - - public static PutCohereResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutCohereResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutCohereResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutCohereResponse build() { - _checkSingleUse(); - - return new PutCohereResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutCohereResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, PutCohereResponse::setupPutCohereResponseDeserializer); - - protected static void setupPutCohereResponseDeserializer(ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisResponse.java deleted file mode 100644 index 04f54e36c..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisResponse.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_eis.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutEisResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutEisResponse(Builder builder) { - super(builder); - - } - - public static PutEisResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutEisResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutEisResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutEisResponse build() { - _checkSingleUse(); - - return new PutEisResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutEisResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, - PutEisResponse::setupPutEisResponseDeserializer); - - protected static void setupPutEisResponseDeserializer(ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchResponse.java deleted file mode 100644 index fcc1ec47b..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchResponse.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_elasticsearch.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutElasticsearchResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutElasticsearchResponse(Builder builder) { - super(builder); - - } - - public static PutElasticsearchResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutElasticsearchResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutElasticsearchResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutElasticsearchResponse build() { - _checkSingleUse(); - - return new PutElasticsearchResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutElasticsearchResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, PutElasticsearchResponse::setupPutElasticsearchResponseDeserializer); - - protected static void setupPutElasticsearchResponseDeserializer( - ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserResponse.java deleted file mode 100644 index 565d8f80b..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserResponse.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_elser.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutElserResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutElserResponse(Builder builder) { - super(builder); - - } - - public static PutElserResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutElserResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutElserResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutElserResponse build() { - _checkSingleUse(); - - return new PutElserResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutElserResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, - PutElserResponse::setupPutElserResponseDeserializer); - - protected static void setupPutElserResponseDeserializer(ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioResponse.java deleted file mode 100644 index ec5b9255e..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioResponse.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_googleaistudio.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutGoogleaistudioResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutGoogleaistudioResponse(Builder builder) { - super(builder); - - } - - public static PutGoogleaistudioResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutGoogleaistudioResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutGoogleaistudioResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutGoogleaistudioResponse build() { - _checkSingleUse(); - - return new PutGoogleaistudioResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutGoogleaistudioResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, PutGoogleaistudioResponse::setupPutGoogleaistudioResponseDeserializer); - - protected static void setupPutGoogleaistudioResponseDeserializer( - ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiResponse.java deleted file mode 100644 index 8eb2d84cb..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiResponse.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_googlevertexai.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutGooglevertexaiResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutGooglevertexaiResponse(Builder builder) { - super(builder); - - } - - public static PutGooglevertexaiResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutGooglevertexaiResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutGooglevertexaiResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutGooglevertexaiResponse build() { - _checkSingleUse(); - - return new PutGooglevertexaiResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutGooglevertexaiResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, PutGooglevertexaiResponse::setupPutGooglevertexaiResponseDeserializer); - - protected static void setupPutGooglevertexaiResponseDeserializer( - ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceResponse.java deleted file mode 100644 index 8ed26042f..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceResponse.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_hugging_face.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutHuggingFaceResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutHuggingFaceResponse(Builder builder) { - super(builder); - - } - - public static PutHuggingFaceResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutHuggingFaceResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutHuggingFaceResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutHuggingFaceResponse build() { - _checkSingleUse(); - - return new PutHuggingFaceResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutHuggingFaceResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, PutHuggingFaceResponse::setupPutHuggingFaceResponseDeserializer); - - protected static void setupPutHuggingFaceResponseDeserializer( - ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiResponse.java deleted file mode 100644 index 6d40a39ab..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiResponse.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_jinaai.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutJinaaiResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutJinaaiResponse(Builder builder) { - super(builder); - - } - - public static PutJinaaiResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutJinaaiResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutJinaaiResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutJinaaiResponse build() { - _checkSingleUse(); - - return new PutJinaaiResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutJinaaiResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, PutJinaaiResponse::setupPutJinaaiResponseDeserializer); - - protected static void setupPutJinaaiResponseDeserializer(ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralResponse.java deleted file mode 100644 index 6774ddb62..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralResponse.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_mistral.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutMistralResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutMistralResponse(Builder builder) { - super(builder); - - } - - public static PutMistralResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutMistralResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutMistralResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutMistralResponse build() { - _checkSingleUse(); - - return new PutMistralResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutMistralResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, PutMistralResponse::setupPutMistralResponseDeserializer); - - protected static void setupPutMistralResponseDeserializer(ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiResponse.java deleted file mode 100644 index cb46d4b17..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiResponse.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_openai.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutOpenaiResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutOpenaiResponse(Builder builder) { - super(builder); - - } - - public static PutOpenaiResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutOpenaiResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutOpenaiResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutOpenaiResponse build() { - _checkSingleUse(); - - return new PutOpenaiResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutOpenaiResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, PutOpenaiResponse::setupPutOpenaiResponseDeserializer); - - protected static void setupPutOpenaiResponseDeserializer(ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutRequest.java deleted file mode 100644 index 6f734f226..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutRequest.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.elasticsearch._types.RequestBase; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.endpoints.SimpleEndpoint; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import java.lang.String; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put.Request - -/** - * Create an inference endpoint. When you create an inference endpoint, the - * associated machine learning model is automatically deployed if it is not - * already running. After creating the endpoint, wait for the model deployment - * to complete before using it. To verify the deployment status, use the get - * trained model statistics API. Look for - * "state": "fully_allocated" in the response - * and ensure that the "allocation_count" matches the - * "target_allocation_count". Avoid creating multiple - * endpoints for the same model unless required, as each endpoint consumes - * significant resources. - *

- * IMPORTANT: The inference APIs enable you to use certain services, such as - * built-in machine learning models (ELSER, E5), models uploaded through Eland, - * Cohere, OpenAI, Mistral, Azure OpenAI, Google AI Studio, Google Vertex AI, - * Anthropic, Watsonx.ai, or Hugging Face. For built-in models and models - * uploaded through Eland, the inference APIs offer an alternative way to use - * and manage trained models. However, if you do not plan to use the inference - * APIs to use these models or if you want to use non-NLP models, use the - * machine learning trained model APIs. - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutRequest extends RequestBase implements JsonpSerializable { - private final String inferenceId; - - @Nullable - private final TaskType taskType; - - private final InferenceEndpoint inferenceConfig; - - // --------------------------------------------------------------------------------------------- - - private PutRequest(Builder builder) { - - this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); - this.taskType = builder.taskType; - this.inferenceConfig = ApiTypeHelper.requireNonNull(builder.inferenceConfig, this, "inferenceConfig"); - - } - - public static PutRequest of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The inference Id - *

- * API name: {@code inference_id} - */ - public final String inferenceId() { - return this.inferenceId; - } - - /** - * The task type - *

- * API name: {@code task_type} - */ - @Nullable - public final TaskType taskType() { - return this.taskType; - } - - /** - * Required - Request body. - */ - public final InferenceEndpoint inferenceConfig() { - return this.inferenceConfig; - } - - /** - * Serialize this value to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - this.inferenceConfig.serialize(generator, mapper); - - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutRequest}. - */ - - public static class Builder extends RequestBase.AbstractBuilder implements ObjectBuilder { - private String inferenceId; - - @Nullable - private TaskType taskType; - - private InferenceEndpoint inferenceConfig; - - /** - * Required - The inference Id - *

- * API name: {@code inference_id} - */ - public final Builder inferenceId(String value) { - this.inferenceId = value; - return this; - } - - /** - * The task type - *

- * API name: {@code task_type} - */ - public final Builder taskType(@Nullable TaskType value) { - this.taskType = value; - return this; - } - - /** - * Required - Request body. - */ - public final Builder inferenceConfig(InferenceEndpoint value) { - this.inferenceConfig = value; - return this; - } - - /** - * Required - Request body. - */ - public final Builder inferenceConfig(Function> fn) { - return this.inferenceConfig(fn.apply(new InferenceEndpoint.Builder()).build()); - } - - @Override - public Builder withJson(JsonParser parser, JsonpMapper mapper) { - - @SuppressWarnings("unchecked") - InferenceEndpoint value = (InferenceEndpoint) InferenceEndpoint._DESERIALIZER.deserialize(parser, mapper); - return this.inferenceConfig(value); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutRequest}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutRequest build() { - _checkSingleUse(); - - return new PutRequest(this); - } - } - - public static final JsonpDeserializer _DESERIALIZER = createPutRequestDeserializer(); - protected static JsonpDeserializer createPutRequestDeserializer() { - - JsonpDeserializer valueDeserializer = InferenceEndpoint._DESERIALIZER; - - return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() - .inferenceConfig(valueDeserializer.deserialize(parser, mapper, event)).build()); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Endpoint "{@code inference.put}". - */ - public static final Endpoint _ENDPOINT = new SimpleEndpoint<>( - "es/inference.put", - - // Request method - request -> { - return "PUT"; - - }, - - // Request path - request -> { - final int _inferenceId = 1 << 0; - final int _taskType = 1 << 1; - - int propsSet = 0; - - propsSet |= _inferenceId; - if (request.taskType() != null) - propsSet |= _taskType; - - if (propsSet == (_inferenceId)) { - StringBuilder buf = new StringBuilder(); - buf.append("/_inference"); - buf.append("/"); - SimpleEndpoint.pathEncode(request.inferenceId, buf); - return buf.toString(); - } - if (propsSet == (_taskType | _inferenceId)) { - StringBuilder buf = new StringBuilder(); - buf.append("/_inference"); - buf.append("/"); - SimpleEndpoint.pathEncode(request.taskType.jsonValue(), buf); - buf.append("/"); - SimpleEndpoint.pathEncode(request.inferenceId, buf); - return buf.toString(); - } - throw SimpleEndpoint.noPathTemplateFound("path"); - - }, - - // Path parameters - request -> { - Map params = new HashMap<>(); - final int _inferenceId = 1 << 0; - final int _taskType = 1 << 1; - - int propsSet = 0; - - propsSet |= _inferenceId; - if (request.taskType() != null) - propsSet |= _taskType; - - if (propsSet == (_inferenceId)) { - params.put("inferenceId", request.inferenceId); - } - if (propsSet == (_taskType | _inferenceId)) { - params.put("taskType", request.taskType.jsonValue()); - params.put("inferenceId", request.inferenceId); - } - return params; - }, - - // Request parameters - request -> { - return Collections.emptyMap(); - - }, SimpleEndpoint.emptyMap(), true, PutResponse._DESERIALIZER); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutResponse.java deleted file mode 100644 index ec984c519..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutResponse.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutResponse(Builder builder) { - super(builder); - - } - - public static PutResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutResponse build() { - _checkSingleUse(); - - return new PutResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, - PutResponse::setupPutResponseDeserializer); - - protected static void setupPutResponseDeserializer(ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiResponse.java deleted file mode 100644 index bda8463e7..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiResponse.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_voyageai.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutVoyageaiResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutVoyageaiResponse(Builder builder) { - super(builder); - - } - - public static PutVoyageaiResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutVoyageaiResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutVoyageaiResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutVoyageaiResponse build() { - _checkSingleUse(); - - return new PutVoyageaiResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutVoyageaiResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, PutVoyageaiResponse::setupPutVoyageaiResponseDeserializer); - - protected static void setupPutVoyageaiResponseDeserializer(ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxResponse.java deleted file mode 100644 index 6bfff7621..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxResponse.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_watsonx.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class PutWatsonxResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private PutWatsonxResponse(Builder builder) { - super(builder); - - } - - public static PutWatsonxResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link PutWatsonxResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link PutWatsonxResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public PutWatsonxResponse build() { - _checkSingleUse(); - - return new PutWatsonxResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link PutWatsonxResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, PutWatsonxResponse::setupPutWatsonxResponseDeserializer); - - protected static void setupPutWatsonxResponseDeserializer(ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RankedDocument.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RankedDocument.java deleted file mode 100644 index 2cd435013..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RankedDocument.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Float; -import java.lang.Integer; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference._types.RankedDocument - -/** - * The rerank result object representing a single ranked document id: the - * original index of the document in the request relevance_score: the - * relevance_score of the document relative to the query text: Optional, the - * text of the document, if requested - * - * @see API - * specification - */ -@JsonpDeserializable -public class RankedDocument implements JsonpSerializable { - private final int index; - - private final float relevanceScore; - - @Nullable - private final String text; - - // --------------------------------------------------------------------------------------------- - - private RankedDocument(Builder builder) { - - this.index = ApiTypeHelper.requireNonNull(builder.index, this, "index"); - this.relevanceScore = ApiTypeHelper.requireNonNull(builder.relevanceScore, this, "relevanceScore"); - this.text = builder.text; - - } - - public static RankedDocument of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - API name: {@code index} - */ - public final int index() { - return this.index; - } - - /** - * Required - API name: {@code relevance_score} - */ - public final float relevanceScore() { - return this.relevanceScore; - } - - /** - * API name: {@code text} - */ - @Nullable - public final String text() { - return this.text; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("index"); - generator.write(this.index); - - generator.writeKey("relevance_score"); - generator.write(this.relevanceScore); - - if (this.text != null) { - generator.writeKey("text"); - generator.write(this.text); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link RankedDocument}. - */ - - public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { - private Integer index; - - private Float relevanceScore; - - @Nullable - private String text; - - /** - * Required - API name: {@code index} - */ - public final Builder index(int value) { - this.index = value; - return this; - } - - /** - * Required - API name: {@code relevance_score} - */ - public final Builder relevanceScore(float value) { - this.relevanceScore = value; - return this; - } - - /** - * API name: {@code text} - */ - public final Builder text(@Nullable String value) { - this.text = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link RankedDocument}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public RankedDocument build() { - _checkSingleUse(); - - return new RankedDocument(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link RankedDocument} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, - RankedDocument::setupRankedDocumentDeserializer); - - protected static void setupRankedDocumentDeserializer(ObjectDeserializer op) { - - op.add(Builder::index, JsonpDeserializer.integerDeserializer(), "index"); - op.add(Builder::relevanceScore, JsonpDeserializer.floatDeserializer(), "relevance_score"); - op.add(Builder::text, JsonpDeserializer.stringDeserializer(), "text"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RateLimitSetting.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RateLimitSetting.java deleted file mode 100644 index d26e76129..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RateLimitSetting.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference._types.RateLimitSetting - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class RateLimitSetting implements JsonpSerializable { - @Nullable - private final Integer requestsPerMinute; - - // --------------------------------------------------------------------------------------------- - - private RateLimitSetting(Builder builder) { - - this.requestsPerMinute = builder.requestsPerMinute; - - } - - public static RateLimitSetting of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * The number of requests allowed per minute. - *

- * API name: {@code requests_per_minute} - */ - @Nullable - public final Integer requestsPerMinute() { - return this.requestsPerMinute; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.requestsPerMinute != null) { - generator.writeKey("requests_per_minute"); - generator.write(this.requestsPerMinute); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link RateLimitSetting}. - */ - - public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { - @Nullable - private Integer requestsPerMinute; - - /** - * The number of requests allowed per minute. - *

- * API name: {@code requests_per_minute} - */ - public final Builder requestsPerMinute(@Nullable Integer value) { - this.requestsPerMinute = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link RateLimitSetting}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public RateLimitSetting build() { - _checkSingleUse(); - - return new RateLimitSetting(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link RateLimitSetting} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, - RateLimitSetting::setupRateLimitSettingDeserializer); - - protected static void setupRateLimitSettingDeserializer(ObjectDeserializer op) { - - op.add(Builder::requestsPerMinute, JsonpDeserializer.integerDeserializer(), "requests_per_minute"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RequestChatCompletionBase.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RequestChatCompletionBase.java deleted file mode 100644 index 1941152d1..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RequestChatCompletionBase.java +++ /dev/null @@ -1,461 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.elasticsearch._types.RequestBase; -import co.elastic.clients.elasticsearch.inference.chat_completion_unified.CompletionTool; -import co.elastic.clients.elasticsearch.inference.chat_completion_unified.CompletionToolType; -import co.elastic.clients.elasticsearch.inference.chat_completion_unified.Message; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Float; -import java.lang.Long; -import java.lang.String; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference._types.RequestChatCompletionBase - -/** - * - * @see API - * specification - */ - -public abstract class RequestChatCompletionBase extends RequestBase implements JsonpSerializable { - private final List messages; - - @Nullable - private final String model; - - @Nullable - private final Long maxCompletionTokens; - - private final List stop; - - @Nullable - private final Float temperature; - - @Nullable - private final CompletionToolType toolChoice; - - private final List tools; - - @Nullable - private final Float topP; - - // --------------------------------------------------------------------------------------------- - - protected RequestChatCompletionBase(AbstractBuilder builder) { - - this.messages = ApiTypeHelper.unmodifiableRequired(builder.messages, this, "messages"); - this.model = builder.model; - this.maxCompletionTokens = builder.maxCompletionTokens; - this.stop = ApiTypeHelper.unmodifiable(builder.stop); - this.temperature = builder.temperature; - this.toolChoice = builder.toolChoice; - this.tools = ApiTypeHelper.unmodifiable(builder.tools); - this.topP = builder.topP; - - } - - /** - * Required - A list of objects representing the conversation. - *

- * API name: {@code messages} - */ - public final List messages() { - return this.messages; - } - - /** - * The ID of the model to use. - *

- * API name: {@code model} - */ - @Nullable - public final String model() { - return this.model; - } - - /** - * The upper bound limit for the number of tokens that can be generated for a - * completion request. - *

- * API name: {@code max_completion_tokens} - */ - @Nullable - public final Long maxCompletionTokens() { - return this.maxCompletionTokens; - } - - /** - * A sequence of strings to control when the model should stop generating - * additional tokens. - *

- * API name: {@code stop} - */ - public final List stop() { - return this.stop; - } - - /** - * The sampling temperature to use. - *

- * API name: {@code temperature} - */ - @Nullable - public final Float temperature() { - return this.temperature; - } - - /** - * Controls which tool is called by the model. - *

- * API name: {@code tool_choice} - */ - @Nullable - public final CompletionToolType toolChoice() { - return this.toolChoice; - } - - /** - * A list of tools that the model can call. - *

- * API name: {@code tools} - */ - public final List tools() { - return this.tools; - } - - /** - * Nucleus sampling, an alternative to sampling with temperature. - *

- * API name: {@code top_p} - */ - @Nullable - public final Float topP() { - return this.topP; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (ApiTypeHelper.isDefined(this.messages)) { - generator.writeKey("messages"); - generator.writeStartArray(); - for (Message item0 : this.messages) { - item0.serialize(generator, mapper); - - } - generator.writeEnd(); - - } - if (this.model != null) { - generator.writeKey("model"); - generator.write(this.model); - - } - if (this.maxCompletionTokens != null) { - generator.writeKey("max_completion_tokens"); - generator.write(this.maxCompletionTokens); - - } - if (ApiTypeHelper.isDefined(this.stop)) { - generator.writeKey("stop"); - generator.writeStartArray(); - for (String item0 : this.stop) { - generator.write(item0); - - } - generator.writeEnd(); - - } - if (this.temperature != null) { - generator.writeKey("temperature"); - generator.write(this.temperature); - - } - if (this.toolChoice != null) { - generator.writeKey("tool_choice"); - this.toolChoice.serialize(generator, mapper); - - } - if (ApiTypeHelper.isDefined(this.tools)) { - generator.writeKey("tools"); - generator.writeStartArray(); - for (CompletionTool item0 : this.tools) { - item0.serialize(generator, mapper); - - } - generator.writeEnd(); - - } - if (this.topP != null) { - generator.writeKey("top_p"); - generator.write(this.topP); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - public abstract static class AbstractBuilder> - extends - RequestBase.AbstractBuilder { - private List messages; - - @Nullable - private String model; - - @Nullable - private Long maxCompletionTokens; - - @Nullable - private List stop; - - @Nullable - private Float temperature; - - @Nullable - private CompletionToolType toolChoice; - - @Nullable - private List tools; - - @Nullable - private Float topP; - - /** - * Required - A list of objects representing the conversation. - *

- * API name: {@code messages} - *

- * Adds all elements of list to messages. - */ - public final BuilderT messages(List list) { - this.messages = _listAddAll(this.messages, list); - return self(); - } - - /** - * Required - A list of objects representing the conversation. - *

- * API name: {@code messages} - *

- * Adds one or more values to messages. - */ - public final BuilderT messages(Message value, Message... values) { - this.messages = _listAdd(this.messages, value, values); - return self(); - } - - /** - * Required - A list of objects representing the conversation. - *

- * API name: {@code messages} - *

- * Adds a value to messages using a builder lambda. - */ - public final BuilderT messages(Function> fn) { - return messages(fn.apply(new Message.Builder()).build()); - } - - /** - * The ID of the model to use. - *

- * API name: {@code model} - */ - public final BuilderT model(@Nullable String value) { - this.model = value; - return self(); - } - - /** - * The upper bound limit for the number of tokens that can be generated for a - * completion request. - *

- * API name: {@code max_completion_tokens} - */ - public final BuilderT maxCompletionTokens(@Nullable Long value) { - this.maxCompletionTokens = value; - return self(); - } - - /** - * A sequence of strings to control when the model should stop generating - * additional tokens. - *

- * API name: {@code stop} - *

- * Adds all elements of list to stop. - */ - public final BuilderT stop(List list) { - this.stop = _listAddAll(this.stop, list); - return self(); - } - - /** - * A sequence of strings to control when the model should stop generating - * additional tokens. - *

- * API name: {@code stop} - *

- * Adds one or more values to stop. - */ - public final BuilderT stop(String value, String... values) { - this.stop = _listAdd(this.stop, value, values); - return self(); - } - - /** - * The sampling temperature to use. - *

- * API name: {@code temperature} - */ - public final BuilderT temperature(@Nullable Float value) { - this.temperature = value; - return self(); - } - - /** - * Controls which tool is called by the model. - *

- * API name: {@code tool_choice} - */ - public final BuilderT toolChoice(@Nullable CompletionToolType value) { - this.toolChoice = value; - return self(); - } - - /** - * Controls which tool is called by the model. - *

- * API name: {@code tool_choice} - */ - public final BuilderT toolChoice(Function> fn) { - return this.toolChoice(fn.apply(new CompletionToolType.Builder()).build()); - } - - /** - * A list of tools that the model can call. - *

- * API name: {@code tools} - *

- * Adds all elements of list to tools. - */ - public final BuilderT tools(List list) { - this.tools = _listAddAll(this.tools, list); - return self(); - } - - /** - * A list of tools that the model can call. - *

- * API name: {@code tools} - *

- * Adds one or more values to tools. - */ - public final BuilderT tools(CompletionTool value, CompletionTool... values) { - this.tools = _listAdd(this.tools, value, values); - return self(); - } - - /** - * A list of tools that the model can call. - *

- * API name: {@code tools} - *

- * Adds a value to tools using a builder lambda. - */ - public final BuilderT tools(Function> fn) { - return tools(fn.apply(new CompletionTool.Builder()).build()); - } - - /** - * Nucleus sampling, an alternative to sampling with temperature. - *

- * API name: {@code top_p} - */ - public final BuilderT topP(@Nullable Float value) { - this.topP = value; - return self(); - } - - protected abstract BuilderT self(); - - } - - // --------------------------------------------------------------------------------------------- - protected static > void setupRequestChatCompletionBaseDeserializer( - ObjectDeserializer op) { - - op.add(AbstractBuilder::messages, JsonpDeserializer.arrayDeserializer(Message._DESERIALIZER), "messages"); - op.add(AbstractBuilder::model, JsonpDeserializer.stringDeserializer(), "model"); - op.add(AbstractBuilder::maxCompletionTokens, JsonpDeserializer.longDeserializer(), "max_completion_tokens"); - op.add(AbstractBuilder::stop, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), - "stop"); - op.add(AbstractBuilder::temperature, JsonpDeserializer.floatDeserializer(), "temperature"); - op.add(AbstractBuilder::toolChoice, CompletionToolType._DESERIALIZER, "tool_choice"); - op.add(AbstractBuilder::tools, JsonpDeserializer.arrayDeserializer(CompletionTool._DESERIALIZER), "tools"); - op.add(AbstractBuilder::topP, JsonpDeserializer.floatDeserializer(), "top_p"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankRequest.java deleted file mode 100644 index f1f853029..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankRequest.java +++ /dev/null @@ -1,383 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.elasticsearch._types.RequestBase; -import co.elastic.clients.elasticsearch._types.Time; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.endpoints.SimpleEndpoint; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.rerank.Request - -/** - * Perform rereanking inference on the service - * - * @see API - * specification - */ -@JsonpDeserializable -public class RerankRequest extends RequestBase implements JsonpSerializable { - private final String inferenceId; - - private final List input; - - private final String query; - - @Nullable - private final JsonData taskSettings; - - @Nullable - private final Time timeout; - - // --------------------------------------------------------------------------------------------- - - private RerankRequest(Builder builder) { - - this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); - this.input = ApiTypeHelper.unmodifiableRequired(builder.input, this, "input"); - this.query = ApiTypeHelper.requireNonNull(builder.query, this, "query"); - this.taskSettings = builder.taskSettings; - this.timeout = builder.timeout; - - } - - public static RerankRequest of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The unique identifier for the inference endpoint. - *

- * API name: {@code inference_id} - */ - public final String inferenceId() { - return this.inferenceId; - } - - /** - * Required - The text on which you want to perform the inference task. It can - * be a single string or an array.

- *

- * info Inference endpoints for the completion task type currently - * only support a single string as input. - *

- *
- *

- * API name: {@code input} - */ - public final List input() { - return this.input; - } - - /** - * Required - Query input. - *

- * API name: {@code query} - */ - public final String query() { - return this.query; - } - - /** - * Task settings for the individual inference request. These settings are - * specific to the task type you specified and override the task settings - * specified when initializing the service. - *

- * API name: {@code task_settings} - */ - @Nullable - public final JsonData taskSettings() { - return this.taskSettings; - } - - /** - * The amount of time to wait for the inference request to complete. - *

- * API name: {@code timeout} - */ - @Nullable - public final Time timeout() { - return this.timeout; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (ApiTypeHelper.isDefined(this.input)) { - generator.writeKey("input"); - generator.writeStartArray(); - for (String item0 : this.input) { - generator.write(item0); - - } - generator.writeEnd(); - - } - generator.writeKey("query"); - generator.write(this.query); - - if (this.taskSettings != null) { - generator.writeKey("task_settings"); - this.taskSettings.serialize(generator, mapper); - - } - - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link RerankRequest}. - */ - - public static class Builder extends RequestBase.AbstractBuilder implements ObjectBuilder { - private String inferenceId; - - private List input; - - private String query; - - @Nullable - private JsonData taskSettings; - - @Nullable - private Time timeout; - - /** - * Required - The unique identifier for the inference endpoint. - *

- * API name: {@code inference_id} - */ - public final Builder inferenceId(String value) { - this.inferenceId = value; - return this; - } - - /** - * Required - The text on which you want to perform the inference task. It can - * be a single string or an array.

- *

- * info Inference endpoints for the completion task type currently - * only support a single string as input. - *

- *
- *

- * API name: {@code input} - *

- * Adds all elements of list to input. - */ - public final Builder input(List list) { - this.input = _listAddAll(this.input, list); - return this; - } - - /** - * Required - The text on which you want to perform the inference task. It can - * be a single string or an array.

- *

- * info Inference endpoints for the completion task type currently - * only support a single string as input. - *

- *
- *

- * API name: {@code input} - *

- * Adds one or more values to input. - */ - public final Builder input(String value, String... values) { - this.input = _listAdd(this.input, value, values); - return this; - } - - /** - * Required - Query input. - *

- * API name: {@code query} - */ - public final Builder query(String value) { - this.query = value; - return this; - } - - /** - * Task settings for the individual inference request. These settings are - * specific to the task type you specified and override the task settings - * specified when initializing the service. - *

- * API name: {@code task_settings} - */ - public final Builder taskSettings(@Nullable JsonData value) { - this.taskSettings = value; - return this; - } - - /** - * The amount of time to wait for the inference request to complete. - *

- * API name: {@code timeout} - */ - public final Builder timeout(@Nullable Time value) { - this.timeout = value; - return this; - } - - /** - * The amount of time to wait for the inference request to complete. - *

- * API name: {@code timeout} - */ - public final Builder timeout(Function> fn) { - return this.timeout(fn.apply(new Time.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link RerankRequest}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public RerankRequest build() { - _checkSingleUse(); - - return new RerankRequest(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link RerankRequest} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, - RerankRequest::setupRerankRequestDeserializer); - - protected static void setupRerankRequestDeserializer(ObjectDeserializer op) { - - op.add(Builder::input, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), "input"); - op.add(Builder::query, JsonpDeserializer.stringDeserializer(), "query"); - op.add(Builder::taskSettings, JsonData._DESERIALIZER, "task_settings"); - - } - - // --------------------------------------------------------------------------------------------- - - /** - * Endpoint "{@code inference.rerank}". - */ - public static final Endpoint _ENDPOINT = new SimpleEndpoint<>( - "es/inference.rerank", - - // Request method - request -> { - return "POST"; - - }, - - // Request path - request -> { - final int _inferenceId = 1 << 0; - - int propsSet = 0; - - propsSet |= _inferenceId; - - if (propsSet == (_inferenceId)) { - StringBuilder buf = new StringBuilder(); - buf.append("/_inference"); - buf.append("/rerank"); - buf.append("/"); - SimpleEndpoint.pathEncode(request.inferenceId, buf); - return buf.toString(); - } - throw SimpleEndpoint.noPathTemplateFound("path"); - - }, - - // Path parameters - request -> { - Map params = new HashMap<>(); - final int _inferenceId = 1 << 0; - - int propsSet = 0; - - propsSet |= _inferenceId; - - if (propsSet == (_inferenceId)) { - params.put("inferenceId", request.inferenceId); - } - return params; - }, - - // Request parameters - request -> { - Map params = new HashMap<>(); - if (request.timeout != null) { - params.put("timeout", request.timeout._toJsonString()); - } - return params; - - }, SimpleEndpoint.emptyMap(), true, RerankResponse._DESERIALIZER); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankResponse.java deleted file mode 100644 index 9cb497631..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankResponse.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.rerank.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class RerankResponse extends RerankedInferenceResult { - // --------------------------------------------------------------------------------------------- - - private RerankResponse(Builder builder) { - super(builder); - - } - - public static RerankResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link RerankResponse}. - */ - - public static class Builder extends RerankedInferenceResult.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link RerankResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public RerankResponse build() { - _checkSingleUse(); - - return new RerankResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link RerankResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, - RerankResponse::setupRerankResponseDeserializer); - - protected static void setupRerankResponseDeserializer(ObjectDeserializer op) { - RerankedInferenceResult.setupRerankedInferenceResultDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankedInferenceResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankedInferenceResult.java deleted file mode 100644 index 62c2f8f6a..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankedInferenceResult.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference._types.RerankedInferenceResult - -/** - * Defines the response for a rerank request. - * - * @see API - * specification - */ - -public abstract class RerankedInferenceResult implements JsonpSerializable { - private final List rerank; - - // --------------------------------------------------------------------------------------------- - - protected RerankedInferenceResult(AbstractBuilder builder) { - - this.rerank = ApiTypeHelper.unmodifiableRequired(builder.rerank, this, "rerank"); - - } - - /** - * Required - API name: {@code rerank} - */ - public final List rerank() { - return this.rerank; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (ApiTypeHelper.isDefined(this.rerank)) { - generator.writeKey("rerank"); - generator.writeStartArray(); - for (RankedDocument item0 : this.rerank) { - item0.serialize(generator, mapper); - - } - generator.writeEnd(); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - public abstract static class AbstractBuilder> - extends - WithJsonObjectBuilderBase { - private List rerank; - - /** - * Required - API name: {@code rerank} - *

- * Adds all elements of list to rerank. - */ - public final BuilderT rerank(List list) { - this.rerank = _listAddAll(this.rerank, list); - return self(); - } - - /** - * Required - API name: {@code rerank} - *

- * Adds one or more values to rerank. - */ - public final BuilderT rerank(RankedDocument value, RankedDocument... values) { - this.rerank = _listAdd(this.rerank, value, values); - return self(); - } - - /** - * Required - API name: {@code rerank} - *

- * Adds a value to rerank using a builder lambda. - */ - public final BuilderT rerank(Function> fn) { - return rerank(fn.apply(new RankedDocument.Builder()).build()); - } - - protected abstract BuilderT self(); - - } - - // --------------------------------------------------------------------------------------------- - protected static > void setupRerankedInferenceResultDeserializer( - ObjectDeserializer op) { - - op.add(AbstractBuilder::rerank, JsonpDeserializer.arrayDeserializer(RankedDocument._DESERIALIZER), "rerank"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingInferenceResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingInferenceResult.java deleted file mode 100644 index 75ef28131..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingInferenceResult.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference._types.SparseEmbeddingInferenceResult - -/** - * The response format for the sparse embedding request. - * - * @see API - * specification - */ - -public abstract class SparseEmbeddingInferenceResult implements JsonpSerializable { - private final List sparseEmbedding; - - // --------------------------------------------------------------------------------------------- - - protected SparseEmbeddingInferenceResult(AbstractBuilder builder) { - - this.sparseEmbedding = ApiTypeHelper.unmodifiableRequired(builder.sparseEmbedding, this, "sparseEmbedding"); - - } - - /** - * Required - API name: {@code sparse_embedding} - */ - public final List sparseEmbedding() { - return this.sparseEmbedding; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (ApiTypeHelper.isDefined(this.sparseEmbedding)) { - generator.writeKey("sparse_embedding"); - generator.writeStartArray(); - for (SparseEmbeddingResult item0 : this.sparseEmbedding) { - item0.serialize(generator, mapper); - - } - generator.writeEnd(); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - public abstract static class AbstractBuilder> - extends - WithJsonObjectBuilderBase { - private List sparseEmbedding; - - /** - * Required - API name: {@code sparse_embedding} - *

- * Adds all elements of list to sparseEmbedding. - */ - public final BuilderT sparseEmbedding(List list) { - this.sparseEmbedding = _listAddAll(this.sparseEmbedding, list); - return self(); - } - - /** - * Required - API name: {@code sparse_embedding} - *

- * Adds one or more values to sparseEmbedding. - */ - public final BuilderT sparseEmbedding(SparseEmbeddingResult value, SparseEmbeddingResult... values) { - this.sparseEmbedding = _listAdd(this.sparseEmbedding, value, values); - return self(); - } - - /** - * Required - API name: {@code sparse_embedding} - *

- * Adds a value to sparseEmbedding using a builder lambda. - */ - public final BuilderT sparseEmbedding( - Function> fn) { - return sparseEmbedding(fn.apply(new SparseEmbeddingResult.Builder()).build()); - } - - protected abstract BuilderT self(); - - } - - // --------------------------------------------------------------------------------------------- - protected static > void setupSparseEmbeddingInferenceResultDeserializer( - ObjectDeserializer op) { - - op.add(AbstractBuilder::sparseEmbedding, - JsonpDeserializer.arrayDeserializer(SparseEmbeddingResult._DESERIALIZER), "sparse_embedding"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingRequest.java deleted file mode 100644 index dc311f406..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingRequest.java +++ /dev/null @@ -1,337 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.elasticsearch._types.RequestBase; -import co.elastic.clients.elasticsearch._types.Time; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.endpoints.SimpleEndpoint; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.sparse_embedding.Request - -/** - * Perform sparse embedding inference on the service - * - * @see API - * specification - */ -@JsonpDeserializable -public class SparseEmbeddingRequest extends RequestBase implements JsonpSerializable { - private final String inferenceId; - - private final List input; - - @Nullable - private final JsonData taskSettings; - - @Nullable - private final Time timeout; - - // --------------------------------------------------------------------------------------------- - - private SparseEmbeddingRequest(Builder builder) { - - this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); - this.input = ApiTypeHelper.unmodifiableRequired(builder.input, this, "input"); - this.taskSettings = builder.taskSettings; - this.timeout = builder.timeout; - - } - - public static SparseEmbeddingRequest of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The inference Id - *

- * API name: {@code inference_id} - */ - public final String inferenceId() { - return this.inferenceId; - } - - /** - * Required - Inference input. Either a string or an array of strings. - *

- * API name: {@code input} - */ - public final List input() { - return this.input; - } - - /** - * Optional task settings - *

- * API name: {@code task_settings} - */ - @Nullable - public final JsonData taskSettings() { - return this.taskSettings; - } - - /** - * Specifies the amount of time to wait for the inference request to complete. - *

- * API name: {@code timeout} - */ - @Nullable - public final Time timeout() { - return this.timeout; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (ApiTypeHelper.isDefined(this.input)) { - generator.writeKey("input"); - generator.writeStartArray(); - for (String item0 : this.input) { - generator.write(item0); - - } - generator.writeEnd(); - - } - if (this.taskSettings != null) { - generator.writeKey("task_settings"); - this.taskSettings.serialize(generator, mapper); - - } - - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link SparseEmbeddingRequest}. - */ - - public static class Builder extends RequestBase.AbstractBuilder - implements - ObjectBuilder { - private String inferenceId; - - private List input; - - @Nullable - private JsonData taskSettings; - - @Nullable - private Time timeout; - - /** - * Required - The inference Id - *

- * API name: {@code inference_id} - */ - public final Builder inferenceId(String value) { - this.inferenceId = value; - return this; - } - - /** - * Required - Inference input. Either a string or an array of strings. - *

- * API name: {@code input} - *

- * Adds all elements of list to input. - */ - public final Builder input(List list) { - this.input = _listAddAll(this.input, list); - return this; - } - - /** - * Required - Inference input. Either a string or an array of strings. - *

- * API name: {@code input} - *

- * Adds one or more values to input. - */ - public final Builder input(String value, String... values) { - this.input = _listAdd(this.input, value, values); - return this; - } - - /** - * Optional task settings - *

- * API name: {@code task_settings} - */ - public final Builder taskSettings(@Nullable JsonData value) { - this.taskSettings = value; - return this; - } - - /** - * Specifies the amount of time to wait for the inference request to complete. - *

- * API name: {@code timeout} - */ - public final Builder timeout(@Nullable Time value) { - this.timeout = value; - return this; - } - - /** - * Specifies the amount of time to wait for the inference request to complete. - *

- * API name: {@code timeout} - */ - public final Builder timeout(Function> fn) { - return this.timeout(fn.apply(new Time.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link SparseEmbeddingRequest}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public SparseEmbeddingRequest build() { - _checkSingleUse(); - - return new SparseEmbeddingRequest(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link SparseEmbeddingRequest} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, SparseEmbeddingRequest::setupSparseEmbeddingRequestDeserializer); - - protected static void setupSparseEmbeddingRequestDeserializer( - ObjectDeserializer op) { - - op.add(Builder::input, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), "input"); - op.add(Builder::taskSettings, JsonData._DESERIALIZER, "task_settings"); - - } - - // --------------------------------------------------------------------------------------------- - - /** - * Endpoint "{@code inference.sparse_embedding}". - */ - public static final Endpoint _ENDPOINT = new SimpleEndpoint<>( - "es/inference.sparse_embedding", - - // Request method - request -> { - return "POST"; - - }, - - // Request path - request -> { - final int _inferenceId = 1 << 0; - - int propsSet = 0; - - propsSet |= _inferenceId; - - if (propsSet == (_inferenceId)) { - StringBuilder buf = new StringBuilder(); - buf.append("/_inference"); - buf.append("/sparse_embedding"); - buf.append("/"); - SimpleEndpoint.pathEncode(request.inferenceId, buf); - return buf.toString(); - } - throw SimpleEndpoint.noPathTemplateFound("path"); - - }, - - // Path parameters - request -> { - Map params = new HashMap<>(); - final int _inferenceId = 1 << 0; - - int propsSet = 0; - - propsSet |= _inferenceId; - - if (propsSet == (_inferenceId)) { - params.put("inferenceId", request.inferenceId); - } - return params; - }, - - // Request parameters - request -> { - Map params = new HashMap<>(); - if (request.timeout != null) { - params.put("timeout", request.timeout._toJsonString()); - } - return params; - - }, SimpleEndpoint.emptyMap(), true, SparseEmbeddingResponse._DESERIALIZER); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingResponse.java deleted file mode 100644 index 17be5993e..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingResponse.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.sparse_embedding.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class SparseEmbeddingResponse extends SparseEmbeddingInferenceResult { - // --------------------------------------------------------------------------------------------- - - private SparseEmbeddingResponse(Builder builder) { - super(builder); - - } - - public static SparseEmbeddingResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link SparseEmbeddingResponse}. - */ - - public static class Builder extends SparseEmbeddingInferenceResult.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link SparseEmbeddingResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public SparseEmbeddingResponse build() { - _checkSingleUse(); - - return new SparseEmbeddingResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link SparseEmbeddingResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, SparseEmbeddingResponse::setupSparseEmbeddingResponseDeserializer); - - protected static void setupSparseEmbeddingResponseDeserializer( - ObjectDeserializer op) { - SparseEmbeddingInferenceResult.setupSparseEmbeddingInferenceResultDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingResult.java deleted file mode 100644 index 7538e4951..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingResult.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Float; -import java.lang.String; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference._types.SparseEmbeddingResult - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class SparseEmbeddingResult implements JsonpSerializable { - private final Map embedding; - - // --------------------------------------------------------------------------------------------- - - private SparseEmbeddingResult(Builder builder) { - - this.embedding = ApiTypeHelper.unmodifiableRequired(builder.embedding, this, "embedding"); - - } - - public static SparseEmbeddingResult of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - API name: {@code embedding} - */ - public final Map embedding() { - return this.embedding; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (ApiTypeHelper.isDefined(this.embedding)) { - generator.writeKey("embedding"); - generator.writeStartObject(); - for (Map.Entry item0 : this.embedding.entrySet()) { - generator.writeKey(item0.getKey()); - generator.write(item0.getValue()); - - } - generator.writeEnd(); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link SparseEmbeddingResult}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private Map embedding; - - /** - * Required - API name: {@code embedding} - *

- * Adds all entries of map to embedding. - */ - public final Builder embedding(Map map) { - this.embedding = _mapPutAll(this.embedding, map); - return this; - } - - /** - * Required - API name: {@code embedding} - *

- * Adds an entry to embedding. - */ - public final Builder embedding(String key, Float value) { - this.embedding = _mapPut(this.embedding, key, value); - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link SparseEmbeddingResult}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public SparseEmbeddingResult build() { - _checkSingleUse(); - - return new SparseEmbeddingResult(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link SparseEmbeddingResult} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, SparseEmbeddingResult::setupSparseEmbeddingResultDeserializer); - - protected static void setupSparseEmbeddingResultDeserializer(ObjectDeserializer op) { - - op.add(Builder::embedding, JsonpDeserializer.stringMapDeserializer(JsonpDeserializer.floatDeserializer()), - "embedding"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/StreamCompletionRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/StreamCompletionRequest.java deleted file mode 100644 index fe389c828..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/StreamCompletionRequest.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.elasticsearch._types.RequestBase; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.endpoints.BinaryEndpoint; -import co.elastic.clients.transport.endpoints.BinaryResponse; -import co.elastic.clients.transport.endpoints.SimpleEndpoint; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.stream_completion.Request - -/** - * Perform streaming inference. Get real-time responses for completion tasks by - * delivering answers incrementally, reducing response times during computation. - * This API works only with the completion task type. - *

- * IMPORTANT: The inference APIs enable you to use certain services, such as - * built-in machine learning models (ELSER, E5), models uploaded through Eland, - * Cohere, OpenAI, Azure, Google AI Studio, Google Vertex AI, Anthropic, - * Watsonx.ai, or Hugging Face. For built-in models and models uploaded through - * Eland, the inference APIs offer an alternative way to use and manage trained - * models. However, if you do not plan to use the inference APIs to use these - * models or if you want to use non-NLP models, use the machine learning trained - * model APIs. - *

- * This API requires the monitor_inference cluster privilege (the - * built-in inference_admin and inference_user roles - * grant this privilege). You must use a client that supports streaming. - * - * @see API - * specification - */ -@JsonpDeserializable -public class StreamCompletionRequest extends RequestBase implements JsonpSerializable { - private final String inferenceId; - - private final List input; - - @Nullable - private final JsonData taskSettings; - - // --------------------------------------------------------------------------------------------- - - private StreamCompletionRequest(Builder builder) { - - this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); - this.input = ApiTypeHelper.unmodifiableRequired(builder.input, this, "input"); - this.taskSettings = builder.taskSettings; - - } - - public static StreamCompletionRequest of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The unique identifier for the inference endpoint. - *

- * API name: {@code inference_id} - */ - public final String inferenceId() { - return this.inferenceId; - } - - /** - * Required - The text on which you want to perform the inference task. It can - * be a single string or an array. - *

- * NOTE: Inference endpoints for the completion task type currently only support - * a single string as input. - *

- * API name: {@code input} - */ - public final List input() { - return this.input; - } - - /** - * Optional task settings - *

- * API name: {@code task_settings} - */ - @Nullable - public final JsonData taskSettings() { - return this.taskSettings; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (ApiTypeHelper.isDefined(this.input)) { - generator.writeKey("input"); - generator.writeStartArray(); - for (String item0 : this.input) { - generator.write(item0); - - } - generator.writeEnd(); - - } - if (this.taskSettings != null) { - generator.writeKey("task_settings"); - this.taskSettings.serialize(generator, mapper); - - } - - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link StreamCompletionRequest}. - */ - - public static class Builder extends RequestBase.AbstractBuilder - implements - ObjectBuilder { - private String inferenceId; - - private List input; - - @Nullable - private JsonData taskSettings; - - /** - * Required - The unique identifier for the inference endpoint. - *

- * API name: {@code inference_id} - */ - public final Builder inferenceId(String value) { - this.inferenceId = value; - return this; - } - - /** - * Required - The text on which you want to perform the inference task. It can - * be a single string or an array. - *

- * NOTE: Inference endpoints for the completion task type currently only support - * a single string as input. - *

- * API name: {@code input} - *

- * Adds all elements of list to input. - */ - public final Builder input(List list) { - this.input = _listAddAll(this.input, list); - return this; - } - - /** - * Required - The text on which you want to perform the inference task. It can - * be a single string or an array. - *

- * NOTE: Inference endpoints for the completion task type currently only support - * a single string as input. - *

- * API name: {@code input} - *

- * Adds one or more values to input. - */ - public final Builder input(String value, String... values) { - this.input = _listAdd(this.input, value, values); - return this; - } - - /** - * Optional task settings - *

- * API name: {@code task_settings} - */ - public final Builder taskSettings(@Nullable JsonData value) { - this.taskSettings = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link StreamCompletionRequest}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public StreamCompletionRequest build() { - _checkSingleUse(); - - return new StreamCompletionRequest(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link StreamCompletionRequest} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, StreamCompletionRequest::setupStreamCompletionRequestDeserializer); - - protected static void setupStreamCompletionRequestDeserializer( - ObjectDeserializer op) { - - op.add(Builder::input, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), "input"); - op.add(Builder::taskSettings, JsonData._DESERIALIZER, "task_settings"); - - } - - // --------------------------------------------------------------------------------------------- - - /** - * Endpoint "{@code inference.stream_completion}". - */ - public static final Endpoint _ENDPOINT = new BinaryEndpoint<>( - "es/inference.stream_completion", - - // Request method - request -> { - return "POST"; - - }, - - // Request path - request -> { - final int _inferenceId = 1 << 0; - - int propsSet = 0; - - propsSet |= _inferenceId; - - if (propsSet == (_inferenceId)) { - StringBuilder buf = new StringBuilder(); - buf.append("/_inference"); - buf.append("/completion"); - buf.append("/"); - SimpleEndpoint.pathEncode(request.inferenceId, buf); - buf.append("/_stream"); - return buf.toString(); - } - throw SimpleEndpoint.noPathTemplateFound("path"); - - }, - - // Path parameters - request -> { - Map params = new HashMap<>(); - final int _inferenceId = 1 << 0; - - int propsSet = 0; - - propsSet |= _inferenceId; - - if (propsSet == (_inferenceId)) { - params.put("inferenceId", request.inferenceId); - } - return params; - }, - - // Request parameters - request -> { - return Collections.emptyMap(); - - }, SimpleEndpoint.emptyMap(), true, null); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TaskType.java deleted file mode 100644 index 6b1fbab65..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TaskType.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum TaskType implements JsonEnum { - SparseEmbedding("sparse_embedding"), - - TextEmbedding("text_embedding"), - - Rerank("rerank"), - - Completion("completion"), - - ChatCompletion("chat_completion"), - - ; - - private final String jsonValue; - - TaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>(TaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingByteResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingByteResult.java deleted file mode 100644 index 2143fa6c4..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingByteResult.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Number; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference._types.TextEmbeddingByteResult - -/** - * The text embedding result object for byte representation - * - * @see API - * specification - */ -@JsonpDeserializable -public class TextEmbeddingByteResult implements JsonpSerializable { - private final List embedding; - - // --------------------------------------------------------------------------------------------- - - private TextEmbeddingByteResult(Builder builder) { - - this.embedding = ApiTypeHelper.unmodifiableRequired(builder.embedding, this, "embedding"); - - } - - public static TextEmbeddingByteResult of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - API name: {@code embedding} - */ - public final List embedding() { - return this.embedding; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (ApiTypeHelper.isDefined(this.embedding)) { - generator.writeKey("embedding"); - generator.writeStartArray(); - for (Number item0 : this.embedding) { - generator.write(item0.doubleValue()); - - } - generator.writeEnd(); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link TextEmbeddingByteResult}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private List embedding; - - /** - * Required - API name: {@code embedding} - *

- * Adds all elements of list to embedding. - */ - public final Builder embedding(List list) { - this.embedding = _listAddAll(this.embedding, list); - return this; - } - - /** - * Required - API name: {@code embedding} - *

- * Adds one or more values to embedding. - */ - public final Builder embedding(Number value, Number... values) { - this.embedding = _listAdd(this.embedding, value, values); - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link TextEmbeddingByteResult}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public TextEmbeddingByteResult build() { - _checkSingleUse(); - - return new TextEmbeddingByteResult(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link TextEmbeddingByteResult} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, TextEmbeddingByteResult::setupTextEmbeddingByteResultDeserializer); - - protected static void setupTextEmbeddingByteResultDeserializer( - ObjectDeserializer op) { - - op.add(Builder::embedding, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.numberDeserializer()), - "embedding"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResult.java deleted file mode 100644 index 0bd25d6d6..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResult.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.TaggedUnion; -import co.elastic.clients.util.TaggedUnionUtils; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Object; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference._types.TextEmbeddingInferenceResult - -/** - * TextEmbeddingInferenceResult is an aggregation of mutually exclusive - * text_embedding variants - * - * @see API - * specification - */ -@JsonpDeserializable -public class TextEmbeddingInferenceResult - implements - TaggedUnion, - JsonpSerializable { - - /** - * {@link TextEmbeddingInferenceResult} variant kinds. - * - * @see API - * specification - */ - - public enum Kind implements JsonEnum { - TextEmbeddingBytes("text_embedding_bytes"), - - TextEmbeddingBits("text_embedding_bits"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - Kind(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - } - - private final Kind _kind; - private final Object _value; - - @Override - public final Kind _kind() { - return _kind; - } - - @Override - public final Object _get() { - return _value; - } - - public TextEmbeddingInferenceResult(TextEmbeddingInferenceResultVariant value) { - - this._kind = ApiTypeHelper.requireNonNull(value._textEmbeddingInferenceResultKind(), this, ""); - this._value = ApiTypeHelper.requireNonNull(value, this, ""); - - } - - private TextEmbeddingInferenceResult(Builder builder) { - - this._kind = ApiTypeHelper.requireNonNull(builder._kind, builder, ""); - this._value = ApiTypeHelper.requireNonNull(builder._value, builder, ""); - - } - - public static TextEmbeddingInferenceResult of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Is this variant instance of kind {@code text_embedding_bytes}? - */ - public boolean isTextEmbeddingBytes() { - return _kind == Kind.TextEmbeddingBytes; - } - - /** - * Get the {@code text_embedding_bytes} variant value. - * - * @throws IllegalStateException - * if the current variant is not of the {@code text_embedding_bytes} - * kind. - */ - public List textEmbeddingBytes() { - return TaggedUnionUtils.get(this, Kind.TextEmbeddingBytes); - } - - /** - * Is this variant instance of kind {@code text_embedding_bits}? - */ - public boolean isTextEmbeddingBits() { - return _kind == Kind.TextEmbeddingBits; - } - - /** - * Get the {@code text_embedding_bits} variant value. - * - * @throws IllegalStateException - * if the current variant is not of the {@code text_embedding_bits} - * kind. - */ - public List textEmbeddingBits() { - return TaggedUnionUtils.get(this, Kind.TextEmbeddingBits); - } - - /** - * Is this variant instance of kind {@code text_embedding}? - */ - public boolean isTextEmbedding() { - return _kind == Kind.TextEmbedding; - } - - /** - * Get the {@code text_embedding} variant value. - * - * @throws IllegalStateException - * if the current variant is not of the {@code text_embedding} kind. - */ - public List textEmbedding() { - return TaggedUnionUtils.get(this, Kind.TextEmbedding); - } - - @Override - @SuppressWarnings("unchecked") - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeStartObject(); - - generator.writeKey(_kind.jsonValue()); - if (_value instanceof JsonpSerializable) { - ((JsonpSerializable) _value).serialize(generator, mapper); - } else { - switch (_kind) { - case TextEmbeddingBytes : - generator.writeStartArray(); - for (TextEmbeddingByteResult item0 : ((List) this._value)) { - item0.serialize(generator, mapper); - - } - generator.writeEnd(); - - break; - case TextEmbeddingBits : - generator.writeStartArray(); - for (TextEmbeddingByteResult item0 : ((List) this._value)) { - item0.serialize(generator, mapper); - - } - generator.writeEnd(); - - break; - case TextEmbedding : - generator.writeStartArray(); - for (TextEmbeddingResult item0 : ((List) this._value)) { - item0.serialize(generator, mapper); - - } - generator.writeEnd(); - - break; - } - } - - generator.writeEnd(); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private Kind _kind; - private Object _value; - - @Override - protected Builder self() { - return this; - } - public ObjectBuilder textEmbeddingBytes(List v) { - this._kind = Kind.TextEmbeddingBytes; - this._value = v; - return this; - } - - public ObjectBuilder textEmbeddingBits(List v) { - this._kind = Kind.TextEmbeddingBits; - this._value = v; - return this; - } - - public ObjectBuilder textEmbedding(List v) { - this._kind = Kind.TextEmbedding; - this._value = v; - return this; - } - - public TextEmbeddingInferenceResult build() { - _checkSingleUse(); - return new TextEmbeddingInferenceResult(this); - } - - } - - protected static void setupTextEmbeddingInferenceResultDeserializer(ObjectDeserializer op) { - - op.add(Builder::textEmbeddingBytes, JsonpDeserializer.arrayDeserializer(TextEmbeddingByteResult._DESERIALIZER), - "text_embedding_bytes"); - op.add(Builder::textEmbeddingBits, JsonpDeserializer.arrayDeserializer(TextEmbeddingByteResult._DESERIALIZER), - "text_embedding_bits"); - op.add(Builder::textEmbedding, JsonpDeserializer.arrayDeserializer(TextEmbeddingResult._DESERIALIZER), - "text_embedding"); - - } - - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy( - Builder::new, TextEmbeddingInferenceResult::setupTextEmbeddingInferenceResultDeserializer, Builder::build); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResultBuilders.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResultBuilders.java deleted file mode 100644 index 076daddd4..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResultBuilders.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.util.ObjectBuilder; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * Builders for {@link TextEmbeddingInferenceResult} variants. - *

- * Variants text_embedding_bytes, text_embedding_bits, - * text_embedding are not available here as they don't have a - * dedicated class. Use {@link TextEmbeddingInferenceResult}'s builder for - * these. - * - */ -public class TextEmbeddingInferenceResultBuilders { - private TextEmbeddingInferenceResultBuilders() { - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResultVariant.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResultVariant.java deleted file mode 100644 index 6b3ade5ea..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResultVariant.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * Base interface for {@link TextEmbeddingInferenceResult} variants. - */ -public interface TextEmbeddingInferenceResultVariant { - - TextEmbeddingInferenceResult.Kind _textEmbeddingInferenceResultKind(); - - default TextEmbeddingInferenceResult _toTextEmbeddingInferenceResult() { - return new TextEmbeddingInferenceResult(this); - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingRequest.java deleted file mode 100644 index 042082f7f..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingRequest.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.elasticsearch._types.RequestBase; -import co.elastic.clients.elasticsearch._types.Time; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.endpoints.SimpleEndpoint; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.text_embedding.Request - -/** - * Perform text embedding inference on the service - * - * @see API - * specification - */ -@JsonpDeserializable -public class TextEmbeddingRequest extends RequestBase implements JsonpSerializable { - private final String inferenceId; - - private final List input; - - @Nullable - private final JsonData taskSettings; - - @Nullable - private final Time timeout; - - // --------------------------------------------------------------------------------------------- - - private TextEmbeddingRequest(Builder builder) { - - this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); - this.input = ApiTypeHelper.unmodifiableRequired(builder.input, this, "input"); - this.taskSettings = builder.taskSettings; - this.timeout = builder.timeout; - - } - - public static TextEmbeddingRequest of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The inference Id - *

- * API name: {@code inference_id} - */ - public final String inferenceId() { - return this.inferenceId; - } - - /** - * Required - Inference input. Either a string or an array of strings. - *

- * API name: {@code input} - */ - public final List input() { - return this.input; - } - - /** - * Optional task settings - *

- * API name: {@code task_settings} - */ - @Nullable - public final JsonData taskSettings() { - return this.taskSettings; - } - - /** - * Specifies the amount of time to wait for the inference request to complete. - *

- * API name: {@code timeout} - */ - @Nullable - public final Time timeout() { - return this.timeout; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (ApiTypeHelper.isDefined(this.input)) { - generator.writeKey("input"); - generator.writeStartArray(); - for (String item0 : this.input) { - generator.write(item0); - - } - generator.writeEnd(); - - } - if (this.taskSettings != null) { - generator.writeKey("task_settings"); - this.taskSettings.serialize(generator, mapper); - - } - - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link TextEmbeddingRequest}. - */ - - public static class Builder extends RequestBase.AbstractBuilder - implements - ObjectBuilder { - private String inferenceId; - - private List input; - - @Nullable - private JsonData taskSettings; - - @Nullable - private Time timeout; - - /** - * Required - The inference Id - *

- * API name: {@code inference_id} - */ - public final Builder inferenceId(String value) { - this.inferenceId = value; - return this; - } - - /** - * Required - Inference input. Either a string or an array of strings. - *

- * API name: {@code input} - *

- * Adds all elements of list to input. - */ - public final Builder input(List list) { - this.input = _listAddAll(this.input, list); - return this; - } - - /** - * Required - Inference input. Either a string or an array of strings. - *

- * API name: {@code input} - *

- * Adds one or more values to input. - */ - public final Builder input(String value, String... values) { - this.input = _listAdd(this.input, value, values); - return this; - } - - /** - * Optional task settings - *

- * API name: {@code task_settings} - */ - public final Builder taskSettings(@Nullable JsonData value) { - this.taskSettings = value; - return this; - } - - /** - * Specifies the amount of time to wait for the inference request to complete. - *

- * API name: {@code timeout} - */ - public final Builder timeout(@Nullable Time value) { - this.timeout = value; - return this; - } - - /** - * Specifies the amount of time to wait for the inference request to complete. - *

- * API name: {@code timeout} - */ - public final Builder timeout(Function> fn) { - return this.timeout(fn.apply(new Time.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link TextEmbeddingRequest}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public TextEmbeddingRequest build() { - _checkSingleUse(); - - return new TextEmbeddingRequest(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link TextEmbeddingRequest} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, TextEmbeddingRequest::setupTextEmbeddingRequestDeserializer); - - protected static void setupTextEmbeddingRequestDeserializer(ObjectDeserializer op) { - - op.add(Builder::input, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), "input"); - op.add(Builder::taskSettings, JsonData._DESERIALIZER, "task_settings"); - - } - - // --------------------------------------------------------------------------------------------- - - /** - * Endpoint "{@code inference.text_embedding}". - */ - public static final Endpoint _ENDPOINT = new SimpleEndpoint<>( - "es/inference.text_embedding", - - // Request method - request -> { - return "POST"; - - }, - - // Request path - request -> { - final int _inferenceId = 1 << 0; - - int propsSet = 0; - - propsSet |= _inferenceId; - - if (propsSet == (_inferenceId)) { - StringBuilder buf = new StringBuilder(); - buf.append("/_inference"); - buf.append("/text_embedding"); - buf.append("/"); - SimpleEndpoint.pathEncode(request.inferenceId, buf); - return buf.toString(); - } - throw SimpleEndpoint.noPathTemplateFound("path"); - - }, - - // Path parameters - request -> { - Map params = new HashMap<>(); - final int _inferenceId = 1 << 0; - - int propsSet = 0; - - propsSet |= _inferenceId; - - if (propsSet == (_inferenceId)) { - params.put("inferenceId", request.inferenceId); - } - return params; - }, - - // Request parameters - request -> { - Map params = new HashMap<>(); - if (request.timeout != null) { - params.put("timeout", request.timeout._toJsonString()); - } - return params; - - }, SimpleEndpoint.emptyMap(), true, TextEmbeddingResponse._DESERIALIZER); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResult.java deleted file mode 100644 index a237a6945..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResult.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Float; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference._types.TextEmbeddingResult - -/** - * The text embedding result object - * - * @see API - * specification - */ -@JsonpDeserializable -public class TextEmbeddingResult implements JsonpSerializable { - private final List embedding; - - // --------------------------------------------------------------------------------------------- - - private TextEmbeddingResult(Builder builder) { - - this.embedding = ApiTypeHelper.unmodifiableRequired(builder.embedding, this, "embedding"); - - } - - public static TextEmbeddingResult of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - API name: {@code embedding} - */ - public final List embedding() { - return this.embedding; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (ApiTypeHelper.isDefined(this.embedding)) { - generator.writeKey("embedding"); - generator.writeStartArray(); - for (Float item0 : this.embedding) { - generator.write(item0); - - } - generator.writeEnd(); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link TextEmbeddingResult}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private List embedding; - - /** - * Required - API name: {@code embedding} - *

- * Adds all elements of list to embedding. - */ - public final Builder embedding(List list) { - this.embedding = _listAddAll(this.embedding, list); - return this; - } - - /** - * Required - API name: {@code embedding} - *

- * Adds one or more values to embedding. - */ - public final Builder embedding(Float value, Float... values) { - this.embedding = _listAdd(this.embedding, value, values); - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link TextEmbeddingResult}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public TextEmbeddingResult build() { - _checkSingleUse(); - - return new TextEmbeddingResult(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link TextEmbeddingResult} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, TextEmbeddingResult::setupTextEmbeddingResultDeserializer); - - protected static void setupTextEmbeddingResultDeserializer(ObjectDeserializer op) { - - op.add(Builder::embedding, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.floatDeserializer()), - "embedding"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/UpdateInferenceRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/UpdateInferenceRequest.java deleted file mode 100644 index e210ed71f..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/UpdateInferenceRequest.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.elasticsearch._types.RequestBase; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.endpoints.SimpleEndpoint; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import java.lang.String; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.update.Request - -/** - * Update an inference endpoint. - *

- * Modify task_settings, secrets (within - * service_settings), or num_allocations for an - * inference endpoint, depending on the specific endpoint service and - * task_type. - *

- * IMPORTANT: The inference APIs enable you to use certain services, such as - * built-in machine learning models (ELSER, E5), models uploaded through Eland, - * Cohere, OpenAI, Azure, Google AI Studio, Google Vertex AI, Anthropic, - * Watsonx.ai, or Hugging Face. For built-in models and models uploaded through - * Eland, the inference APIs offer an alternative way to use and manage trained - * models. However, if you do not plan to use the inference APIs to use these - * models or if you want to use non-NLP models, use the machine learning trained - * model APIs. - * - * @see API - * specification - */ -@JsonpDeserializable -public class UpdateInferenceRequest extends RequestBase implements JsonpSerializable { - private final String inferenceId; - - @Nullable - private final TaskType taskType; - - private final InferenceEndpoint inferenceConfig; - - // --------------------------------------------------------------------------------------------- - - private UpdateInferenceRequest(Builder builder) { - - this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); - this.taskType = builder.taskType; - this.inferenceConfig = ApiTypeHelper.requireNonNull(builder.inferenceConfig, this, "inferenceConfig"); - - } - - public static UpdateInferenceRequest of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The unique identifier of the inference endpoint. - *

- * API name: {@code inference_id} - */ - public final String inferenceId() { - return this.inferenceId; - } - - /** - * The type of inference task that the model performs. - *

- * API name: {@code task_type} - */ - @Nullable - public final TaskType taskType() { - return this.taskType; - } - - /** - * Required - Request body. - */ - public final InferenceEndpoint inferenceConfig() { - return this.inferenceConfig; - } - - /** - * Serialize this value to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - this.inferenceConfig.serialize(generator, mapper); - - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link UpdateInferenceRequest}. - */ - - public static class Builder extends RequestBase.AbstractBuilder - implements - ObjectBuilder { - private String inferenceId; - - @Nullable - private TaskType taskType; - - private InferenceEndpoint inferenceConfig; - - /** - * Required - The unique identifier of the inference endpoint. - *

- * API name: {@code inference_id} - */ - public final Builder inferenceId(String value) { - this.inferenceId = value; - return this; - } - - /** - * The type of inference task that the model performs. - *

- * API name: {@code task_type} - */ - public final Builder taskType(@Nullable TaskType value) { - this.taskType = value; - return this; - } - - /** - * Required - Request body. - */ - public final Builder inferenceConfig(InferenceEndpoint value) { - this.inferenceConfig = value; - return this; - } - - /** - * Required - Request body. - */ - public final Builder inferenceConfig(Function> fn) { - return this.inferenceConfig(fn.apply(new InferenceEndpoint.Builder()).build()); - } - - @Override - public Builder withJson(JsonParser parser, JsonpMapper mapper) { - - @SuppressWarnings("unchecked") - InferenceEndpoint value = (InferenceEndpoint) InferenceEndpoint._DESERIALIZER.deserialize(parser, mapper); - return this.inferenceConfig(value); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link UpdateInferenceRequest}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public UpdateInferenceRequest build() { - _checkSingleUse(); - - return new UpdateInferenceRequest(this); - } - } - - public static final JsonpDeserializer _DESERIALIZER = createUpdateInferenceRequestDeserializer(); - protected static JsonpDeserializer createUpdateInferenceRequestDeserializer() { - - JsonpDeserializer valueDeserializer = InferenceEndpoint._DESERIALIZER; - - return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() - .inferenceConfig(valueDeserializer.deserialize(parser, mapper, event)).build()); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Endpoint "{@code inference.update}". - */ - public static final Endpoint _ENDPOINT = new SimpleEndpoint<>( - "es/inference.update", - - // Request method - request -> { - return "PUT"; - - }, - - // Request path - request -> { - final int _inferenceId = 1 << 0; - final int _taskType = 1 << 1; - - int propsSet = 0; - - propsSet |= _inferenceId; - if (request.taskType() != null) - propsSet |= _taskType; - - if (propsSet == (_inferenceId)) { - StringBuilder buf = new StringBuilder(); - buf.append("/_inference"); - buf.append("/"); - SimpleEndpoint.pathEncode(request.inferenceId, buf); - buf.append("/_update"); - return buf.toString(); - } - if (propsSet == (_taskType | _inferenceId)) { - StringBuilder buf = new StringBuilder(); - buf.append("/_inference"); - buf.append("/"); - SimpleEndpoint.pathEncode(request.taskType.jsonValue(), buf); - buf.append("/"); - SimpleEndpoint.pathEncode(request.inferenceId, buf); - buf.append("/_update"); - return buf.toString(); - } - throw SimpleEndpoint.noPathTemplateFound("path"); - - }, - - // Path parameters - request -> { - Map params = new HashMap<>(); - final int _inferenceId = 1 << 0; - final int _taskType = 1 << 1; - - int propsSet = 0; - - propsSet |= _inferenceId; - if (request.taskType() != null) - propsSet |= _taskType; - - if (propsSet == (_inferenceId)) { - params.put("inferenceId", request.inferenceId); - } - if (propsSet == (_taskType | _inferenceId)) { - params.put("taskType", request.taskType.jsonValue()); - params.put("inferenceId", request.inferenceId); - } - return params; - }, - - // Request parameters - request -> { - return Collections.emptyMap(); - - }, SimpleEndpoint.emptyMap(), true, UpdateInferenceResponse._DESERIALIZER); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/UpdateInferenceResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/UpdateInferenceResponse.java deleted file mode 100644 index 2979876ac..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/UpdateInferenceResponse.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import java.util.Objects; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.update.Response - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class UpdateInferenceResponse extends InferenceEndpointInfo { - // --------------------------------------------------------------------------------------------- - - private UpdateInferenceResponse(Builder builder) { - super(builder); - - } - - public static UpdateInferenceResponse of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link UpdateInferenceResponse}. - */ - - public static class Builder extends InferenceEndpointInfo.AbstractBuilder - implements - ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link UpdateInferenceResponse}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public UpdateInferenceResponse build() { - _checkSingleUse(); - - return new UpdateInferenceResponse(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link UpdateInferenceResponse} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, UpdateInferenceResponse::setupUpdateInferenceResponseDeserializer); - - protected static void setupUpdateInferenceResponseDeserializer( - ObjectDeserializer op) { - InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudServiceSettings.java deleted file mode 100644 index 55d8c7ef9..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudServiceSettings.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_alibabacloud; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_alibabacloud.AlibabaCloudServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AlibabaCloudServiceSettings implements JsonpSerializable { - private final String apiKey; - - private final String host; - - @Nullable - private final RateLimitSetting rateLimit; - - private final String serviceId; - - private final String workspace; - - // --------------------------------------------------------------------------------------------- - - private AlibabaCloudServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.host = ApiTypeHelper.requireNonNull(builder.host, this, "host"); - this.rateLimit = builder.rateLimit; - this.serviceId = ApiTypeHelper.requireNonNull(builder.serviceId, this, "serviceId"); - this.workspace = ApiTypeHelper.requireNonNull(builder.workspace, this, "workspace"); - - } - - public static AlibabaCloudServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid API key for the AlibabaCloud AI Search API. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * Required - The name of the host address used for the inference task. You can - * find the host address in the API keys section of the documentation. - *

- * API name: {@code host} - */ - public final String host() { - return this.host; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * AlibabaCloud AI Search. By default, the alibabacloud-ai-search - * service sets the number of requests allowed per minute to 1000. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Required - The name of the model service to use for the inference task. The - * following service IDs are available for the completion task: - *

    - *
  • ops-qwen-turbo
  • - *
  • qwen-turbo
  • - *
  • qwen-plus
  • - *
  • qwen-max ÷ qwen-max-longcontext
  • - *
- *

- * The following service ID is available for the rerank task: - *

    - *
  • ops-bge-reranker-larger
  • - *
- *

- * The following service ID is available for the sparse_embedding - * task: - *

    - *
  • ops-text-sparse-embedding-001
  • - *
- *

- * The following service IDs are available for the text_embedding - * task: - *

- * ops-text-embedding-001 ops-text-embedding-zh-001 - * ops-text-embedding-en-001 ops-text-embedding-002 - *

- * API name: {@code service_id} - */ - public final String serviceId() { - return this.serviceId; - } - - /** - * Required - The name of the workspace used for the inference task. - *

- * API name: {@code workspace} - */ - public final String workspace() { - return this.workspace; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - generator.writeKey("host"); - generator.write(this.host); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - generator.writeKey("service_id"); - generator.write(this.serviceId); - - generator.writeKey("workspace"); - generator.write(this.workspace); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AlibabaCloudServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - private String host; - - @Nullable - private RateLimitSetting rateLimit; - - private String serviceId; - - private String workspace; - - /** - * Required - A valid API key for the AlibabaCloud AI Search API. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * Required - The name of the host address used for the inference task. You can - * find the host address in the API keys section of the documentation. - *

- * API name: {@code host} - */ - public final Builder host(String value) { - this.host = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * AlibabaCloud AI Search. By default, the alibabacloud-ai-search - * service sets the number of requests allowed per minute to 1000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * AlibabaCloud AI Search. By default, the alibabacloud-ai-search - * service sets the number of requests allowed per minute to 1000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * Required - The name of the model service to use for the inference task. The - * following service IDs are available for the completion task: - *

    - *
  • ops-qwen-turbo
  • - *
  • qwen-turbo
  • - *
  • qwen-plus
  • - *
  • qwen-max ÷ qwen-max-longcontext
  • - *
- *

- * The following service ID is available for the rerank task: - *

    - *
  • ops-bge-reranker-larger
  • - *
- *

- * The following service ID is available for the sparse_embedding - * task: - *

    - *
  • ops-text-sparse-embedding-001
  • - *
- *

- * The following service IDs are available for the text_embedding - * task: - *

- * ops-text-embedding-001 ops-text-embedding-zh-001 - * ops-text-embedding-en-001 ops-text-embedding-002 - *

- * API name: {@code service_id} - */ - public final Builder serviceId(String value) { - this.serviceId = value; - return this; - } - - /** - * Required - The name of the workspace used for the inference task. - *

- * API name: {@code workspace} - */ - public final Builder workspace(String value) { - this.workspace = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AlibabaCloudServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AlibabaCloudServiceSettings build() { - _checkSingleUse(); - - return new AlibabaCloudServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AlibabaCloudServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AlibabaCloudServiceSettings::setupAlibabaCloudServiceSettingsDeserializer); - - protected static void setupAlibabaCloudServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::host, JsonpDeserializer.stringDeserializer(), "host"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::serviceId, JsonpDeserializer.stringDeserializer(), "service_id"); - op.add(Builder::workspace, JsonpDeserializer.stringDeserializer(), "workspace"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskSettings.java deleted file mode 100644 index 288d3e0d1..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskSettings.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_alibabacloud; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_alibabacloud.AlibabaCloudTaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AlibabaCloudTaskSettings implements JsonpSerializable { - @Nullable - private final String inputType; - - @Nullable - private final Boolean returnToken; - - // --------------------------------------------------------------------------------------------- - - private AlibabaCloudTaskSettings(Builder builder) { - - this.inputType = builder.inputType; - this.returnToken = builder.returnToken; - - } - - public static AlibabaCloudTaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * For a sparse_embedding or text_embedding task, - * specify the type of input passed to the model. Valid values are: - *

    - *
  • ingest for storing document embeddings in a vector - * database.
  • - *
  • search for storing embeddings of search queries run against - * a vector database to find relevant documents.
  • - *
- *

- * API name: {@code input_type} - */ - @Nullable - public final String inputType() { - return this.inputType; - } - - /** - * For a sparse_embedding task, it affects whether the token name - * will be returned in the response. It defaults to false, which - * means only the token ID will be returned in the response. - *

- * API name: {@code return_token} - */ - @Nullable - public final Boolean returnToken() { - return this.returnToken; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.inputType != null) { - generator.writeKey("input_type"); - generator.write(this.inputType); - - } - if (this.returnToken != null) { - generator.writeKey("return_token"); - generator.write(this.returnToken); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AlibabaCloudTaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private String inputType; - - @Nullable - private Boolean returnToken; - - /** - * For a sparse_embedding or text_embedding task, - * specify the type of input passed to the model. Valid values are: - *

    - *
  • ingest for storing document embeddings in a vector - * database.
  • - *
  • search for storing embeddings of search queries run against - * a vector database to find relevant documents.
  • - *
- *

- * API name: {@code input_type} - */ - public final Builder inputType(@Nullable String value) { - this.inputType = value; - return this; - } - - /** - * For a sparse_embedding task, it affects whether the token name - * will be returned in the response. It defaults to false, which - * means only the token ID will be returned in the response. - *

- * API name: {@code return_token} - */ - public final Builder returnToken(@Nullable Boolean value) { - this.returnToken = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AlibabaCloudTaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AlibabaCloudTaskSettings build() { - _checkSingleUse(); - - return new AlibabaCloudTaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AlibabaCloudTaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AlibabaCloudTaskSettings::setupAlibabaCloudTaskSettingsDeserializer); - - protected static void setupAlibabaCloudTaskSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::inputType, JsonpDeserializer.stringDeserializer(), "input_type"); - op.add(Builder::returnToken, JsonpDeserializer.booleanDeserializer(), "return_token"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskType.java deleted file mode 100644 index 8adf946a1..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskType.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_alibabacloud; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum AlibabaCloudTaskType implements JsonEnum { - Completion("completion"), - - Rerank("rerank"), - - SpaceEmbedding("space_embedding"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - AlibabaCloudTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - AlibabaCloudTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/ServiceType.java deleted file mode 100644 index 010f0bfdf..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_alibabacloud; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - AlibabacloudAiSearch("alibabacloud-ai-search"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockServiceSettings.java deleted file mode 100644 index 06417819f..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockServiceSettings.java +++ /dev/null @@ -1,371 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_amazonbedrock; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_amazonbedrock.AmazonBedrockServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AmazonBedrockServiceSettings implements JsonpSerializable { - private final String accessKey; - - private final String model; - - @Nullable - private final String provider; - - private final String region; - - @Nullable - private final RateLimitSetting rateLimit; - - private final String secretKey; - - // --------------------------------------------------------------------------------------------- - - private AmazonBedrockServiceSettings(Builder builder) { - - this.accessKey = ApiTypeHelper.requireNonNull(builder.accessKey, this, "accessKey"); - this.model = ApiTypeHelper.requireNonNull(builder.model, this, "model"); - this.provider = builder.provider; - this.region = ApiTypeHelper.requireNonNull(builder.region, this, "region"); - this.rateLimit = builder.rateLimit; - this.secretKey = ApiTypeHelper.requireNonNull(builder.secretKey, this, "secretKey"); - - } - - public static AmazonBedrockServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid AWS access key that has permissions to use Amazon Bedrock - * and access to models for inference requests. - *

- * API name: {@code access_key} - */ - public final String accessKey() { - return this.accessKey; - } - - /** - * Required - The base model ID or an ARN to a custom model based on a - * foundational model. The base model IDs can be found in the Amazon Bedrock - * documentation. Note that the model ID must be available for the provider - * chosen and your IAM user must have access to the model. - *

- * API name: {@code model} - */ - public final String model() { - return this.model; - } - - /** - * The model provider for your deployment. Note that some providers may support - * only certain task types. Supported providers include: - *

    - *
  • amazontitan - available for text_embedding and - * completion task types
  • - *
  • anthropic - available for completion task type - * only
  • - *
  • ai21labs - available for completion task type - * only
  • - *
  • cohere - available for text_embedding and - * completion task types
  • - *
  • meta - available for completion task type - * only
  • - *
  • mistral - available for completion task type - * only
  • - *
- *

- * API name: {@code provider} - */ - @Nullable - public final String provider() { - return this.provider; - } - - /** - * Required - The region that your model or ARN is deployed in. The list of - * available regions per model can be found in the Amazon Bedrock documentation. - *

- * API name: {@code region} - */ - public final String region() { - return this.region; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Watsonx. By default, the watsonxai service sets the number of - * requests allowed per minute to 120. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Required - A valid AWS secret key that is paired with the - * access_key. For informationg about creating and managing access - * and secret keys, refer to the AWS documentation. - *

- * API name: {@code secret_key} - */ - public final String secretKey() { - return this.secretKey; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("access_key"); - generator.write(this.accessKey); - - generator.writeKey("model"); - generator.write(this.model); - - if (this.provider != null) { - generator.writeKey("provider"); - generator.write(this.provider); - - } - generator.writeKey("region"); - generator.write(this.region); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - generator.writeKey("secret_key"); - generator.write(this.secretKey); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AmazonBedrockServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String accessKey; - - private String model; - - @Nullable - private String provider; - - private String region; - - @Nullable - private RateLimitSetting rateLimit; - - private String secretKey; - - /** - * Required - A valid AWS access key that has permissions to use Amazon Bedrock - * and access to models for inference requests. - *

- * API name: {@code access_key} - */ - public final Builder accessKey(String value) { - this.accessKey = value; - return this; - } - - /** - * Required - The base model ID or an ARN to a custom model based on a - * foundational model. The base model IDs can be found in the Amazon Bedrock - * documentation. Note that the model ID must be available for the provider - * chosen and your IAM user must have access to the model. - *

- * API name: {@code model} - */ - public final Builder model(String value) { - this.model = value; - return this; - } - - /** - * The model provider for your deployment. Note that some providers may support - * only certain task types. Supported providers include: - *

    - *
  • amazontitan - available for text_embedding and - * completion task types
  • - *
  • anthropic - available for completion task type - * only
  • - *
  • ai21labs - available for completion task type - * only
  • - *
  • cohere - available for text_embedding and - * completion task types
  • - *
  • meta - available for completion task type - * only
  • - *
  • mistral - available for completion task type - * only
  • - *
- *

- * API name: {@code provider} - */ - public final Builder provider(@Nullable String value) { - this.provider = value; - return this; - } - - /** - * Required - The region that your model or ARN is deployed in. The list of - * available regions per model can be found in the Amazon Bedrock documentation. - *

- * API name: {@code region} - */ - public final Builder region(String value) { - this.region = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Watsonx. By default, the watsonxai service sets the number of - * requests allowed per minute to 120. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Watsonx. By default, the watsonxai service sets the number of - * requests allowed per minute to 120. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * Required - A valid AWS secret key that is paired with the - * access_key. For informationg about creating and managing access - * and secret keys, refer to the AWS documentation. - *

- * API name: {@code secret_key} - */ - public final Builder secretKey(String value) { - this.secretKey = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AmazonBedrockServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AmazonBedrockServiceSettings build() { - _checkSingleUse(); - - return new AmazonBedrockServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AmazonBedrockServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AmazonBedrockServiceSettings::setupAmazonBedrockServiceSettingsDeserializer); - - protected static void setupAmazonBedrockServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::accessKey, JsonpDeserializer.stringDeserializer(), "access_key"); - op.add(Builder::model, JsonpDeserializer.stringDeserializer(), "model"); - op.add(Builder::provider, JsonpDeserializer.stringDeserializer(), "provider"); - op.add(Builder::region, JsonpDeserializer.stringDeserializer(), "region"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::secretKey, JsonpDeserializer.stringDeserializer(), "secret_key"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskSettings.java deleted file mode 100644 index 3ada2fc38..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskSettings.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_amazonbedrock; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Float; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_amazonbedrock.AmazonBedrockTaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AmazonBedrockTaskSettings implements JsonpSerializable { - @Nullable - private final Integer maxNewTokens; - - @Nullable - private final Float temperature; - - @Nullable - private final Float topK; - - @Nullable - private final Float topP; - - // --------------------------------------------------------------------------------------------- - - private AmazonBedrockTaskSettings(Builder builder) { - - this.maxNewTokens = builder.maxNewTokens; - this.temperature = builder.temperature; - this.topK = builder.topK; - this.topP = builder.topP; - - } - - public static AmazonBedrockTaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * For a completion task, it sets the maximum number for the output - * tokens to be generated. - *

- * API name: {@code max_new_tokens} - */ - @Nullable - public final Integer maxNewTokens() { - return this.maxNewTokens; - } - - /** - * For a completion task, it is a number between 0.0 and 1.0 that - * controls the apparent creativity of the results. At temperature 0.0 the model - * is most deterministic, at temperature 1.0 most random. It should not be used - * if top_p or top_k is specified. - *

- * API name: {@code temperature} - */ - @Nullable - public final Float temperature() { - return this.temperature; - } - - /** - * For a completion task, it limits samples to the top-K most - * likely words, balancing coherence and variability. It is only available for - * anthropic, cohere, and mistral providers. It is an alternative to - * temperature; it should not be used if temperature - * is specified. - *

- * API name: {@code top_k} - */ - @Nullable - public final Float topK() { - return this.topK; - } - - /** - * For a completion task, it is a number in the range of 0.0 to - * 1.0, to eliminate low-probability tokens. Top-p uses nucleus sampling to - * select top tokens whose sum of likelihoods does not exceed a certain value, - * ensuring both variety and coherence. It is an alternative to - * temperature; it should not be used if temperature - * is specified. - *

- * API name: {@code top_p} - */ - @Nullable - public final Float topP() { - return this.topP; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.maxNewTokens != null) { - generator.writeKey("max_new_tokens"); - generator.write(this.maxNewTokens); - - } - if (this.temperature != null) { - generator.writeKey("temperature"); - generator.write(this.temperature); - - } - if (this.topK != null) { - generator.writeKey("top_k"); - generator.write(this.topK); - - } - if (this.topP != null) { - generator.writeKey("top_p"); - generator.write(this.topP); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AmazonBedrockTaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private Integer maxNewTokens; - - @Nullable - private Float temperature; - - @Nullable - private Float topK; - - @Nullable - private Float topP; - - /** - * For a completion task, it sets the maximum number for the output - * tokens to be generated. - *

- * API name: {@code max_new_tokens} - */ - public final Builder maxNewTokens(@Nullable Integer value) { - this.maxNewTokens = value; - return this; - } - - /** - * For a completion task, it is a number between 0.0 and 1.0 that - * controls the apparent creativity of the results. At temperature 0.0 the model - * is most deterministic, at temperature 1.0 most random. It should not be used - * if top_p or top_k is specified. - *

- * API name: {@code temperature} - */ - public final Builder temperature(@Nullable Float value) { - this.temperature = value; - return this; - } - - /** - * For a completion task, it limits samples to the top-K most - * likely words, balancing coherence and variability. It is only available for - * anthropic, cohere, and mistral providers. It is an alternative to - * temperature; it should not be used if temperature - * is specified. - *

- * API name: {@code top_k} - */ - public final Builder topK(@Nullable Float value) { - this.topK = value; - return this; - } - - /** - * For a completion task, it is a number in the range of 0.0 to - * 1.0, to eliminate low-probability tokens. Top-p uses nucleus sampling to - * select top tokens whose sum of likelihoods does not exceed a certain value, - * ensuring both variety and coherence. It is an alternative to - * temperature; it should not be used if temperature - * is specified. - *

- * API name: {@code top_p} - */ - public final Builder topP(@Nullable Float value) { - this.topP = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AmazonBedrockTaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AmazonBedrockTaskSettings build() { - _checkSingleUse(); - - return new AmazonBedrockTaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AmazonBedrockTaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AmazonBedrockTaskSettings::setupAmazonBedrockTaskSettingsDeserializer); - - protected static void setupAmazonBedrockTaskSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::maxNewTokens, JsonpDeserializer.integerDeserializer(), "max_new_tokens"); - op.add(Builder::temperature, JsonpDeserializer.floatDeserializer(), "temperature"); - op.add(Builder::topK, JsonpDeserializer.floatDeserializer(), "top_k"); - op.add(Builder::topP, JsonpDeserializer.floatDeserializer(), "top_p"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskType.java deleted file mode 100644 index 67d56cc4f..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskType.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_amazonbedrock; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum AmazonBedrockTaskType implements JsonEnum { - Completion("completion"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - AmazonBedrockTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - AmazonBedrockTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/ServiceType.java deleted file mode 100644 index 417d4e7c7..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_amazonbedrock; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Amazonbedrock("amazonbedrock"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicServiceSettings.java deleted file mode 100644 index fd1133481..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicServiceSettings.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_anthropic; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_anthropic.AnthropicServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AnthropicServiceSettings implements JsonpSerializable { - private final String apiKey; - - private final String modelId; - - @Nullable - private final RateLimitSetting rateLimit; - - // --------------------------------------------------------------------------------------------- - - private AnthropicServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); - this.rateLimit = builder.rateLimit; - - } - - public static AnthropicServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid API key for the Anthropic API. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * Anthropic documentation for the list of supported models. - *

- * API name: {@code model_id} - */ - public final String modelId() { - return this.modelId; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Anthropic. By default, the anthropic service sets the number of - * requests allowed per minute to 50. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - generator.writeKey("model_id"); - generator.write(this.modelId); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AnthropicServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - private String modelId; - - @Nullable - private RateLimitSetting rateLimit; - - /** - * Required - A valid API key for the Anthropic API. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * Anthropic documentation for the list of supported models. - *

- * API name: {@code model_id} - */ - public final Builder modelId(String value) { - this.modelId = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Anthropic. By default, the anthropic service sets the number of - * requests allowed per minute to 50. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Anthropic. By default, the anthropic service sets the number of - * requests allowed per minute to 50. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AnthropicServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AnthropicServiceSettings build() { - _checkSingleUse(); - - return new AnthropicServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AnthropicServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AnthropicServiceSettings::setupAnthropicServiceSettingsDeserializer); - - protected static void setupAnthropicServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskSettings.java deleted file mode 100644 index cababb804..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskSettings.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_anthropic; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Float; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_anthropic.AnthropicTaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AnthropicTaskSettings implements JsonpSerializable { - private final int maxTokens; - - @Nullable - private final Float temperature; - - @Nullable - private final Integer topK; - - @Nullable - private final Float topP; - - // --------------------------------------------------------------------------------------------- - - private AnthropicTaskSettings(Builder builder) { - - this.maxTokens = ApiTypeHelper.requireNonNull(builder.maxTokens, this, "maxTokens"); - this.temperature = builder.temperature; - this.topK = builder.topK; - this.topP = builder.topP; - - } - - public static AnthropicTaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - For a completion task, it is the maximum number of - * tokens to generate before stopping. - *

- * API name: {@code max_tokens} - */ - public final int maxTokens() { - return this.maxTokens; - } - - /** - * For a completion task, it is the amount of randomness injected - * into the response. For more details about the supported range, refer to - * Anthropic documentation. - *

- * API name: {@code temperature} - */ - @Nullable - public final Float temperature() { - return this.temperature; - } - - /** - * For a completion task, it specifies to only sample from the top - * K options for each subsequent token. It is recommended for advanced use cases - * only. You usually only need to use temperature. - *

- * API name: {@code top_k} - */ - @Nullable - public final Integer topK() { - return this.topK; - } - - /** - * For a completion task, it specifies to use Anthropic's nucleus - * sampling. In nucleus sampling, Anthropic computes the cumulative distribution - * over all the options for each subsequent token in decreasing probability - * order and cuts it off once it reaches the specified probability. You should - * either alter temperature or top_p, but not both. It - * is recommended for advanced use cases only. You usually only need to use - * temperature. - *

- * API name: {@code top_p} - */ - @Nullable - public final Float topP() { - return this.topP; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("max_tokens"); - generator.write(this.maxTokens); - - if (this.temperature != null) { - generator.writeKey("temperature"); - generator.write(this.temperature); - - } - if (this.topK != null) { - generator.writeKey("top_k"); - generator.write(this.topK); - - } - if (this.topP != null) { - generator.writeKey("top_p"); - generator.write(this.topP); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AnthropicTaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private Integer maxTokens; - - @Nullable - private Float temperature; - - @Nullable - private Integer topK; - - @Nullable - private Float topP; - - /** - * Required - For a completion task, it is the maximum number of - * tokens to generate before stopping. - *

- * API name: {@code max_tokens} - */ - public final Builder maxTokens(int value) { - this.maxTokens = value; - return this; - } - - /** - * For a completion task, it is the amount of randomness injected - * into the response. For more details about the supported range, refer to - * Anthropic documentation. - *

- * API name: {@code temperature} - */ - public final Builder temperature(@Nullable Float value) { - this.temperature = value; - return this; - } - - /** - * For a completion task, it specifies to only sample from the top - * K options for each subsequent token. It is recommended for advanced use cases - * only. You usually only need to use temperature. - *

- * API name: {@code top_k} - */ - public final Builder topK(@Nullable Integer value) { - this.topK = value; - return this; - } - - /** - * For a completion task, it specifies to use Anthropic's nucleus - * sampling. In nucleus sampling, Anthropic computes the cumulative distribution - * over all the options for each subsequent token in decreasing probability - * order and cuts it off once it reaches the specified probability. You should - * either alter temperature or top_p, but not both. It - * is recommended for advanced use cases only. You usually only need to use - * temperature. - *

- * API name: {@code top_p} - */ - public final Builder topP(@Nullable Float value) { - this.topP = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AnthropicTaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AnthropicTaskSettings build() { - _checkSingleUse(); - - return new AnthropicTaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AnthropicTaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AnthropicTaskSettings::setupAnthropicTaskSettingsDeserializer); - - protected static void setupAnthropicTaskSettingsDeserializer(ObjectDeserializer op) { - - op.add(Builder::maxTokens, JsonpDeserializer.integerDeserializer(), "max_tokens"); - op.add(Builder::temperature, JsonpDeserializer.floatDeserializer(), "temperature"); - op.add(Builder::topK, JsonpDeserializer.integerDeserializer(), "top_k"); - op.add(Builder::topP, JsonpDeserializer.floatDeserializer(), "top_p"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskType.java deleted file mode 100644 index 4599e9d31..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_anthropic; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum AnthropicTaskType implements JsonEnum { - Completion("completion"), - - ; - - private final String jsonValue; - - AnthropicTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - AnthropicTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/ServiceType.java deleted file mode 100644 index 2d6288747..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_anthropic; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Anthropic("anthropic"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioServiceSettings.java deleted file mode 100644 index a407ad66b..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioServiceSettings.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_azureaistudio; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_azureaistudio.AzureAiStudioServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AzureAiStudioServiceSettings implements JsonpSerializable { - private final String apiKey; - - private final String endpointType; - - private final String target; - - private final String provider; - - @Nullable - private final RateLimitSetting rateLimit; - - // --------------------------------------------------------------------------------------------- - - private AzureAiStudioServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.endpointType = ApiTypeHelper.requireNonNull(builder.endpointType, this, "endpointType"); - this.target = ApiTypeHelper.requireNonNull(builder.target, this, "target"); - this.provider = ApiTypeHelper.requireNonNull(builder.provider, this, "provider"); - this.rateLimit = builder.rateLimit; - - } - - public static AzureAiStudioServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid API key of your Azure AI Studio model deployment. This key - * can be found on the overview page for your deployment in the management - * section of your Azure AI Studio account. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * Required - The type of endpoint that is available for deployment through - * Azure AI Studio: token or realtime. The - * token endpoint type is for "pay as you go" endpoints - * that are billed per token. The realtime endpoint type is for - * "real-time" endpoints that are billed per hour of usage. - *

- * API name: {@code endpoint_type} - */ - public final String endpointType() { - return this.endpointType; - } - - /** - * Required - The target URL of your Azure AI Studio model deployment. This can - * be found on the overview page for your deployment in the management section - * of your Azure AI Studio account. - *

- * API name: {@code target} - */ - public final String target() { - return this.target; - } - - /** - * Required - The model provider for your deployment. Note that some providers - * may support only certain task types. Supported providers include: - *

    - *
  • cohere - available for text_embedding and - * completion task types
  • - *
  • databricks - available for completion task type - * only
  • - *
  • meta - available for completion task type - * only
  • - *
  • microsoft_phi - available for completion task - * type only
  • - *
  • mistral - available for completion task type - * only
  • - *
  • openai - available for text_embedding and - * completion task types
  • - *
- *

- * API name: {@code provider} - */ - public final String provider() { - return this.provider; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Azure AI Studio. By default, the azureaistudio service sets the - * number of requests allowed per minute to 240. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - generator.writeKey("endpoint_type"); - generator.write(this.endpointType); - - generator.writeKey("target"); - generator.write(this.target); - - generator.writeKey("provider"); - generator.write(this.provider); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AzureAiStudioServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - private String endpointType; - - private String target; - - private String provider; - - @Nullable - private RateLimitSetting rateLimit; - - /** - * Required - A valid API key of your Azure AI Studio model deployment. This key - * can be found on the overview page for your deployment in the management - * section of your Azure AI Studio account. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * Required - The type of endpoint that is available for deployment through - * Azure AI Studio: token or realtime. The - * token endpoint type is for "pay as you go" endpoints - * that are billed per token. The realtime endpoint type is for - * "real-time" endpoints that are billed per hour of usage. - *

- * API name: {@code endpoint_type} - */ - public final Builder endpointType(String value) { - this.endpointType = value; - return this; - } - - /** - * Required - The target URL of your Azure AI Studio model deployment. This can - * be found on the overview page for your deployment in the management section - * of your Azure AI Studio account. - *

- * API name: {@code target} - */ - public final Builder target(String value) { - this.target = value; - return this; - } - - /** - * Required - The model provider for your deployment. Note that some providers - * may support only certain task types. Supported providers include: - *

    - *
  • cohere - available for text_embedding and - * completion task types
  • - *
  • databricks - available for completion task type - * only
  • - *
  • meta - available for completion task type - * only
  • - *
  • microsoft_phi - available for completion task - * type only
  • - *
  • mistral - available for completion task type - * only
  • - *
  • openai - available for text_embedding and - * completion task types
  • - *
- *

- * API name: {@code provider} - */ - public final Builder provider(String value) { - this.provider = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Azure AI Studio. By default, the azureaistudio service sets the - * number of requests allowed per minute to 240. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Azure AI Studio. By default, the azureaistudio service sets the - * number of requests allowed per minute to 240. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AzureAiStudioServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AzureAiStudioServiceSettings build() { - _checkSingleUse(); - - return new AzureAiStudioServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AzureAiStudioServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AzureAiStudioServiceSettings::setupAzureAiStudioServiceSettingsDeserializer); - - protected static void setupAzureAiStudioServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::endpointType, JsonpDeserializer.stringDeserializer(), "endpoint_type"); - op.add(Builder::target, JsonpDeserializer.stringDeserializer(), "target"); - op.add(Builder::provider, JsonpDeserializer.stringDeserializer(), "provider"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskSettings.java deleted file mode 100644 index df846c062..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskSettings.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_azureaistudio; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Float; -import java.lang.Integer; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_azureaistudio.AzureAiStudioTaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AzureAiStudioTaskSettings implements JsonpSerializable { - @Nullable - private final Float doSample; - - @Nullable - private final Integer maxNewTokens; - - @Nullable - private final Float temperature; - - @Nullable - private final Float topP; - - @Nullable - private final String user; - - // --------------------------------------------------------------------------------------------- - - private AzureAiStudioTaskSettings(Builder builder) { - - this.doSample = builder.doSample; - this.maxNewTokens = builder.maxNewTokens; - this.temperature = builder.temperature; - this.topP = builder.topP; - this.user = builder.user; - - } - - public static AzureAiStudioTaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * For a completion task, instruct the inference process to perform - * sampling. It has no effect unless temperature or - * top_p is specified. - *

- * API name: {@code do_sample} - */ - @Nullable - public final Float doSample() { - return this.doSample; - } - - /** - * For a completion task, provide a hint for the maximum number of - * output tokens to be generated. - *

- * API name: {@code max_new_tokens} - */ - @Nullable - public final Integer maxNewTokens() { - return this.maxNewTokens; - } - - /** - * For a completion task, control the apparent creativity of - * generated completions with a sampling temperature. It must be a number in the - * range of 0.0 to 2.0. It should not be used if top_p is - * specified. - *

- * API name: {@code temperature} - */ - @Nullable - public final Float temperature() { - return this.temperature; - } - - /** - * For a completion task, make the model consider the results of - * the tokens with nucleus sampling probability. It is an alternative value to - * temperature and must be a number in the range of 0.0 to 2.0. It - * should not be used if temperature is specified. - *

- * API name: {@code top_p} - */ - @Nullable - public final Float topP() { - return this.topP; - } - - /** - * For a text_embedding task, specify the user issuing the request. - * This information can be used for abuse detection. - *

- * API name: {@code user} - */ - @Nullable - public final String user() { - return this.user; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.doSample != null) { - generator.writeKey("do_sample"); - generator.write(this.doSample); - - } - if (this.maxNewTokens != null) { - generator.writeKey("max_new_tokens"); - generator.write(this.maxNewTokens); - - } - if (this.temperature != null) { - generator.writeKey("temperature"); - generator.write(this.temperature); - - } - if (this.topP != null) { - generator.writeKey("top_p"); - generator.write(this.topP); - - } - if (this.user != null) { - generator.writeKey("user"); - generator.write(this.user); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AzureAiStudioTaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private Float doSample; - - @Nullable - private Integer maxNewTokens; - - @Nullable - private Float temperature; - - @Nullable - private Float topP; - - @Nullable - private String user; - - /** - * For a completion task, instruct the inference process to perform - * sampling. It has no effect unless temperature or - * top_p is specified. - *

- * API name: {@code do_sample} - */ - public final Builder doSample(@Nullable Float value) { - this.doSample = value; - return this; - } - - /** - * For a completion task, provide a hint for the maximum number of - * output tokens to be generated. - *

- * API name: {@code max_new_tokens} - */ - public final Builder maxNewTokens(@Nullable Integer value) { - this.maxNewTokens = value; - return this; - } - - /** - * For a completion task, control the apparent creativity of - * generated completions with a sampling temperature. It must be a number in the - * range of 0.0 to 2.0. It should not be used if top_p is - * specified. - *

- * API name: {@code temperature} - */ - public final Builder temperature(@Nullable Float value) { - this.temperature = value; - return this; - } - - /** - * For a completion task, make the model consider the results of - * the tokens with nucleus sampling probability. It is an alternative value to - * temperature and must be a number in the range of 0.0 to 2.0. It - * should not be used if temperature is specified. - *

- * API name: {@code top_p} - */ - public final Builder topP(@Nullable Float value) { - this.topP = value; - return this; - } - - /** - * For a text_embedding task, specify the user issuing the request. - * This information can be used for abuse detection. - *

- * API name: {@code user} - */ - public final Builder user(@Nullable String value) { - this.user = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AzureAiStudioTaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AzureAiStudioTaskSettings build() { - _checkSingleUse(); - - return new AzureAiStudioTaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AzureAiStudioTaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AzureAiStudioTaskSettings::setupAzureAiStudioTaskSettingsDeserializer); - - protected static void setupAzureAiStudioTaskSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::doSample, JsonpDeserializer.floatDeserializer(), "do_sample"); - op.add(Builder::maxNewTokens, JsonpDeserializer.integerDeserializer(), "max_new_tokens"); - op.add(Builder::temperature, JsonpDeserializer.floatDeserializer(), "temperature"); - op.add(Builder::topP, JsonpDeserializer.floatDeserializer(), "top_p"); - op.add(Builder::user, JsonpDeserializer.stringDeserializer(), "user"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskType.java deleted file mode 100644 index 7a8b074fe..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskType.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_azureaistudio; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum AzureAiStudioTaskType implements JsonEnum { - Completion("completion"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - AzureAiStudioTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - AzureAiStudioTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/ServiceType.java deleted file mode 100644 index 5e3b80f0e..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_azureaistudio; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Azureaistudio("azureaistudio"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAIServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAIServiceSettings.java deleted file mode 100644 index 849f7bee6..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAIServiceSettings.java +++ /dev/null @@ -1,368 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_azureopenai; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_azureopenai.AzureOpenAIServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AzureOpenAIServiceSettings implements JsonpSerializable { - @Nullable - private final String apiKey; - - private final String apiVersion; - - private final String deploymentId; - - @Nullable - private final String entraId; - - @Nullable - private final RateLimitSetting rateLimit; - - private final String resourceName; - - // --------------------------------------------------------------------------------------------- - - private AzureOpenAIServiceSettings(Builder builder) { - - this.apiKey = builder.apiKey; - this.apiVersion = ApiTypeHelper.requireNonNull(builder.apiVersion, this, "apiVersion"); - this.deploymentId = ApiTypeHelper.requireNonNull(builder.deploymentId, this, "deploymentId"); - this.entraId = builder.entraId; - this.rateLimit = builder.rateLimit; - this.resourceName = ApiTypeHelper.requireNonNull(builder.resourceName, this, "resourceName"); - - } - - public static AzureOpenAIServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * A valid API key for your Azure OpenAI account. You must specify either - * api_key or entra_id. If you do not provide either - * or you provide both, you will receive an error when you try to create your - * model. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - @Nullable - public final String apiKey() { - return this.apiKey; - } - - /** - * Required - The Azure API version ID to use. It is recommended to use the - * latest supported non-preview version. - *

- * API name: {@code api_version} - */ - public final String apiVersion() { - return this.apiVersion; - } - - /** - * Required - The deployment name of your deployed models. Your Azure OpenAI - * deployments can be found though the Azure OpenAI Studio portal that is linked - * to your subscription. - *

- * API name: {@code deployment_id} - */ - public final String deploymentId() { - return this.deploymentId; - } - - /** - * A valid Microsoft Entra token. You must specify either api_key - * or entra_id. If you do not provide either or you provide both, - * you will receive an error when you try to create your model. - *

- * API name: {@code entra_id} - */ - @Nullable - public final String entraId() { - return this.entraId; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Azure. The azureopenai service sets a default number of requests - * allowed per minute depending on the task type. For - * text_embedding, it is set to 1440. For - * completion, it is set to 120. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Required - The name of your Azure OpenAI resource. You can find this from the - * list of resources in the Azure Portal for your subscription. - *

- * API name: {@code resource_name} - */ - public final String resourceName() { - return this.resourceName; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.apiKey != null) { - generator.writeKey("api_key"); - generator.write(this.apiKey); - - } - generator.writeKey("api_version"); - generator.write(this.apiVersion); - - generator.writeKey("deployment_id"); - generator.write(this.deploymentId); - - if (this.entraId != null) { - generator.writeKey("entra_id"); - generator.write(this.entraId); - - } - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - generator.writeKey("resource_name"); - generator.write(this.resourceName); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AzureOpenAIServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private String apiKey; - - private String apiVersion; - - private String deploymentId; - - @Nullable - private String entraId; - - @Nullable - private RateLimitSetting rateLimit; - - private String resourceName; - - /** - * A valid API key for your Azure OpenAI account. You must specify either - * api_key or entra_id. If you do not provide either - * or you provide both, you will receive an error when you try to create your - * model. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(@Nullable String value) { - this.apiKey = value; - return this; - } - - /** - * Required - The Azure API version ID to use. It is recommended to use the - * latest supported non-preview version. - *

- * API name: {@code api_version} - */ - public final Builder apiVersion(String value) { - this.apiVersion = value; - return this; - } - - /** - * Required - The deployment name of your deployed models. Your Azure OpenAI - * deployments can be found though the Azure OpenAI Studio portal that is linked - * to your subscription. - *

- * API name: {@code deployment_id} - */ - public final Builder deploymentId(String value) { - this.deploymentId = value; - return this; - } - - /** - * A valid Microsoft Entra token. You must specify either api_key - * or entra_id. If you do not provide either or you provide both, - * you will receive an error when you try to create your model. - *

- * API name: {@code entra_id} - */ - public final Builder entraId(@Nullable String value) { - this.entraId = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Azure. The azureopenai service sets a default number of requests - * allowed per minute depending on the task type. For - * text_embedding, it is set to 1440. For - * completion, it is set to 120. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Azure. The azureopenai service sets a default number of requests - * allowed per minute depending on the task type. For - * text_embedding, it is set to 1440. For - * completion, it is set to 120. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * Required - The name of your Azure OpenAI resource. You can find this from the - * list of resources in the Azure Portal for your subscription. - *

- * API name: {@code resource_name} - */ - public final Builder resourceName(String value) { - this.resourceName = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AzureOpenAIServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AzureOpenAIServiceSettings build() { - _checkSingleUse(); - - return new AzureOpenAIServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AzureOpenAIServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AzureOpenAIServiceSettings::setupAzureOpenAIServiceSettingsDeserializer); - - protected static void setupAzureOpenAIServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::apiVersion, JsonpDeserializer.stringDeserializer(), "api_version"); - op.add(Builder::deploymentId, JsonpDeserializer.stringDeserializer(), "deployment_id"); - op.add(Builder::entraId, JsonpDeserializer.stringDeserializer(), "entra_id"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::resourceName, JsonpDeserializer.stringDeserializer(), "resource_name"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAITaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAITaskType.java deleted file mode 100644 index 4c6414276..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAITaskType.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_azureopenai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum AzureOpenAITaskType implements JsonEnum { - Completion("completion"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - AzureOpenAITaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - AzureOpenAITaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/ServiceType.java deleted file mode 100644 index c27837b69..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_azureopenai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Azureopenai("azureopenai"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereServiceSettings.java deleted file mode 100644 index 86c1c9e24..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereServiceSettings.java +++ /dev/null @@ -1,363 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_cohere; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_cohere.CohereServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class CohereServiceSettings implements JsonpSerializable { - private final String apiKey; - - @Nullable - private final EmbeddingType embeddingType; - - @Nullable - private final String modelId; - - @Nullable - private final RateLimitSetting rateLimit; - - @Nullable - private final SimilarityType similarity; - - // --------------------------------------------------------------------------------------------- - - private CohereServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.embeddingType = builder.embeddingType; - this.modelId = builder.modelId; - this.rateLimit = builder.rateLimit; - this.similarity = builder.similarity; - - } - - public static CohereServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid API key for your Cohere account. You can find or create - * your Cohere API keys on the Cohere API key settings page. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * For a text_embedding task, the types of embeddings you want to - * get back. Use byte for signed int8 embeddings (this is a synonym - * of int8). Use float for the default float - * embeddings. Use int8 for signed int8 embeddings. - *

- * API name: {@code embedding_type} - */ - @Nullable - public final EmbeddingType embeddingType() { - return this.embeddingType; - } - - /** - * For a completion, rerank, or - * text_embedding task, the name of the model to use for the - * inference task. - *

- *

- * The default value for a text embedding task is - * embed-english-v2.0. - *

- * API name: {@code model_id} - */ - @Nullable - public final String modelId() { - return this.modelId; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Cohere. By default, the cohere service sets the number of - * requests allowed per minute to 10000. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * The similarity measure. If the embedding_type is - * float, the default value is dot_product. If the - * embedding_type is int8 or byte, the - * default value is cosine. - *

- * API name: {@code similarity} - */ - @Nullable - public final SimilarityType similarity() { - return this.similarity; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - if (this.embeddingType != null) { - generator.writeKey("embedding_type"); - this.embeddingType.serialize(generator, mapper); - } - if (this.modelId != null) { - generator.writeKey("model_id"); - generator.write(this.modelId); - - } - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - if (this.similarity != null) { - generator.writeKey("similarity"); - this.similarity.serialize(generator, mapper); - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link CohereServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - @Nullable - private EmbeddingType embeddingType; - - @Nullable - private String modelId; - - @Nullable - private RateLimitSetting rateLimit; - - @Nullable - private SimilarityType similarity; - - /** - * Required - A valid API key for your Cohere account. You can find or create - * your Cohere API keys on the Cohere API key settings page. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * For a text_embedding task, the types of embeddings you want to - * get back. Use byte for signed int8 embeddings (this is a synonym - * of int8). Use float for the default float - * embeddings. Use int8 for signed int8 embeddings. - *

- * API name: {@code embedding_type} - */ - public final Builder embeddingType(@Nullable EmbeddingType value) { - this.embeddingType = value; - return this; - } - - /** - * For a completion, rerank, or - * text_embedding task, the name of the model to use for the - * inference task. - *

- *

- * The default value for a text embedding task is - * embed-english-v2.0. - *

- * API name: {@code model_id} - */ - public final Builder modelId(@Nullable String value) { - this.modelId = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Cohere. By default, the cohere service sets the number of - * requests allowed per minute to 10000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Cohere. By default, the cohere service sets the number of - * requests allowed per minute to 10000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * The similarity measure. If the embedding_type is - * float, the default value is dot_product. If the - * embedding_type is int8 or byte, the - * default value is cosine. - *

- * API name: {@code similarity} - */ - public final Builder similarity(@Nullable SimilarityType value) { - this.similarity = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link CohereServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public CohereServiceSettings build() { - _checkSingleUse(); - - return new CohereServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link CohereServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, CohereServiceSettings::setupCohereServiceSettingsDeserializer); - - protected static void setupCohereServiceSettingsDeserializer(ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::embeddingType, EmbeddingType._DESERIALIZER, "embedding_type"); - op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::similarity, SimilarityType._DESERIALIZER, "similarity"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskSettings.java deleted file mode 100644 index 77947b3ee..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskSettings.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_cohere; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_cohere.CohereTaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class CohereTaskSettings implements JsonpSerializable { - @Nullable - private final InputType inputType; - - @Nullable - private final Boolean returnDocuments; - - @Nullable - private final Integer topN; - - @Nullable - private final TruncateType truncate; - - // --------------------------------------------------------------------------------------------- - - private CohereTaskSettings(Builder builder) { - - this.inputType = builder.inputType; - this.returnDocuments = builder.returnDocuments; - this.topN = builder.topN; - this.truncate = builder.truncate; - - } - - public static CohereTaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * For a text_embedding task, the type of input passed to the - * model. Valid values are: - *

    - *
  • classification: Use it for embeddings passed through a text - * classifier.
  • - *
  • clustering: Use it for the embeddings run through a - * clustering algorithm.
  • - *
  • ingest: Use it for storing document embeddings in a vector - * database.
  • - *
  • search: Use it for storing embeddings of search queries run - * against a vector database to find relevant documents.
  • - *
- *

- * IMPORTANT: The input_type field is required when using embedding - * models v3 and higher. - *

- * API name: {@code input_type} - */ - @Nullable - public final InputType inputType() { - return this.inputType; - } - - /** - * For a rerank task, return doc text within the results. - *

- * API name: {@code return_documents} - */ - @Nullable - public final Boolean returnDocuments() { - return this.returnDocuments; - } - - /** - * For a rerank task, the number of most relevant documents to - * return. It defaults to the number of the documents. If this inference - * endpoint is used in a text_similarity_reranker retriever query - * and top_n is set, it must be greater than or equal to - * rank_window_size in the query. - *

- * API name: {@code top_n} - */ - @Nullable - public final Integer topN() { - return this.topN; - } - - /** - * For a text_embedding task, the method to handle inputs longer - * than the maximum token length. Valid values are: - *

    - *
  • END: When the input exceeds the maximum input token length, - * the end of the input is discarded.
  • - *
  • NONE: When the input exceeds the maximum input token length, - * an error is returned.
  • - *
  • START: When the input exceeds the maximum input token - * length, the start of the input is discarded.
  • - *
- *

- * API name: {@code truncate} - */ - @Nullable - public final TruncateType truncate() { - return this.truncate; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.inputType != null) { - generator.writeKey("input_type"); - this.inputType.serialize(generator, mapper); - } - if (this.returnDocuments != null) { - generator.writeKey("return_documents"); - generator.write(this.returnDocuments); - - } - if (this.topN != null) { - generator.writeKey("top_n"); - generator.write(this.topN); - - } - if (this.truncate != null) { - generator.writeKey("truncate"); - this.truncate.serialize(generator, mapper); - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link CohereTaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private InputType inputType; - - @Nullable - private Boolean returnDocuments; - - @Nullable - private Integer topN; - - @Nullable - private TruncateType truncate; - - /** - * For a text_embedding task, the type of input passed to the - * model. Valid values are: - *

    - *
  • classification: Use it for embeddings passed through a text - * classifier.
  • - *
  • clustering: Use it for the embeddings run through a - * clustering algorithm.
  • - *
  • ingest: Use it for storing document embeddings in a vector - * database.
  • - *
  • search: Use it for storing embeddings of search queries run - * against a vector database to find relevant documents.
  • - *
- *

- * IMPORTANT: The input_type field is required when using embedding - * models v3 and higher. - *

- * API name: {@code input_type} - */ - public final Builder inputType(@Nullable InputType value) { - this.inputType = value; - return this; - } - - /** - * For a rerank task, return doc text within the results. - *

- * API name: {@code return_documents} - */ - public final Builder returnDocuments(@Nullable Boolean value) { - this.returnDocuments = value; - return this; - } - - /** - * For a rerank task, the number of most relevant documents to - * return. It defaults to the number of the documents. If this inference - * endpoint is used in a text_similarity_reranker retriever query - * and top_n is set, it must be greater than or equal to - * rank_window_size in the query. - *

- * API name: {@code top_n} - */ - public final Builder topN(@Nullable Integer value) { - this.topN = value; - return this; - } - - /** - * For a text_embedding task, the method to handle inputs longer - * than the maximum token length. Valid values are: - *

    - *
  • END: When the input exceeds the maximum input token length, - * the end of the input is discarded.
  • - *
  • NONE: When the input exceeds the maximum input token length, - * an error is returned.
  • - *
  • START: When the input exceeds the maximum input token - * length, the start of the input is discarded.
  • - *
- *

- * API name: {@code truncate} - */ - public final Builder truncate(@Nullable TruncateType value) { - this.truncate = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link CohereTaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public CohereTaskSettings build() { - _checkSingleUse(); - - return new CohereTaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link CohereTaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, CohereTaskSettings::setupCohereTaskSettingsDeserializer); - - protected static void setupCohereTaskSettingsDeserializer(ObjectDeserializer op) { - - op.add(Builder::inputType, InputType._DESERIALIZER, "input_type"); - op.add(Builder::returnDocuments, JsonpDeserializer.booleanDeserializer(), "return_documents"); - op.add(Builder::topN, JsonpDeserializer.integerDeserializer(), "top_n"); - op.add(Builder::truncate, TruncateType._DESERIALIZER, "truncate"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskType.java deleted file mode 100644 index 81025c4aa..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskType.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_cohere; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum CohereTaskType implements JsonEnum { - Completion("completion"), - - Rerank("rerank"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - CohereTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - CohereTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/EmbeddingType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/EmbeddingType.java deleted file mode 100644 index 0527144d6..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/EmbeddingType.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_cohere; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum EmbeddingType implements JsonEnum { - Byte("byte"), - - Float("float"), - - Int8("int8"), - - ; - - private final String jsonValue; - - EmbeddingType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - EmbeddingType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/InputType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/InputType.java deleted file mode 100644 index e4ff40c8f..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/InputType.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_cohere; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum InputType implements JsonEnum { - Classification("classification"), - - Clustering("clustering"), - - Ingest("ingest"), - - Search("search"), - - ; - - private final String jsonValue; - - InputType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - InputType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/ServiceType.java deleted file mode 100644 index ff717e85a..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_cohere; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Cohere("cohere"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/SimilarityType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/SimilarityType.java deleted file mode 100644 index 651346c62..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/SimilarityType.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_cohere; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum SimilarityType implements JsonEnum { - Cosine("cosine"), - - DotProduct("dot_product"), - - L2Norm("l2_norm"), - - ; - - private final String jsonValue; - - SimilarityType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - SimilarityType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/TruncateType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/TruncateType.java deleted file mode 100644 index b3f7691cd..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/TruncateType.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_cohere; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum TruncateType implements JsonEnum { - End("END"), - - None("NONE"), - - Start("START"), - - ; - - private final String jsonValue; - - TruncateType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - TruncateType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/AdaptiveAllocations.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/AdaptiveAllocations.java deleted file mode 100644 index b5c60a2ae..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/AdaptiveAllocations.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_elasticsearch; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_elasticsearch.AdaptiveAllocations - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AdaptiveAllocations implements JsonpSerializable { - @Nullable - private final Boolean enabled; - - @Nullable - private final Integer maxNumberOfAllocations; - - @Nullable - private final Integer minNumberOfAllocations; - - // --------------------------------------------------------------------------------------------- - - private AdaptiveAllocations(Builder builder) { - - this.enabled = builder.enabled; - this.maxNumberOfAllocations = builder.maxNumberOfAllocations; - this.minNumberOfAllocations = builder.minNumberOfAllocations; - - } - - public static AdaptiveAllocations of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Turn on adaptive_allocations. - *

- * API name: {@code enabled} - */ - @Nullable - public final Boolean enabled() { - return this.enabled; - } - - /** - * The maximum number of allocations to scale to. If set, it must be greater - * than or equal to min_number_of_allocations. - *

- * API name: {@code max_number_of_allocations} - */ - @Nullable - public final Integer maxNumberOfAllocations() { - return this.maxNumberOfAllocations; - } - - /** - * The minimum number of allocations to scale to. If set, it must be greater - * than or equal to 0. If not defined, the deployment scales to 0. - *

- * API name: {@code min_number_of_allocations} - */ - @Nullable - public final Integer minNumberOfAllocations() { - return this.minNumberOfAllocations; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.enabled != null) { - generator.writeKey("enabled"); - generator.write(this.enabled); - - } - if (this.maxNumberOfAllocations != null) { - generator.writeKey("max_number_of_allocations"); - generator.write(this.maxNumberOfAllocations); - - } - if (this.minNumberOfAllocations != null) { - generator.writeKey("min_number_of_allocations"); - generator.write(this.minNumberOfAllocations); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AdaptiveAllocations}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private Boolean enabled; - - @Nullable - private Integer maxNumberOfAllocations; - - @Nullable - private Integer minNumberOfAllocations; - - /** - * Turn on adaptive_allocations. - *

- * API name: {@code enabled} - */ - public final Builder enabled(@Nullable Boolean value) { - this.enabled = value; - return this; - } - - /** - * The maximum number of allocations to scale to. If set, it must be greater - * than or equal to min_number_of_allocations. - *

- * API name: {@code max_number_of_allocations} - */ - public final Builder maxNumberOfAllocations(@Nullable Integer value) { - this.maxNumberOfAllocations = value; - return this; - } - - /** - * The minimum number of allocations to scale to. If set, it must be greater - * than or equal to 0. If not defined, the deployment scales to 0. - *

- * API name: {@code min_number_of_allocations} - */ - public final Builder minNumberOfAllocations(@Nullable Integer value) { - this.minNumberOfAllocations = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AdaptiveAllocations}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AdaptiveAllocations build() { - _checkSingleUse(); - - return new AdaptiveAllocations(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AdaptiveAllocations} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AdaptiveAllocations::setupAdaptiveAllocationsDeserializer); - - protected static void setupAdaptiveAllocationsDeserializer(ObjectDeserializer op) { - - op.add(Builder::enabled, JsonpDeserializer.booleanDeserializer(), "enabled"); - op.add(Builder::maxNumberOfAllocations, JsonpDeserializer.integerDeserializer(), "max_number_of_allocations"); - op.add(Builder::minNumberOfAllocations, JsonpDeserializer.integerDeserializer(), "min_number_of_allocations"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchServiceSettings.java deleted file mode 100644 index e9e60d46a..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchServiceSettings.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_elasticsearch; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Integer; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_elasticsearch.ElasticsearchServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class ElasticsearchServiceSettings implements JsonpSerializable { - @Nullable - private final AdaptiveAllocations adaptiveAllocations; - - @Nullable - private final String deploymentId; - - private final String modelId; - - @Nullable - private final Integer numAllocations; - - private final int numThreads; - - // --------------------------------------------------------------------------------------------- - - private ElasticsearchServiceSettings(Builder builder) { - - this.adaptiveAllocations = builder.adaptiveAllocations; - this.deploymentId = builder.deploymentId; - this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); - this.numAllocations = builder.numAllocations; - this.numThreads = ApiTypeHelper.requireNonNull(builder.numThreads, this, "numThreads"); - - } - - public static ElasticsearchServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Adaptive allocations configuration details. If enabled is true, - * the number of allocations of the model is set based on the current load the - * process gets. When the load is high, a new model allocation is automatically - * created, respecting the value of max_number_of_allocations if - * it's set. When the load is low, a model allocation is automatically removed, - * respecting the value of min_number_of_allocations if it's set. - * If enabled is true, do not set the number of allocations - * manually. - *

- * API name: {@code adaptive_allocations} - */ - @Nullable - public final AdaptiveAllocations adaptiveAllocations() { - return this.adaptiveAllocations; - } - - /** - * The deployment identifier for a trained model deployment. When - * deployment_id is used the model_id is optional. - *

- * API name: {@code deployment_id} - */ - @Nullable - public final String deploymentId() { - return this.deploymentId; - } - - /** - * Required - The name of the model to use for the inference task. It can be the - * ID of a built-in model (for example, .multilingual-e5-small for - * E5) or a text embedding model that was uploaded by using the Eland client. - *

- * API name: {@code model_id} - */ - public final String modelId() { - return this.modelId; - } - - /** - * The total number of allocations that are assigned to the model across machine - * learning nodes. Increasing this value generally increases the throughput. If - * adaptive allocations are enabled, do not set this value because it's - * automatically set. - *

- * API name: {@code num_allocations} - */ - @Nullable - public final Integer numAllocations() { - return this.numAllocations; - } - - /** - * Required - The number of threads used by each model allocation during - * inference. This setting generally increases the speed per inference request. - * The inference process is a compute-bound process; - * threads_per_allocations must not exceed the number of available - * allocated processors per node. The value must be a power of 2. The maximum - * value is 32. - *

- * API name: {@code num_threads} - */ - public final int numThreads() { - return this.numThreads; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.adaptiveAllocations != null) { - generator.writeKey("adaptive_allocations"); - this.adaptiveAllocations.serialize(generator, mapper); - - } - if (this.deploymentId != null) { - generator.writeKey("deployment_id"); - generator.write(this.deploymentId); - - } - generator.writeKey("model_id"); - generator.write(this.modelId); - - if (this.numAllocations != null) { - generator.writeKey("num_allocations"); - generator.write(this.numAllocations); - - } - generator.writeKey("num_threads"); - generator.write(this.numThreads); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link ElasticsearchServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private AdaptiveAllocations adaptiveAllocations; - - @Nullable - private String deploymentId; - - private String modelId; - - @Nullable - private Integer numAllocations; - - private Integer numThreads; - - /** - * Adaptive allocations configuration details. If enabled is true, - * the number of allocations of the model is set based on the current load the - * process gets. When the load is high, a new model allocation is automatically - * created, respecting the value of max_number_of_allocations if - * it's set. When the load is low, a model allocation is automatically removed, - * respecting the value of min_number_of_allocations if it's set. - * If enabled is true, do not set the number of allocations - * manually. - *

- * API name: {@code adaptive_allocations} - */ - public final Builder adaptiveAllocations(@Nullable AdaptiveAllocations value) { - this.adaptiveAllocations = value; - return this; - } - - /** - * Adaptive allocations configuration details. If enabled is true, - * the number of allocations of the model is set based on the current load the - * process gets. When the load is high, a new model allocation is automatically - * created, respecting the value of max_number_of_allocations if - * it's set. When the load is low, a model allocation is automatically removed, - * respecting the value of min_number_of_allocations if it's set. - * If enabled is true, do not set the number of allocations - * manually. - *

- * API name: {@code adaptive_allocations} - */ - public final Builder adaptiveAllocations( - Function> fn) { - return this.adaptiveAllocations(fn.apply(new AdaptiveAllocations.Builder()).build()); - } - - /** - * The deployment identifier for a trained model deployment. When - * deployment_id is used the model_id is optional. - *

- * API name: {@code deployment_id} - */ - public final Builder deploymentId(@Nullable String value) { - this.deploymentId = value; - return this; - } - - /** - * Required - The name of the model to use for the inference task. It can be the - * ID of a built-in model (for example, .multilingual-e5-small for - * E5) or a text embedding model that was uploaded by using the Eland client. - *

- * API name: {@code model_id} - */ - public final Builder modelId(String value) { - this.modelId = value; - return this; - } - - /** - * The total number of allocations that are assigned to the model across machine - * learning nodes. Increasing this value generally increases the throughput. If - * adaptive allocations are enabled, do not set this value because it's - * automatically set. - *

- * API name: {@code num_allocations} - */ - public final Builder numAllocations(@Nullable Integer value) { - this.numAllocations = value; - return this; - } - - /** - * Required - The number of threads used by each model allocation during - * inference. This setting generally increases the speed per inference request. - * The inference process is a compute-bound process; - * threads_per_allocations must not exceed the number of available - * allocated processors per node. The value must be a power of 2. The maximum - * value is 32. - *

- * API name: {@code num_threads} - */ - public final Builder numThreads(int value) { - this.numThreads = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link ElasticsearchServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public ElasticsearchServiceSettings build() { - _checkSingleUse(); - - return new ElasticsearchServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link ElasticsearchServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, ElasticsearchServiceSettings::setupElasticsearchServiceSettingsDeserializer); - - protected static void setupElasticsearchServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::adaptiveAllocations, AdaptiveAllocations._DESERIALIZER, "adaptive_allocations"); - op.add(Builder::deploymentId, JsonpDeserializer.stringDeserializer(), "deployment_id"); - op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); - op.add(Builder::numAllocations, JsonpDeserializer.integerDeserializer(), "num_allocations"); - op.add(Builder::numThreads, JsonpDeserializer.integerDeserializer(), "num_threads"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskSettings.java deleted file mode 100644 index 085c5faad..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskSettings.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_elasticsearch; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_elasticsearch.ElasticsearchTaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class ElasticsearchTaskSettings implements JsonpSerializable { - @Nullable - private final Boolean returnDocuments; - - // --------------------------------------------------------------------------------------------- - - private ElasticsearchTaskSettings(Builder builder) { - - this.returnDocuments = builder.returnDocuments; - - } - - public static ElasticsearchTaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * For a rerank task, return the document instead of only the - * index. - *

- * API name: {@code return_documents} - */ - @Nullable - public final Boolean returnDocuments() { - return this.returnDocuments; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.returnDocuments != null) { - generator.writeKey("return_documents"); - generator.write(this.returnDocuments); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link ElasticsearchTaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private Boolean returnDocuments; - - /** - * For a rerank task, return the document instead of only the - * index. - *

- * API name: {@code return_documents} - */ - public final Builder returnDocuments(@Nullable Boolean value) { - this.returnDocuments = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link ElasticsearchTaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public ElasticsearchTaskSettings build() { - _checkSingleUse(); - - return new ElasticsearchTaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link ElasticsearchTaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, ElasticsearchTaskSettings::setupElasticsearchTaskSettingsDeserializer); - - protected static void setupElasticsearchTaskSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::returnDocuments, JsonpDeserializer.booleanDeserializer(), "return_documents"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskType.java deleted file mode 100644 index bdd5a9230..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskType.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_elasticsearch; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ElasticsearchTaskType implements JsonEnum { - Rerank("rerank"), - - SparseEmbedding("sparse_embedding"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - ElasticsearchTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ElasticsearchTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ServiceType.java deleted file mode 100644 index 623a65181..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_elasticsearch; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Elasticsearch("elasticsearch"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/AdaptiveAllocations.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/AdaptiveAllocations.java deleted file mode 100644 index 3facca41b..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/AdaptiveAllocations.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_elser; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_elser.AdaptiveAllocations - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AdaptiveAllocations implements JsonpSerializable { - @Nullable - private final Boolean enabled; - - @Nullable - private final Integer maxNumberOfAllocations; - - @Nullable - private final Integer minNumberOfAllocations; - - // --------------------------------------------------------------------------------------------- - - private AdaptiveAllocations(Builder builder) { - - this.enabled = builder.enabled; - this.maxNumberOfAllocations = builder.maxNumberOfAllocations; - this.minNumberOfAllocations = builder.minNumberOfAllocations; - - } - - public static AdaptiveAllocations of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Turn on adaptive_allocations. - *

- * API name: {@code enabled} - */ - @Nullable - public final Boolean enabled() { - return this.enabled; - } - - /** - * The maximum number of allocations to scale to. If set, it must be greater - * than or equal to min_number_of_allocations. - *

- * API name: {@code max_number_of_allocations} - */ - @Nullable - public final Integer maxNumberOfAllocations() { - return this.maxNumberOfAllocations; - } - - /** - * The minimum number of allocations to scale to. If set, it must be greater - * than or equal to 0. If not defined, the deployment scales to 0. - *

- * API name: {@code min_number_of_allocations} - */ - @Nullable - public final Integer minNumberOfAllocations() { - return this.minNumberOfAllocations; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.enabled != null) { - generator.writeKey("enabled"); - generator.write(this.enabled); - - } - if (this.maxNumberOfAllocations != null) { - generator.writeKey("max_number_of_allocations"); - generator.write(this.maxNumberOfAllocations); - - } - if (this.minNumberOfAllocations != null) { - generator.writeKey("min_number_of_allocations"); - generator.write(this.minNumberOfAllocations); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AdaptiveAllocations}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private Boolean enabled; - - @Nullable - private Integer maxNumberOfAllocations; - - @Nullable - private Integer minNumberOfAllocations; - - /** - * Turn on adaptive_allocations. - *

- * API name: {@code enabled} - */ - public final Builder enabled(@Nullable Boolean value) { - this.enabled = value; - return this; - } - - /** - * The maximum number of allocations to scale to. If set, it must be greater - * than or equal to min_number_of_allocations. - *

- * API name: {@code max_number_of_allocations} - */ - public final Builder maxNumberOfAllocations(@Nullable Integer value) { - this.maxNumberOfAllocations = value; - return this; - } - - /** - * The minimum number of allocations to scale to. If set, it must be greater - * than or equal to 0. If not defined, the deployment scales to 0. - *

- * API name: {@code min_number_of_allocations} - */ - public final Builder minNumberOfAllocations(@Nullable Integer value) { - this.minNumberOfAllocations = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AdaptiveAllocations}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AdaptiveAllocations build() { - _checkSingleUse(); - - return new AdaptiveAllocations(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AdaptiveAllocations} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AdaptiveAllocations::setupAdaptiveAllocationsDeserializer); - - protected static void setupAdaptiveAllocationsDeserializer(ObjectDeserializer op) { - - op.add(Builder::enabled, JsonpDeserializer.booleanDeserializer(), "enabled"); - op.add(Builder::maxNumberOfAllocations, JsonpDeserializer.integerDeserializer(), "max_number_of_allocations"); - op.add(Builder::minNumberOfAllocations, JsonpDeserializer.integerDeserializer(), "min_number_of_allocations"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserServiceSettings.java deleted file mode 100644 index 5cee104ba..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserServiceSettings.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_elser; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_elser.ElserServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class ElserServiceSettings implements JsonpSerializable { - @Nullable - private final AdaptiveAllocations adaptiveAllocations; - - private final int numAllocations; - - private final int numThreads; - - // --------------------------------------------------------------------------------------------- - - private ElserServiceSettings(Builder builder) { - - this.adaptiveAllocations = builder.adaptiveAllocations; - this.numAllocations = ApiTypeHelper.requireNonNull(builder.numAllocations, this, "numAllocations"); - this.numThreads = ApiTypeHelper.requireNonNull(builder.numThreads, this, "numThreads"); - - } - - public static ElserServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Adaptive allocations configuration details. If enabled is true, - * the number of allocations of the model is set based on the current load the - * process gets. When the load is high, a new model allocation is automatically - * created, respecting the value of max_number_of_allocations if - * it's set. When the load is low, a model allocation is automatically removed, - * respecting the value of min_number_of_allocations if it's set. - * If enabled is true, do not set the number of allocations - * manually. - *

- * API name: {@code adaptive_allocations} - */ - @Nullable - public final AdaptiveAllocations adaptiveAllocations() { - return this.adaptiveAllocations; - } - - /** - * Required - The total number of allocations this model is assigned across - * machine learning nodes. Increasing this value generally increases the - * throughput. If adaptive allocations is enabled, do not set this value because - * it's automatically set. - *

- * API name: {@code num_allocations} - */ - public final int numAllocations() { - return this.numAllocations; - } - - /** - * Required - The number of threads used by each model allocation during - * inference. Increasing this value generally increases the speed per inference - * request. The inference process is a compute-bound process; - * threads_per_allocations must not exceed the number of available - * allocated processors per node. The value must be a power of 2. The maximum - * value is 32.

- *

- * info If you want to optimize your ELSER endpoint for ingest, set the number - * of threads to 1. If you want to optimize your ELSER endpoint for search, set - * the number of threads to greater than 1. - *

- *
- *

- * API name: {@code num_threads} - */ - public final int numThreads() { - return this.numThreads; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.adaptiveAllocations != null) { - generator.writeKey("adaptive_allocations"); - this.adaptiveAllocations.serialize(generator, mapper); - - } - generator.writeKey("num_allocations"); - generator.write(this.numAllocations); - - generator.writeKey("num_threads"); - generator.write(this.numThreads); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link ElserServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private AdaptiveAllocations adaptiveAllocations; - - private Integer numAllocations; - - private Integer numThreads; - - /** - * Adaptive allocations configuration details. If enabled is true, - * the number of allocations of the model is set based on the current load the - * process gets. When the load is high, a new model allocation is automatically - * created, respecting the value of max_number_of_allocations if - * it's set. When the load is low, a model allocation is automatically removed, - * respecting the value of min_number_of_allocations if it's set. - * If enabled is true, do not set the number of allocations - * manually. - *

- * API name: {@code adaptive_allocations} - */ - public final Builder adaptiveAllocations(@Nullable AdaptiveAllocations value) { - this.adaptiveAllocations = value; - return this; - } - - /** - * Adaptive allocations configuration details. If enabled is true, - * the number of allocations of the model is set based on the current load the - * process gets. When the load is high, a new model allocation is automatically - * created, respecting the value of max_number_of_allocations if - * it's set. When the load is low, a model allocation is automatically removed, - * respecting the value of min_number_of_allocations if it's set. - * If enabled is true, do not set the number of allocations - * manually. - *

- * API name: {@code adaptive_allocations} - */ - public final Builder adaptiveAllocations( - Function> fn) { - return this.adaptiveAllocations(fn.apply(new AdaptiveAllocations.Builder()).build()); - } - - /** - * Required - The total number of allocations this model is assigned across - * machine learning nodes. Increasing this value generally increases the - * throughput. If adaptive allocations is enabled, do not set this value because - * it's automatically set. - *

- * API name: {@code num_allocations} - */ - public final Builder numAllocations(int value) { - this.numAllocations = value; - return this; - } - - /** - * Required - The number of threads used by each model allocation during - * inference. Increasing this value generally increases the speed per inference - * request. The inference process is a compute-bound process; - * threads_per_allocations must not exceed the number of available - * allocated processors per node. The value must be a power of 2. The maximum - * value is 32.

- *

- * info If you want to optimize your ELSER endpoint for ingest, set the number - * of threads to 1. If you want to optimize your ELSER endpoint for search, set - * the number of threads to greater than 1. - *

- *
- *

- * API name: {@code num_threads} - */ - public final Builder numThreads(int value) { - this.numThreads = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link ElserServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public ElserServiceSettings build() { - _checkSingleUse(); - - return new ElserServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link ElserServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, ElserServiceSettings::setupElserServiceSettingsDeserializer); - - protected static void setupElserServiceSettingsDeserializer(ObjectDeserializer op) { - - op.add(Builder::adaptiveAllocations, AdaptiveAllocations._DESERIALIZER, "adaptive_allocations"); - op.add(Builder::numAllocations, JsonpDeserializer.integerDeserializer(), "num_allocations"); - op.add(Builder::numThreads, JsonpDeserializer.integerDeserializer(), "num_threads"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserTaskType.java deleted file mode 100644 index b06065905..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserTaskType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_elser; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ElserTaskType implements JsonEnum { - SparseEmbedding("sparse_embedding"), - - ; - - private final String jsonValue; - - ElserTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ElserTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioServiceSettings.java deleted file mode 100644 index 9fa3878c5..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioServiceSettings.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_googleaistudio; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_googleaistudio.GoogleAiStudioServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class GoogleAiStudioServiceSettings implements JsonpSerializable { - private final String apiKey; - - private final String modelId; - - @Nullable - private final RateLimitSetting rateLimit; - - // --------------------------------------------------------------------------------------------- - - private GoogleAiStudioServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); - this.rateLimit = builder.rateLimit; - - } - - public static GoogleAiStudioServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid API key of your Google Gemini account. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * Google documentation for the list of supported models. - *

- * API name: {@code model_id} - */ - public final String modelId() { - return this.modelId; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Google AI Studio. By default, the googleaistudio service sets - * the number of requests allowed per minute to 360. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - generator.writeKey("model_id"); - generator.write(this.modelId); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link GoogleAiStudioServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - private String modelId; - - @Nullable - private RateLimitSetting rateLimit; - - /** - * Required - A valid API key of your Google Gemini account. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * Google documentation for the list of supported models. - *

- * API name: {@code model_id} - */ - public final Builder modelId(String value) { - this.modelId = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Google AI Studio. By default, the googleaistudio service sets - * the number of requests allowed per minute to 360. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Google AI Studio. By default, the googleaistudio service sets - * the number of requests allowed per minute to 360. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link GoogleAiStudioServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public GoogleAiStudioServiceSettings build() { - _checkSingleUse(); - - return new GoogleAiStudioServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link GoogleAiStudioServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, GoogleAiStudioServiceSettings::setupGoogleAiStudioServiceSettingsDeserializer); - - protected static void setupGoogleAiStudioServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioTaskType.java deleted file mode 100644 index 7c9fa04ea..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioTaskType.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_googleaistudio; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum GoogleAiStudioTaskType implements JsonEnum { - Completion("completion"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - GoogleAiStudioTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - GoogleAiStudioTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/ServiceType.java deleted file mode 100644 index cc2d8aca2..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_googleaistudio; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Googleaistudio("googleaistudio"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAIServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAIServiceSettings.java deleted file mode 100644 index 8482cbdfa..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAIServiceSettings.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_googlevertexai; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_googlevertexai.GoogleVertexAIServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class GoogleVertexAIServiceSettings implements JsonpSerializable { - private final String location; - - private final String modelId; - - private final String projectId; - - @Nullable - private final RateLimitSetting rateLimit; - - private final String serviceAccountJson; - - // --------------------------------------------------------------------------------------------- - - private GoogleVertexAIServiceSettings(Builder builder) { - - this.location = ApiTypeHelper.requireNonNull(builder.location, this, "location"); - this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); - this.projectId = ApiTypeHelper.requireNonNull(builder.projectId, this, "projectId"); - this.rateLimit = builder.rateLimit; - this.serviceAccountJson = ApiTypeHelper.requireNonNull(builder.serviceAccountJson, this, "serviceAccountJson"); - - } - - public static GoogleVertexAIServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The name of the location to use for the inference task. Refer to - * the Google documentation for the list of supported locations. - *

- * API name: {@code location} - */ - public final String location() { - return this.location; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * Google documentation for the list of supported models. - *

- * API name: {@code model_id} - */ - public final String modelId() { - return this.modelId; - } - - /** - * Required - The name of the project to use for the inference task. - *

- * API name: {@code project_id} - */ - public final String projectId() { - return this.projectId; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Google Vertex AI. By default, the googlevertexai service sets - * the number of requests allowed per minute to 30.000. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Required - A valid service account in JSON format for the Google Vertex AI - * API. - *

- * API name: {@code service_account_json} - */ - public final String serviceAccountJson() { - return this.serviceAccountJson; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("location"); - generator.write(this.location); - - generator.writeKey("model_id"); - generator.write(this.modelId); - - generator.writeKey("project_id"); - generator.write(this.projectId); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - generator.writeKey("service_account_json"); - generator.write(this.serviceAccountJson); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link GoogleVertexAIServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String location; - - private String modelId; - - private String projectId; - - @Nullable - private RateLimitSetting rateLimit; - - private String serviceAccountJson; - - /** - * Required - The name of the location to use for the inference task. Refer to - * the Google documentation for the list of supported locations. - *

- * API name: {@code location} - */ - public final Builder location(String value) { - this.location = value; - return this; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * Google documentation for the list of supported models. - *

- * API name: {@code model_id} - */ - public final Builder modelId(String value) { - this.modelId = value; - return this; - } - - /** - * Required - The name of the project to use for the inference task. - *

- * API name: {@code project_id} - */ - public final Builder projectId(String value) { - this.projectId = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Google Vertex AI. By default, the googlevertexai service sets - * the number of requests allowed per minute to 30.000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Google Vertex AI. By default, the googlevertexai service sets - * the number of requests allowed per minute to 30.000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * Required - A valid service account in JSON format for the Google Vertex AI - * API. - *

- * API name: {@code service_account_json} - */ - public final Builder serviceAccountJson(String value) { - this.serviceAccountJson = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link GoogleVertexAIServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public GoogleVertexAIServiceSettings build() { - _checkSingleUse(); - - return new GoogleVertexAIServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link GoogleVertexAIServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, GoogleVertexAIServiceSettings::setupGoogleVertexAIServiceSettingsDeserializer); - - protected static void setupGoogleVertexAIServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::location, JsonpDeserializer.stringDeserializer(), "location"); - op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); - op.add(Builder::projectId, JsonpDeserializer.stringDeserializer(), "project_id"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::serviceAccountJson, JsonpDeserializer.stringDeserializer(), "service_account_json"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskSettings.java deleted file mode 100644 index 99ea25c03..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskSettings.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_googlevertexai; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_googlevertexai.GoogleVertexAITaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class GoogleVertexAITaskSettings implements JsonpSerializable { - @Nullable - private final Boolean autoTruncate; - - @Nullable - private final Integer topN; - - // --------------------------------------------------------------------------------------------- - - private GoogleVertexAITaskSettings(Builder builder) { - - this.autoTruncate = builder.autoTruncate; - this.topN = builder.topN; - - } - - public static GoogleVertexAITaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * For a text_embedding task, truncate inputs longer than the - * maximum token length automatically. - *

- * API name: {@code auto_truncate} - */ - @Nullable - public final Boolean autoTruncate() { - return this.autoTruncate; - } - - /** - * For a rerank task, the number of the top N documents that should - * be returned. - *

- * API name: {@code top_n} - */ - @Nullable - public final Integer topN() { - return this.topN; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.autoTruncate != null) { - generator.writeKey("auto_truncate"); - generator.write(this.autoTruncate); - - } - if (this.topN != null) { - generator.writeKey("top_n"); - generator.write(this.topN); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link GoogleVertexAITaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private Boolean autoTruncate; - - @Nullable - private Integer topN; - - /** - * For a text_embedding task, truncate inputs longer than the - * maximum token length automatically. - *

- * API name: {@code auto_truncate} - */ - public final Builder autoTruncate(@Nullable Boolean value) { - this.autoTruncate = value; - return this; - } - - /** - * For a rerank task, the number of the top N documents that should - * be returned. - *

- * API name: {@code top_n} - */ - public final Builder topN(@Nullable Integer value) { - this.topN = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link GoogleVertexAITaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public GoogleVertexAITaskSettings build() { - _checkSingleUse(); - - return new GoogleVertexAITaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link GoogleVertexAITaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, GoogleVertexAITaskSettings::setupGoogleVertexAITaskSettingsDeserializer); - - protected static void setupGoogleVertexAITaskSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::autoTruncate, JsonpDeserializer.booleanDeserializer(), "auto_truncate"); - op.add(Builder::topN, JsonpDeserializer.integerDeserializer(), "top_n"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskType.java deleted file mode 100644 index 4b1859642..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskType.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_googlevertexai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum GoogleVertexAITaskType implements JsonEnum { - Rerank("rerank"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - GoogleVertexAITaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - GoogleVertexAITaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/ServiceType.java deleted file mode 100644 index 65b054f2e..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_googlevertexai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Googlevertexai("googlevertexai"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceServiceSettings.java deleted file mode 100644 index 07464ac58..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceServiceSettings.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_hugging_face; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_hugging_face.HuggingFaceServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class HuggingFaceServiceSettings implements JsonpSerializable { - private final String apiKey; - - @Nullable - private final RateLimitSetting rateLimit; - - private final String url; - - // --------------------------------------------------------------------------------------------- - - private HuggingFaceServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.rateLimit = builder.rateLimit; - this.url = ApiTypeHelper.requireNonNull(builder.url, this, "url"); - - } - - public static HuggingFaceServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid access token for your HuggingFace account. You can create - * or find your access tokens on the HuggingFace settings page. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Hugging Face. By default, the hugging_face service sets the - * number of requests allowed per minute to 3000. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Required - The URL endpoint to use for the requests. - *

- * API name: {@code url} - */ - public final String url() { - return this.url; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - generator.writeKey("url"); - generator.write(this.url); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link HuggingFaceServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - @Nullable - private RateLimitSetting rateLimit; - - private String url; - - /** - * Required - A valid access token for your HuggingFace account. You can create - * or find your access tokens on the HuggingFace settings page. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Hugging Face. By default, the hugging_face service sets the - * number of requests allowed per minute to 3000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Hugging Face. By default, the hugging_face service sets the - * number of requests allowed per minute to 3000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * Required - The URL endpoint to use for the requests. - *

- * API name: {@code url} - */ - public final Builder url(String value) { - this.url = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link HuggingFaceServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public HuggingFaceServiceSettings build() { - _checkSingleUse(); - - return new HuggingFaceServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link HuggingFaceServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, HuggingFaceServiceSettings::setupHuggingFaceServiceSettingsDeserializer); - - protected static void setupHuggingFaceServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::url, JsonpDeserializer.stringDeserializer(), "url"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceTaskType.java deleted file mode 100644 index 3a36ada42..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceTaskType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_hugging_face; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum HuggingFaceTaskType implements JsonEnum { - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - HuggingFaceTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - HuggingFaceTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/ServiceType.java deleted file mode 100644 index 870661dba..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_hugging_face; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - HuggingFace("hugging_face"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAIServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAIServiceSettings.java deleted file mode 100644 index 26f5e7643..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAIServiceSettings.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_jinaai; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_jinaai.JinaAIServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class JinaAIServiceSettings implements JsonpSerializable { - private final String apiKey; - - @Nullable - private final String modelId; - - @Nullable - private final RateLimitSetting rateLimit; - - @Nullable - private final SimilarityType similarity; - - // --------------------------------------------------------------------------------------------- - - private JinaAIServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.modelId = builder.modelId; - this.rateLimit = builder.rateLimit; - this.similarity = builder.similarity; - - } - - public static JinaAIServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid API key of your JinaAI account. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * The name of the model to use for the inference task. For a - * rerank task, it is required. For a text_embedding - * task, it is optional. - *

- * API name: {@code model_id} - */ - @Nullable - public final String modelId() { - return this.modelId; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * JinaAI. By default, the jinaai service sets the number of - * requests allowed per minute to 2000 for all task types. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * For a text_embedding task, the similarity measure. One of - * cosine, dot_product, l2_norm. The default values varies with the embedding - * type. For example, a float embedding type uses a dot_product - * similarity measure by default. - *

- * API name: {@code similarity} - */ - @Nullable - public final SimilarityType similarity() { - return this.similarity; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - if (this.modelId != null) { - generator.writeKey("model_id"); - generator.write(this.modelId); - - } - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - if (this.similarity != null) { - generator.writeKey("similarity"); - this.similarity.serialize(generator, mapper); - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link JinaAIServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - @Nullable - private String modelId; - - @Nullable - private RateLimitSetting rateLimit; - - @Nullable - private SimilarityType similarity; - - /** - * Required - A valid API key of your JinaAI account. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * The name of the model to use for the inference task. For a - * rerank task, it is required. For a text_embedding - * task, it is optional. - *

- * API name: {@code model_id} - */ - public final Builder modelId(@Nullable String value) { - this.modelId = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * JinaAI. By default, the jinaai service sets the number of - * requests allowed per minute to 2000 for all task types. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * JinaAI. By default, the jinaai service sets the number of - * requests allowed per minute to 2000 for all task types. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * For a text_embedding task, the similarity measure. One of - * cosine, dot_product, l2_norm. The default values varies with the embedding - * type. For example, a float embedding type uses a dot_product - * similarity measure by default. - *

- * API name: {@code similarity} - */ - public final Builder similarity(@Nullable SimilarityType value) { - this.similarity = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link JinaAIServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public JinaAIServiceSettings build() { - _checkSingleUse(); - - return new JinaAIServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link JinaAIServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, JinaAIServiceSettings::setupJinaAIServiceSettingsDeserializer); - - protected static void setupJinaAIServiceSettingsDeserializer(ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::similarity, SimilarityType._DESERIALIZER, "similarity"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskSettings.java deleted file mode 100644 index 25888bdce..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskSettings.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_jinaai; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_jinaai.JinaAITaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class JinaAITaskSettings implements JsonpSerializable { - @Nullable - private final Boolean returnDocuments; - - @Nullable - private final TextEmbeddingTask task; - - @Nullable - private final Integer topN; - - // --------------------------------------------------------------------------------------------- - - private JinaAITaskSettings(Builder builder) { - - this.returnDocuments = builder.returnDocuments; - this.task = builder.task; - this.topN = builder.topN; - - } - - public static JinaAITaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * For a rerank task, return the doc text within the results. - *

- * API name: {@code return_documents} - */ - @Nullable - public final Boolean returnDocuments() { - return this.returnDocuments; - } - - /** - * For a text_embedding task, the task passed to the model. Valid - * values are: - *

    - *
  • classification: Use it for embeddings passed through a text - * classifier.
  • - *
  • clustering: Use it for the embeddings run through a - * clustering algorithm.
  • - *
  • ingest: Use it for storing document embeddings in a vector - * database.
  • - *
  • search: Use it for storing embeddings of search queries run - * against a vector database to find relevant documents.
  • - *
- *

- * API name: {@code task} - */ - @Nullable - public final TextEmbeddingTask task() { - return this.task; - } - - /** - * For a rerank task, the number of most relevant documents to - * return. It defaults to the number of the documents. If this inference - * endpoint is used in a text_similarity_reranker retriever query - * and top_n is set, it must be greater than or equal to - * rank_window_size in the query. - *

- * API name: {@code top_n} - */ - @Nullable - public final Integer topN() { - return this.topN; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.returnDocuments != null) { - generator.writeKey("return_documents"); - generator.write(this.returnDocuments); - - } - if (this.task != null) { - generator.writeKey("task"); - this.task.serialize(generator, mapper); - } - if (this.topN != null) { - generator.writeKey("top_n"); - generator.write(this.topN); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link JinaAITaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private Boolean returnDocuments; - - @Nullable - private TextEmbeddingTask task; - - @Nullable - private Integer topN; - - /** - * For a rerank task, return the doc text within the results. - *

- * API name: {@code return_documents} - */ - public final Builder returnDocuments(@Nullable Boolean value) { - this.returnDocuments = value; - return this; - } - - /** - * For a text_embedding task, the task passed to the model. Valid - * values are: - *

    - *
  • classification: Use it for embeddings passed through a text - * classifier.
  • - *
  • clustering: Use it for the embeddings run through a - * clustering algorithm.
  • - *
  • ingest: Use it for storing document embeddings in a vector - * database.
  • - *
  • search: Use it for storing embeddings of search queries run - * against a vector database to find relevant documents.
  • - *
- *

- * API name: {@code task} - */ - public final Builder task(@Nullable TextEmbeddingTask value) { - this.task = value; - return this; - } - - /** - * For a rerank task, the number of most relevant documents to - * return. It defaults to the number of the documents. If this inference - * endpoint is used in a text_similarity_reranker retriever query - * and top_n is set, it must be greater than or equal to - * rank_window_size in the query. - *

- * API name: {@code top_n} - */ - public final Builder topN(@Nullable Integer value) { - this.topN = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link JinaAITaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public JinaAITaskSettings build() { - _checkSingleUse(); - - return new JinaAITaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link JinaAITaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, JinaAITaskSettings::setupJinaAITaskSettingsDeserializer); - - protected static void setupJinaAITaskSettingsDeserializer(ObjectDeserializer op) { - - op.add(Builder::returnDocuments, JsonpDeserializer.booleanDeserializer(), "return_documents"); - op.add(Builder::task, TextEmbeddingTask._DESERIALIZER, "task"); - op.add(Builder::topN, JsonpDeserializer.integerDeserializer(), "top_n"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskType.java deleted file mode 100644 index 0d8771a24..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskType.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_jinaai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum JinaAITaskType implements JsonEnum { - Rerank("rerank"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - JinaAITaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - JinaAITaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/ServiceType.java deleted file mode 100644 index f9df9ea40..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_jinaai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Jinaai("jinaai"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/SimilarityType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/SimilarityType.java deleted file mode 100644 index 970051384..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/SimilarityType.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_jinaai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum SimilarityType implements JsonEnum { - Cosine("cosine"), - - DotProduct("dot_product"), - - L2Norm("l2_norm"), - - ; - - private final String jsonValue; - - SimilarityType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - SimilarityType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/TextEmbeddingTask.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/TextEmbeddingTask.java deleted file mode 100644 index 1a1667667..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/TextEmbeddingTask.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_jinaai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum TextEmbeddingTask implements JsonEnum { - Classification("classification"), - - Clustering("clustering"), - - Ingest("ingest"), - - Search("search"), - - ; - - private final String jsonValue; - - TextEmbeddingTask(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - TextEmbeddingTask.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralServiceSettings.java deleted file mode 100644 index fbcc888ec..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralServiceSettings.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_mistral; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Integer; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_mistral.MistralServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class MistralServiceSettings implements JsonpSerializable { - private final String apiKey; - - @Nullable - private final Integer maxInputTokens; - - private final String model; - - @Nullable - private final RateLimitSetting rateLimit; - - // --------------------------------------------------------------------------------------------- - - private MistralServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.maxInputTokens = builder.maxInputTokens; - this.model = ApiTypeHelper.requireNonNull(builder.model, this, "model"); - this.rateLimit = builder.rateLimit; - - } - - public static MistralServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid API key of your Mistral account. You can find your Mistral - * API keys or you can create a new one on the API Keys page. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * The maximum number of tokens per input before chunking occurs. - *

- * API name: {@code max_input_tokens} - */ - @Nullable - public final Integer maxInputTokens() { - return this.maxInputTokens; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * Mistral models documentation for the list of available text embedding models. - *

- * API name: {@code model} - */ - public final String model() { - return this.model; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * the Mistral API. By default, the mistral service sets the number - * of requests allowed per minute to 240. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - if (this.maxInputTokens != null) { - generator.writeKey("max_input_tokens"); - generator.write(this.maxInputTokens); - - } - generator.writeKey("model"); - generator.write(this.model); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link MistralServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - @Nullable - private Integer maxInputTokens; - - private String model; - - @Nullable - private RateLimitSetting rateLimit; - - /** - * Required - A valid API key of your Mistral account. You can find your Mistral - * API keys or you can create a new one on the API Keys page. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * The maximum number of tokens per input before chunking occurs. - *

- * API name: {@code max_input_tokens} - */ - public final Builder maxInputTokens(@Nullable Integer value) { - this.maxInputTokens = value; - return this; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * Mistral models documentation for the list of available text embedding models. - *

- * API name: {@code model} - */ - public final Builder model(String value) { - this.model = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * the Mistral API. By default, the mistral service sets the number - * of requests allowed per minute to 240. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * the Mistral API. By default, the mistral service sets the number - * of requests allowed per minute to 240. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link MistralServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public MistralServiceSettings build() { - _checkSingleUse(); - - return new MistralServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link MistralServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, MistralServiceSettings::setupMistralServiceSettingsDeserializer); - - protected static void setupMistralServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::maxInputTokens, JsonpDeserializer.integerDeserializer(), "max_input_tokens"); - op.add(Builder::model, JsonpDeserializer.stringDeserializer(), "model"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralTaskType.java deleted file mode 100644 index 94c34e12c..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralTaskType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_mistral; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum MistralTaskType implements JsonEnum { - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - MistralTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - MistralTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/ServiceType.java deleted file mode 100644 index 36f555841..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_mistral; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Mistral("mistral"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} From 295ece652b5c2af87f761f5e1e4c5516cab55e32 Mon Sep 17 00:00:00 2001 From: Sylvain Wallez Date: Fri, 28 Mar 2025 19:25:20 +0100 Subject: [PATCH 26/38] Reduce public API surface --- .../main/java/co/elastic/clients/transport/http/Node.java | 4 ++++ .../rest5_client/low_level/BasicAsyncEntityProducer.java | 6 +++--- .../rest5_client/low_level/BasicAsyncResponseConsumer.java | 4 ++-- .../rest5_client/low_level/BufferedByteConsumer.java | 4 ++-- .../clients/transport/rest5_client/low_level/Constants.java | 2 +- .../transport/rest5_client/low_level/RequestLogger.java | 2 +- 6 files changed, 13 insertions(+), 9 deletions(-) create mode 100644 java-client/src/main/java/co/elastic/clients/transport/http/Node.java diff --git a/java-client/src/main/java/co/elastic/clients/transport/http/Node.java b/java-client/src/main/java/co/elastic/clients/transport/http/Node.java new file mode 100644 index 000000000..fa7253d7f --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/http/Node.java @@ -0,0 +1,4 @@ +package co.elastic.clients.transport.http; + +public class Node { +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncEntityProducer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncEntityProducer.java index 312111903..060c71fea 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncEntityProducer.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncEntityProducer.java @@ -37,7 +37,7 @@ /** * Basic implementation of {@link AsyncEntityProducer} */ -public class BasicAsyncEntityProducer implements AsyncEntityProducer { +class BasicAsyncEntityProducer implements AsyncEntityProducer { private final HttpEntity entity; private final ByteBuffer buffer; @@ -50,7 +50,7 @@ public class BasicAsyncEntityProducer implements AsyncEntityProducer { /** * Create new basic entity producer */ - public BasicAsyncEntityProducer(final HttpEntity entity, final int bufferSize) { + BasicAsyncEntityProducer(final HttpEntity entity, final int bufferSize) { this.entity = Args.notNull(entity, "Http Entity"); this.buffer = ByteBuffer.allocate(bufferSize); this.channelRef = new AtomicReference<>(); @@ -62,7 +62,7 @@ public BasicAsyncEntityProducer(final HttpEntity entity, final int bufferSize) { /** * Create new basic entity producer with default buffer limit of 100MB */ - public BasicAsyncEntityProducer(final HttpEntity entity) { + BasicAsyncEntityProducer(final HttpEntity entity) { this(entity, DEFAULT_BUFFER_INITIAL_CAPACITY); } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncResponseConsumer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncResponseConsumer.java index 22dc180b5..39b3d0ee8 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncResponseConsumer.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/BasicAsyncResponseConsumer.java @@ -29,7 +29,7 @@ import org.apache.hc.core5.http.nio.support.AbstractAsyncResponseConsumer; import org.apache.hc.core5.http.protocol.HttpContext; -public class BasicAsyncResponseConsumer extends AbstractAsyncResponseConsumer { private volatile BasicClassicHttpResponse finalResponse; @@ -39,7 +39,7 @@ public class BasicAsyncResponseConsumer extends AbstractAsyncResponseConsumer { +class BufferedByteConsumer extends AbstractBinAsyncEntityConsumer { private volatile ByteArrayBuffer buffer; private final int limit; private ContentType contentType; - public BufferedByteConsumer(int bufferLimit) { + BufferedByteConsumer(int bufferLimit) { super(); if (bufferLimit <= 0) { throw new IllegalArgumentException("Buffer limit must be greater than 0"); diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Constants.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Constants.java index 6c2e18e1a..9cecb019d 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Constants.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/Constants.java @@ -19,7 +19,7 @@ package co.elastic.clients.transport.rest5_client.low_level; -public class Constants { +class Constants { // default buffer limit is 100MB public static final int DEFAULT_BUFFER_LIMIT = 100 * 1024 * 1024; public static final int DEFAULT_BUFFER_INITIAL_CAPACITY = 8192; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestLogger.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestLogger.java index 517bca27c..4f41421ad 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestLogger.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/RequestLogger.java @@ -43,7 +43,7 @@ */ final class RequestLogger { - private static final Log tracer = LogFactory.getLog("tracer"); + private static final Log tracer = LogFactory.getLog(Request.class); private RequestLogger() { } From c95508039fba1a39cb382972c32bb4057598df84 Mon Sep 17 00:00:00 2001 From: Sylvain Wallez Date: Fri, 28 Mar 2025 19:32:43 +0100 Subject: [PATCH 27/38] Extract HttpRequest.Node (future-proof this class for later use) --- .../elastic/clients/transport/http/Node.java | 138 ++++++++++++++++++ .../http/RepeatableBodyResponse.java | 2 +- .../transport/http/TransportHttpClient.java | 76 ---------- .../rest5_client/Rest5ClientHttpClient.java | 1 + .../rest_client/RestClientHttpClient.java | 1 + .../clients/testkit/MockHttpClient.java | 5 +- .../endpoints/SimpleEndpointTest.java | 1 + 7 files changed, 145 insertions(+), 79 deletions(-) diff --git a/java-client/src/main/java/co/elastic/clients/transport/http/Node.java b/java-client/src/main/java/co/elastic/clients/transport/http/Node.java index fa7253d7f..0cc2dd96f 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/http/Node.java +++ b/java-client/src/main/java/co/elastic/clients/transport/http/Node.java @@ -1,4 +1,142 @@ +/* + * 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. + */ + package co.elastic.clients.transport.http; +import javax.annotation.Nullable; +import java.net.URI; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * A node/host to send requests to. + */ public class Node { + private final URI uri; + private final String name; + private final String version; + private final Set roles; + private final Map attributes; + private final List boundHosts; + + /** + * Create a node with its URI, roles and attributes. + *

+ * If the URI doesn't end with a '{@code /}', then one is added. + * + * @param uri the node's URI + * @param name the node name/identifier + * @param version the node's version, if known + * @param roles the node's roles (such as "master", "ingest", etc). + * @param attributes the node's attributes. This can be used for routing decisions by multi-node implementations. + * @param boundHosts addresses on which the node is listening. Useful to find a host based on any address it's listening to. + */ + public Node( + URI uri, + @Nullable String name, + @Nullable String version, + @Nullable Set roles, + @Nullable Map attributes, + @Nullable List boundHosts + ) { + + if (!uri.isAbsolute()) { + throw new IllegalArgumentException("Node URIs must be absolute: " + uri); + } + + if (!uri.getRawPath().endsWith("/")) { + uri = uri.resolve(uri.getRawPath() + "/"); + } + + this.uri = uri; + this.name = name; + this.version = version; + this.roles = roles; + this.attributes = attributes; + this.boundHosts = boundHosts; + } + + public Node(URI uri) { + this(uri, null, null, null, null, null); + } + + public Node(String uri) { + this(URI.create(uri), null, null, null, null, null); + } + + /** + * The URI of this node. This is an absolute URL with a path ending with a "/". + */ + public URI uri() { + return this.uri; + } + + /** + * The node name/identifier + */ + @Nullable + public String name() { + return name; + } + + @Nullable + public String version() { + return version; + } + + @Nullable + public Set roles() { + return roles; + } + + @Nullable + public Map attributes() { + return attributes; + } + + @Nullable + public List boundHosts() { + return boundHosts; + } + + @Override + public String toString() { + return uri.toString(); + } + + /** + * Two nodes are considered equal if their URIs are equal. Other properties are ignored. + */ + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Node node)) return false; + return Objects.equals(uri, node.uri); + } + + /** + * A node's hash code is that of its URI. Other properties are ignored. + */ + @Override + public int hashCode() { + return Objects.hash(uri); + } } diff --git a/java-client/src/main/java/co/elastic/clients/transport/http/RepeatableBodyResponse.java b/java-client/src/main/java/co/elastic/clients/transport/http/RepeatableBodyResponse.java index d578cdcec..708499a3f 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/http/RepeatableBodyResponse.java +++ b/java-client/src/main/java/co/elastic/clients/transport/http/RepeatableBodyResponse.java @@ -45,7 +45,7 @@ public RepeatableBodyResponse(TransportHttpClient.Response response) throws IOEx } @Override - public TransportHttpClient.Node node() { + public Node node() { return response.node(); } diff --git a/java-client/src/main/java/co/elastic/clients/transport/http/TransportHttpClient.java b/java-client/src/main/java/co/elastic/clients/transport/http/TransportHttpClient.java index 74ce8bd7a..677ddfd22 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/http/TransportHttpClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/http/TransportHttpClient.java @@ -26,13 +26,9 @@ import javax.annotation.Nullable; import java.io.Closeable; import java.io.IOException; -import java.net.URI; import java.nio.ByteBuffer; -import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.Set; import java.util.concurrent.CompletableFuture; /** @@ -90,78 +86,6 @@ default TransportOptions createOptions(@Nullable TransportOptions options) { */ void close() throws IOException; - /** - * A node/host to send requests to. - */ - class Node { - private final URI uri; - private final Set roles; - private final Map attributes; - - /** - * Create a node with its URI, roles and attributes. - *

- * If the URI doesn't end with a '{@code /}', then one is added. - * - * @param uri the node's URI - * @param roles the node's roles (such as "master", "ingest", etc). This can be used for routing decisions by multi-node - * implementations. - * @param attributes the node's attributes. This can be used for routing decisions by multi-node implementations. - */ - public Node(URI uri, Set roles, Map attributes) { - if (!uri.isAbsolute()) { - throw new IllegalArgumentException("Node URIs must be absolute: " + uri); - } - - if (!uri.getRawPath().endsWith("/")) { - uri = uri.resolve(uri.getRawPath() + "/"); - } - - this.uri = uri; - this.roles = roles; - this.attributes = attributes; - } - - public Node(URI uri) { - this(uri, Collections.emptySet(), Collections.emptyMap()); - } - - public Node(String uri) { - this(URI.create(uri), Collections.emptySet(), Collections.emptyMap()); - } - - /** - * The URI of this node. This is an absolute URL with a path ending with a "/". - */ - public URI uri() { - return this.uri; - } - - @Override - public String toString() { - return uri.toString(); - } - - /** - * Two nodes are considered equal if their URIs are equal. Roles and attributes are ignored. - */ - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Node)) return false; - Node node = (Node) o; - return Objects.equals(uri, node.uri); - } - - /** - * A node's hash code is that of its URI. Roles and attributes are ignored. - */ - @Override - public int hashCode() { - return Objects.hash(uri); - } - } - /** * An http request. */ diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java index a8649fe65..3cbf1722c 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java @@ -21,6 +21,7 @@ import co.elastic.clients.transport.TransportOptions; import co.elastic.clients.transport.http.HeaderMap; +import co.elastic.clients.transport.http.Node; import co.elastic.clients.transport.http.TransportHttpClient; import co.elastic.clients.transport.rest5_client.low_level.Cancellable; import co.elastic.clients.transport.rest5_client.low_level.ResponseListener; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java index 85b92c107..d0e4d3393 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java @@ -21,6 +21,7 @@ import co.elastic.clients.transport.TransportOptions; import co.elastic.clients.transport.http.HeaderMap; +import co.elastic.clients.transport.http.Node; import co.elastic.clients.transport.http.TransportHttpClient; import co.elastic.clients.util.BinaryData; import co.elastic.clients.util.NoCopyByteArrayOutputStream; diff --git a/java-client/src/test/java/co/elastic/clients/testkit/MockHttpClient.java b/java-client/src/test/java/co/elastic/clients/testkit/MockHttpClient.java index 27b3fba3e..4ab3269d4 100644 --- a/java-client/src/test/java/co/elastic/clients/testkit/MockHttpClient.java +++ b/java-client/src/test/java/co/elastic/clients/testkit/MockHttpClient.java @@ -24,6 +24,7 @@ import co.elastic.clients.transport.ElasticsearchTransportBase; import co.elastic.clients.transport.TransportException; import co.elastic.clients.transport.TransportOptions; +import co.elastic.clients.transport.http.Node; import co.elastic.clients.transport.http.TransportHttpClient; import co.elastic.clients.util.BinaryData; import org.jetbrains.annotations.Nullable; @@ -69,7 +70,7 @@ public void close() throws IOException { @Override public Response performRequest( - String endpointId, @Nullable TransportHttpClient.Node node, Request request, TransportOptions option + String endpointId, @Nullable Node node, Request request, TransportOptions option ) throws IOException { Response response = responses.get(request.path()); @@ -82,7 +83,7 @@ public Response performRequest( @Override public CompletableFuture performRequestAsync( - String endpointId, @Nullable TransportHttpClient.Node node, Request request, TransportOptions options + String endpointId, @Nullable Node node, Request request, TransportOptions options ) { CompletableFuture result = new CompletableFuture<>(); try { diff --git a/java-client/src/test/java/co/elastic/clients/transport/endpoints/SimpleEndpointTest.java b/java-client/src/test/java/co/elastic/clients/transport/endpoints/SimpleEndpointTest.java index 263e94ac8..6bff41f28 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/endpoints/SimpleEndpointTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/endpoints/SimpleEndpointTest.java @@ -26,6 +26,7 @@ import co.elastic.clients.transport.ElasticsearchTransport; import co.elastic.clients.transport.ElasticsearchTransportBase; import co.elastic.clients.transport.TransportOptions; +import co.elastic.clients.transport.http.Node; import co.elastic.clients.transport.http.TransportHttpClient; import org.jetbrains.annotations.Nullable; import org.junit.jupiter.api.Test; From 45566134b113fa3857f5fa4dfeaa91a48943a10e Mon Sep 17 00:00:00 2001 From: Sylvain Wallez Date: Sat, 29 Mar 2025 07:42:42 +0100 Subject: [PATCH 28/38] Remove Node.boundHosts: it's mostly useless in the container era --- .../elastic/clients/transport/http/Node.java | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/java-client/src/main/java/co/elastic/clients/transport/http/Node.java b/java-client/src/main/java/co/elastic/clients/transport/http/Node.java index 0cc2dd96f..1299df277 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/http/Node.java +++ b/java-client/src/main/java/co/elastic/clients/transport/http/Node.java @@ -21,7 +21,6 @@ import javax.annotation.Nullable; import java.net.URI; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -35,7 +34,6 @@ public class Node { private final String version; private final Set roles; private final Map attributes; - private final List boundHosts; /** * Create a node with its URI, roles and attributes. @@ -45,17 +43,15 @@ public class Node { * @param uri the node's URI * @param name the node name/identifier * @param version the node's version, if known - * @param roles the node's roles (such as "master", "ingest", etc). + * @param roles the node's roles, such as "master", "ingest", etc. * @param attributes the node's attributes. This can be used for routing decisions by multi-node implementations. - * @param boundHosts addresses on which the node is listening. Useful to find a host based on any address it's listening to. */ public Node( URI uri, @Nullable String name, @Nullable String version, @Nullable Set roles, - @Nullable Map attributes, - @Nullable List boundHosts + @Nullable Map attributes ) { if (!uri.isAbsolute()) { @@ -71,15 +67,14 @@ public Node( this.version = version; this.roles = roles; this.attributes = attributes; - this.boundHosts = boundHosts; } public Node(URI uri) { - this(uri, null, null, null, null, null); + this(uri, null, null, null, null); } public Node(String uri) { - this(URI.create(uri), null, null, null, null, null); + this(URI.create(uri), null, null, null, null); } /** @@ -112,11 +107,6 @@ public Map attributes() { return attributes; } - @Nullable - public List boundHosts() { - return boundHosts; - } - @Override public String toString() { return uri.toString(); From 507707e0d6930a80a7a9c3ec5c73f815858c654d Mon Sep 17 00:00:00 2001 From: Sylvain Wallez Date: Sun, 30 Mar 2025 10:55:28 +0200 Subject: [PATCH 29/38] Port RestClient's sniffer to Rest5Client --- .../sniffer/ElasticsearchNodesSniffer.java | 313 +++++++++ .../low_level/sniffer/NodesSniffer.java | 34 + .../sniffer/SniffOnFailureListener.java | 63 ++ .../low_level/sniffer/Sniffer.java | 322 +++++++++ .../low_level/sniffer/SnifferBuilder.java | 91 +++ .../low_level/RestClientTestCase.java | 28 +- .../ElasticsearchNodesSnifferParseTests.java | 188 +++++ .../ElasticsearchNodesSnifferTests.java | 378 ++++++++++ .../low_level/sniffer/MockNodesSniffer.java | 36 + .../sniffer/SniffOnFailureListenerTests.java | 64 ++ .../sniffer/SnifferBuilderTests.java | 89 +++ .../low_level/sniffer/SnifferTests.java | 661 ++++++++++++++++++ .../documentation/SnifferDocumentation.java | 135 ++++ .../low_level/sniffer/2.0.0_nodes_http.json | 201 ++++++ .../low_level/sniffer/5.0.0_nodes_http.json | 217 ++++++ .../low_level/sniffer/6.0.0_nodes_http.json | 217 ++++++ .../low_level/sniffer/7.3.0_nodes_http.json | 218 ++++++ .../sniffer/create_test_nodes_info.bash | 107 +++ .../es6_nodes_publication_address_format.json | 30 + .../es7_nodes_publication_address_format.json | 30 + .../rest5_client/low_level/sniffer/readme.txt | 6 + 21 files changed, 3427 insertions(+), 1 deletion(-) create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/ElasticsearchNodesSniffer.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/NodesSniffer.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SniffOnFailureListener.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/Sniffer.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SnifferBuilder.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/ElasticsearchNodesSnifferParseTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/ElasticsearchNodesSnifferTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/MockNodesSniffer.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SniffOnFailureListenerTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SnifferBuilderTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SnifferTests.java create mode 100644 java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/documentation/SnifferDocumentation.java create mode 100644 java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/2.0.0_nodes_http.json create mode 100644 java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/5.0.0_nodes_http.json create mode 100644 java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/6.0.0_nodes_http.json create mode 100644 java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/7.3.0_nodes_http.json create mode 100644 java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/create_test_nodes_info.bash create mode 100644 java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/es6_nodes_publication_address_format.json create mode 100644 java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/es7_nodes_publication_address_format.json create mode 100644 java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/readme.txt diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/ElasticsearchNodesSniffer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/ElasticsearchNodesSniffer.java new file mode 100644 index 000000000..73e4185c5 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/ElasticsearchNodesSniffer.java @@ -0,0 +1,313 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level.sniffer; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; +import co.elastic.clients.transport.rest5_client.low_level.Node; +import co.elastic.clients.transport.rest5_client.low_level.Node.Roles; +import co.elastic.clients.transport.rest5_client.low_level.Request; +import co.elastic.clients.transport.rest5_client.low_level.Response; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.util.ArrayList; +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.TreeSet; +import java.util.concurrent.TimeUnit; + +import static java.util.Collections.singletonList; +import static java.util.Collections.unmodifiableList; +import static java.util.Collections.unmodifiableMap; + +/** + * Class responsible for sniffing the http hosts from elasticsearch through the nodes info api and returning them back. + * Compatible with elasticsearch 2.x+. + */ +public final class ElasticsearchNodesSniffer implements NodesSniffer { + + private static final Log logger = LogFactory.getLog(ElasticsearchNodesSniffer.class); + + public static final long DEFAULT_SNIFF_REQUEST_TIMEOUT = TimeUnit.SECONDS.toMillis(1); + + private final Rest5Client restClient; + private final Request request; + private final Scheme scheme; + private final JsonFactory jsonFactory = new JsonFactory(); + + /** + * Creates a new instance of the Elasticsearch sniffer. It will use the provided {@link Rest5Client} to fetch the hosts, + * through the nodes info api, the default sniff request timeout value {@link #DEFAULT_SNIFF_REQUEST_TIMEOUT} and http + * as the scheme for all the hosts. + * @param restClient client used to fetch the hosts from elasticsearch through nodes info api. Usually the same instance + * that is also provided to {@link Sniffer#builder(Rest5Client)}, so that the hosts are set to the same + * client that was used to fetch them. + */ + public ElasticsearchNodesSniffer(Rest5Client restClient) { + this(restClient, DEFAULT_SNIFF_REQUEST_TIMEOUT, ElasticsearchNodesSniffer.Scheme.HTTP); + } + + /** + * Creates a new instance of the Elasticsearch sniffer. It will use the provided {@link Rest5Client} to fetch the hosts + * through the nodes info api, the provided sniff request timeout value and scheme. + * @param restClient client used to fetch the hosts from elasticsearch through nodes info api. Usually the same instance + * that is also provided to {@link Sniffer#builder(Rest5Client)}, so that the hosts are set to the same + * client that was used to sniff them. + * @param sniffRequestTimeoutMillis the sniff request timeout (in milliseconds) to be passed in as a query string parameter + * to elasticsearch. Allows to halt the request without any failure, as only the nodes + * that have responded within this timeout will be returned. + * @param scheme the scheme to associate sniffed nodes with (as it is not returned by elasticsearch) + */ + public ElasticsearchNodesSniffer(Rest5Client restClient, long sniffRequestTimeoutMillis, Scheme scheme) { + this.restClient = Objects.requireNonNull(restClient, "restClient cannot be null"); + if (sniffRequestTimeoutMillis < 0) { + throw new IllegalArgumentException("sniffRequestTimeoutMillis must be greater than 0"); + } + this.request = new Request("GET", "/_nodes/http"); + request.addParameter("timeout", sniffRequestTimeoutMillis + "ms"); + this.scheme = Objects.requireNonNull(scheme, "scheme cannot be null"); + } + + /** + * Calls the elasticsearch nodes info api, parses the response and returns all the found http hosts + */ + @Override + public List sniff() throws IOException { + Response response = restClient.performRequest(request); + return readHosts(response.getEntity(), scheme, jsonFactory); + } + + static List readHosts(HttpEntity entity, Scheme scheme, JsonFactory jsonFactory) throws IOException { + try (InputStream inputStream = entity.getContent()) { + JsonParser parser = jsonFactory.createParser(inputStream); + if (parser.nextToken() != JsonToken.START_OBJECT) { + throw new IOException("expected data to start with an object"); + } + List nodes = new ArrayList<>(); + while (parser.nextToken() != JsonToken.END_OBJECT) { + if (parser.getCurrentToken() == JsonToken.START_OBJECT) { + if ("nodes".equals(parser.getCurrentName())) { + while (parser.nextToken() != JsonToken.END_OBJECT) { + JsonToken token = parser.nextToken(); + assert token == JsonToken.START_OBJECT; + String nodeId = parser.getCurrentName(); + Node node = readNode(nodeId, parser, scheme); + if (node != null) { + nodes.add(node); + } + } + } else { + parser.skipChildren(); + } + } + } + return nodes; + } + } + + private static Node readNode(String nodeId, JsonParser parser, Scheme scheme) throws IOException { + HttpHost publishedHost = null; + /* + * We sniff the bound hosts so we can look up the node based on any + * address on which it is listening. This is useful in Elasticsearch's + * test framework where we sometimes publish ipv6 addresses but the + * tests contact the node on ipv4. + */ + Set boundHosts = new HashSet<>(); + String name = null; + String version = null; + /* + * Multi-valued attributes come with key = `real_key.index` and we + * unflip them after reading them because we can't rely on the order + * that they arive. + */ + final Map protoAttributes = new HashMap(); + + boolean sawRoles = false; + final Set roles = new TreeSet<>(); + + String fieldName = null; + while (parser.nextToken() != JsonToken.END_OBJECT) { + if (parser.getCurrentToken() == JsonToken.FIELD_NAME) { + fieldName = parser.getCurrentName(); + } else if (parser.getCurrentToken() == JsonToken.START_OBJECT) { + if ("http".equals(fieldName)) { + while (parser.nextToken() != JsonToken.END_OBJECT) { + if (parser.getCurrentToken() == JsonToken.VALUE_STRING && "publish_address".equals(parser.getCurrentName())) { + String address = parser.getValueAsString(); + String host; + URI publishAddressAsURI; + + // ES7 cname/ip:port format + if (address.contains("/")) { + String[] cnameAndURI = address.split("/", 2); + publishAddressAsURI = URI.create(scheme + "://" + cnameAndURI[1]); + host = cnameAndURI[0]; + } else { + publishAddressAsURI = URI.create(scheme + "://" + address); + host = publishAddressAsURI.getHost(); + } + publishedHost = new HttpHost(publishAddressAsURI.getScheme(), host, publishAddressAsURI.getPort()); + } else if (parser.currentToken() == JsonToken.START_ARRAY && "bound_address".equals(parser.getCurrentName())) { + while (parser.nextToken() != JsonToken.END_ARRAY) { + URI boundAddressAsURI = URI.create(scheme + "://" + parser.getValueAsString()); + boundHosts.add( + new HttpHost(boundAddressAsURI.getScheme(), boundAddressAsURI.getHost(), boundAddressAsURI.getPort()) + ); + } + } else if (parser.getCurrentToken() == JsonToken.START_OBJECT) { + parser.skipChildren(); + } + } + } else if ("attributes".equals(fieldName)) { + while (parser.nextToken() != JsonToken.END_OBJECT) { + if (parser.getCurrentToken() == JsonToken.VALUE_STRING) { + String oldValue = protoAttributes.put(parser.getCurrentName(), parser.getValueAsString()); + if (oldValue != null) { + throw new IOException("repeated attribute key [" + parser.getCurrentName() + "]"); + } + } else { + parser.skipChildren(); + } + } + } else { + parser.skipChildren(); + } + } else if (parser.currentToken() == JsonToken.START_ARRAY) { + if ("roles".equals(fieldName)) { + sawRoles = true; + while (parser.nextToken() != JsonToken.END_ARRAY) { + roles.add(parser.getText()); + } + } else { + parser.skipChildren(); + } + } else if (parser.currentToken().isScalarValue()) { + if ("version".equals(fieldName)) { + version = parser.getText(); + } else if ("name".equals(fieldName)) { + name = parser.getText(); + } + } + } + // http section is not present if http is not enabled on the node, ignore such nodes + if (publishedHost == null) { + logger.debug("skipping node [" + nodeId + "] with http disabled"); + return null; + } + + Map> realAttributes = new HashMap<>(protoAttributes.size()); + List keys = new ArrayList<>(protoAttributes.keySet()); + for (String key : keys) { + if (key.endsWith(".0")) { + String realKey = key.substring(0, key.length() - 2); + List values = new ArrayList<>(); + int i = 0; + while (true) { + String value = protoAttributes.remove(realKey + "." + i); + if (value == null) { + break; + } + values.add(value); + i++; + } + realAttributes.put(realKey, unmodifiableList(values)); + } + } + for (Map.Entry entry : protoAttributes.entrySet()) { + realAttributes.put(entry.getKey(), singletonList(entry.getValue())); + } + + if (version.startsWith("2.")) { + /* + * 2.x doesn't send roles, instead we try to read them from + * attributes. + */ + boolean clientAttribute = v2RoleAttributeValue(realAttributes, "client", false); + Boolean masterAttribute = v2RoleAttributeValue(realAttributes, "master", null); + Boolean dataAttribute = v2RoleAttributeValue(realAttributes, "data", null); + if ((masterAttribute == null && false == clientAttribute) || masterAttribute) { + roles.add("master"); + } + if ((dataAttribute == null && false == clientAttribute) || dataAttribute) { + roles.add("data"); + } + } else { + assert sawRoles : "didn't see roles for [" + nodeId + "]"; + } + assert boundHosts.contains(publishedHost) : "[" + nodeId + "] doesn't make sense! publishedHost should be in boundHosts"; + logger.trace("adding node [" + nodeId + "]"); + return new Node(publishedHost, boundHosts, name, version, new Roles(roles), unmodifiableMap(realAttributes)); + } + + /** + * Returns {@code defaultValue} if the attribute didn't come back, + * {@code true} or {@code false} if it did come back as + * either of those, or throws an IOException if the attribute + * came back in a strange way. + */ + private static Boolean v2RoleAttributeValue(Map> attributes, String name, Boolean defaultValue) + throws IOException { + List valueList = attributes.remove(name); + if (valueList == null) { + return defaultValue; + } + if (valueList.size() != 1) { + throw new IOException("expected only a single attribute value for [" + name + "] but got " + valueList); + } + switch (valueList.get(0)) { + case "true": + return true; + case "false": + return false; + default: + throw new IOException("expected [" + name + "] to be either [true] or [false] but was [" + valueList.get(0) + "]"); + } + } + + public enum Scheme { + HTTP("http"), + HTTPS("https"); + + private final String name; + + Scheme(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/NodesSniffer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/NodesSniffer.java new file mode 100644 index 000000000..552d6317c --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/NodesSniffer.java @@ -0,0 +1,34 @@ +/* + * 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. + */ +package co.elastic.clients.transport.rest5_client.low_level.sniffer; + +import co.elastic.clients.transport.rest5_client.low_level.Node; + +import java.io.IOException; +import java.util.List; + +/** + * Responsible for sniffing the http hosts + */ +public interface NodesSniffer { + /** + * Returns the sniffed Elasticsearch nodes. + */ + List sniff() throws IOException; +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SniffOnFailureListener.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SniffOnFailureListener.java new file mode 100644 index 000000000..0127945f9 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SniffOnFailureListener.java @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level.sniffer; + +import co.elastic.clients.transport.rest5_client.low_level.Node; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; + +import java.util.Objects; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * {@link Rest5Client.FailureListener} implementation that allows to perform + * sniffing on failure. Gets notified whenever a failure happens and uses a {@link Sniffer} instance + * to manually reload hosts and sets them back to the {@link Rest5Client}. The {@link Sniffer} instance + * needs to be lazily set through {@link #setSniffer(Sniffer)}. + */ +public class SniffOnFailureListener extends Rest5Client.FailureListener { + + private volatile Sniffer sniffer; + private final AtomicBoolean set; + + public SniffOnFailureListener() { + this.set = new AtomicBoolean(false); + } + + /** + * Sets the {@link Sniffer} instance used to perform sniffing + * @throws IllegalStateException if the sniffer was already set, as it can only be set once + */ + public void setSniffer(Sniffer sniffer) { + Objects.requireNonNull(sniffer, "sniffer must not be null"); + if (set.compareAndSet(false, true)) { + this.sniffer = sniffer; + } else { + throw new IllegalStateException("sniffer can only be set once"); + } + } + + @Override + public void onFailure(Node node) { + if (sniffer == null) { + throw new IllegalStateException("sniffer was not set, unable to sniff on failure"); + } + sniffer.sniffOnFailure(); + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/Sniffer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/Sniffer.java new file mode 100644 index 000000000..1e7ff6cb5 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/Sniffer.java @@ -0,0 +1,322 @@ +/* + * 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. + */ +package co.elastic.clients.transport.rest5_client.low_level.sniffer; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import co.elastic.clients.transport.rest5_client.low_level.Node; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; +import co.elastic.clients.transport.rest5_client.low_level.Rest5ClientBuilder; + +import java.io.Closeable; +import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Class responsible for sniffing nodes from some source (default is elasticsearch itself) and setting them to a provided instance of + * {@link Rest5Client}. Must be created via {@link SnifferBuilder}, which allows to set all of the different options or rely on defaults. + * A background task fetches the nodes through the {@link NodesSniffer} and sets them to the {@link Rest5Client} instance. + * It is possible to perform sniffing on failure by creating a {@link SniffOnFailureListener} and providing it as an argument to + * {@link Rest5ClientBuilder#setFailureListener(Rest5Client.FailureListener)}. The Sniffer implementation needs to be lazily set to the + * previously created SniffOnFailureListener through {@link SniffOnFailureListener#setSniffer(Sniffer)}. + */ +public class Sniffer implements Closeable { + + private static final Log logger = LogFactory.getLog(Sniffer.class); + private static final String SNIFFER_THREAD_NAME = "es_rest_client_sniffer"; + + private final NodesSniffer nodesSniffer; + private final Rest5Client restClient; + private final long sniffIntervalMillis; + private final long sniffAfterFailureDelayMillis; + private final Scheduler scheduler; + private final AtomicBoolean initialized = new AtomicBoolean(false); + private volatile ScheduledTask nextScheduledTask; + + Sniffer(Rest5Client restClient, NodesSniffer nodesSniffer, long sniffInterval, long sniffAfterFailureDelay) { + this(restClient, nodesSniffer, new DefaultScheduler(), sniffInterval, sniffAfterFailureDelay); + } + + Sniffer(Rest5Client restClient, NodesSniffer nodesSniffer, Scheduler scheduler, long sniffInterval, long sniffAfterFailureDelay) { + this.nodesSniffer = nodesSniffer; + this.restClient = restClient; + this.sniffIntervalMillis = sniffInterval; + this.sniffAfterFailureDelayMillis = sniffAfterFailureDelay; + this.scheduler = scheduler; + /* + * The first sniffing round is async, so this constructor returns before nextScheduledTask is assigned to a task. + * The initialized flag is a protection against NPE due to that. + */ + Task task = new Task(sniffIntervalMillis) { + @Override + public void run() { + super.run(); + initialized.compareAndSet(false, true); + } + }; + /* + * We do not keep track of the returned future as we never intend to cancel the initial sniffing round, we rather + * prevent any other operation from being executed till the sniffer is properly initialized + */ + scheduler.schedule(task, 0L); + } + + /** + * Schedule sniffing to run as soon as possible if it isn't already running. Once such sniffing round runs + * it will also schedule a new round after sniffAfterFailureDelay ms. + */ + public void sniffOnFailure() { + // sniffOnFailure does nothing until the initial sniffing round has been completed + if (initialized.get()) { + /* + * If sniffing is already running, there is no point in scheduling another round right after the current one. + * Concurrent calls may be checking the same task state, but only the first skip call on the same task returns true. + * The task may also get replaced while we check its state, in which case calling skip on it returns false. + */ + if (this.nextScheduledTask.skip()) { + /* + * We do not keep track of this future as the task will immediately run and we don't intend to cancel it + * due to concurrent sniffOnFailure runs. Effectively the previous (now cancelled or skipped) task will stay + * assigned to nextTask till this onFailure round gets run and schedules its corresponding afterFailure round. + */ + scheduler.schedule(new Task(sniffAfterFailureDelayMillis), 0L); + } + } + } + + enum TaskState { + WAITING, + SKIPPED, + STARTED + } + + class Task implements Runnable { + final long nextTaskDelay; + final AtomicReference taskState = new AtomicReference<>(TaskState.WAITING); + + Task(long nextTaskDelay) { + this.nextTaskDelay = nextTaskDelay; + } + + @Override + public void run() { + /* + * Skipped or already started tasks do nothing. In most cases tasks will be cancelled and not run, but we want to protect for + * cases where future#cancel returns true yet the task runs. We want to make sure that such tasks do nothing otherwise they will + * schedule another round at the end and so on, leaving us with multiple parallel sniffing "tracks" whish is undesirable. + */ + if (taskState.compareAndSet(TaskState.WAITING, TaskState.STARTED) == false) { + return; + } + try { + sniff(); + } catch (Exception e) { + logger.error("error while sniffing nodes", e); + } finally { + Task task = new Task(sniffIntervalMillis); + Future future = scheduler.schedule(task, nextTaskDelay); + // tasks are run by a single threaded executor, so swapping is safe with a simple volatile variable + ScheduledTask previousTask = nextScheduledTask; + nextScheduledTask = new ScheduledTask(task, future); + assert initialized.get() == false || previousTask.task.isSkipped() || previousTask.task.hasStarted() + : "task that we are replacing is neither cancelled nor has it ever started"; + } + } + + /** + * Returns true if the task has started, false in case it didn't start (yet?) or it was skipped + */ + boolean hasStarted() { + return taskState.get() == TaskState.STARTED; + } + + /** + * Sets this task to be skipped. Returns true if the task will be skipped, false if the task has already started. + */ + boolean skip() { + /* + * Threads may still get run although future#cancel returns true. We make sure that a task is either cancelled (or skipped), + * or entirely run. In the odd case that future#cancel returns true and the thread still runs, the task won't do anything. + * In case future#cancel returns true but the task has already started, this state change will not succeed hence this method + * returns false and the task will normally run. + */ + return taskState.compareAndSet(TaskState.WAITING, TaskState.SKIPPED); + } + + /** + * Returns true if the task was set to be skipped before it was started + */ + boolean isSkipped() { + return taskState.get() == TaskState.SKIPPED; + } + } + + static final class ScheduledTask { + final Task task; + final Future future; + + ScheduledTask(Task task, Future future) { + this.task = task; + this.future = future; + } + + /** + * Cancels this task. Returns true if the task has been successfully cancelled, meaning it won't be executed + * or if it is its execution won't have any effect. Returns false if the task cannot be cancelled (possibly it was + * already cancelled or already completed). + */ + boolean skip() { + /* + * Future#cancel should return false whenever a task cannot be cancelled, most likely as it has already started. We don't + * trust it much though so we try to cancel hoping that it will work. At the same time we always call skip too, which means + * that if the task has already started the state change will fail. We could potentially not call skip when cancel returns + * false but we prefer to stay on the safe side. + */ + future.cancel(false); + return task.skip(); + } + } + + final void sniff() throws IOException { + List sniffedNodes = nodesSniffer.sniff(); + if (logger.isDebugEnabled()) { + logger.debug("sniffed nodes: " + sniffedNodes); + } + if (sniffedNodes.isEmpty()) { + logger.warn("no nodes to set, nodes will be updated at the next sniffing round"); + } else { + restClient.setNodes(sniffedNodes); + } + } + + @Override + public void close() { + if (initialized.get()) { + nextScheduledTask.skip(); + } + this.scheduler.shutdown(); + } + + /** + * Returns a new {@link SnifferBuilder} to help with {@link Sniffer} creation. + * + * @param restClient the client that gets its hosts set (via + * {@link Rest5Client#setNodes(Collection)}) once they are fetched + * @return a new instance of {@link SnifferBuilder} + */ + public static SnifferBuilder builder(Rest5Client restClient) { + return new SnifferBuilder(restClient); + } + + /** + * The Scheduler interface allows to isolate the sniffing scheduling aspects so that we can test + * the sniffer by injecting when needed a custom scheduler that is more suited for testing. + */ + interface Scheduler { + /** + * Schedules the provided {@link Runnable} to be executed in delayMillis milliseconds + */ + Future schedule(Task task, long delayMillis); + + /** + * Shuts this scheduler down + */ + void shutdown(); + } + + /** + * Default implementation of {@link Scheduler}, based on {@link ScheduledExecutorService} + */ + static final class DefaultScheduler implements Scheduler { + final ScheduledExecutorService executor; + + DefaultScheduler() { + this(initScheduledExecutorService()); + } + + DefaultScheduler(ScheduledExecutorService executor) { + this.executor = executor; + } + + private static ScheduledExecutorService initScheduledExecutorService() { + ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, new SnifferThreadFactory(SNIFFER_THREAD_NAME)); + executor.setRemoveOnCancelPolicy(true); + return executor; + } + + @Override + public Future schedule(Task task, long delayMillis) { + return executor.schedule(task, delayMillis, TimeUnit.MILLISECONDS); + } + + @Override + public void shutdown() { + executor.shutdown(); + try { + if (executor.awaitTermination(1000, TimeUnit.MILLISECONDS)) { + return; + } + executor.shutdownNow(); + } catch (InterruptedException ignore) { + Thread.currentThread().interrupt(); + } + } + } + + static class SnifferThreadFactory implements ThreadFactory { + private final AtomicInteger threadNumber = new AtomicInteger(1); + private final String namePrefix; + private final ThreadFactory originalThreadFactory; + + private SnifferThreadFactory(String namePrefix) { + this.namePrefix = namePrefix; + this.originalThreadFactory = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public ThreadFactory run() { + return Executors.defaultThreadFactory(); + } + }); + } + + @Override + public Thread newThread(final Runnable r) { + return AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Thread run() { + Thread t = originalThreadFactory.newThread(r); + t.setName(namePrefix + "[T#" + threadNumber.getAndIncrement() + "]"); + t.setDaemon(true); + return t; + } + }); + } + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SnifferBuilder.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SnifferBuilder.java new file mode 100644 index 000000000..a04009350 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SnifferBuilder.java @@ -0,0 +1,91 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level.sniffer; + +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; + +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +/** + * Sniffer builder. Helps creating a new {@link Sniffer}. + */ +public final class SnifferBuilder { + public static final long DEFAULT_SNIFF_INTERVAL = TimeUnit.MINUTES.toMillis(5); + public static final long DEFAULT_SNIFF_AFTER_FAILURE_DELAY = TimeUnit.MINUTES.toMillis(1); + + private final Rest5Client restClient; + private long sniffIntervalMillis = DEFAULT_SNIFF_INTERVAL; + private long sniffAfterFailureDelayMillis = DEFAULT_SNIFF_AFTER_FAILURE_DELAY; + private NodesSniffer nodesSniffer; + + /** + * Creates a new builder instance by providing the {@link Rest5Client} that will be used to communicate with elasticsearch + */ + SnifferBuilder(Rest5Client restClient) { + Objects.requireNonNull(restClient, "restClient cannot be null"); + this.restClient = restClient; + } + + /** + * Sets the interval between consecutive ordinary sniff executions in milliseconds. Will be honoured when + * sniffOnFailure is disabled or when there are no failures between consecutive sniff executions. + * @throws IllegalArgumentException if sniffIntervalMillis is not greater than 0 + */ + public SnifferBuilder setSniffIntervalMillis(int sniffIntervalMillis) { + if (sniffIntervalMillis <= 0) { + throw new IllegalArgumentException("sniffIntervalMillis must be greater than 0"); + } + this.sniffIntervalMillis = sniffIntervalMillis; + return this; + } + + /** + * Sets the delay of a sniff execution scheduled after a failure (in milliseconds) + */ + public SnifferBuilder setSniffAfterFailureDelayMillis(int sniffAfterFailureDelayMillis) { + if (sniffAfterFailureDelayMillis <= 0) { + throw new IllegalArgumentException("sniffAfterFailureDelayMillis must be greater than 0"); + } + this.sniffAfterFailureDelayMillis = sniffAfterFailureDelayMillis; + return this; + } + + /** + * Sets the {@link NodesSniffer} to be used to read hosts. A default instance of {@link ElasticsearchNodesSniffer} + * is created when not provided. This method can be used to change the configuration of the {@link ElasticsearchNodesSniffer}, + * or to provide a different implementation (e.g. in case hosts need to taken from a different source). + */ + public SnifferBuilder setNodesSniffer(NodesSniffer nodesSniffer) { + Objects.requireNonNull(nodesSniffer, "nodesSniffer cannot be null"); + this.nodesSniffer = nodesSniffer; + return this; + } + + /** + * Creates the {@link Sniffer} based on the provided configuration. + */ + public Sniffer build() { + if (nodesSniffer == null) { + this.nodesSniffer = new ElasticsearchNodesSniffer(restClient); + } + return new Sniffer(restClient, nodesSniffer, sniffIntervalMillis, sniffAfterFailureDelayMillis); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestCase.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestCase.java index db982ed19..3d1a7dd31 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestCase.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/RestClientTestCase.java @@ -29,6 +29,7 @@ import java.util.Map; import java.util.Random; import java.util.Set; +import java.util.concurrent.ThreadLocalRandom; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -104,12 +105,22 @@ public static boolean inFipsJvm() { return Boolean.parseBoolean(System.getProperty("tests.fips.enabled")); } + public static Random getRandom() { + return ThreadLocalRandom.current(); + } + public static int randomIntBetween(int min, int max) { - return new Random().ints(min, max) + return getRandom().ints(min, max) .findFirst() .getAsInt(); } + public static long randomLongBetween(long min, long max) { + return getRandom().longs(min, max) + .findFirst() + .getAsLong(); + } + public static boolean randomBoolean() { return randomIntBetween(0, 1) == 0; } @@ -131,6 +142,7 @@ public static String randomAsciiLettersOfLengthBetween(int min, int max) { } public static T randomFrom(T[] array) { + checkZeroLength(array.length); int index = randomIntBetween(0, array.length); return array[index]; } @@ -145,4 +157,18 @@ public static byte[] randomBytesOfLength(int length) { new Random().nextBytes(b); return b; } + + public static boolean rarely() { + return randomIntBetween(0, 100) >= 90; + } + + public static boolean frequently() { + return !rarely(); + } + + private static void checkZeroLength(int length) { + if (length == 0) { + throw new IllegalArgumentException("Can't pick a random object from an empty array."); + } + } } diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/ElasticsearchNodesSnifferParseTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/ElasticsearchNodesSnifferParseTests.java new file mode 100644 index 000000000..e2ecc3c24 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/ElasticsearchNodesSnifferParseTests.java @@ -0,0 +1,188 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level.sniffer; + +import co.elastic.clients.transport.rest5_client.low_level.Node; +import co.elastic.clients.transport.rest5_client.low_level.RestClientTestCase; +import com.fasterxml.jackson.core.JsonFactory; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.io.entity.InputStreamEntity; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import static java.util.Collections.singletonList; +import static org.hamcrest.Matchers.hasSize; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +/** + * Test parsing the response from the {@code /_nodes/http} API from fixed + * versions of Elasticsearch. + */ +public class ElasticsearchNodesSnifferParseTests extends RestClientTestCase { + + private void checkFile(String file, Node... expected) throws IOException { + InputStream in = this.getClass().getResourceAsStream(file); + if (in == null) { + throw new IllegalArgumentException("Couldn't find [" + file + "]"); + } + try { + HttpEntity entity = new InputStreamEntity(in, ContentType.APPLICATION_JSON); + List nodes = ElasticsearchNodesSniffer.readHosts(entity, ElasticsearchNodesSniffer.Scheme.HTTP, new JsonFactory()); + /* + * Use these assertions because the error messages are nicer + * than hasItems and we know the results are in order because + * that is how we generated the file. + */ + assertThat(nodes, hasSize(expected.length)); + for (int i = 0; i < expected.length; i++) { + assertEquals(expected[i], nodes.get(i)); + } + } finally { + in.close(); + } + } + + @Test + public void test2x() throws IOException { + checkFile( + "2.0.0_nodes_http.json", + node(9200, "m1", "2.0.0", true, false, false), + node(9201, "m2", "2.0.0", true, true, false), + node(9202, "m3", "2.0.0", true, false, false), + node(9203, "d1", "2.0.0", false, true, false), + node(9204, "d2", "2.0.0", false, true, false), + node(9205, "d3", "2.0.0", false, true, false), + node(9206, "c1", "2.0.0", false, false, false), + node(9207, "c2", "2.0.0", false, false, false) + ); + } + + @Test + public void test5x() throws IOException { + checkFile( + "5.0.0_nodes_http.json", + node(9200, "m1", "5.0.0", true, false, true), + node(9201, "m2", "5.0.0", true, true, true), + node(9202, "m3", "5.0.0", true, false, true), + node(9203, "d1", "5.0.0", false, true, true), + node(9204, "d2", "5.0.0", false, true, true), + node(9205, "d3", "5.0.0", false, true, true), + node(9206, "c1", "5.0.0", false, false, true), + node(9207, "c2", "5.0.0", false, false, true) + ); + } + + @Test + public void test6x() throws IOException { + checkFile( + "6.0.0_nodes_http.json", + node(9200, "m1", "6.0.0", true, false, true), + node(9201, "m2", "6.0.0", true, true, true), + node(9202, "m3", "6.0.0", true, false, true), + node(9203, "d1", "6.0.0", false, true, true), + node(9204, "d2", "6.0.0", false, true, true), + node(9205, "d3", "6.0.0", false, true, true), + node(9206, "c1", "6.0.0", false, false, true), + node(9207, "c2", "6.0.0", false, false, true) + ); + } + + @Test + public void test7x() throws IOException { + checkFile( + "7.3.0_nodes_http.json", + node(9200, "m1", "7.3.0", "master", "ingest"), + node(9201, "m2", "7.3.0", "master", "data", "ingest"), + node(9202, "m3", "7.3.0", "master", "ingest"), + node(9203, "d1", "7.3.0", "data", "ingest", "ml"), + node(9204, "d2", "7.3.0", "data", "ingest"), + node(9205, "d3", "7.3.0", "data", "ingest"), + node(9206, "c1", "7.3.0", "ingest"), + node(9207, "c2", "7.3.0", "ingest") + ); + } + + @Test + public void testParsingPublishAddressWithPreES7Format() throws IOException { + InputStream in = this.getClass().getResourceAsStream("es6_nodes_publication_address_format.json"); + + HttpEntity entity = new InputStreamEntity(in, ContentType.APPLICATION_JSON); + List nodes = ElasticsearchNodesSniffer.readHosts(entity, ElasticsearchNodesSniffer.Scheme.HTTP, new JsonFactory()); + + assertEquals("127.0.0.1", nodes.get(0).getHost().getHostName()); + assertEquals(9200, nodes.get(0).getHost().getPort()); + assertEquals("http", nodes.get(0).getHost().getSchemeName()); + } + + @Test + public void testParsingPublishAddressWithES7Format() throws IOException { + InputStream in = this.getClass().getResourceAsStream("es7_nodes_publication_address_format.json"); + + HttpEntity entity = new InputStreamEntity(in, ContentType.APPLICATION_JSON); + List nodes = ElasticsearchNodesSniffer.readHosts(entity, ElasticsearchNodesSniffer.Scheme.HTTP, new JsonFactory()); + + assertEquals("elastic.test", nodes.get(0).getHost().getHostName()); + assertEquals(9200, nodes.get(0).getHost().getPort()); + assertEquals("http", nodes.get(0).getHost().getSchemeName()); + } + + private Node node(int port, String name, String version, boolean master, boolean data, boolean ingest) { + final Set roles = new TreeSet<>(); + if (master) { + roles.add("master"); + } + if (data) { + roles.add("data"); + } + if (ingest) { + roles.add("ingest"); + } + return node(port, name, version, roles); + } + + private Node node(int port, String name, String version, String... roles) { + return node(port, name, version, new TreeSet<>(Arrays.asList(roles))); + } + + private Node node(int port, String name, String version, Set roles) { + HttpHost host = new HttpHost("127.0.0.1", port); + Set boundHosts = new HashSet<>(2); + boundHosts.add(host); + boundHosts.add(new HttpHost("[::1]", port)); + Map> attributes = new HashMap<>(); + attributes.put("dummy", singletonList("everyone_has_me")); + attributes.put("number", singletonList(name.substring(1))); + attributes.put("array", Arrays.asList(name.substring(0, 1), name.substring(1))); + return new Node(host, boundHosts, name, version, new Node.Roles(new TreeSet<>(roles)), attributes); + } + +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/ElasticsearchNodesSnifferTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/ElasticsearchNodesSnifferTests.java new file mode 100644 index 000000000..a7694eac2 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/ElasticsearchNodesSnifferTests.java @@ -0,0 +1,378 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level.sniffer; + +import co.elastic.clients.transport.rest5_client.low_level.Node; +import co.elastic.clients.transport.rest5_client.low_level.Response; +import co.elastic.clients.transport.rest5_client.low_level.ResponseException; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; +import co.elastic.clients.transport.rest5_client.low_level.RestClientTestCase; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; + +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.core5.http.HttpHost; +import org.elasticsearch.mocksocket.MockHttpServer; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.StringWriter; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +public class ElasticsearchNodesSnifferTests extends RestClientTestCase { + + private static int sniffRequestTimeout; + private static ElasticsearchNodesSniffer.Scheme scheme; + private static SniffResponse sniffResponse; + private static HttpServer httpServer; + + @BeforeAll + public static void startHttpServer() throws IOException { + sniffRequestTimeout = randomIntBetween(1000, 10000); + scheme = randomFrom(ElasticsearchNodesSniffer.Scheme.values()); + if (rarely()) { + sniffResponse = SniffResponse.buildFailure(); + } else { + sniffResponse = buildSniffResponse(scheme); + } + httpServer = createHttpServer(sniffResponse, sniffRequestTimeout); + httpServer.start(); + } + + @AfterAll + public static void stopHttpServer() throws IOException { + httpServer.stop(0); + } + + @Test + public void testConstructorValidation() throws IOException { + try { + new ElasticsearchNodesSniffer(null, 1, ElasticsearchNodesSniffer.Scheme.HTTP); + fail("should have failed"); + } catch (NullPointerException e) { + assertEquals("restClient cannot be null", e.getMessage()); + } + HttpHost httpHost = new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()); + try (Rest5Client restClient = Rest5Client.builder(httpHost).build()) { + try { + new ElasticsearchNodesSniffer(restClient, 1, null); + fail("should have failed"); + } catch (NullPointerException e) { + assertEquals(e.getMessage(), "scheme cannot be null"); + } + try { + new ElasticsearchNodesSniffer( + restClient, + randomIntBetween(Integer.MIN_VALUE, 0), + ElasticsearchNodesSniffer.Scheme.HTTP + ); + fail("should have failed"); + } catch (IllegalArgumentException e) { + assertEquals(e.getMessage(), "sniffRequestTimeoutMillis must be greater than 0"); + } + } + } + + @Test + public void testSniffNodes() throws IOException { + HttpHost httpHost = new HttpHost(httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()); + try (Rest5Client restClient = Rest5Client.builder(httpHost).build()) { + ElasticsearchNodesSniffer sniffer = new ElasticsearchNodesSniffer(restClient, sniffRequestTimeout, scheme); + try { + List sniffedNodes = sniffer.sniff(); + if (sniffResponse.isFailure) { + fail("sniffNodes should have failed"); + } + assertEquals(sniffResponse.result, sniffedNodes); + } catch (ResponseException e) { + Response response = e.getResponse(); + if (sniffResponse.isFailure) { + final String errorPrefix = "method [GET], host [" + + httpHost + + "], URI [/_nodes/http?timeout=" + + sniffRequestTimeout + + "ms], status line [HTTP/1.1"; + assertThat(e.getMessage(), startsWith(errorPrefix)); + assertThat(e.getMessage(), containsString(Integer.toString(sniffResponse.nodesInfoResponseCode))); + assertThat(response.getHost(), equalTo(httpHost)); + assertThat(response.getStatusCode(), equalTo(sniffResponse.nodesInfoResponseCode)); + assertThat( + response.getRequestLine().toString(), + equalTo("GET /_nodes/http?timeout=" + sniffRequestTimeout + "ms HTTP/1.1") + ); + } else { + fail("sniffNodes should have succeeded: " + response.getStatusCode()); + } + } + } + } + + private static HttpServer createHttpServer(final SniffResponse sniffResponse, final int sniffTimeoutMillis) throws IOException { + HttpServer httpServer = MockHttpServer.createHttp(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + httpServer.createContext("/_nodes/http", new ResponseHandler(sniffTimeoutMillis, sniffResponse)); + return httpServer; + } + + private static class ResponseHandler implements HttpHandler { + private final int sniffTimeoutMillis; + private final SniffResponse sniffResponse; + + ResponseHandler(int sniffTimeoutMillis, SniffResponse sniffResponse) { + this.sniffTimeoutMillis = sniffTimeoutMillis; + this.sniffResponse = sniffResponse; + } + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + if (httpExchange.getRequestMethod().equals(HttpGet.METHOD_NAME)) { + if (httpExchange.getRequestURI().getRawQuery().equals("timeout=" + sniffTimeoutMillis + "ms")) { + String nodesInfoBody = sniffResponse.nodesInfoBody; + httpExchange.sendResponseHeaders(sniffResponse.nodesInfoResponseCode, nodesInfoBody.length()); + try (OutputStream out = httpExchange.getResponseBody()) { + out.write(nodesInfoBody.getBytes(StandardCharsets.UTF_8)); + return; + } + } + } + httpExchange.sendResponseHeaders(404, 0); + httpExchange.close(); + } + } + + private static SniffResponse buildSniffResponse(ElasticsearchNodesSniffer.Scheme scheme) throws IOException { + int numNodes = randomIntBetween(1, 5); + List nodes = new ArrayList<>(numNodes); + JsonFactory jsonFactory = new JsonFactory(); + StringWriter writer = new StringWriter(); + JsonGenerator generator = jsonFactory.createGenerator(writer); + generator.writeStartObject(); + if (getRandom().nextBoolean()) { + generator.writeStringField("cluster_name", "elasticsearch"); + } + if (getRandom().nextBoolean()) { + generator.writeObjectFieldStart("bogus_object"); + generator.writeEndObject(); + } + generator.writeObjectFieldStart("nodes"); + for (int i = 0; i < numNodes; i++) { + String nodeId = randomAsciiLettersOfLengthBetween(5, 10); + String host = "host" + i; + int port = randomIntBetween(9200, 9299); + HttpHost publishHost = new HttpHost( scheme.toString(), host, port); + Set boundHosts = new HashSet<>(); + boundHosts.add(publishHost); + + if (randomBoolean()) { + int bound = randomIntBetween(1, 5); + for (int b = 0; b < bound; b++) { + boundHosts.add(new HttpHost(scheme.toString(), host + b, port)); + } + } + + int numAttributes = randomIntBetween(0, 5); + Map> attributes = new HashMap<>(numAttributes); + for (int j = 0; j < numAttributes; j++) { + int numValues = frequently() ? 1 : randomIntBetween(2, 5); + List values = new ArrayList<>(); + for (int v = 0; v < numValues; v++) { + values.add(j + "value" + v); + } + attributes.put("attr" + j, values); + } + + final Set nodeRoles = new TreeSet<>(); + if (randomBoolean()) { + nodeRoles.add("master"); + } + if (randomBoolean()) { + nodeRoles.add("data"); + } + if (randomBoolean()) { + nodeRoles.add("data_content"); + } + if (randomBoolean()) { + nodeRoles.add("data_hot"); + } + if (randomBoolean()) { + nodeRoles.add("data_warm"); + } + if (randomBoolean()) { + nodeRoles.add("data_cold"); + } + if (randomBoolean()) { + nodeRoles.add("data_frozen"); + } + if (randomBoolean()) { + nodeRoles.add("ingest"); + } + + Node node = new Node( + publishHost, + boundHosts, + randomAsciiAlphanumOfLength(5), + randomAsciiAlphanumOfLength(5), + new Node.Roles(nodeRoles), + attributes + ); + + generator.writeObjectFieldStart(nodeId); + if (getRandom().nextBoolean()) { + generator.writeObjectFieldStart("bogus_object"); + generator.writeEndObject(); + } + if (getRandom().nextBoolean()) { + generator.writeArrayFieldStart("bogus_array"); + generator.writeStartObject(); + generator.writeEndObject(); + generator.writeEndArray(); + } + boolean isHttpEnabled = rarely() == false; + if (isHttpEnabled) { + nodes.add(node); + generator.writeObjectFieldStart("http"); + generator.writeArrayFieldStart("bound_address"); + for (HttpHost bound : boundHosts) { + generator.writeString(bound.toHostString()); + } + generator.writeEndArray(); + if (getRandom().nextBoolean()) { + generator.writeObjectFieldStart("bogus_object"); + generator.writeEndObject(); + } + generator.writeStringField("publish_address", publishHost.toHostString()); + if (getRandom().nextBoolean()) { + generator.writeNumberField("max_content_length_in_bytes", 104857600); + } + generator.writeEndObject(); + } + + List roles = Arrays.asList( + new String[] { "master", "data", "ingest", "data_content", "data_hot", "data_warm", "data_cold", "data_frozen" } + ); + Collections.shuffle(roles, getRandom()); + generator.writeArrayFieldStart("roles"); + for (String role : roles) { + if ("master".equals(role) && node.getRoles().isMasterEligible()) { + generator.writeString("master"); + } + if ("data".equals(role) && node.getRoles().hasDataRole()) { + generator.writeString("data"); + } + if ("data_content".equals(role) && node.getRoles().hasDataContentRole()) { + generator.writeString("data_content"); + } + if ("data_hot".equals(role) && node.getRoles().hasDataHotRole()) { + generator.writeString("data_hot"); + } + if ("data_warm".equals(role) && node.getRoles().hasDataWarmRole()) { + generator.writeString("data_warm"); + } + if ("data_cold".equals(role) && node.getRoles().hasDataColdRole()) { + generator.writeString("data_cold"); + } + if ("data_frozen".equals(role) && node.getRoles().hasDataFrozenRole()) { + generator.writeString("data_frozen"); + } + if ("ingest".equals(role) && node.getRoles().isIngest()) { + generator.writeString("ingest"); + } + } + generator.writeEndArray(); + + generator.writeFieldName("version"); + generator.writeString(node.getVersion()); + generator.writeFieldName("name"); + generator.writeString(node.getName()); + + if (numAttributes > 0) { + generator.writeObjectFieldStart("attributes"); + for (Map.Entry> entry : attributes.entrySet()) { + if (entry.getValue().size() == 1) { + generator.writeStringField(entry.getKey(), entry.getValue().get(0)); + } else { + for (int v = 0; v < entry.getValue().size(); v++) { + generator.writeStringField(entry.getKey() + "." + v, entry.getValue().get(v)); + } + } + } + generator.writeEndObject(); + } + generator.writeEndObject(); + } + generator.writeEndObject(); + generator.writeEndObject(); + generator.close(); + return SniffResponse.buildResponse(writer.toString(), nodes); + } + + private static class SniffResponse { + private final String nodesInfoBody; + private final int nodesInfoResponseCode; + private final List result; + private final boolean isFailure; + + SniffResponse(String nodesInfoBody, List result, boolean isFailure) { + this.nodesInfoBody = nodesInfoBody; + this.result = result; + this.isFailure = isFailure; + if (isFailure) { + this.nodesInfoResponseCode = randomErrorResponseCode(); + } else { + this.nodesInfoResponseCode = 200; + } + } + + static SniffResponse buildFailure() { + return new SniffResponse("", Collections.emptyList(), true); + } + + static SniffResponse buildResponse(String nodesInfoBody, List nodes) { + return new SniffResponse(nodesInfoBody, nodes, false); + } + } + + private static int randomErrorResponseCode() { + return randomIntBetween(400, 599); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/MockNodesSniffer.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/MockNodesSniffer.java new file mode 100644 index 000000000..8e54410d9 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/MockNodesSniffer.java @@ -0,0 +1,36 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level.sniffer; + +import co.elastic.clients.transport.rest5_client.low_level.Node; +import org.apache.hc.core5.http.HttpHost; + +import java.util.Collections; +import java.util.List; + +/** + * Mock implementation of {@link NodesSniffer}. Useful to prevent any connection attempt while testing builders etc. + */ +class MockNodesSniffer implements NodesSniffer { + @Override + public List sniff() { + return Collections.singletonList(new Node(new HttpHost("localhost", 9200))); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SniffOnFailureListenerTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SniffOnFailureListenerTests.java new file mode 100644 index 000000000..9f826cae4 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SniffOnFailureListenerTests.java @@ -0,0 +1,64 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level.sniffer; + +import co.elastic.clients.transport.rest5_client.low_level.Node; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; +import co.elastic.clients.transport.rest5_client.low_level.RestClientTestCase; +import org.apache.hc.core5.http.HttpHost; +import org.junit.jupiter.api.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class SniffOnFailureListenerTests extends RestClientTestCase { + + @Test + public void testSetSniffer() throws Exception { + SniffOnFailureListener listener = new SniffOnFailureListener(); + + try { + listener.onFailure(null); + fail("should have failed"); + } catch (IllegalStateException e) { + assertEquals("sniffer was not set, unable to sniff on failure", e.getMessage()); + } + + try { + listener.setSniffer(null); + fail("should have failed"); + } catch (NullPointerException e) { + assertEquals("sniffer must not be null", e.getMessage()); + } + + try (Rest5Client restClient = Rest5Client.builder(new HttpHost("localhost", 9200)).build()) { + try (Sniffer sniffer = Sniffer.builder(restClient).setNodesSniffer(new MockNodesSniffer()).build()) { + listener.setSniffer(sniffer); + try { + listener.setSniffer(sniffer); + fail("should have failed"); + } catch (IllegalStateException e) { + assertEquals("sniffer can only be set once", e.getMessage()); + } + listener.onFailure(new Node(new HttpHost("localhost", 9200))); + } + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SnifferBuilderTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SnifferBuilderTests.java new file mode 100644 index 000000000..3322b7f69 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SnifferBuilderTests.java @@ -0,0 +1,89 @@ +/* + * 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. + */ +package co.elastic.clients.transport.rest5_client.low_level.sniffer; + +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; +import co.elastic.clients.transport.rest5_client.low_level.RestClientTestCase; +import org.apache.hc.core5.http.HttpHost; +import org.junit.jupiter.api.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +public class SnifferBuilderTests extends RestClientTestCase { + + @Test + public void testBuild() throws Exception { + int numNodes = randomIntBetween(1, 5); + HttpHost[] hosts = new HttpHost[numNodes]; + for (int i = 0; i < numNodes; i++) { + hosts[i] = new HttpHost("localhost", 9200 + i); + } + + try (Rest5Client client = Rest5Client.builder(hosts).build()) { + try { + Sniffer.builder(null).build(); + fail("should have failed"); + } catch (NullPointerException e) { + assertEquals("restClient cannot be null", e.getMessage()); + } + + try { + Sniffer.builder(client).setSniffIntervalMillis(randomIntBetween(Integer.MIN_VALUE, 0)); + fail("should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("sniffIntervalMillis must be greater than 0", e.getMessage()); + } + + try { + Sniffer.builder(client).setSniffAfterFailureDelayMillis(randomIntBetween(Integer.MIN_VALUE, 0)); + fail("should have failed"); + } catch (IllegalArgumentException e) { + assertEquals("sniffAfterFailureDelayMillis must be greater than 0", e.getMessage()); + } + + try { + Sniffer.builder(client).setNodesSniffer(null); + fail("should have failed"); + } catch (NullPointerException e) { + assertEquals("nodesSniffer cannot be null", e.getMessage()); + } + + try (Sniffer sniffer = Sniffer.builder(client).build()) { + assertNotNull(sniffer); + } + + SnifferBuilder builder = Sniffer.builder(client); + if (getRandom().nextBoolean()) { + builder.setSniffIntervalMillis(randomIntBetween(1, Integer.MAX_VALUE)); + } + if (getRandom().nextBoolean()) { + builder.setSniffAfterFailureDelayMillis(randomIntBetween(1, Integer.MAX_VALUE)); + } + if (getRandom().nextBoolean()) { + builder.setNodesSniffer(new MockNodesSniffer()); + } + + try (Sniffer sniffer = builder.build()) { + assertNotNull(sniffer); + } + } + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SnifferTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SnifferTests.java new file mode 100644 index 000000000..11b22fa63 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SnifferTests.java @@ -0,0 +1,661 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level.sniffer; + +import co.elastic.clients.transport.rest5_client.low_level.Node; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; +import co.elastic.clients.transport.rest5_client.low_level.RestClientTestCase; +import org.apache.hc.core5.http.HttpHost; +import org.junit.jupiter.api.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyCollection; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +public class SnifferTests extends RestClientTestCase { + + /** + * Tests the {@link Sniffer#sniff()} method in isolation. Verifies that it uses the {@link NodesSniffer} implementation + * to retrieve nodes and set them (when not empty) to the provided {@link Rest5Client} instance. + */ + @Test + public void testSniff() throws IOException { + Node initialNode = new Node(new HttpHost("localhost", 9200)); + try (Rest5Client restClient = Rest5Client.builder(initialNode).build()) { + Sniffer.Scheduler noOpScheduler = new Sniffer.Scheduler() { + @Override + public Future schedule(Sniffer.Task task, long delayMillis) { + return mock(Future.class); + } + + @Override + public void shutdown() { + + } + }; + CountingNodesSniffer nodesSniffer = new CountingNodesSniffer(); + int iters = randomIntBetween(5, 30); + try (Sniffer sniffer = new Sniffer(restClient, nodesSniffer, noOpScheduler, 1000L, -1)) { + { + assertEquals(1, restClient.getNodes().size()); + Node node = restClient.getNodes().get(0); + assertEquals("localhost", node.getHost().getHostName()); + assertEquals(9200, node.getHost().getPort()); + } + int emptyList = 0; + int failures = 0; + int runs = 0; + List lastNodes = Collections.singletonList(initialNode); + for (int i = 0; i < iters; i++) { + try { + runs++; + sniffer.sniff(); + if (nodesSniffer.failures.get() > failures) { + failures++; + fail("should have failed given that nodesSniffer says it threw an exception"); + } else if (nodesSniffer.emptyList.get() > emptyList) { + emptyList++; + assertEquals(lastNodes, restClient.getNodes()); + } else { + assertNotEquals(lastNodes, restClient.getNodes()); + List expectedNodes = CountingNodesSniffer.buildNodes(runs); + assertEquals(expectedNodes, restClient.getNodes()); + lastNodes = restClient.getNodes(); + } + } catch (IOException e) { + if (nodesSniffer.failures.get() > failures) { + failures++; + assertEquals("communication breakdown", e.getMessage()); + } + } + } + assertEquals(nodesSniffer.emptyList.get(), emptyList); + assertEquals(nodesSniffer.failures.get(), failures); + assertEquals(nodesSniffer.runs.get(), runs); + } + } + } + + /** + * Test multiple sniffing rounds by mocking the {@link Sniffer.Scheduler} as well as the {@link NodesSniffer}. + * Simulates the ordinary behaviour of {@link Sniffer} when sniffing on failure is not enabled. + * The {@link CountingNodesSniffer} doesn't make any network connection but may throw exception or return no nodes, which makes + * it possible to verify that errors are properly handled and don't affect subsequent runs and their scheduling. + * The {@link Sniffer.Scheduler} implementation submits rather than scheduling tasks, meaning that it doesn't respect the requested sniff + * delays while allowing to assert that the requested delays for each requested run and the following one are the expected values. + */ + @Test + public void testOrdinarySniffRounds() throws Exception { + final long sniffInterval = randomLongBetween(1, Long.MAX_VALUE); + long sniffAfterFailureDelay = randomLongBetween(1, Long.MAX_VALUE); + Rest5Client restClient = mock(Rest5Client.class); + CountingNodesSniffer nodesSniffer = new CountingNodesSniffer(); + final int iters = randomIntBetween(30, 100); + final Set> futures = new CopyOnWriteArraySet<>(); + final CountDownLatch completionLatch = new CountDownLatch(1); + final AtomicInteger runs = new AtomicInteger(iters); + final ExecutorService executor = Executors.newSingleThreadExecutor(); + final AtomicReference> lastFuture = new AtomicReference<>(); + final AtomicReference lastTask = new AtomicReference<>(); + Sniffer.Scheduler scheduler = new Sniffer.Scheduler() { + @Override + public Future schedule(Sniffer.Task task, long delayMillis) { + assertEquals(sniffInterval, task.nextTaskDelay); + int numberOfRuns = runs.getAndDecrement(); + if (numberOfRuns == iters) { + // the first call is to schedule the first sniff round from the Sniffer constructor, with delay O + assertEquals(0L, delayMillis); + assertEquals(sniffInterval, task.nextTaskDelay); + } else { + // all of the subsequent times "schedule" is called with delay set to the configured sniff interval + assertEquals(sniffInterval, delayMillis); + assertEquals(sniffInterval, task.nextTaskDelay); + if (numberOfRuns == 0) { + completionLatch.countDown(); + return null; + } + } + // we submit rather than scheduling to make the test quick and not depend on time + Future future = executor.submit(task); + futures.add(future); + if (numberOfRuns == 1) { + lastFuture.set(future); + lastTask.set(task); + } + return future; + } + + @Override + public void shutdown() { + // the executor is closed externally, shutdown is tested separately + } + }; + try { + new Sniffer(restClient, nodesSniffer, scheduler, sniffInterval, sniffAfterFailureDelay); + assertTrue("timeout waiting for sniffing rounds to be completed", completionLatch.await(1000, TimeUnit.MILLISECONDS)); + assertEquals(iters, futures.size()); + // the last future is the only one that may not be completed yet, as the count down happens + // while scheduling the next round which is still part of the execution of the runnable itself. + assertTrue(lastTask.get().hasStarted()); + lastFuture.get().get(); + for (Future future : futures) { + assertTrue(future.isDone()); + future.get(); + } + } finally { + executor.shutdown(); + assertTrue(executor.awaitTermination(1000, TimeUnit.MILLISECONDS)); + } + int totalRuns = nodesSniffer.runs.get(); + assertEquals(iters, totalRuns); + int setNodesRuns = totalRuns - nodesSniffer.failures.get() - nodesSniffer.emptyList.get(); + verify(restClient, times(setNodesRuns)).setNodes(anyCollection()); + verifyNoMoreInteractions(restClient); + } + + /** + * Test that {@link Sniffer#close()} shuts down the underlying {@link Sniffer.Scheduler}, and that such calls are idempotent. + * Also verifies that the next scheduled round gets cancelled. + */ + @Test + public void testClose() { + final Future future = mock(Future.class); + long sniffInterval = randomLongBetween(1, Long.MAX_VALUE); + long sniffAfterFailureDelay = randomLongBetween(1, Long.MAX_VALUE); + Rest5Client restClient = mock(Rest5Client.class); + final AtomicInteger shutdown = new AtomicInteger(0); + final AtomicBoolean initialized = new AtomicBoolean(false); + Sniffer.Scheduler scheduler = new Sniffer.Scheduler() { + @Override + public Future schedule(Sniffer.Task task, long delayMillis) { + if (initialized.compareAndSet(false, true)) { + // run from the same thread so the sniffer gets for sure initialized and the scheduled task gets cancelled on close + task.run(); + } + return future; + } + + @Override + public void shutdown() { + shutdown.incrementAndGet(); + } + }; + + Sniffer sniffer = new Sniffer(restClient, new MockNodesSniffer(), scheduler, sniffInterval, sniffAfterFailureDelay); + assertEquals(0, shutdown.get()); + int iters = randomIntBetween(3, 10); + for (int i = 1; i <= iters; i++) { + sniffer.close(); + verify(future, times(i)).cancel(false); + assertEquals(i, shutdown.get()); + } + } + + @Test + public void testSniffOnFailureNotInitialized() { + Rest5Client restClient = mock(Rest5Client.class); + CountingNodesSniffer nodesSniffer = new CountingNodesSniffer(); + long sniffInterval = randomLongBetween(1, Long.MAX_VALUE); + long sniffAfterFailureDelay = randomLongBetween(1, Long.MAX_VALUE); + final AtomicInteger scheduleCalls = new AtomicInteger(0); + Sniffer.Scheduler scheduler = new Sniffer.Scheduler() { + @Override + public Future schedule(Sniffer.Task task, long delayMillis) { + scheduleCalls.incrementAndGet(); + return null; + } + + @Override + public void shutdown() {} + }; + + Sniffer sniffer = new Sniffer(restClient, nodesSniffer, scheduler, sniffInterval, sniffAfterFailureDelay); + for (int i = 0; i < 10; i++) { + sniffer.sniffOnFailure(); + } + assertEquals(1, scheduleCalls.get()); + int totalRuns = nodesSniffer.runs.get(); + assertEquals(0, totalRuns); + int setNodesRuns = totalRuns - nodesSniffer.failures.get() - nodesSniffer.emptyList.get(); + verify(restClient, times(setNodesRuns)).setNodes(anyCollection()); + verifyNoMoreInteractions(restClient); + } + + /** + * Test behaviour when a bunch of onFailure sniffing rounds are triggered in parallel. Each run will always + * schedule a subsequent afterFailure round. Also, for each onFailure round that starts, the net scheduled round + * (either afterFailure or ordinary) gets cancelled. + */ + @Test + public void testSniffOnFailure() throws Exception { + Rest5Client restClient = mock(Rest5Client.class); + CountingNodesSniffer nodesSniffer = new CountingNodesSniffer(); + final AtomicBoolean initializing = new AtomicBoolean(true); + final long sniffInterval = randomLongBetween(1, Long.MAX_VALUE); + final long sniffAfterFailureDelay = randomLongBetween(1, Long.MAX_VALUE); + int minNumOnFailureRounds = randomIntBetween(5, 10); + final CountDownLatch initializingLatch = new CountDownLatch(1); + final Set ordinaryRoundsTasks = new CopyOnWriteArraySet<>(); + final AtomicReference> initializingFuture = new AtomicReference<>(); + final Set onFailureTasks = new CopyOnWriteArraySet<>(); + final Set afterFailureTasks = new CopyOnWriteArraySet<>(); + final AtomicBoolean onFailureCompleted = new AtomicBoolean(false); + final CountDownLatch completionLatch = new CountDownLatch(1); + final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + try { + Sniffer.Scheduler scheduler = new Sniffer.Scheduler() { + @Override + public Future schedule(final Sniffer.Task task, long delayMillis) { + if (initializing.compareAndSet(true, false)) { + assertEquals(0L, delayMillis); + Future future = executor.submit(new Runnable() { + @Override + public void run() { + try { + task.run(); + } finally { + // we need to make sure that the sniffer is initialized, so the sniffOnFailure + // call does what it needs to do. Otherwise nothing happens until initialized. + initializingLatch.countDown(); + } + } + }); + assertTrue(initializingFuture.compareAndSet(null, future)); + return future; + } + if (delayMillis == 0L) { + Future future = executor.submit(task); + onFailureTasks.add(new Sniffer.ScheduledTask(task, future)); + return future; + } + if (delayMillis == sniffAfterFailureDelay) { + Future future = scheduleOrSubmit(task); + afterFailureTasks.add(new Sniffer.ScheduledTask(task, future)); + return future; + } + + assertEquals(sniffInterval, delayMillis); + assertEquals(sniffInterval, task.nextTaskDelay); + + if (onFailureCompleted.get() && onFailureTasks.size() == afterFailureTasks.size()) { + completionLatch.countDown(); + return mock(Future.class); + } + + Future future = scheduleOrSubmit(task); + ordinaryRoundsTasks.add(new Sniffer.ScheduledTask(task, future)); + return future; + } + + private Future scheduleOrSubmit(Sniffer.Task task) { + if (randomBoolean()) { + return executor.schedule(task, randomLongBetween(0L, 200L), TimeUnit.MILLISECONDS); + } else { + return executor.submit(task); + } + } + + @Override + public void shutdown() {} + }; + final Sniffer sniffer = new Sniffer(restClient, nodesSniffer, scheduler, sniffInterval, sniffAfterFailureDelay); + assertTrue("timeout waiting for sniffer to get initialized", initializingLatch.await(1000, TimeUnit.MILLISECONDS)); + + ExecutorService onFailureExecutor = Executors.newFixedThreadPool(randomIntBetween(5, 20)); + Set> onFailureFutures = new CopyOnWriteArraySet<>(); + try { + // with tasks executing quickly one after each other, it is very likely that the onFailure round gets skipped + // as another round is already running. We retry till enough runs get through as that's what we want to test. + while (onFailureTasks.size() < minNumOnFailureRounds) { + onFailureFutures.add(onFailureExecutor.submit(new Runnable() { + @Override + public void run() { + sniffer.sniffOnFailure(); + } + })); + } + assertThat(onFailureFutures.size(), greaterThanOrEqualTo(minNumOnFailureRounds)); + for (Future onFailureFuture : onFailureFutures) { + assertNull(onFailureFuture.get()); + } + onFailureCompleted.set(true); + } finally { + onFailureExecutor.shutdown(); + onFailureExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS); + } + + assertFalse(initializingFuture.get().isCancelled()); + assertTrue(initializingFuture.get().isDone()); + assertNull(initializingFuture.get().get()); + + assertTrue("timeout waiting for sniffing rounds to be completed", completionLatch.await(1000, TimeUnit.MILLISECONDS)); + assertThat(onFailureTasks.size(), greaterThanOrEqualTo(minNumOnFailureRounds)); + assertEquals(onFailureTasks.size(), afterFailureTasks.size()); + + for (Sniffer.ScheduledTask onFailureTask : onFailureTasks) { + assertFalse(onFailureTask.future.isCancelled()); + assertTrue(onFailureTask.future.isDone()); + assertNull(onFailureTask.future.get()); + assertTrue(onFailureTask.task.hasStarted()); + assertFalse(onFailureTask.task.isSkipped()); + } + + int cancelledTasks = 0; + int completedTasks = onFailureTasks.size() + 1; + for (Sniffer.ScheduledTask afterFailureTask : afterFailureTasks) { + if (assertTaskCancelledOrCompleted(afterFailureTask)) { + completedTasks++; + } else { + cancelledTasks++; + } + } + + assertThat(ordinaryRoundsTasks.size(), greaterThan(0)); + for (Sniffer.ScheduledTask task : ordinaryRoundsTasks) { + if (assertTaskCancelledOrCompleted(task)) { + completedTasks++; + } else { + cancelledTasks++; + } + } + assertEquals(onFailureTasks.size(), cancelledTasks); + + assertEquals(completedTasks, nodesSniffer.runs.get()); + int setNodesRuns = nodesSniffer.runs.get() - nodesSniffer.failures.get() - nodesSniffer.emptyList.get(); + verify(restClient, times(setNodesRuns)).setNodes(anyCollection()); + verifyNoMoreInteractions(restClient); + } finally { + executor.shutdown(); + executor.awaitTermination(1000L, TimeUnit.MILLISECONDS); + } + } + + private static boolean assertTaskCancelledOrCompleted(Sniffer.ScheduledTask task) throws ExecutionException, InterruptedException { + if (task.task.isSkipped()) { + assertTrue(task.future.isCancelled()); + try { + task.future.get(); + fail("cancellation exception should have been thrown"); + } catch (CancellationException ignore) {} + return false; + } else { + try { + assertNull(task.future.get()); + } catch (CancellationException ignore) { + assertTrue(task.future.isCancelled()); + } + assertTrue(task.future.isDone()); + assertTrue(task.task.hasStarted()); + return true; + } + } + + @Test + public void testTaskCancelling() throws Exception { + Rest5Client restClient = mock(Rest5Client.class); + NodesSniffer nodesSniffer = mock(NodesSniffer.class); + Sniffer.Scheduler noOpScheduler = new Sniffer.Scheduler() { + @Override + public Future schedule(Sniffer.Task task, long delayMillis) { + return null; + } + + @Override + public void shutdown() {} + }; + Sniffer sniffer = new Sniffer(restClient, nodesSniffer, noOpScheduler, 0L, 0L); + ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + try { + int numIters = randomIntBetween(50, 100); + for (int i = 0; i < numIters; i++) { + Sniffer.Task task = sniffer.new Task(0L); + TaskWrapper wrapper = new TaskWrapper(task); + Future future; + if (rarely()) { + future = executor.schedule(wrapper, randomLongBetween(0L, 200L), TimeUnit.MILLISECONDS); + } else { + future = executor.submit(wrapper); + } + Sniffer.ScheduledTask scheduledTask = new Sniffer.ScheduledTask(task, future); + boolean skip = scheduledTask.skip(); + try { + assertNull(future.get()); + } catch (CancellationException ignore) { + assertTrue(future.isCancelled()); + } + + if (skip) { + // the task was either cancelled before starting, in which case it will never start (thanks to Future#cancel), + // or skipped, in which case it will run but do nothing (thanks to Task#skip). + // Here we want to make sure that whenever skip returns true, the task either won't run or it won't do anything, + // otherwise we may end up with parallel sniffing tracks given that each task schedules the following one. We need to + // make sure that onFailure takes scheduling over while at the same time ordinary rounds don't go on. + assertFalse(task.hasStarted()); + assertTrue(task.isSkipped()); + assertTrue(future.isCancelled()); + assertTrue(future.isDone()); + } else { + // if a future is cancelled when its execution has already started, future#get throws CancellationException before + // completion. The execution continues though so we use a latch to try and wait for the task to be completed. + // Here we want to make sure that whenever skip returns false, the task will be completed, otherwise we may be + // missing to schedule the following round, which means no sniffing will ever happen again besides on failure sniffing. + assertTrue(wrapper.await()); + // the future may or may not be cancelled but the task has for sure started and completed + assertTrue(task.toString(), task.hasStarted()); + assertFalse(task.isSkipped()); + assertTrue(future.isDone()); + } + // subsequent cancel calls return false for sure + int cancelCalls = randomIntBetween(1, 10); + for (int j = 0; j < cancelCalls; j++) { + assertFalse(scheduledTask.skip()); + } + } + } finally { + executor.shutdown(); + executor.awaitTermination(1000, TimeUnit.MILLISECONDS); + } + } + + /** + * Wraps a {@link Sniffer.Task} and allows to wait for its completion. This is needed to verify + * that tasks are either never started or always completed. Calling {@link Future#get()} against a cancelled future will + * throw {@link CancellationException} straight-away but the execution of the task will continue if it had already started, + * in which case {@link Future#cancel(boolean)} returns true which is not very helpful. + */ + private static final class TaskWrapper implements Runnable { + final Sniffer.Task task; + final CountDownLatch completionLatch = new CountDownLatch(1); + + TaskWrapper(Sniffer.Task task) { + this.task = task; + } + + @Override + public void run() { + try { + task.run(); + } finally { + completionLatch.countDown(); + } + } + + boolean await() throws InterruptedException { + return completionLatch.await(1000, TimeUnit.MILLISECONDS); + } + } + + /** + * Mock {@link NodesSniffer} implementation used for testing, which most of the times return a fixed node. + * It rarely throws exception or return an empty list of nodes, to make sure that such situations are properly handled. + * It also asserts that it never gets called concurrently, based on the assumption that only one sniff run can be run + * at a given point in time. + */ + private static class CountingNodesSniffer implements NodesSniffer { + private final AtomicInteger runs = new AtomicInteger(0); + private final AtomicInteger failures = new AtomicInteger(0); + private final AtomicInteger emptyList = new AtomicInteger(0); + + @Override + public List sniff() throws IOException { + int run = runs.incrementAndGet(); + if (rarely()) { + failures.incrementAndGet(); + // check that if communication breaks, sniffer keeps on working + throw new IOException("communication breakdown"); + } + if (rarely()) { + emptyList.incrementAndGet(); + return Collections.emptyList(); + } + return buildNodes(run); + } + + private static List buildNodes(int run) { + int size = run % 5 + 1; + assert size > 0; + List nodes = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + nodes.add(new Node(new HttpHost("sniffed-" + run, 9200 + i))); + } + return nodes; + } + } + + @Test + public void testDefaultSchedulerSchedule() { + Rest5Client restClient = mock(Rest5Client.class); + NodesSniffer nodesSniffer = mock(NodesSniffer.class); + Sniffer.Scheduler noOpScheduler = new Sniffer.Scheduler() { + @Override + public Future schedule(Sniffer.Task task, long delayMillis) { + return mock(Future.class); + } + + @Override + public void shutdown() { + + } + }; + Sniffer sniffer = new Sniffer(restClient, nodesSniffer, noOpScheduler, 0L, 0L); + Sniffer.Task task = sniffer.new Task(randomLongBetween(1, Long.MAX_VALUE)); + + ScheduledExecutorService scheduledExecutorService = mock(ScheduledExecutorService.class); + final ScheduledFuture mockedFuture = mock(ScheduledFuture.class); + when(scheduledExecutorService.schedule(any(Runnable.class), any(Long.class), any(TimeUnit.class))).then( + new Answer>() { + @Override + public ScheduledFuture answer(InvocationOnMock invocationOnMock) { + return mockedFuture; + } + } + ); + Sniffer.DefaultScheduler scheduler = new Sniffer.DefaultScheduler(scheduledExecutorService); + long delay = randomLongBetween(1, Long.MAX_VALUE); + Future future = scheduler.schedule(task, delay); + assertSame(mockedFuture, future); + verify(scheduledExecutorService).schedule(task, delay, TimeUnit.MILLISECONDS); + verifyNoMoreInteractions(scheduledExecutorService, mockedFuture); + } + + @Test + public void testDefaultSchedulerThreadFactory() { + Sniffer.DefaultScheduler defaultScheduler = new Sniffer.DefaultScheduler(); + try { + ScheduledExecutorService executorService = defaultScheduler.executor; + assertThat(executorService, instanceOf(ScheduledThreadPoolExecutor.class)); + assertThat(executorService, instanceOf(ScheduledThreadPoolExecutor.class)); + ScheduledThreadPoolExecutor executor = (ScheduledThreadPoolExecutor) executorService; + assertTrue(executor.getRemoveOnCancelPolicy()); + assertFalse(executor.getContinueExistingPeriodicTasksAfterShutdownPolicy()); + assertTrue(executor.getExecuteExistingDelayedTasksAfterShutdownPolicy()); + assertThat(executor.getThreadFactory(), instanceOf(Sniffer.SnifferThreadFactory.class)); + int iters = randomIntBetween(3, 10); + for (int i = 1; i <= iters; i++) { + Thread thread = executor.getThreadFactory().newThread(new Runnable() { + @Override + public void run() { + + } + }); + assertThat(thread.getName(), equalTo("es_rest_client_sniffer[T#" + i + "]")); + assertThat(thread.isDaemon(), is(true)); + } + } finally { + defaultScheduler.shutdown(); + } + } + + @Test + public void testDefaultSchedulerShutdown() throws Exception { + ScheduledThreadPoolExecutor executor = mock(ScheduledThreadPoolExecutor.class); + Sniffer.DefaultScheduler defaultScheduler = new Sniffer.DefaultScheduler(executor); + defaultScheduler.shutdown(); + verify(executor).shutdown(); + verify(executor).awaitTermination(1000, TimeUnit.MILLISECONDS); + verify(executor).shutdownNow(); + verifyNoMoreInteractions(executor); + + when(executor.awaitTermination(1000, TimeUnit.MILLISECONDS)).thenReturn(true); + defaultScheduler.shutdown(); + verify(executor, times(2)).shutdown(); + verify(executor, times(2)).awaitTermination(1000, TimeUnit.MILLISECONDS); + verifyNoMoreInteractions(executor); + } +} diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/documentation/SnifferDocumentation.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/documentation/SnifferDocumentation.java new file mode 100644 index 000000000..995d16670 --- /dev/null +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/documentation/SnifferDocumentation.java @@ -0,0 +1,135 @@ +/* + * 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. + */ + +package co.elastic.clients.transport.rest5_client.low_level.sniffer.documentation; + +import org.apache.hc.core5.http.HttpHost; +import co.elastic.clients.transport.rest5_client.low_level.Node; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; +import co.elastic.clients.transport.rest5_client.low_level.sniffer.ElasticsearchNodesSniffer; +import co.elastic.clients.transport.rest5_client.low_level.sniffer.NodesSniffer; +import co.elastic.clients.transport.rest5_client.low_level.sniffer.SniffOnFailureListener; +import co.elastic.clients.transport.rest5_client.low_level.sniffer.Sniffer; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * This class is used to generate the Java low-level REST client documentation. + * You need to wrap your code between two tags like: + * // tag::example[] + * // end::example[] + * + * Where example is your tag name. + * + * Then in the documentation, you can extract what is between tag and end tags with + * ["source","java",subs="attributes,callouts,macros"] + * -------------------------------------------------- + * include-tagged::{doc-tests}/SnifferDocumentation.java[example] + * -------------------------------------------------- + * + * Note that this is not a test class as we are only interested in testing that docs snippets compile. We don't want + * to send requests to a node and we don't even have the tools to do it. + */ +@SuppressWarnings("unused") +public class SnifferDocumentation { + + @SuppressWarnings("unused") + public void usage() throws IOException, URISyntaxException { + { + //tag::sniffer-init + Rest5Client restClient = Rest5Client.builder( + HttpHost.create("http://localhost:9200")) + .build(); + Sniffer sniffer = Sniffer.builder(restClient).build(); + //end::sniffer-init + + //tag::sniffer-close + sniffer.close(); + restClient.close(); + //end::sniffer-close + } + { + //tag::sniffer-interval + Rest5Client restClient = Rest5Client.builder( + new HttpHost("localhost", 9200)) + .build(); + Sniffer sniffer = Sniffer.builder(restClient) + .setSniffIntervalMillis(60000).build(); + //end::sniffer-interval + } + { + //tag::sniff-on-failure + SniffOnFailureListener sniffOnFailureListener = + new SniffOnFailureListener(); + Rest5Client restClient = Rest5Client.builder( + new HttpHost("localhost", 9200)) + .setFailureListener(sniffOnFailureListener) // <1> + .build(); + Sniffer sniffer = Sniffer.builder(restClient) + .setSniffAfterFailureDelayMillis(30000) // <2> + .build(); + sniffOnFailureListener.setSniffer(sniffer); // <3> + //end::sniff-on-failure + } + { + //tag::sniffer-https + Rest5Client restClient = Rest5Client.builder( + new HttpHost("localhost", 9200)) + .build(); + NodesSniffer nodesSniffer = new ElasticsearchNodesSniffer( + restClient, + ElasticsearchNodesSniffer.DEFAULT_SNIFF_REQUEST_TIMEOUT, + ElasticsearchNodesSniffer.Scheme.HTTPS); + Sniffer sniffer = Sniffer.builder(restClient) + .setNodesSniffer(nodesSniffer).build(); + //end::sniffer-https + } + { + //tag::sniff-request-timeout + Rest5Client restClient = Rest5Client.builder( + new HttpHost("localhost", 9200)) + .build(); + NodesSniffer nodesSniffer = new ElasticsearchNodesSniffer( + restClient, + TimeUnit.SECONDS.toMillis(5), + ElasticsearchNodesSniffer.Scheme.HTTP); + Sniffer sniffer = Sniffer.builder(restClient) + .setNodesSniffer(nodesSniffer).build(); + //end::sniff-request-timeout + } + { + //tag::custom-nodes-sniffer + Rest5Client restClient = Rest5Client.builder( + HttpHost.create("http://localhost:9200")) + .build(); + NodesSniffer nodesSniffer = new NodesSniffer() { + @Override + public List sniff() throws IOException { + return null; // <1> + } + }; + Sniffer sniffer = Sniffer.builder(restClient) + .setNodesSniffer(nodesSniffer).build(); + //end::custom-nodes-sniffer + } + } +} diff --git a/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/2.0.0_nodes_http.json b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/2.0.0_nodes_http.json new file mode 100644 index 000000000..22dc4ec13 --- /dev/null +++ b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/2.0.0_nodes_http.json @@ -0,0 +1,201 @@ +{ + "cluster_name": "elasticsearch", + "nodes": { + "qr-SOrELSaGW8SlU8nflBw": { + "name": "m1", + "transport_address": "127.0.0.1:9300", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "2.0.0", + "build": "de54438", + "http_address": "127.0.0.1:9200", + "attributes": { + "dummy": "everyone_has_me", + "number": "1", + "array.0": "m", + "data": "false", + "array.1": "1", + "master": "true" + }, + "http": { + "bound_address": [ + "127.0.0.1:9200", + "[::1]:9200" + ], + "publish_address": "127.0.0.1:9200", + "max_content_length_in_bytes": 104857600 + } + }, + "osfiXxUOQzCVIs-eepgSCA": { + "name": "m2", + "transport_address": "127.0.0.1:9301", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "2.0.0", + "build": "de54438", + "http_address": "127.0.0.1:9201", + "attributes": { + "dummy": "everyone_has_me", + "number": "2", + "array.0": "m", + "array.1": "2", + "master": "true" + }, + "http": { + "bound_address": [ + "127.0.0.1:9201", + "[::1]:9201" + ], + "publish_address": "127.0.0.1:9201", + "max_content_length_in_bytes": 104857600 + } + }, + "lazeJFiIQ8eHHV4GeIdMPg": { + "name": "m3", + "transport_address": "127.0.0.1:9302", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "2.0.0", + "build": "de54438", + "http_address": "127.0.0.1:9202", + "attributes": { + "dummy": "everyone_has_me", + "number": "3", + "array.0": "m", + "data": "false", + "array.1": "3", + "master": "true" + }, + "http": { + "bound_address": [ + "127.0.0.1:9202", + "[::1]:9202" + ], + "publish_address": "127.0.0.1:9202", + "max_content_length_in_bytes": 104857600 + } + }, + "t9WxK-fNRsqV5G0Mm09KpQ": { + "name": "d1", + "transport_address": "127.0.0.1:9303", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "2.0.0", + "build": "de54438", + "http_address": "127.0.0.1:9203", + "attributes": { + "dummy": "everyone_has_me", + "number": "1", + "array.0": "d", + "array.1": "1", + "master": "false" + }, + "http": { + "bound_address": [ + "127.0.0.1:9203", + "[::1]:9203" + ], + "publish_address": "127.0.0.1:9203", + "max_content_length_in_bytes": 104857600 + } + }, + "wgoDzluvTViwUjEsmVesKw": { + "name": "d2", + "transport_address": "127.0.0.1:9304", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "2.0.0", + "build": "de54438", + "http_address": "127.0.0.1:9204", + "attributes": { + "dummy": "everyone_has_me", + "number": "2", + "array.0": "d", + "array.1": "2", + "master": "false" + }, + "http": { + "bound_address": [ + "127.0.0.1:9204", + "[::1]:9204" + ], + "publish_address": "127.0.0.1:9204", + "max_content_length_in_bytes": 104857600 + } + }, + "6j_t3pPhSm-oRTyypTzu5g": { + "name": "d3", + "transport_address": "127.0.0.1:9305", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "2.0.0", + "build": "de54438", + "http_address": "127.0.0.1:9205", + "attributes": { + "dummy": "everyone_has_me", + "number": "3", + "array.0": "d", + "array.1": "3", + "master": "false" + }, + "http": { + "bound_address": [ + "127.0.0.1:9205", + "[::1]:9205" + ], + "publish_address": "127.0.0.1:9205", + "max_content_length_in_bytes": 104857600 + } + }, + "PaEkm0z7Ssiuyfkh3aASag": { + "name": "c1", + "transport_address": "127.0.0.1:9306", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "2.0.0", + "build": "de54438", + "http_address": "127.0.0.1:9206", + "attributes": { + "dummy": "everyone_has_me", + "number": "1", + "array.0": "c", + "data": "false", + "array.1": "1", + "master": "false" + }, + "http": { + "bound_address": [ + "127.0.0.1:9206", + "[::1]:9206" + ], + "publish_address": "127.0.0.1:9206", + "max_content_length_in_bytes": 104857600 + } + }, + "LAFKr2K_QmupqnM_atJqkQ": { + "name": "c2", + "transport_address": "127.0.0.1:9307", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "2.0.0", + "build": "de54438", + "http_address": "127.0.0.1:9207", + "attributes": { + "dummy": "everyone_has_me", + "number": "2", + "array.0": "c", + "data": "false", + "array.1": "2", + "master": "false" + }, + "http": { + "bound_address": [ + "127.0.0.1:9207", + "[::1]:9207" + ], + "publish_address": "127.0.0.1:9207", + "max_content_length_in_bytes": 104857600 + } + } + } +} diff --git a/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/5.0.0_nodes_http.json b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/5.0.0_nodes_http.json new file mode 100644 index 000000000..135843823 --- /dev/null +++ b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/5.0.0_nodes_http.json @@ -0,0 +1,217 @@ +{ + "_nodes": { + "total": 8, + "successful": 8, + "failed": 0 + }, + "cluster_name": "elasticsearch", + "nodes": { + "0S4r3NurTYSFSb8R9SxwWA": { + "name": "m1", + "transport_address": "127.0.0.1:9300", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "5.0.0", + "build_hash": "253032b", + "roles": [ + "master", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "1", + "array.0": "m", + "array.1": "1" + }, + "http": { + "bound_address": [ + "[::1]:9200", + "127.0.0.1:9200" + ], + "publish_address": "127.0.0.1:9200", + "max_content_length_in_bytes": 104857600 + } + }, + "k_CBrMXARkS57Qb5-3Mw5g": { + "name": "m2", + "transport_address": "127.0.0.1:9301", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "5.0.0", + "build_hash": "253032b", + "roles": [ + "master", + "data", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "2", + "array.0": "m", + "array.1": "2" + }, + "http": { + "bound_address": [ + "[::1]:9201", + "127.0.0.1:9201" + ], + "publish_address": "127.0.0.1:9201", + "max_content_length_in_bytes": 104857600 + } + }, + "6eynRPQ1RleJTeGDuTR9mw": { + "name": "m3", + "transport_address": "127.0.0.1:9302", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "5.0.0", + "build_hash": "253032b", + "roles": [ + "master", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "3", + "array.0": "m", + "array.1": "3" + }, + "http": { + "bound_address": [ + "[::1]:9202", + "127.0.0.1:9202" + ], + "publish_address": "127.0.0.1:9202", + "max_content_length_in_bytes": 104857600 + } + }, + "cbGC-ay1QNWaESvEh5513w": { + "name": "d1", + "transport_address": "127.0.0.1:9303", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "5.0.0", + "build_hash": "253032b", + "roles": [ + "data", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "1", + "array.0": "d", + "array.1": "1" + }, + "http": { + "bound_address": [ + "[::1]:9203", + "127.0.0.1:9203" + ], + "publish_address": "127.0.0.1:9203", + "max_content_length_in_bytes": 104857600 + } + }, + "LexndPpXR2ytYsU5fTElnQ": { + "name": "d2", + "transport_address": "127.0.0.1:9304", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "5.0.0", + "build_hash": "253032b", + "roles": [ + "data", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "2", + "array.0": "d", + "array.1": "2" + }, + "http": { + "bound_address": [ + "[::1]:9204", + "127.0.0.1:9204" + ], + "publish_address": "127.0.0.1:9204", + "max_content_length_in_bytes": 104857600 + } + }, + "SbNG1DKYSBu20zfOz2gDZQ": { + "name": "d3", + "transport_address": "127.0.0.1:9305", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "5.0.0", + "build_hash": "253032b", + "roles": [ + "data", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "3", + "array.0": "d", + "array.1": "3" + }, + "http": { + "bound_address": [ + "[::1]:9205", + "127.0.0.1:9205" + ], + "publish_address": "127.0.0.1:9205", + "max_content_length_in_bytes": 104857600 + } + }, + "fM4H-m2WTDWmsGsL7jIJew": { + "name": "c1", + "transport_address": "127.0.0.1:9306", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "5.0.0", + "build_hash": "253032b", + "roles": [ + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "1", + "array.0": "c", + "array.1": "1" + }, + "http": { + "bound_address": [ + "[::1]:9206", + "127.0.0.1:9206" + ], + "publish_address": "127.0.0.1:9206", + "max_content_length_in_bytes": 104857600 + } + }, + "pFoh7d0BTbqqI3HKd9na5A": { + "name": "c2", + "transport_address": "127.0.0.1:9307", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "5.0.0", + "build_hash": "253032b", + "roles": [ + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "2", + "array.0": "c", + "array.1": "2" + }, + "http": { + "bound_address": [ + "[::1]:9207", + "127.0.0.1:9207" + ], + "publish_address": "127.0.0.1:9207", + "max_content_length_in_bytes": 104857600 + } + } + } +} diff --git a/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/6.0.0_nodes_http.json b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/6.0.0_nodes_http.json new file mode 100644 index 000000000..f0535dfdf --- /dev/null +++ b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/6.0.0_nodes_http.json @@ -0,0 +1,217 @@ +{ + "_nodes": { + "total": 8, + "successful": 8, + "failed": 0 + }, + "cluster_name": "elasticsearch", + "nodes": { + "ikXK_skVTfWkhONhldnbkw": { + "name": "m1", + "transport_address": "127.0.0.1:9300", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "6.0.0", + "build_hash": "8f0685b", + "roles": [ + "master", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "1", + "array.0": "m", + "array.1": "1" + }, + "http": { + "bound_address": [ + "[::1]:9200", + "127.0.0.1:9200" + ], + "publish_address": "127.0.0.1:9200", + "max_content_length_in_bytes": 104857600 + } + }, + "TMHa34w4RqeuYoHCfJGXZg": { + "name": "m2", + "transport_address": "127.0.0.1:9301", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "6.0.0", + "build_hash": "8f0685b", + "roles": [ + "master", + "data", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "2", + "array.0": "m", + "array.1": "2" + }, + "http": { + "bound_address": [ + "[::1]:9201", + "127.0.0.1:9201" + ], + "publish_address": "127.0.0.1:9201", + "max_content_length_in_bytes": 104857600 + } + }, + "lzaMRJTVT166sgVZdQ5thA": { + "name": "m3", + "transport_address": "127.0.0.1:9302", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "6.0.0", + "build_hash": "8f0685b", + "roles": [ + "master", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "3", + "array.0": "m", + "array.1": "3" + }, + "http": { + "bound_address": [ + "[::1]:9202", + "127.0.0.1:9202" + ], + "publish_address": "127.0.0.1:9202", + "max_content_length_in_bytes": 104857600 + } + }, + "tGP5sUecSd6BLTWk1NWF8Q": { + "name": "d1", + "transport_address": "127.0.0.1:9303", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "6.0.0", + "build_hash": "8f0685b", + "roles": [ + "data", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "1", + "array.0": "d", + "array.1": "1" + }, + "http": { + "bound_address": [ + "[::1]:9203", + "127.0.0.1:9203" + ], + "publish_address": "127.0.0.1:9203", + "max_content_length_in_bytes": 104857600 + } + }, + "c1UgW5ROTkSa2YnM_T56tw": { + "name": "d2", + "transport_address": "127.0.0.1:9304", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "6.0.0", + "build_hash": "8f0685b", + "roles": [ + "data", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "2", + "array.0": "d", + "array.1": "2" + }, + "http": { + "bound_address": [ + "[::1]:9204", + "127.0.0.1:9204" + ], + "publish_address": "127.0.0.1:9204", + "max_content_length_in_bytes": 104857600 + } + }, + "QM9yjqjmS72MstpNYV_trg": { + "name": "d3", + "transport_address": "127.0.0.1:9305", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "6.0.0", + "build_hash": "8f0685b", + "roles": [ + "data", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "3", + "array.0": "d", + "array.1": "3" + }, + "http": { + "bound_address": [ + "[::1]:9205", + "127.0.0.1:9205" + ], + "publish_address": "127.0.0.1:9205", + "max_content_length_in_bytes": 104857600 + } + }, + "wLtzAssoQYeX_4TstgCj0Q": { + "name": "c1", + "transport_address": "127.0.0.1:9306", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "6.0.0", + "build_hash": "8f0685b", + "roles": [ + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "1", + "array.0": "c", + "array.1": "1" + }, + "http": { + "bound_address": [ + "[::1]:9206", + "127.0.0.1:9206" + ], + "publish_address": "127.0.0.1:9206", + "max_content_length_in_bytes": 104857600 + } + }, + "ONOzpst8TH-ZebG7fxGwaA": { + "name": "c2", + "transport_address": "127.0.0.1:9307", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "6.0.0", + "build_hash": "8f0685b", + "roles": [ + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "2", + "array.0": "c", + "array.1": "2" + }, + "http": { + "bound_address": [ + "[::1]:9207", + "127.0.0.1:9207" + ], + "publish_address": "127.0.0.1:9207", + "max_content_length_in_bytes": 104857600 + } + } + } +} diff --git a/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/7.3.0_nodes_http.json b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/7.3.0_nodes_http.json new file mode 100644 index 000000000..893aa4885 --- /dev/null +++ b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/7.3.0_nodes_http.json @@ -0,0 +1,218 @@ +{ + "_nodes": { + "total": 8, + "successful": 8, + "failed": 0 + }, + "cluster_name": "elasticsearch", + "nodes": { + "ikXK_skVTfWkhONhldnbkw": { + "name": "m1", + "transport_address": "127.0.0.1:9300", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "7.3.0", + "build_hash": "8f0685b", + "roles": [ + "master", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "1", + "array.0": "m", + "array.1": "1" + }, + "http": { + "bound_address": [ + "[::1]:9200", + "127.0.0.1:9200" + ], + "publish_address": "127.0.0.1:9200", + "max_content_length_in_bytes": 104857600 + } + }, + "TMHa34w4RqeuYoHCfJGXZg": { + "name": "m2", + "transport_address": "127.0.0.1:9301", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "7.3.0", + "build_hash": "8f0685b", + "roles": [ + "master", + "data", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "2", + "array.0": "m", + "array.1": "2" + }, + "http": { + "bound_address": [ + "[::1]:9201", + "127.0.0.1:9201" + ], + "publish_address": "127.0.0.1:9201", + "max_content_length_in_bytes": 104857600 + } + }, + "lzaMRJTVT166sgVZdQ5thA": { + "name": "m3", + "transport_address": "127.0.0.1:9302", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "7.3.0", + "build_hash": "8f0685b", + "roles": [ + "master", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "3", + "array.0": "m", + "array.1": "3" + }, + "http": { + "bound_address": [ + "[::1]:9202", + "127.0.0.1:9202" + ], + "publish_address": "127.0.0.1:9202", + "max_content_length_in_bytes": 104857600 + } + }, + "tGP5sUecSd6BLTWk1NWF8Q": { + "name": "d1", + "transport_address": "127.0.0.1:9303", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "7.3.0", + "build_hash": "8f0685b", + "roles": [ + "data", + "ingest", + "ml" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "1", + "array.0": "d", + "array.1": "1" + }, + "http": { + "bound_address": [ + "[::1]:9203", + "127.0.0.1:9203" + ], + "publish_address": "127.0.0.1:9203", + "max_content_length_in_bytes": 104857600 + } + }, + "c1UgW5ROTkSa2YnM_T56tw": { + "name": "d2", + "transport_address": "127.0.0.1:9304", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "7.3.0", + "build_hash": "8f0685b", + "roles": [ + "data", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "2", + "array.0": "d", + "array.1": "2" + }, + "http": { + "bound_address": [ + "[::1]:9204", + "127.0.0.1:9204" + ], + "publish_address": "127.0.0.1:9204", + "max_content_length_in_bytes": 104857600 + } + }, + "QM9yjqjmS72MstpNYV_trg": { + "name": "d3", + "transport_address": "127.0.0.1:9305", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "7.3.0", + "build_hash": "8f0685b", + "roles": [ + "data", + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "3", + "array.0": "d", + "array.1": "3" + }, + "http": { + "bound_address": [ + "[::1]:9205", + "127.0.0.1:9205" + ], + "publish_address": "127.0.0.1:9205", + "max_content_length_in_bytes": 104857600 + } + }, + "wLtzAssoQYeX_4TstgCj0Q": { + "name": "c1", + "transport_address": "127.0.0.1:9306", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "7.3.0", + "build_hash": "8f0685b", + "roles": [ + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "1", + "array.0": "c", + "array.1": "1" + }, + "http": { + "bound_address": [ + "[::1]:9206", + "127.0.0.1:9206" + ], + "publish_address": "127.0.0.1:9206", + "max_content_length_in_bytes": 104857600 + } + }, + "ONOzpst8TH-ZebG7fxGwaA": { + "name": "c2", + "transport_address": "127.0.0.1:9307", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "7.3.0", + "build_hash": "8f0685b", + "roles": [ + "ingest" + ], + "attributes": { + "dummy": "everyone_has_me", + "number": "2", + "array.0": "c", + "array.1": "2" + }, + "http": { + "bound_address": [ + "[::1]:9207", + "127.0.0.1:9207" + ], + "publish_address": "127.0.0.1:9207", + "max_content_length_in_bytes": 104857600 + } + } + } +} diff --git a/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/create_test_nodes_info.bash b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/create_test_nodes_info.bash new file mode 100644 index 000000000..aa20ddffc --- /dev/null +++ b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/create_test_nodes_info.bash @@ -0,0 +1,107 @@ +#!/bin/bash + +# Recreates the v_nodes_http.json files in this directory. This is +# meant to be an "every once in a while" thing that we do only when +# we want to add a new version of Elasticsearch or configure the +# nodes differently. That is why we don't do this in gradle. It also +# allows us to play fast and loose with error handling. If something +# goes wrong you have to manually clean up which is good because it +# leaves around the kinds of things that we need to debug the failure. + +# I built this file so the next time I have to regenerate these +# v_nodes_http.json files I won't have to reconfigure Elasticsearch +# from scratch. While I was at it I took the time to make sure that +# when we do rebuild the files they don't jump around too much. That +# way the diffs are smaller. + +set -e + +script_path="$( cd "$(dirname "$0")" ; pwd -P )" +work=$(mktemp -d) +pushd ${work} >> /dev/null +echo Working in ${work} + +wget https://download.elasticsearch.org/elasticsearch/release/org/elasticsearch/distribution/tar/elasticsearch/2.0.0/elasticsearch-2.0.0.tar.gz +wget https://artifacts-no-kpi.elastic.co/downloads/elasticsearch/elasticsearch-5.0.0.tar.gz +wget https://artifacts-no-kpi.elastic.co/downloads/elasticsearch/elasticsearch-6.0.0.tar.gz +sha1sum -c - << __SHAs +e369d8579bd3a2e8b5344278d5043f19f14cac88 elasticsearch-2.0.0.tar.gz +d25f6547bccec9f0b5ea7583815f96a6f50849e0 elasticsearch-5.0.0.tar.gz +__SHAs +sha512sum -c - << __SHAs +25bb622d2fc557d8b8eded634a9b333766f7b58e701359e1bcfafee390776eb323cb7ea7a5e02e8803e25d8b1d3aabec0ec1b0cf492d0bab5689686fe440181c elasticsearch-6.0.0.tar.gz +__SHAs + + +function do_version() { + local version=$1 + local nodes='m1 m2 m3 d1 d2 d3 c1 c2' + rm -rf ${version} + mkdir -p ${version} + pushd ${version} >> /dev/null + + tar xf ../elasticsearch-${version}.tar.gz + local http_port=9200 + for node in ${nodes}; do + mkdir ${node} + cp -r elasticsearch-${version}/* ${node} + local master=$([[ "$node" =~ ^m.* ]] && echo true || echo false) + local data=$([[ "$node" =~ ^d.* ]] && echo true || echo false) + # m2 is always master and data for these test just so we have a node like that + data=$([[ "$node" == 'm2' ]] && echo true || echo ${data}) + local attr=$([ ${version} == '2.0.0' ] && echo '' || echo '.attr') + local transport_port=$((http_port+100)) + + cat >> ${node}/config/elasticsearch.yml << __ES_YML +node.name: ${node} +node.master: ${master} +node.data: ${data} +node${attr}.dummy: everyone_has_me +node${attr}.number: ${node:1} +node${attr}.array: [${node:0:1}, ${node:1}] +http.port: ${http_port} +transport.tcp.port: ${transport_port} +discovery.zen.minimum_master_nodes: 3 +discovery.zen.ping.unicast.hosts: ['localhost:9300','localhost:9301','localhost:9302'] +__ES_YML + + if [ ${version} != '2.0.0' ]; then + perl -pi -e 's/-Xm([sx]).+/-Xm${1}512m/g' ${node}/config/jvm.options + fi + + echo "starting ${version}/${node}..." + ${node}/bin/elasticsearch -d -p ${node}/pidfile + + ((http_port++)) + done + + echo "waiting for cluster to form" + # got to wait for all the nodes + until curl -s localhost:9200; do + sleep .25 + done + + echo "waiting for all nodes to join" + until [ $(echo ${nodes} | wc -w) -eq $(curl -s localhost:9200/_cat/nodes | wc -l) ]; do + sleep .25 + done + + # jq sorts the nodes by their http host so the file doesn't jump around when we regenerate it + curl -s localhost:9200/_nodes/http?pretty \ + | jq '[to_entries[] | ( select(.key == "nodes").value|to_entries|sort_by(.value.http.publish_address)|from_entries|{"key": "nodes", "value": .} ) // .] | from_entries' \ + > ${script_path}/${version}_nodes_http.json + + for node in ${nodes}; do + echo "stopping ${version}/${node}..." + kill $(cat ${node}/pidfile) + done + + popd >> /dev/null +} + +JAVA_HOME=$JAVA8_HOME do_version 2.0.0 +JAVA_HOME=$JAVA8_HOME do_version 5.0.0 +JAVA_HOME=$JAVA8_HOME do_version 6.0.0 + +popd >> /dev/null +rm -rf ${work} diff --git a/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/es6_nodes_publication_address_format.json b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/es6_nodes_publication_address_format.json new file mode 100644 index 000000000..7ded043b8 --- /dev/null +++ b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/es6_nodes_publication_address_format.json @@ -0,0 +1,30 @@ +{ + "_nodes": { + "total": 8, + "successful": 8, + "failed": 0 + }, + "cluster_name": "elasticsearch", + "nodes": { + "ikXK_skVTfWkhONhldnbkw": { + "name": "m1", + "transport_address": "127.0.0.1:9300", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "6.0.0", + "build_hash": "8f0685b", + "roles": [ + "master", + "ingest" + ], + "attributes": { }, + "http": { + "bound_address": [ + "127.0.0.1:9200" + ], + "publish_address": "127.0.0.1:9200", + "max_content_length_in_bytes": 104857600 + } + } + } +} diff --git a/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/es7_nodes_publication_address_format.json b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/es7_nodes_publication_address_format.json new file mode 100644 index 000000000..295bf3cbd --- /dev/null +++ b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/es7_nodes_publication_address_format.json @@ -0,0 +1,30 @@ +{ + "_nodes": { + "total": 8, + "successful": 8, + "failed": 0 + }, + "cluster_name": "elasticsearch", + "nodes": { + "ikXK_skVTfWkhONhldnbkw": { + "name": "m1", + "transport_address": "127.0.0.1:9300", + "host": "127.0.0.1", + "ip": "127.0.0.1", + "version": "6.0.0", + "build_hash": "8f0685b", + "roles": [ + "master", + "ingest" + ], + "attributes": { }, + "http": { + "bound_address": [ + "elastic.test:9200" + ], + "publish_address": "elastic.test/127.0.0.1:9200", + "max_content_length_in_bytes": 104857600 + } + } + } +} diff --git a/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/readme.txt b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/readme.txt new file mode 100644 index 000000000..c6dd32a04 --- /dev/null +++ b/java-client/src/test/resources/co/elastic/clients/transport/rest5_client/low_level/sniffer/readme.txt @@ -0,0 +1,6 @@ +`*_node_http.json` contains files created by spinning up toy clusters with a +few nodes in different configurations locally at various versions. They are +for testing `ElasticsearchNodesSniffer` against different versions of +Elasticsearch. + +See create_test_nodes_info.bash for how to create these. From c1a8656de9b0e96d2b15d88ca01530cf1d0bead8 Mon Sep 17 00:00:00 2001 From: Sylvain Wallez Date: Sun, 30 Mar 2025 11:28:25 +0200 Subject: [PATCH 30/38] Move Node back to its original location. TransportHttpClient is self-contained --- .../elastic/clients/transport/http/Node.java | 132 ------------------ .../http/RepeatableBodyResponse.java | 2 +- .../transport/http/TransportHttpClient.java | 109 +++++++++++++++ .../rest5_client/Rest5ClientHttpClient.java | 1 - .../rest_client/RestClientHttpClient.java | 1 - .../clients/testkit/MockHttpClient.java | 1 - .../endpoints/SimpleEndpointTest.java | 1 - 7 files changed, 110 insertions(+), 137 deletions(-) delete mode 100644 java-client/src/main/java/co/elastic/clients/transport/http/Node.java diff --git a/java-client/src/main/java/co/elastic/clients/transport/http/Node.java b/java-client/src/main/java/co/elastic/clients/transport/http/Node.java deleted file mode 100644 index 1299df277..000000000 --- a/java-client/src/main/java/co/elastic/clients/transport/http/Node.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport.http; - -import javax.annotation.Nullable; -import java.net.URI; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -/** - * A node/host to send requests to. - */ -public class Node { - private final URI uri; - private final String name; - private final String version; - private final Set roles; - private final Map attributes; - - /** - * Create a node with its URI, roles and attributes. - *

- * If the URI doesn't end with a '{@code /}', then one is added. - * - * @param uri the node's URI - * @param name the node name/identifier - * @param version the node's version, if known - * @param roles the node's roles, such as "master", "ingest", etc. - * @param attributes the node's attributes. This can be used for routing decisions by multi-node implementations. - */ - public Node( - URI uri, - @Nullable String name, - @Nullable String version, - @Nullable Set roles, - @Nullable Map attributes - ) { - - if (!uri.isAbsolute()) { - throw new IllegalArgumentException("Node URIs must be absolute: " + uri); - } - - if (!uri.getRawPath().endsWith("/")) { - uri = uri.resolve(uri.getRawPath() + "/"); - } - - this.uri = uri; - this.name = name; - this.version = version; - this.roles = roles; - this.attributes = attributes; - } - - public Node(URI uri) { - this(uri, null, null, null, null); - } - - public Node(String uri) { - this(URI.create(uri), null, null, null, null); - } - - /** - * The URI of this node. This is an absolute URL with a path ending with a "/". - */ - public URI uri() { - return this.uri; - } - - /** - * The node name/identifier - */ - @Nullable - public String name() { - return name; - } - - @Nullable - public String version() { - return version; - } - - @Nullable - public Set roles() { - return roles; - } - - @Nullable - public Map attributes() { - return attributes; - } - - @Override - public String toString() { - return uri.toString(); - } - - /** - * Two nodes are considered equal if their URIs are equal. Other properties are ignored. - */ - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Node node)) return false; - return Objects.equals(uri, node.uri); - } - - /** - * A node's hash code is that of its URI. Other properties are ignored. - */ - @Override - public int hashCode() { - return Objects.hash(uri); - } -} diff --git a/java-client/src/main/java/co/elastic/clients/transport/http/RepeatableBodyResponse.java b/java-client/src/main/java/co/elastic/clients/transport/http/RepeatableBodyResponse.java index 708499a3f..d578cdcec 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/http/RepeatableBodyResponse.java +++ b/java-client/src/main/java/co/elastic/clients/transport/http/RepeatableBodyResponse.java @@ -45,7 +45,7 @@ public RepeatableBodyResponse(TransportHttpClient.Response response) throws IOEx } @Override - public Node node() { + public TransportHttpClient.Node node() { return response.node(); } diff --git a/java-client/src/main/java/co/elastic/clients/transport/http/TransportHttpClient.java b/java-client/src/main/java/co/elastic/clients/transport/http/TransportHttpClient.java index 677ddfd22..4a8b3ffa3 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/http/TransportHttpClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/http/TransportHttpClient.java @@ -26,9 +26,12 @@ import javax.annotation.Nullable; import java.io.Closeable; import java.io.IOException; +import java.net.URI; import java.nio.ByteBuffer; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.Set; import java.util.concurrent.CompletableFuture; /** @@ -182,4 +185,110 @@ interface Response extends Closeable { */ void close() throws IOException; } + + /** + * A node/host to send requests to. + */ + class Node { + private final URI uri; + private final String name; + private final String version; + private final Set roles; + private final Map attributes; + + /** + * Create a node with its URI, roles and attributes. + *

+ * If the URI doesn't end with a '{@code /}', then one is added. + * + * @param uri the node's URI + * @param name the node name/identifier + * @param version the node's version, if known + * @param roles the node's roles, such as "master", "ingest", etc. + * @param attributes the node's attributes. This can be used for routing decisions by multi-node implementations. + */ + public Node( + URI uri, + @Nullable String name, + @Nullable String version, + @Nullable Set roles, + @Nullable Map attributes + ) { + + if (!uri.isAbsolute()) { + throw new IllegalArgumentException("Node URIs must be absolute: " + uri); + } + + if (!uri.getRawPath().endsWith("/")) { + uri = uri.resolve(uri.getRawPath() + "/"); + } + + this.uri = uri; + this.name = name; + this.version = version; + this.roles = roles; + this.attributes = attributes; + } + + public Node(URI uri) { + this(uri, null, null, null, null); + } + + public Node(String uri) { + this(URI.create(uri), null, null, null, null); + } + + /** + * The URI of this node. This is an absolute URL with a path ending with a "/". + */ + public URI uri() { + return this.uri; + } + + /** + * The node name/identifier + */ + @Nullable + public String name() { + return name; + } + + @Nullable + public String version() { + return version; + } + + @Nullable + public Set roles() { + return roles; + } + + @Nullable + public Map attributes() { + return attributes; + } + + @Override + public String toString() { + return uri.toString(); + } + + /** + * Two nodes are considered equal if their URIs are equal. Other properties are ignored. + */ + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Node node)) return false; + return Objects.equals(uri, node.uri); + } + + /** + * A node's hash code is that of its URI. Other properties are ignored. + */ + @Override + public int hashCode() { + return Objects.hash(uri); + } + } } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java index 3cbf1722c..a8649fe65 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientHttpClient.java @@ -21,7 +21,6 @@ import co.elastic.clients.transport.TransportOptions; import co.elastic.clients.transport.http.HeaderMap; -import co.elastic.clients.transport.http.Node; import co.elastic.clients.transport.http.TransportHttpClient; import co.elastic.clients.transport.rest5_client.low_level.Cancellable; import co.elastic.clients.transport.rest5_client.low_level.ResponseListener; diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java index d0e4d3393..85b92c107 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientHttpClient.java @@ -21,7 +21,6 @@ import co.elastic.clients.transport.TransportOptions; import co.elastic.clients.transport.http.HeaderMap; -import co.elastic.clients.transport.http.Node; import co.elastic.clients.transport.http.TransportHttpClient; import co.elastic.clients.util.BinaryData; import co.elastic.clients.util.NoCopyByteArrayOutputStream; diff --git a/java-client/src/test/java/co/elastic/clients/testkit/MockHttpClient.java b/java-client/src/test/java/co/elastic/clients/testkit/MockHttpClient.java index 4ab3269d4..a54c8c876 100644 --- a/java-client/src/test/java/co/elastic/clients/testkit/MockHttpClient.java +++ b/java-client/src/test/java/co/elastic/clients/testkit/MockHttpClient.java @@ -24,7 +24,6 @@ import co.elastic.clients.transport.ElasticsearchTransportBase; import co.elastic.clients.transport.TransportException; import co.elastic.clients.transport.TransportOptions; -import co.elastic.clients.transport.http.Node; import co.elastic.clients.transport.http.TransportHttpClient; import co.elastic.clients.util.BinaryData; import org.jetbrains.annotations.Nullable; diff --git a/java-client/src/test/java/co/elastic/clients/transport/endpoints/SimpleEndpointTest.java b/java-client/src/test/java/co/elastic/clients/transport/endpoints/SimpleEndpointTest.java index 6bff41f28..263e94ac8 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/endpoints/SimpleEndpointTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/endpoints/SimpleEndpointTest.java @@ -26,7 +26,6 @@ import co.elastic.clients.transport.ElasticsearchTransport; import co.elastic.clients.transport.ElasticsearchTransportBase; import co.elastic.clients.transport.TransportOptions; -import co.elastic.clients.transport.http.Node; import co.elastic.clients.transport.http.TransportHttpClient; import org.jetbrains.annotations.Nullable; import org.junit.jupiter.api.Test; From 6304e32835ccb3f1540bb79087f785ecb8430a44 Mon Sep 17 00:00:00 2001 From: Sylvain Wallez Date: Sun, 30 Mar 2025 19:22:53 +0200 Subject: [PATCH 31/38] Refactor client builder to transport configuration --- .../ElasticsearchAsyncClient.java | 17 +- .../elasticsearch/ElasticsearchClient.java | 15 +- .../ElasticsearchClientBuilderBase.java | 276 ------------------ .../ElasticsearchTransportConfig.java | 236 +++++++++++++++ .../rest5_client/Rest5ClientTransport.java | 46 +++ .../rest_client/RestClientTransport.java | 48 +++ .../ElasticsearchTestClient.java | 67 ++--- .../ElasticsearchTransportConfigTest.java} | 12 +- .../low_level/sniffer/SnifferTests.java | 5 +- 9 files changed, 376 insertions(+), 346 deletions(-) delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilderBase.java create mode 100644 java-client/src/main/java/co/elastic/clients/transport/ElasticsearchTransportConfig.java rename java-client/src/test/java/co/elastic/clients/{elasticsearch/_helpers/ClientBuildersTest.java => transport/ElasticsearchTransportConfigTest.java} (92%) diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java index 0c61095bf..c8c94db51 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java @@ -20,7 +20,6 @@ package co.elastic.clients.elasticsearch; import co.elastic.clients.ApiClient; -import co.elastic.clients.elasticsearch._helpers.builders.ElasticsearchClientBuilderBase; import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch.async_search.ElasticsearchAsyncSearchAsyncClient; import co.elastic.clients.elasticsearch.autoscaling.ElasticsearchAutoscalingAsyncClient; @@ -146,6 +145,7 @@ import co.elastic.clients.elasticsearch.watcher.ElasticsearchWatcherAsyncClient; import co.elastic.clients.elasticsearch.xpack.ElasticsearchXpackAsyncClient; import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.ElasticsearchTransportConfig; import co.elastic.clients.transport.Endpoint; import co.elastic.clients.transport.JsonEndpoint; import co.elastic.clients.transport.Transport; @@ -178,16 +178,15 @@ * Client for the namespace. */ public class ElasticsearchAsyncClient extends ApiClient { - public static class Builder extends ElasticsearchClientBuilderBase { - @Override - public ElasticsearchAsyncClient build() { - return ElasticsearchClientBuilderBase.buildAsync(this); - } - } public static ElasticsearchAsyncClient of( - Function fn) { - return ElasticsearchClientBuilderBase.buildAsync(fn.apply(new ElasticsearchAsyncClient.Builder())); + Function fn) { + return new ElasticsearchAsyncClient( + fn.apply(new ElasticsearchTransportConfig.Builder()).build().buildTransport()); + } + + public ElasticsearchAsyncClient(ElasticsearchTransportConfig config) { + this(config.buildTransport()); } public ElasticsearchAsyncClient(ElasticsearchTransport transport) { diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java index 4550a4bf3..997ac03e0 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java @@ -20,7 +20,6 @@ package co.elastic.clients.elasticsearch; import co.elastic.clients.ApiClient; -import co.elastic.clients.elasticsearch._helpers.builders.ElasticsearchClientBuilderBase; import co.elastic.clients.elasticsearch._types.ElasticsearchException; import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch.async_search.ElasticsearchAsyncSearchClient; @@ -147,6 +146,7 @@ import co.elastic.clients.elasticsearch.watcher.ElasticsearchWatcherClient; import co.elastic.clients.elasticsearch.xpack.ElasticsearchXpackClient; import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.ElasticsearchTransportConfig; import co.elastic.clients.transport.Endpoint; import co.elastic.clients.transport.JsonEndpoint; import co.elastic.clients.transport.Transport; @@ -179,15 +179,14 @@ * Client for the namespace. */ public class ElasticsearchClient extends ApiClient { - public static class Builder extends ElasticsearchClientBuilderBase { - @Override - public ElasticsearchClient build() { - return ElasticsearchClientBuilderBase.buildSync(this); - } + + public static ElasticsearchClient of( + Function fn) { + return new ElasticsearchClient(fn.apply(new ElasticsearchTransportConfig.Builder()).build().buildTransport()); } - public static ElasticsearchClient of(Function fn) { - return ElasticsearchClientBuilderBase.buildSync(fn.apply(new ElasticsearchClient.Builder())); + public ElasticsearchClient(ElasticsearchTransportConfig config) { + this(config.buildTransport()); } public ElasticsearchClient(ElasticsearchTransport transport) { diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilderBase.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilderBase.java deleted file mode 100644 index 9eae9f2bb..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/_helpers/builders/ElasticsearchClientBuilderBase.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch._helpers.builders; - -import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.DefaultTransportOptions; -import co.elastic.clients.transport.TransportOptions; -import co.elastic.clients.transport.instrumentation.Instrumentation; -import co.elastic.clients.transport.rest5_client.Rest5ClientOptions; -import co.elastic.clients.transport.rest5_client.Rest5ClientTransport; -import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; -import co.elastic.clients.transport.rest5_client.low_level.Rest5ClientBuilder; -import co.elastic.clients.transport.rest_client.RestClientOptions; -import co.elastic.clients.transport.rest_client.RestClientTransport; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.json.JsonMapper; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.message.BasicHeader; -import org.apache.http.HttpHost; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; - -import javax.net.ssl.SSLContext; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Base64; -import java.util.List; -import java.util.function.Function; - -/** - * Base builder class for Elasticsearch sync an async clients. - * - * @see ElasticsearchClient.Builder - * @see ElasticsearchAsyncClient.Builder - */ -public abstract class ElasticsearchClientBuilderBase { - - protected List hosts; - protected String username; - protected String password; - protected String token; - protected String apiKey; - protected SSLContext sslContext; - protected JsonpMapper mapper; - protected TransportOptions transportOptions; - protected Instrumentation instrumentation; - protected boolean useLegacyTransport = false; - - public abstract T build(); - - public ElasticsearchClientBuilderBase host(String url) { - try { - this.hosts = List.of(new URI(url)); - } catch (URISyntaxException e) { - // Avoid requiring a checked exception in the builder - throw new RuntimeException(e); - } - return this; - } - - public ElasticsearchClientBuilderBase host(URI url) { - this.hosts = List.of(url); - return this; - } - - public ElasticsearchClientBuilderBase hosts(List hosts) { - this.hosts = hosts; - return this; - } - - /** - * Set the username and password to use to connect to Elasticsearch. - */ - public ElasticsearchClientBuilderBase usernameAndPassword(String username, String password) { - checkNull(this.token, "token", "username/password"); - checkNull(this.apiKey, "API key", "username/password"); - this.username = username; - this.password = password; - return this; - } - - /** - * Set the bearer token to use to authenticate to Elasticsearch. - */ - public ElasticsearchClientBuilderBase token(String token) { - checkNull(this.apiKey, "API key", "token"); - checkNull(this.username, "username", "token"); - this.token = token; - return this; - } - - /** - * Set the API key to use to authenticate to Elasticsearch. - */ - public ElasticsearchClientBuilderBase apiKey(String apiKey) { - checkNull(this.token, "token", "API key"); - checkNull(this.username, "username", "API key"); - this.apiKey = apiKey; - return this; - } - - /** - * Set the SSL context. See {@link co.elastic.clients.transport.TransportUtils} to create it - * from certificate files or a certificate fingerprint. - * - * @see co.elastic.clients.transport.TransportUtils - */ - public ElasticsearchClientBuilderBase sslContext(SSLContext sslContext) { - this.sslContext = sslContext; - return this; - } - - public ElasticsearchClientBuilderBase setHosts(List hosts) { - this.hosts = hosts; - return this; - } - - /** - * Set the JSON mapper. - */ - public ElasticsearchClientBuilderBase jsonMapper(JsonpMapper mapper) { - this.mapper = mapper; - return this; - } - - public ElasticsearchClientBuilderBase instrumentation(Instrumentation instrumentation) { - this.instrumentation = instrumentation; - return this; - } - - public ElasticsearchClientBuilderBase transportOptions(TransportOptions transportOptions) { - this.transportOptions = transportOptions; - return this; - } - - /** - * Sets lower level transport options. This method adds options to the ones already set, if any. - */ - public ElasticsearchClientBuilderBase transportOptions(Function fn) { - var builder = this.transportOptions == null ? new DefaultTransportOptions.Builder() : transportOptions.toBuilder(); - this.transportOptions = fn.apply(builder).build(); - return this; - } - - /** - * Should we use the legacy http implementation based on Elasticsearch's Low Level Rest Client? - */ - public ElasticsearchClientBuilderBase useLegacyTransport(boolean useLegacyTransport) { - this.useLegacyTransport = useLegacyTransport; - return this; - } - - protected ElasticsearchClient doBuild() { - if (this.hosts == null || this.hosts.isEmpty()) { - throw new IllegalArgumentException("hosts is required"); - } - - return useLegacyTransport ? buildRest4() : buildRest5(); - } - - public static ElasticsearchClient buildSync(ElasticsearchClientBuilderBase builder) { - return builder.doBuild(); - } - - public static ElasticsearchAsyncClient buildAsync(ElasticsearchClientBuilderBase builder) { - ElasticsearchClient client = builder.doBuild(); - TransportOptions clientOptions = client._transportOptions(); - if (client._transport().options() == clientOptions) { - // No options defined at the client level - clientOptions = null; - } - return new ElasticsearchAsyncClient(client._transport(), clientOptions); - } - - private ElasticsearchClient buildRest5() { - - Rest5ClientBuilder restClientBuilder = Rest5Client.builder(hosts); - - if (this.username != null && this.password != null) { - var cred = Base64.getEncoder().encodeToString((username + ":" + password).getBytes()); - restClientBuilder.setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "Basic " + cred) - }); - } else if (this.apiKey != null) { - restClientBuilder.setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "ApiKey " + apiKey) - }); - } else if (this.token != null) { - restClientBuilder.setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "Bearer " + token) - }); - } - - if (this.sslContext != null) { - restClientBuilder.setSSLContext(this.sslContext); - } - - if (this.mapper == null) { - ObjectMapper mapper = JsonMapper.builder().build(); - this.mapper = new JacksonJsonpMapper(mapper); - } - - Rest5ClientTransport transport = new Rest5ClientTransport( - restClientBuilder.build(), - mapper, - Rest5ClientOptions.of(transportOptions), - instrumentation - ); - return new ElasticsearchClient(transport); - } - - private ElasticsearchClient buildRest4() { - - RestClientBuilder restClientBuilder = RestClient.builder(hosts.stream() - .map(h -> HttpHost.create(h.toString())).toArray(HttpHost[]::new) - ); - - if (this.username != null && this.password != null) { - var cred = Base64.getEncoder().encodeToString((username + ":" + password).getBytes()); - restClientBuilder.setDefaultHeaders(new org.apache.http.Header[]{ - new org.apache.http.message.BasicHeader("Authorization", "Basic " + cred) - }); - } else if (this.apiKey != null) { - restClientBuilder.setDefaultHeaders(new org.apache.http.Header[]{ - new org.apache.http.message.BasicHeader("Authorization", "ApiKey " + apiKey) - }); - } else if (this.token != null) { - restClientBuilder.setDefaultHeaders(new org.apache.http.Header[]{ - new org.apache.http.message.BasicHeader("Authorization", "Bearer " + token) - }); - } - - if (sslContext != null) { - restClientBuilder.setHttpClientConfigCallback(hc -> hc.setSSLContext(sslContext)); - } - - if (this.mapper == null) { - ObjectMapper mapper = JsonMapper.builder().build(); - this.mapper = new JacksonJsonpMapper(mapper); - } - - RestClientTransport transport = new RestClientTransport( - restClientBuilder.build(), - mapper, - RestClientOptions.of(transportOptions), - instrumentation - ); - return new ElasticsearchClient(transport); - } - - private void checkNull(Object value, String name, String other) { - if (value != null) { - throw new IllegalStateException("Cannot set both " + other + " and " + name + "."); - } - } -} diff --git a/java-client/src/main/java/co/elastic/clients/transport/ElasticsearchTransportConfig.java b/java-client/src/main/java/co/elastic/clients/transport/ElasticsearchTransportConfig.java new file mode 100644 index 000000000..8f8c720a4 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/transport/ElasticsearchTransportConfig.java @@ -0,0 +1,236 @@ +/* + * 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. + */ + +package co.elastic.clients.transport; + +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.instrumentation.Instrumentation; +import co.elastic.clients.transport.rest5_client.Rest5ClientTransport; +import co.elastic.clients.transport.rest_client.RestClientTransport; + +import javax.annotation.Nullable; +import javax.net.ssl.SSLContext; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import java.util.function.Function; + +public class ElasticsearchTransportConfig { + private List hosts; + private String username; + private String password; + private String token; + private String apiKey; + private SSLContext sslContext; + private JsonpMapper mapper; + private TransportOptions transportOptions; + private Instrumentation instrumentation; + private Function transportFactory; + + public List hosts() { + return hosts; + } + + @Nullable + public String username() { + return username; + } + + @Nullable + public String password() { + return password; + } + + @Nullable + public String token() { + return token; + } + + @Nullable + public String apiKey() { + return apiKey; + } + + @Nullable + public SSLContext sslContext() { + return sslContext; + } + + public JsonpMapper mapper() { + return mapper; + } + + public TransportOptions transportOptions() { + return transportOptions; + } + + @Nullable + public Instrumentation instrumentation() { + return instrumentation; + } + + public Function transportFactory() { + return transportFactory; + } + + public ElasticsearchTransport buildTransport() { + return this.transportFactory.apply(this); + } + + //--------------------------------------------------------------------------------------------- + + public static class Builder { + + public final ElasticsearchTransportConfig config = new ElasticsearchTransportConfig(); + + public ElasticsearchTransportConfig build() { + if (config.hosts() == null || config.hosts.isEmpty()) { + throw new IllegalStateException("hosts cannot be empty"); + } + + if (config.mapper == null) { + config.mapper = new JacksonJsonpMapper(); + } + + if (config.transportFactory == null) { + config.transportFactory = Rest5ClientTransport::new; + } + + return config; + } + + public Builder host(String url) { + try { + config.hosts = List.of(new URI(url)); + } catch (URISyntaxException e) { + // Avoid requiring a checked exception in the builder + throw new RuntimeException(e); + } + return this; + } + + public Builder host(URI url) { + config.hosts = List.of(url); + return this; + } + + public Builder hosts(List hosts) { + config.hosts = hosts; + return this; + } + + /** + * Set the username and password to use to connect to Elasticsearch. + */ + public Builder usernameAndPassword(String username, String password) { + checkNull(config.token, "token", "username/password"); + checkNull(config.apiKey, "API key", "username/password"); + config.username = username; + config.password = password; + return this; + } + + /** + * Set the bearer token to use to authenticate to Elasticsearch. + */ + public Builder token(String token) { + checkNull(config.apiKey, "API key", "token"); + checkNull(config.username, "username", "token"); + config.token = token; + return this; + } + + /** + * Set the API key to use to authenticate to Elasticsearch. + */ + public Builder apiKey(String apiKey) { + checkNull(config.token, "token", "API key"); + checkNull(config.username, "username", "API key"); + config.apiKey = apiKey; + return this; + } + + /** + * Set the SSL context. See {@link co.elastic.clients.transport.TransportUtils} to create it + * from certificate files or a certificate fingerprint. + * + * @see co.elastic.clients.transport.TransportUtils + */ + public Builder sslContext(SSLContext sslContext) { + config.sslContext = sslContext; + return this; + } + + public Builder setHosts(List hosts) { + config.hosts = hosts; + return this; + } + + /** + * Set the JSON mapper. + */ + public Builder jsonMapper(JsonpMapper mapper) { + config.mapper = mapper; + return this; + } + + public Builder instrumentation(Instrumentation instrumentation) { + config.instrumentation = instrumentation; + return this; + } + + public Builder transportOptions(TransportOptions transportOptions) { + config.transportOptions = transportOptions; + return this; + } + + /** + * Sets lower level transport options. This method adds options to the ones already set, if any. + */ + public Builder transportOptions(Function fn) { + var builder = config.transportOptions == null ? new DefaultTransportOptions.Builder() : config.transportOptions.toBuilder(); + config.transportOptions = fn.apply(builder).build(); + return this; + } + + public Builder transportFactory(Function factory) { + config.transportFactory = factory; + return this; + } + + /** + * Should we use the legacy http implementation based on Elasticsearch's Low Level Rest Client? + */ + public Builder useLegacyTransport(boolean useLegacyTransport) { + if (useLegacyTransport) { + config.transportFactory = RestClientTransport.FACTORY; + } else { + config.transportFactory = null; + } + return this; + } + + private void checkNull(Object value, String name, String other) { + if (value != null) { + throw new IllegalStateException("Cannot set both " + other + " and " + name + "."); + } + } + } +} diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java index fecf4071f..180e8d224 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java @@ -20,18 +20,39 @@ package co.elastic.clients.transport.rest5_client; import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; import co.elastic.clients.transport.ElasticsearchTransportBase; import co.elastic.clients.transport.Transport; +import co.elastic.clients.transport.ElasticsearchTransportConfig; import co.elastic.clients.transport.TransportOptions; import co.elastic.clients.transport.instrumentation.Instrumentation; import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; +import co.elastic.clients.transport.rest5_client.low_level.Rest5ClientBuilder; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.message.BasicHeader; import javax.annotation.Nullable; +import java.util.Base64; +import java.util.function.Function; public class Rest5ClientTransport extends ElasticsearchTransportBase { + /** + * Factory function to be used for {@link ElasticsearchTransportConfig#transportFactory()}. + */ + public static final Function FACTORY = Rest5ClientTransport::new; + private final Rest5Client restClient; + public Rest5ClientTransport(ElasticsearchTransportConfig config) { + this( + buildRest5Client(config), + config.mapper(), + Rest5ClientOptions.of(config.transportOptions()), + config.instrumentation() + ); + } + public Rest5ClientTransport(Rest5Client restClient, JsonpMapper jsonpMapper) { this(restClient, jsonpMapper, null); } @@ -47,6 +68,31 @@ public Rest5ClientTransport(Rest5Client restClient, JsonpMapper jsonpMapper, Res this.restClient = restClient; } + private static Rest5Client buildRest5Client(ElasticsearchTransportConfig config) { + Rest5ClientBuilder restClientBuilder = Rest5Client.builder(config.hosts()); + + if (config.username() != null && config.password() != null) { + var cred = Base64.getEncoder().encodeToString((config.username() + ":" + config.password()).getBytes()); + restClientBuilder.setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Basic " + cred) + }); + } else if (config.apiKey() != null) { + restClientBuilder.setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "ApiKey " + config.apiKey()) + }); + } else if (config.token() != null) { + restClientBuilder.setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Bearer " + config.token()) + }); + } + + if (config.sslContext() != null) { + restClientBuilder.setSSLContext(config.sslContext()); + } + + return restClientBuilder.build(); + } + public Rest5Client restClient() { return this.restClient; } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java index cd7357e9c..4dc9bf785 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java @@ -20,18 +20,39 @@ package co.elastic.clients.transport.rest_client; import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; import co.elastic.clients.transport.ElasticsearchTransportBase; import co.elastic.clients.transport.Transport; +import co.elastic.clients.transport.ElasticsearchTransportConfig; import co.elastic.clients.transport.TransportOptions; import co.elastic.clients.transport.instrumentation.Instrumentation; +import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; import javax.annotation.Nullable; +import java.util.Base64; +import java.util.function.Function; public class RestClientTransport extends ElasticsearchTransportBase { + /** + * Factory function to be used for {@link ElasticsearchTransportConfig#transportFactory()}. + */ + public static final Function FACTORY = RestClientTransport::new; + + private final RestClient restClient; + public RestClientTransport(ElasticsearchTransportConfig config) { + this( + buildRestClient(config), + config.mapper(), + RestClientOptions.of(config.transportOptions()), + config.instrumentation() + ); + } + public RestClientTransport(RestClient restClient, JsonpMapper jsonpMapper) { this(restClient, jsonpMapper, null); } @@ -46,6 +67,33 @@ public RestClientTransport(RestClient restClient, JsonpMapper jsonpMapper, RestC this.restClient = restClient; } + private static RestClient buildRestClient(ElasticsearchTransportConfig config) { + RestClientBuilder restClientBuilder = RestClient.builder(config.hosts().stream() + .map(h -> HttpHost.create(h.toString())).toArray(HttpHost[]::new) + ); + + if (config.username() != null && config.password() != null) { + var cred = Base64.getEncoder().encodeToString((config.username() + ":" + config.password()).getBytes()); + restClientBuilder.setDefaultHeaders(new org.apache.http.Header[]{ + new org.apache.http.message.BasicHeader("Authorization", "Basic " + cred) + }); + } else if (config.apiKey() != null) { + restClientBuilder.setDefaultHeaders(new org.apache.http.Header[]{ + new org.apache.http.message.BasicHeader("Authorization", "ApiKey " + config.apiKey()) + }); + } else if (config.token() != null) { + restClientBuilder.setDefaultHeaders(new org.apache.http.Header[]{ + new org.apache.http.message.BasicHeader("Authorization", "Bearer " + config.token()) + }); + } + + if (config.sslContext() != null) { + restClientBuilder.setHttpClientConfigCallback(hc -> hc.setSSLContext(config.sslContext())); + } + + return restClientBuilder.build(); + } + public RestClient restClient() { return this.restClient; } diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestClient.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestClient.java index 206a1e35c..87461bc93 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestClient.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestClient.java @@ -21,27 +21,30 @@ import co.elastic.clients.json.JsonpMapper; import co.elastic.clients.json.jsonb.JsonbJsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.ElasticsearchTransportConfig; import co.elastic.clients.transport.rest5_client.Rest5ClientTransport; -import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; import co.elastic.clients.transport.rest_client.RestClientTransport; import com.sun.net.httpserver.HttpServer; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.message.BasicHeader; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.elasticsearch.client.RestClient; import javax.annotation.Nullable; import javax.net.ssl.SSLContext; -import java.net.URI; import java.security.SecureRandom; -import java.util.Base64; +import java.util.function.Function; public class ElasticsearchTestClient { - protected enum ClientImpl { Rest4, Rest5 } + protected enum ClientImpl { + Rest4, + Rest5; + + Function transportFactory() { + return switch (this) { + case Rest4 -> RestClientTransport::new; + case Rest5 -> Rest5ClientTransport::new; + }; + } + } // Same value for all tests in a test run private static final ClientImpl flavor; @@ -56,44 +59,18 @@ private static JsonpMapper mapper(JsonpMapper mapper) { public static ElasticsearchClient createClient(String url, @Nullable JsonpMapper mapper, @Nullable SSLContext sslContext) { System.out.println("Using a " + flavor + " client"); - return switch (flavor) { - case Rest4 -> createRest4Client(url, mapper, sslContext); - case Rest5 -> createRest5Client(url, mapper, sslContext); - }; + + return ElasticsearchClient.of(b -> b + .host(url) + .jsonMapper(mapper(mapper)) + .usernameAndPassword("elastic", "changeme") + .sslContext(sslContext) + .transportFactory(flavor.transportFactory()) + ); } public static ElasticsearchClient createClient(HttpServer server, @Nullable JsonpMapper mapper) { var address = server.getAddress(); return createClient("http://" + address.getHostString() + ":" + address.getPort(), mapper, null); } - - public static ElasticsearchClient createRest4Client(String url, @Nullable JsonpMapper mapper, @Nullable SSLContext sslContext) { - BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); - credsProv.setCredentials( - AuthScope.ANY, new UsernamePasswordCredentials("elastic", "changeme") - ); - var restClient = RestClient.builder(HttpHost.create(url)) - .setHttpClientConfigCallback(hc -> hc - .setDefaultCredentialsProvider(credsProv) - .setSSLContext(sslContext) - ) - .build(); - var transport = new RestClientTransport(restClient, mapper(mapper)); - return new ElasticsearchClient(transport); - } - - public static ElasticsearchClient createRest5Client(String url, @Nullable JsonpMapper mapper, @Nullable SSLContext sslContext) { - var pwd = Base64.getEncoder().encodeToString("elastic:changeme".getBytes()); - var restClientBuilder = Rest5Client.builder(org.apache.hc.core5.http.HttpHost.create(URI.create(url))) - .setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "Basic " + pwd) - }); - - if (sslContext != null) { - restClientBuilder.setSSLContext(sslContext); - } - - var transport = new Rest5ClientTransport(restClientBuilder.build(), mapper(mapper)); - return new ElasticsearchClient(transport); - } } diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java b/java-client/src/test/java/co/elastic/clients/transport/ElasticsearchTransportConfigTest.java similarity index 92% rename from java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java rename to java-client/src/test/java/co/elastic/clients/transport/ElasticsearchTransportConfigTest.java index 024464c2e..f99d3e956 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/_helpers/ClientBuildersTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/ElasticsearchTransportConfigTest.java @@ -17,7 +17,7 @@ * under the License. */ -package co.elastic.clients.elasticsearch._helpers; +package co.elastic.clients.transport; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.transport.rest5_client.Rest5ClientOptions; @@ -30,17 +30,17 @@ import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; -public class ClientBuildersTest { +public class ElasticsearchTransportConfigTest { @Test public void buildLegacy() { // create client with helper - ElasticsearchClient client = new ElasticsearchClient.Builder() + ElasticsearchClient client = ElasticsearchClient.of(b -> b .host("http://example.com") .usernameAndPassword("elastic", "changeme") .useLegacyTransport(true) - .build(); + ); RestClientOptions options = new RestClientOptions(RequestOptions.DEFAULT, true); @@ -60,10 +60,10 @@ public void buildLegacy() { public void buildRest5() { // create client with helper - ElasticsearchClient client = new ElasticsearchClient.Builder() + ElasticsearchClient client = ElasticsearchClient.of(b -> b .host("http://example.com") .usernameAndPassword("elastic", "changeme") - .build(); + ); Rest5ClientOptions options = new Rest5ClientOptions(co.elastic.clients.transport.rest5_client.low_level.RequestOptions.DEFAULT, true); diff --git a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SnifferTests.java b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SnifferTests.java index 11b22fa63..f7d543f05 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SnifferTests.java +++ b/java-client/src/test/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/SnifferTests.java @@ -137,8 +137,9 @@ public void shutdown() { * Simulates the ordinary behaviour of {@link Sniffer} when sniffing on failure is not enabled. * The {@link CountingNodesSniffer} doesn't make any network connection but may throw exception or return no nodes, which makes * it possible to verify that errors are properly handled and don't affect subsequent runs and their scheduling. - * The {@link Sniffer.Scheduler} implementation submits rather than scheduling tasks, meaning that it doesn't respect the requested sniff - * delays while allowing to assert that the requested delays for each requested run and the following one are the expected values. + * The {@link Sniffer.Scheduler} implementation submits rather than scheduling tasks, meaning that it doesn't respect the + * requested sniff delays while allowing to assert that the requested delays for each requested run and the following one are the + * expected values. */ @Test public void testOrdinarySniffRounds() throws Exception { From f21b866ec72035290cbecb007b7f417d0d88f683 Mon Sep 17 00:00:00 2001 From: Sylvain Wallez Date: Mon, 31 Mar 2025 13:08:43 +0200 Subject: [PATCH 32/38] Allow extensions of ElasticsearchTransportConfig --- .../ElasticsearchTransportConfig.java | 259 ++++++++++++------ .../rest5_client/Rest5ClientTransport.java | 9 +- .../rest_client/RestClientTransport.java | 10 +- .../ElasticsearchTransportConfigTest.java | 69 ++++- 4 files changed, 243 insertions(+), 104 deletions(-) diff --git a/java-client/src/main/java/co/elastic/clients/transport/ElasticsearchTransportConfig.java b/java-client/src/main/java/co/elastic/clients/transport/ElasticsearchTransportConfig.java index 8f8c720a4..2d7b9ccb3 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/ElasticsearchTransportConfig.java +++ b/java-client/src/main/java/co/elastic/clients/transport/ElasticsearchTransportConfig.java @@ -32,17 +32,17 @@ import java.util.List; import java.util.function.Function; -public class ElasticsearchTransportConfig { - private List hosts; - private String username; - private String password; - private String token; - private String apiKey; - private SSLContext sslContext; - private JsonpMapper mapper; - private TransportOptions transportOptions; - private Instrumentation instrumentation; - private Function transportFactory; +public abstract class ElasticsearchTransportConfig { + protected List hosts; + protected String username; + protected String password; + protected String token; + protected String apiKey; + protected boolean useCompression = false; + protected SSLContext sslContext; + protected JsonpMapper mapper; + protected TransportOptions transportOptions; + protected Instrumentation instrumentation; public List hosts() { return hosts; @@ -68,6 +68,10 @@ public String apiKey() { return apiKey; } + public boolean useCompression() { + return useCompression; + } + @Nullable public SSLContext sslContext() { return sslContext; @@ -86,150 +90,245 @@ public Instrumentation instrumentation() { return instrumentation; } - public Function transportFactory() { - return transportFactory; + public abstract ElasticsearchTransport buildTransport(); + + //--------------------------------------------------------------------------------------------- + + /** + * Default configuration that can be used with any transport implementation. If no transport + * factory is defined with {@link #transportFactory}, a {@link Rest5ClientTransport} is used. + */ + public static class Default extends ElasticsearchTransportConfig { + + protected Function transportFactory; + + public Function transportFactory() { + return transportFactory; + } + + public ElasticsearchTransport buildTransport() { + return this.transportFactory.apply(this); + } } - public ElasticsearchTransport buildTransport() { - return this.transportFactory.apply(this); + /** + * Builder for {@link Default} transport configurations. + */ + public static class Builder extends ElasticsearchTransportConfig.AbstractBuilder { + private final Default dconfig; + + public Builder() { + this(new Default()); + } + + private Builder(Default dconfig) { + super(dconfig); + // Typed accessor to this.config + this.dconfig = dconfig; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Should we use the legacy http implementation based on Elasticsearch's Low Level Rest Client? + *

+ * Shortcut for {@code transportFactory(RestClientTransport::new)}. + * + * @see RestClientTransport + */ + public Builder useLegacyTransport(boolean useLegacyTransport) { + if (useLegacyTransport) { + dconfig.transportFactory = RestClientTransport::new; + } else { + dconfig.transportFactory = null; + } + return this; + } + + /** + * Defines the factory function to create a transport with this configuration. + * + * @see #buildTransport() + */ + public Builder transportFactory(Function factory) { + dconfig.transportFactory = factory; + return this; + } + + @Override + public Default build() { + Default config = (Default) super.build(); + + // Default transport implementation + if (config.transportFactory == null) { + config.transportFactory = Rest5ClientTransport::new; + } + + return config; + } } //--------------------------------------------------------------------------------------------- - public static class Builder { + public abstract static class AbstractBuilder> { + protected final ElasticsearchTransportConfig config; + + public AbstractBuilder(ElasticsearchTransportConfig config) { + this.config = config; + } + + protected abstract BuilderT self(); + + protected ElasticsearchTransportConfig build() { + + //---- Validate credentials + + if (config.username != null) { + checkNull(config.token, "token", "username/password"); + checkNull(config.apiKey, "API key", "username/password"); + if (config.password == null) { + throw new IllegalArgumentException("password required with username"); + } + } else if (config.password != null) { + throw new IllegalArgumentException("username required with password"); + } + + if (config.token != null) { + checkNull(config.apiKey, "API key", "token"); + checkNull(config.username, "username", "token"); + } + + if (config.apiKey != null) { + checkNull(config.token, "token", "API key"); + checkNull(config.username, "username", "API key"); + } - public final ElasticsearchTransportConfig config = new ElasticsearchTransportConfig(); + //---- Validate other settings - public ElasticsearchTransportConfig build() { if (config.hosts() == null || config.hosts.isEmpty()) { - throw new IllegalStateException("hosts cannot be empty"); + throw new IllegalArgumentException("hosts cannot be empty"); } if (config.mapper == null) { config.mapper = new JacksonJsonpMapper(); } - if (config.transportFactory == null) { - config.transportFactory = Rest5ClientTransport::new; - } - return config; - } + }; - public Builder host(String url) { + /** + * Elasticsearch host location + */ + public BuilderT host(String url) { try { config.hosts = List.of(new URI(url)); } catch (URISyntaxException e) { // Avoid requiring a checked exception in the builder throw new RuntimeException(e); } - return this; + return self(); } - public Builder host(URI url) { + /** + * Elasticsearch host location + */ + public BuilderT host(URI url) { config.hosts = List.of(url); - return this; + return self(); } - public Builder hosts(List hosts) { + /** + * Elasticsearch hosts locations + */ + public BuilderT hosts(List hosts) { config.hosts = hosts; - return this; + return self(); } /** * Set the username and password to use to connect to Elasticsearch. */ - public Builder usernameAndPassword(String username, String password) { - checkNull(config.token, "token", "username/password"); - checkNull(config.apiKey, "API key", "username/password"); + public BuilderT usernameAndPassword(String username, String password) { config.username = username; config.password = password; - return this; + return self(); } /** * Set the bearer token to use to authenticate to Elasticsearch. */ - public Builder token(String token) { - checkNull(config.apiKey, "API key", "token"); - checkNull(config.username, "username", "token"); + public BuilderT token(String token) { config.token = token; - return this; + return self(); } /** * Set the API key to use to authenticate to Elasticsearch. */ - public Builder apiKey(String apiKey) { - checkNull(config.token, "token", "API key"); - checkNull(config.username, "username", "API key"); + public BuilderT apiKey(String apiKey) { config.apiKey = apiKey; - return this; + return self(); } /** - * Set the SSL context. See {@link co.elastic.clients.transport.TransportUtils} to create it - * from certificate files or a certificate fingerprint. + * Should request and response body compression be used? + */ + public BuilderT useCompression(boolean useCompression) { + this.config.useCompression = useCompression; + return self(); + } + + /** + * SSL context to use for https connections. See {@link co.elastic.clients.transport.TransportUtils} to create it + * from a certificate file or a certificate fingerprint. * * @see co.elastic.clients.transport.TransportUtils */ - public Builder sslContext(SSLContext sslContext) { + public BuilderT sslContext(SSLContext sslContext) { config.sslContext = sslContext; - return this; - } - - public Builder setHosts(List hosts) { - config.hosts = hosts; - return this; + return self(); } /** - * Set the JSON mapper. + * The JSON mapper to use. Defaults to {@link JacksonJsonpMapper}. */ - public Builder jsonMapper(JsonpMapper mapper) { + public BuilderT jsonMapper(JsonpMapper mapper) { config.mapper = mapper; - return this; + return self(); } - public Builder instrumentation(Instrumentation instrumentation) { + /** + * Transport instrumentation to log client traffic. See + * {@link co.elastic.clients.transport.instrumentation.OpenTelemetryForElasticsearch} for OpenTelemetry integration. + */ + public BuilderT instrumentation(Instrumentation instrumentation) { config.instrumentation = instrumentation; - return this; + return self(); } - public Builder transportOptions(TransportOptions transportOptions) { + /** + * Lower level transport options. + */ + public BuilderT transportOptions(TransportOptions transportOptions) { config.transportOptions = transportOptions; - return this; + return self(); } /** - * Sets lower level transport options. This method adds options to the ones already set, if any. + * Lower level transport options. This method adds options to the ones already set, if any. */ - public Builder transportOptions(Function fn) { + public BuilderT transportOptions(Function fn) { var builder = config.transportOptions == null ? new DefaultTransportOptions.Builder() : config.transportOptions.toBuilder(); config.transportOptions = fn.apply(builder).build(); - return this; - } - - public Builder transportFactory(Function factory) { - config.transportFactory = factory; - return this; - } - - /** - * Should we use the legacy http implementation based on Elasticsearch's Low Level Rest Client? - */ - public Builder useLegacyTransport(boolean useLegacyTransport) { - if (useLegacyTransport) { - config.transportFactory = RestClientTransport.FACTORY; - } else { - config.transportFactory = null; - } - return this; + return self(); } - private void checkNull(Object value, String name, String other) { + protected void checkNull(Object value, String name, String other) { if (value != null) { - throw new IllegalStateException("Cannot set both " + other + " and " + name + "."); + throw new IllegalArgumentException("Cannot set both " + other + " and " + name + "."); } } } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java index 180e8d224..3b0ad7fe6 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/Rest5ClientTransport.java @@ -20,7 +20,6 @@ package co.elastic.clients.transport.rest5_client; import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.transport.ElasticsearchTransport; import co.elastic.clients.transport.ElasticsearchTransportBase; import co.elastic.clients.transport.Transport; import co.elastic.clients.transport.ElasticsearchTransportConfig; @@ -33,15 +32,9 @@ import javax.annotation.Nullable; import java.util.Base64; -import java.util.function.Function; public class Rest5ClientTransport extends ElasticsearchTransportBase { - /** - * Factory function to be used for {@link ElasticsearchTransportConfig#transportFactory()}. - */ - public static final Function FACTORY = Rest5ClientTransport::new; - private final Rest5Client restClient; public Rest5ClientTransport(ElasticsearchTransportConfig config) { @@ -90,6 +83,8 @@ private static Rest5Client buildRest5Client(ElasticsearchTransportConfig config) restClientBuilder.setSSLContext(config.sslContext()); } + restClientBuilder.setCompressionEnabled(config.useCompression()); + return restClientBuilder.build(); } diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java index 4dc9bf785..4ace1d0ed 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest_client/RestClientTransport.java @@ -20,7 +20,6 @@ package co.elastic.clients.transport.rest_client; import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.transport.ElasticsearchTransport; import co.elastic.clients.transport.ElasticsearchTransportBase; import co.elastic.clients.transport.Transport; import co.elastic.clients.transport.ElasticsearchTransportConfig; @@ -32,16 +31,9 @@ import javax.annotation.Nullable; import java.util.Base64; -import java.util.function.Function; public class RestClientTransport extends ElasticsearchTransportBase { - /** - * Factory function to be used for {@link ElasticsearchTransportConfig#transportFactory()}. - */ - public static final Function FACTORY = RestClientTransport::new; - - private final RestClient restClient; public RestClientTransport(ElasticsearchTransportConfig config) { @@ -91,6 +83,8 @@ private static RestClient buildRestClient(ElasticsearchTransportConfig config) { restClientBuilder.setHttpClientConfigCallback(hc -> hc.setSSLContext(config.sslContext())); } + restClientBuilder.setCompressionEnabled(config.useCompression()); + return restClientBuilder.build(); } diff --git a/java-client/src/test/java/co/elastic/clients/transport/ElasticsearchTransportConfigTest.java b/java-client/src/test/java/co/elastic/clients/transport/ElasticsearchTransportConfigTest.java index f99d3e956..18e1b7852 100644 --- a/java-client/src/test/java/co/elastic/clients/transport/ElasticsearchTransportConfigTest.java +++ b/java-client/src/test/java/co/elastic/clients/transport/ElasticsearchTransportConfigTest.java @@ -25,12 +25,10 @@ import co.elastic.clients.transport.rest_client.RestClientOptions; import co.elastic.clients.transport.rest_client.RestClientTransport; import org.elasticsearch.client.RequestOptions; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; - -public class ElasticsearchTransportConfigTest { +public class ElasticsearchTransportConfigTest extends Assertions { @Test public void buildLegacy() { @@ -47,9 +45,9 @@ public void buildLegacy() { client = client.withTransportOptions(options); // checking options correctness - assertTrue(client._transport().getClass().equals(RestClientTransport.class)); + assertEquals(client._transport().getClass(), RestClientTransport.class); assertTrue(client._transportOptions().keepResponseBodyOnException()); - assertTrue(client._transportOptions().headers().size() == 3); + assertEquals(3, client._transportOptions().headers().size()); // token update utility: not supported on legacy transport ElasticsearchClient finalClient = client; @@ -71,14 +69,67 @@ public void buildRest5() { client = client.withTransportOptions(options); // checking options correctness - assertTrue(client._transport().getClass().equals(Rest5ClientTransport.class)); + assertInstanceOf(Rest5ClientTransport.class, client._transport()); assertTrue(client._transportOptions().keepResponseBodyOnException()); - assertTrue(client._transportOptions().headers().size() == 3); + assertEquals(3, client._transportOptions().headers().size()); // token update utility: supported on new transport client._transportOptions().updateToken("token"); - assertTrue(client._transportOptions().headers().size() == 4); + assertEquals(4, client._transportOptions().headers().size()); assertTrue(client._transportOptions().headers().stream().anyMatch(h -> h.getKey().equals( "Authorization"))); } + + @Test + public void credentialCombinations() { + + // Bare minimum is a host URL + new ElasticsearchTransportConfig.Builder() + .host("http://example.com") + .build(); + + assertThrows(IllegalArgumentException.class, () -> new ElasticsearchTransportConfig.Builder() + .host("http://example.com") + .usernameAndPassword("elastic", null) + .build() + ); + + assertThrows(IllegalArgumentException.class, () -> new ElasticsearchTransportConfig.Builder() + .host("http://example.com") + .usernameAndPassword(null, "password") + .build() + ); + + assertThrows(IllegalArgumentException.class, () -> new ElasticsearchTransportConfig.Builder() + .host("http://example.com") + .usernameAndPassword("elastic", "password") + .token("token") + .build() + ); + + assertThrows(IllegalArgumentException.class, () -> new ElasticsearchTransportConfig.Builder() + .host("http://example.com") + .usernameAndPassword("elastic", "password") + .apiKey("api_key") + .build() + ); + + assertThrows(IllegalArgumentException.class, () -> new ElasticsearchTransportConfig.Builder() + .host("http://example.com") + .apiKey("api_key") + .token("token") + .build() + ); + } + + @Test + public void checkDefaultConfig() throws Exception { + ElasticsearchTransportConfig.Default config = new ElasticsearchTransportConfig.Builder() + .host("http://example.com") + .build(); + + try (var transport = config.buildTransport()) { + assertInstanceOf(Rest5ClientTransport.class, transport); + } + } } From 4f6fb2d27e7edbdcb92b08cdeda38966dce49df4 Mon Sep 17 00:00:00 2001 From: Sylvain Wallez Date: Mon, 31 Mar 2025 13:13:19 +0200 Subject: [PATCH 33/38] Remove calls to AccessController which is deprecated for removal --- .../low_level/sniffer/Sniffer.java | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/Sniffer.java b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/Sniffer.java index 1e7ff6cb5..7ed0bcc2c 100644 --- a/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/Sniffer.java +++ b/java-client/src/main/java/co/elastic/clients/transport/rest5_client/low_level/sniffer/Sniffer.java @@ -26,8 +26,6 @@ import java.io.Closeable; import java.io.IOException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Collection; import java.util.List; import java.util.concurrent.Executors; @@ -298,25 +296,15 @@ static class SnifferThreadFactory implements ThreadFactory { private SnifferThreadFactory(String namePrefix) { this.namePrefix = namePrefix; - this.originalThreadFactory = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public ThreadFactory run() { - return Executors.defaultThreadFactory(); - } - }); + this.originalThreadFactory = Executors.defaultThreadFactory(); } @Override public Thread newThread(final Runnable r) { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Thread run() { - Thread t = originalThreadFactory.newThread(r); - t.setName(namePrefix + "[T#" + threadNumber.getAndIncrement() + "]"); - t.setDaemon(true); - return t; - } - }); + Thread t = originalThreadFactory.newThread(r); + t.setName(namePrefix + "[T#" + threadNumber.getAndIncrement() + "]"); + t.setDaemon(true); + return t; } } } From 021eccf243220a7a90e125b8053f1b14c8f183a4 Mon Sep 17 00:00:00 2001 From: Sylvain Wallez Date: Mon, 31 Mar 2025 15:39:50 +0200 Subject: [PATCH 34/38] Fix licenseReport --- java-client/build.gradle.kts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/java-client/build.gradle.kts b/java-client/build.gradle.kts index cdf63090c..84046069f 100644 --- a/java-client/build.gradle.kts +++ b/java-client/build.gradle.kts @@ -297,6 +297,7 @@ class SpdxReporter(val dest: File) : ReportRenderer { "The Apache License, Version 2.0" to "Apache-2.0", "Apache License, Version 2.0" to "Apache-2.0", "The Apache Software License, Version 2.0" to "Apache-2.0", + "MIT License" to "MIT", "BSD Zero Clause License" to "0BSD", "Eclipse Public License 2.0" to "EPL-2.0", "Eclipse Public License v. 2.0" to "EPL-2.0", @@ -323,7 +324,11 @@ class SpdxReporter(val dest: File) : ReportRenderer { val depName = dep.group + ":" + dep.name val info = LicenseDataCollector.multiModuleLicenseInfo(dep) - val depUrl = info.moduleUrls.first() + val depUrl = if (depName.startsWith("org.apache.httpcomponents")) { + "https://hc.apache.org/" + } else { + info.moduleUrls.first() + } val licenseIds = info.licenses.mapNotNull { license -> license.name?.let { From 3f479893a91f84b185927cce70716835a9871d7e Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Mon, 31 Mar 2025 16:13:08 +0200 Subject: [PATCH 35/38] Revert "temp rebase fix" This reverts commit 48f2b57898f4a7d7709dcb7a3f0496c0ec43c769. --- .../ElasticsearchAsyncClient.java | 5 + .../elasticsearch/ElasticsearchClient.java | 5 + .../ChatCompletionUnifiedRequest.java | 27 + .../inference/CompletionInferenceResult.java | 157 ++++++ .../inference/CompletionRequest.java | 335 +++++++++++++ .../inference/CompletionResponse.java | 106 ++++ .../inference/CompletionResult.java | 155 ++++++ .../DeleteInferenceEndpointResult.java | 134 +++++ .../inference/DeleteInferenceRequest.java | 292 +++++++++++ .../inference/DeleteInferenceResponse.java | 107 ++++ .../ElasticsearchInferenceAsyncClient.java | 30 ++ .../ElasticsearchInferenceClient.java | 30 ++ .../inference/GetInferenceRequest.java | 238 +++++++++ .../inference/GetInferenceResponse.java | 186 +++++++ .../inference/InferenceChunkingSettings.java | 279 +++++++++++ .../inference/InferenceEndpoint.java | 275 +++++++++++ .../inference/InferenceEndpointInfo.java | 182 +++++++ .../PostEisChatCompletionRequest.java | 33 ++ .../inference/PutAlibabacloudRequest.java | 26 + .../inference/PutAlibabacloudResponse.java | 108 ++++ .../inference/PutAmazonbedrockRequest.java | 26 + .../inference/PutAmazonbedrockResponse.java | 108 ++++ .../inference/PutAnthropicRequest.java | 26 + .../inference/PutAnthropicResponse.java | 107 ++++ .../inference/PutAzureaistudioRequest.java | 26 + .../inference/PutAzureaistudioResponse.java | 108 ++++ .../inference/PutAzureopenaiRequest.java | 26 + .../inference/PutAzureopenaiResponse.java | 108 ++++ .../inference/PutCohereRequest.java | 26 + .../inference/PutCohereResponse.java | 106 ++++ .../inference/PutEisRequest.java | 26 + .../inference/PutEisResponse.java | 106 ++++ .../inference/PutElasticsearchRequest.java | 26 + .../inference/PutElasticsearchResponse.java | 108 ++++ .../inference/PutElserRequest.java | 26 + .../inference/PutElserResponse.java | 106 ++++ .../inference/PutGoogleaistudioRequest.java | 26 + .../inference/PutGoogleaistudioResponse.java | 108 ++++ .../inference/PutGooglevertexaiRequest.java | 26 + .../inference/PutGooglevertexaiResponse.java | 108 ++++ .../inference/PutHuggingFaceRequest.java | 26 + .../inference/PutHuggingFaceResponse.java | 108 ++++ .../inference/PutJinaaiRequest.java | 26 + .../inference/PutJinaaiResponse.java | 106 ++++ .../inference/PutMistralRequest.java | 26 + .../inference/PutMistralResponse.java | 106 ++++ .../inference/PutOpenaiRequest.java | 27 + .../inference/PutOpenaiResponse.java | 106 ++++ .../elasticsearch/inference/PutRequest.java | 298 +++++++++++ .../elasticsearch/inference/PutResponse.java | 106 ++++ .../inference/PutVoyageaiRequest.java | 27 + .../inference/PutVoyageaiResponse.java | 106 ++++ .../inference/PutWatsonxRequest.java | 26 + .../inference/PutWatsonxResponse.java | 106 ++++ .../inference/RankedDocument.java | 213 ++++++++ .../inference/RateLimitSetting.java | 163 +++++++ .../inference/RequestChatCompletionBase.java | 461 ++++++++++++++++++ .../inference/RerankRequest.java | 383 +++++++++++++++ .../inference/RerankResponse.java | 106 ++++ .../inference/RerankedInferenceResult.java | 156 ++++++ .../SparseEmbeddingInferenceResult.java | 158 ++++++ .../inference/SparseEmbeddingRequest.java | 337 +++++++++++++ .../inference/SparseEmbeddingResponse.java | 108 ++++ .../inference/SparseEmbeddingResult.java | 180 +++++++ .../inference/StreamCompletionRequest.java | 327 +++++++++++++ .../elasticsearch/inference/TaskType.java | 71 +++ .../inference/TextEmbeddingByteResult.java | 180 +++++++ .../TextEmbeddingInferenceResult.java | 284 +++++++++++ .../TextEmbeddingInferenceResultBuilders.java | 53 ++ .../TextEmbeddingInferenceResultVariant.java | 48 ++ .../inference/TextEmbeddingRequest.java | 336 +++++++++++++ .../inference/TextEmbeddingResponse.java | 45 ++ .../inference/TextEmbeddingResult.java | 179 +++++++ .../inference/UpdateInferenceRequest.java | 298 +++++++++++ .../inference/UpdateInferenceResponse.java | 107 ++++ .../CompletionTool.java | 197 ++++++++ .../CompletionToolChoice.java | 199 ++++++++ .../CompletionToolChoiceFunction.java | 162 ++++++ .../CompletionToolFunction.java | 268 ++++++++++ .../CompletionToolType.java | 191 ++++++++ .../CompletionToolTypeBuilders.java | 59 +++ .../ContentObject.java | 187 +++++++ .../chat_completion_unified/Message.java | 297 +++++++++++ .../MessageContent.java | 196 ++++++++ .../MessageContentBuilders.java | 52 ++ .../chat_completion_unified/ToolCall.java | 224 +++++++++ .../ToolCallFunction.java | 187 +++++++ .../AlibabaCloudServiceSettings.java | 344 +++++++++++++ .../AlibabaCloudTaskSettings.java | 218 +++++++++ .../AlibabaCloudTaskType.java | 71 +++ .../put_alibabacloud/ServiceType.java | 65 +++ .../AmazonBedrockServiceSettings.java | 371 ++++++++++++++ .../AmazonBedrockTaskSettings.java | 292 +++++++++++ .../AmazonBedrockTaskType.java | 67 +++ .../put_amazonbedrock/ServiceType.java | 65 +++ .../AnthropicServiceSettings.java | 241 +++++++++ .../put_anthropic/AnthropicTaskSettings.java | 283 +++++++++++ .../put_anthropic/AnthropicTaskType.java | 65 +++ .../inference/put_anthropic/ServiceType.java | 65 +++ .../AzureAiStudioServiceSettings.java | 353 ++++++++++++++ .../AzureAiStudioTaskSettings.java | 320 ++++++++++++ .../AzureAiStudioTaskType.java | 67 +++ .../put_azureaistudio/ServiceType.java | 65 +++ .../AzureOpenAIServiceSettings.java | 368 ++++++++++++++ .../put_azureopenai/AzureOpenAITaskType.java | 67 +++ .../put_azureopenai/ServiceType.java | 65 +++ .../put_cohere/CohereServiceSettings.java | 363 ++++++++++++++ .../put_cohere/CohereTaskSettings.java | 317 ++++++++++++ .../inference/put_cohere/CohereTaskType.java | 69 +++ .../inference/put_cohere/EmbeddingType.java | 69 +++ .../inference/put_cohere/InputType.java | 71 +++ .../inference/put_cohere/ServiceType.java | 65 +++ .../inference/put_cohere/SimilarityType.java | 69 +++ .../inference/put_cohere/TruncateType.java | 69 +++ .../inference/put_eis/EisServiceSettings.java | 210 ++++++++ .../inference/put_eis/EisTaskType.java | 65 +++ .../inference/put_eis/ServiceType.java | 65 +++ .../AdaptiveAllocations.java | 236 +++++++++ .../ElasticsearchServiceSettings.java | 342 +++++++++++++ .../ElasticsearchTaskSettings.java | 168 +++++++ .../ElasticsearchTaskType.java | 69 +++ .../put_elasticsearch/ServiceType.java | 65 +++ .../put_elser/AdaptiveAllocations.java | 236 +++++++++ .../put_elser/ElserServiceSettings.java | 280 +++++++++++ .../inference/put_elser/ElserTaskType.java | 65 +++ .../GoogleAiStudioServiceSettings.java | 241 +++++++++ .../GoogleAiStudioTaskType.java | 67 +++ .../put_googleaistudio/ServiceType.java | 65 +++ .../GoogleVertexAIServiceSettings.java | 300 ++++++++++++ .../GoogleVertexAITaskSettings.java | 204 ++++++++ .../GoogleVertexAITaskType.java | 67 +++ .../put_googlevertexai/ServiceType.java | 65 +++ .../HuggingFaceServiceSettings.java | 252 ++++++++++ .../put_hugging_face/HuggingFaceTaskType.java | 65 +++ .../put_hugging_face/ServiceType.java | 65 +++ .../put_jinaai/JinaAIServiceSettings.java | 297 +++++++++++ .../put_jinaai/JinaAITaskSettings.java | 261 ++++++++++ .../inference/put_jinaai/JinaAITaskType.java | 67 +++ .../inference/put_jinaai/ServiceType.java | 65 +++ .../inference/put_jinaai/SimilarityType.java | 69 +++ .../put_jinaai/TextEmbeddingTask.java | 71 +++ .../put_mistral/MistralServiceSettings.java | 289 +++++++++++ .../put_mistral/MistralTaskType.java | 65 +++ .../inference/put_mistral/ServiceType.java | 65 +++ .../put_openai/OpenAIServiceSettings.java | 368 ++++++++++++++ .../put_openai/OpenAITaskSettings.java | 169 +++++++ .../inference/put_openai/OpenAITaskType.java | 69 +++ .../inference/put_openai/ServiceType.java | 77 +++ .../inference/put_voyageai/ServiceType.java | 65 +++ .../put_voyageai/VoyageAIServiceSettings.java | 303 ++++++++++++ .../put_voyageai/VoyageAITaskSettings.java | 278 +++++++++++ .../put_voyageai/VoyageAITaskType.java | 67 +++ .../inference/put_watsonx/ServiceType.java | 65 +++ .../put_watsonx/WatsonxServiceSettings.java | 346 +++++++++++++ .../put_watsonx/WatsonxTaskType.java | 65 +++ 155 files changed, 22512 insertions(+) create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionInferenceResult.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionRequest.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionResult.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceEndpointResult.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceRequest.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/GetInferenceRequest.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/GetInferenceResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceChunkingSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceEndpoint.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceEndpointInfo.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutRequest.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RankedDocument.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RateLimitSetting.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RequestChatCompletionBase.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankRequest.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankedInferenceResult.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingInferenceResult.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingRequest.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingResult.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/StreamCompletionRequest.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingByteResult.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResult.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResultBuilders.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResultVariant.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingRequest.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResult.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/UpdateInferenceRequest.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/UpdateInferenceResponse.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionTool.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolChoice.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolChoiceFunction.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolFunction.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolTypeBuilders.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ContentObject.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/Message.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/MessageContent.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/MessageContentBuilders.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ToolCall.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ToolCallFunction.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAIServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAITaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/EmbeddingType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/InputType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/SimilarityType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/TruncateType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/EisServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/EisTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/AdaptiveAllocations.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/AdaptiveAllocations.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAIServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAIServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/SimilarityType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/TextEmbeddingTask.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralTaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAIServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAITaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAITaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAIServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAITaskSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAITaskType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/ServiceType.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/WatsonxServiceSettings.java create mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/WatsonxTaskType.java diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java index c8c94db51..0d6e56a29 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java @@ -120,6 +120,7 @@ import co.elastic.clients.elasticsearch.graph.ElasticsearchGraphAsyncClient; import co.elastic.clients.elasticsearch.ilm.ElasticsearchIlmAsyncClient; import co.elastic.clients.elasticsearch.indices.ElasticsearchIndicesAsyncClient; +import co.elastic.clients.elasticsearch.inference.ElasticsearchInferenceAsyncClient; import co.elastic.clients.elasticsearch.ingest.ElasticsearchIngestAsyncClient; import co.elastic.clients.elasticsearch.license.ElasticsearchLicenseAsyncClient; import co.elastic.clients.elasticsearch.logstash.ElasticsearchLogstashAsyncClient; @@ -264,6 +265,10 @@ public ElasticsearchIndicesAsyncClient indices() { return new ElasticsearchIndicesAsyncClient(this.transport, this.transportOptions); } + public ElasticsearchInferenceAsyncClient inference() { + return new ElasticsearchInferenceAsyncClient(this.transport, this.transportOptions); + } + public ElasticsearchIngestAsyncClient ingest() { return new ElasticsearchIngestAsyncClient(this.transport, this.transportOptions); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java index 997ac03e0..e571b6f8f 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java @@ -121,6 +121,7 @@ import co.elastic.clients.elasticsearch.graph.ElasticsearchGraphClient; import co.elastic.clients.elasticsearch.ilm.ElasticsearchIlmClient; import co.elastic.clients.elasticsearch.indices.ElasticsearchIndicesClient; +import co.elastic.clients.elasticsearch.inference.ElasticsearchInferenceClient; import co.elastic.clients.elasticsearch.ingest.ElasticsearchIngestClient; import co.elastic.clients.elasticsearch.license.ElasticsearchLicenseClient; import co.elastic.clients.elasticsearch.logstash.ElasticsearchLogstashClient; @@ -264,6 +265,10 @@ public ElasticsearchIndicesClient indices() { return new ElasticsearchIndicesClient(this.transport, this.transportOptions); } + public ElasticsearchInferenceClient inference() { + return new ElasticsearchInferenceClient(this.transport, this.transportOptions); + } + public ElasticsearchIngestClient ingest() { return new ElasticsearchIngestClient(this.transport, this.transportOptions); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ChatCompletionUnifiedRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ChatCompletionUnifiedRequest.java index 08dbfdc7e..a75c98530 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ChatCompletionUnifiedRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ChatCompletionUnifiedRequest.java @@ -33,9 +33,12 @@ import co.elastic.clients.util.ObjectBuilder; import jakarta.json.stream.JsonGenerator; <<<<<<< HEAD +<<<<<<< HEAD import jakarta.json.stream.JsonParser; ======= >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import java.lang.String; import java.util.HashMap; import java.util.Map; @@ -74,11 +77,14 @@ public class ChatCompletionUnifiedRequest extends RequestChatCompletionBase { @Nullable private final Time timeout; +<<<<<<< HEAD <<<<<<< HEAD private final RequestChatCompletion chatCompletionRequest; ======= >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") // --------------------------------------------------------------------------------------------- private ChatCompletionUnifiedRequest(Builder builder) { @@ -86,11 +92,14 @@ private ChatCompletionUnifiedRequest(Builder builder) { this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); this.timeout = builder.timeout; +<<<<<<< HEAD <<<<<<< HEAD this.chatCompletionRequest = ApiTypeHelper.requireNonNull(builder.chatCompletionRequest, this, "chatCompletionRequest"); ======= >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") } @@ -117,6 +126,7 @@ public final Time timeout() { return this.timeout; } +<<<<<<< HEAD <<<<<<< HEAD /** * Required - Request body. @@ -135,6 +145,8 @@ public void serialize(JsonGenerator generator, JsonpMapper mapper) { ======= >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") // --------------------------------------------------------------------------------------------- /** @@ -149,11 +161,14 @@ public static class Builder extends RequestChatCompletionBase.AbstractBuilder>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") /** * Required - The inference Id *

@@ -183,6 +198,7 @@ public final Builder timeout(Function> fn) { return this.timeout(fn.apply(new Time.Builder()).build()); } +<<<<<<< HEAD <<<<<<< HEAD /** * Required - Request body. @@ -211,6 +227,8 @@ public Builder withJson(JsonParser parser, JsonpMapper mapper) { ======= >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") @Override protected Builder self() { return this; @@ -229,12 +247,17 @@ public ChatCompletionUnifiedRequest build() { } } +<<<<<<< HEAD public static final JsonpDeserializer _DESERIALIZER = createChatCompletionUnifiedRequestDeserializer(); protected static JsonpDeserializer createChatCompletionUnifiedRequestDeserializer() { <<<<<<< HEAD JsonpDeserializer valueDeserializer = RequestChatCompletion._DESERIALIZER; ======= +======= + // --------------------------------------------------------------------------------------------- + +>>>>>>> c49af58dc (Revert "temp rebase fix") /** * Json deserializer for {@link ChatCompletionUnifiedRequest} */ @@ -244,10 +267,14 @@ protected static JsonpDeserializer createChatCompl protected static void setupChatCompletionUnifiedRequestDeserializer( ObjectDeserializer op) { RequestChatCompletionBase.setupRequestChatCompletionBaseDeserializer(op); +<<<<<<< HEAD >>>>>>> 03828daff (regen from latest spec) return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() .chatCompletionRequest(valueDeserializer.deserialize(parser, mapper, event)).build()); +======= + +>>>>>>> c49af58dc (Revert "temp rebase fix") } // --------------------------------------------------------------------------------------------- diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionInferenceResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionInferenceResult.java new file mode 100644 index 000000000..145e988f7 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionInferenceResult.java @@ -0,0 +1,157 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference._types.CompletionInferenceResult + +/** + * Defines the completion result. + * + * @see API + * specification + */ + +public abstract class CompletionInferenceResult implements JsonpSerializable { + private final List completion; + + // --------------------------------------------------------------------------------------------- + + protected CompletionInferenceResult(AbstractBuilder builder) { + + this.completion = ApiTypeHelper.unmodifiableRequired(builder.completion, this, "completion"); + + } + + /** + * Required - API name: {@code completion} + */ + public final List completion() { + return this.completion; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (ApiTypeHelper.isDefined(this.completion)) { + generator.writeKey("completion"); + generator.writeStartArray(); + for (CompletionResult item0 : this.completion) { + item0.serialize(generator, mapper); + + } + generator.writeEnd(); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + public abstract static class AbstractBuilder> + extends + WithJsonObjectBuilderBase { + private List completion; + + /** + * Required - API name: {@code completion} + *

+ * Adds all elements of list to completion. + */ + public final BuilderT completion(List list) { + this.completion = _listAddAll(this.completion, list); + return self(); + } + + /** + * Required - API name: {@code completion} + *

+ * Adds one or more values to completion. + */ + public final BuilderT completion(CompletionResult value, CompletionResult... values) { + this.completion = _listAdd(this.completion, value, values); + return self(); + } + + /** + * Required - API name: {@code completion} + *

+ * Adds a value to completion using a builder lambda. + */ + public final BuilderT completion(Function> fn) { + return completion(fn.apply(new CompletionResult.Builder()).build()); + } + + protected abstract BuilderT self(); + + } + + // --------------------------------------------------------------------------------------------- + protected static > void setupCompletionInferenceResultDeserializer( + ObjectDeserializer op) { + + op.add(AbstractBuilder::completion, JsonpDeserializer.arrayDeserializer(CompletionResult._DESERIALIZER), + "completion"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionRequest.java new file mode 100644 index 000000000..93201e360 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionRequest.java @@ -0,0 +1,335 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch._types.RequestBase; +import co.elastic.clients.elasticsearch._types.Time; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.endpoints.SimpleEndpoint; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.completion.Request + +/** + * Perform completion inference on the service + * + * @see API + * specification + */ +@JsonpDeserializable +public class CompletionRequest extends RequestBase implements JsonpSerializable { + private final String inferenceId; + + private final List input; + + @Nullable + private final JsonData taskSettings; + + @Nullable + private final Time timeout; + + // --------------------------------------------------------------------------------------------- + + private CompletionRequest(Builder builder) { + + this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); + this.input = ApiTypeHelper.unmodifiableRequired(builder.input, this, "input"); + this.taskSettings = builder.taskSettings; + this.timeout = builder.timeout; + + } + + public static CompletionRequest of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The inference Id + *

+ * API name: {@code inference_id} + */ + public final String inferenceId() { + return this.inferenceId; + } + + /** + * Required - Inference input. Either a string or an array of strings. + *

+ * API name: {@code input} + */ + public final List input() { + return this.input; + } + + /** + * Optional task settings + *

+ * API name: {@code task_settings} + */ + @Nullable + public final JsonData taskSettings() { + return this.taskSettings; + } + + /** + * Specifies the amount of time to wait for the inference request to complete. + *

+ * API name: {@code timeout} + */ + @Nullable + public final Time timeout() { + return this.timeout; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (ApiTypeHelper.isDefined(this.input)) { + generator.writeKey("input"); + generator.writeStartArray(); + for (String item0 : this.input) { + generator.write(item0); + + } + generator.writeEnd(); + + } + if (this.taskSettings != null) { + generator.writeKey("task_settings"); + this.taskSettings.serialize(generator, mapper); + + } + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link CompletionRequest}. + */ + + public static class Builder extends RequestBase.AbstractBuilder + implements + ObjectBuilder { + private String inferenceId; + + private List input; + + @Nullable + private JsonData taskSettings; + + @Nullable + private Time timeout; + + /** + * Required - The inference Id + *

+ * API name: {@code inference_id} + */ + public final Builder inferenceId(String value) { + this.inferenceId = value; + return this; + } + + /** + * Required - Inference input. Either a string or an array of strings. + *

+ * API name: {@code input} + *

+ * Adds all elements of list to input. + */ + public final Builder input(List list) { + this.input = _listAddAll(this.input, list); + return this; + } + + /** + * Required - Inference input. Either a string or an array of strings. + *

+ * API name: {@code input} + *

+ * Adds one or more values to input. + */ + public final Builder input(String value, String... values) { + this.input = _listAdd(this.input, value, values); + return this; + } + + /** + * Optional task settings + *

+ * API name: {@code task_settings} + */ + public final Builder taskSettings(@Nullable JsonData value) { + this.taskSettings = value; + return this; + } + + /** + * Specifies the amount of time to wait for the inference request to complete. + *

+ * API name: {@code timeout} + */ + public final Builder timeout(@Nullable Time value) { + this.timeout = value; + return this; + } + + /** + * Specifies the amount of time to wait for the inference request to complete. + *

+ * API name: {@code timeout} + */ + public final Builder timeout(Function> fn) { + return this.timeout(fn.apply(new Time.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link CompletionRequest}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public CompletionRequest build() { + _checkSingleUse(); + + return new CompletionRequest(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link CompletionRequest} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, CompletionRequest::setupCompletionRequestDeserializer); + + protected static void setupCompletionRequestDeserializer(ObjectDeserializer op) { + + op.add(Builder::input, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), "input"); + op.add(Builder::taskSettings, JsonData._DESERIALIZER, "task_settings"); + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Endpoint "{@code inference.completion}". + */ + public static final Endpoint _ENDPOINT = new SimpleEndpoint<>( + "es/inference.completion", + + // Request method + request -> { + return "POST"; + + }, + + // Request path + request -> { + final int _inferenceId = 1 << 0; + + int propsSet = 0; + + propsSet |= _inferenceId; + + if (propsSet == (_inferenceId)) { + StringBuilder buf = new StringBuilder(); + buf.append("/_inference"); + buf.append("/completion"); + buf.append("/"); + SimpleEndpoint.pathEncode(request.inferenceId, buf); + return buf.toString(); + } + throw SimpleEndpoint.noPathTemplateFound("path"); + + }, + + // Path parameters + request -> { + Map params = new HashMap<>(); + final int _inferenceId = 1 << 0; + + int propsSet = 0; + + propsSet |= _inferenceId; + + if (propsSet == (_inferenceId)) { + params.put("inferenceId", request.inferenceId); + } + return params; + }, + + // Request parameters + request -> { + Map params = new HashMap<>(); + if (request.timeout != null) { + params.put("timeout", request.timeout._toJsonString()); + } + return params; + + }, SimpleEndpoint.emptyMap(), true, CompletionResponse._DESERIALIZER); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionResponse.java new file mode 100644 index 000000000..bc21e2246 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionResponse.java @@ -0,0 +1,106 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.completion.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class CompletionResponse extends CompletionInferenceResult { + // --------------------------------------------------------------------------------------------- + + private CompletionResponse(Builder builder) { + super(builder); + + } + + public static CompletionResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link CompletionResponse}. + */ + + public static class Builder extends CompletionInferenceResult.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link CompletionResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public CompletionResponse build() { + _checkSingleUse(); + + return new CompletionResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link CompletionResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, CompletionResponse::setupCompletionResponseDeserializer); + + protected static void setupCompletionResponseDeserializer(ObjectDeserializer op) { + CompletionInferenceResult.setupCompletionInferenceResultDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionResult.java new file mode 100644 index 000000000..345149456 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/CompletionResult.java @@ -0,0 +1,155 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference._types.CompletionResult + +/** + * The completion result object + * + * @see API + * specification + */ +@JsonpDeserializable +public class CompletionResult implements JsonpSerializable { + private final String result; + + // --------------------------------------------------------------------------------------------- + + private CompletionResult(Builder builder) { + + this.result = ApiTypeHelper.requireNonNull(builder.result, this, "result"); + + } + + public static CompletionResult of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - API name: {@code result} + */ + public final String result() { + return this.result; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("result"); + generator.write(this.result); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link CompletionResult}. + */ + + public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { + private String result; + + /** + * Required - API name: {@code result} + */ + public final Builder result(String value) { + this.result = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link CompletionResult}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public CompletionResult build() { + _checkSingleUse(); + + return new CompletionResult(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link CompletionResult} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + CompletionResult::setupCompletionResultDeserializer); + + protected static void setupCompletionResultDeserializer(ObjectDeserializer op) { + + op.add(Builder::result, JsonpDeserializer.stringDeserializer(), "result"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceEndpointResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceEndpointResult.java new file mode 100644 index 000000000..345a060f3 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceEndpointResult.java @@ -0,0 +1,134 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.elasticsearch._types.AcknowledgedResponseBase; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.List; +import java.util.Objects; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference._types.DeleteInferenceEndpointResult + +/** + * Acknowledged response. For dry_run, contains the list of pipelines which + * reference the inference endpoint + * + * @see API + * specification + */ + +public abstract class DeleteInferenceEndpointResult extends AcknowledgedResponseBase { + private final List pipelines; + + // --------------------------------------------------------------------------------------------- + + protected DeleteInferenceEndpointResult(AbstractBuilder builder) { + super(builder); + + this.pipelines = ApiTypeHelper.unmodifiableRequired(builder.pipelines, this, "pipelines"); + + } + + /** + * Required - API name: {@code pipelines} + */ + public final List pipelines() { + return this.pipelines; + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + super.serializeInternal(generator, mapper); + if (ApiTypeHelper.isDefined(this.pipelines)) { + generator.writeKey("pipelines"); + generator.writeStartArray(); + for (String item0 : this.pipelines) { + generator.write(item0); + + } + generator.writeEnd(); + + } + + } + + public abstract static class AbstractBuilder> + extends + AcknowledgedResponseBase.AbstractBuilder { + private List pipelines; + + /** + * Required - API name: {@code pipelines} + *

+ * Adds all elements of list to pipelines. + */ + public final BuilderT pipelines(List list) { + this.pipelines = _listAddAll(this.pipelines, list); + return self(); + } + + /** + * Required - API name: {@code pipelines} + *

+ * Adds one or more values to pipelines. + */ + public final BuilderT pipelines(String value, String... values) { + this.pipelines = _listAdd(this.pipelines, value, values); + return self(); + } + + } + + // --------------------------------------------------------------------------------------------- + protected static > void setupDeleteInferenceEndpointResultDeserializer( + ObjectDeserializer op) { + AcknowledgedResponseBase.setupAcknowledgedResponseBaseDeserializer(op); + op.add(AbstractBuilder::pipelines, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), + "pipelines"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceRequest.java new file mode 100644 index 000000000..96d1ed6f8 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceRequest.java @@ -0,0 +1,292 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch._types.RequestBase; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.endpoints.SimpleEndpoint; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.lang.String; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.delete.Request + +/** + * Delete an inference endpoint + * + * @see API + * specification + */ + +public class DeleteInferenceRequest extends RequestBase { + @Nullable + private final Boolean dryRun; + + @Nullable + private final Boolean force; + + private final String inferenceId; + + @Nullable + private final TaskType taskType; + + // --------------------------------------------------------------------------------------------- + + private DeleteInferenceRequest(Builder builder) { + + this.dryRun = builder.dryRun; + this.force = builder.force; + this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); + this.taskType = builder.taskType; + + } + + public static DeleteInferenceRequest of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * When true, the endpoint is not deleted and a list of ingest processors which + * reference this endpoint is returned. + *

+ * API name: {@code dry_run} + */ + @Nullable + public final Boolean dryRun() { + return this.dryRun; + } + + /** + * When true, the inference endpoint is forcefully deleted even if it is still + * being used by ingest processors or semantic text fields. + *

+ * API name: {@code force} + */ + @Nullable + public final Boolean force() { + return this.force; + } + + /** + * Required - The inference identifier. + *

+ * API name: {@code inference_id} + */ + public final String inferenceId() { + return this.inferenceId; + } + + /** + * The task type + *

+ * API name: {@code task_type} + */ + @Nullable + public final TaskType taskType() { + return this.taskType; + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link DeleteInferenceRequest}. + */ + + public static class Builder extends RequestBase.AbstractBuilder + implements + ObjectBuilder { + @Nullable + private Boolean dryRun; + + @Nullable + private Boolean force; + + private String inferenceId; + + @Nullable + private TaskType taskType; + + /** + * When true, the endpoint is not deleted and a list of ingest processors which + * reference this endpoint is returned. + *

+ * API name: {@code dry_run} + */ + public final Builder dryRun(@Nullable Boolean value) { + this.dryRun = value; + return this; + } + + /** + * When true, the inference endpoint is forcefully deleted even if it is still + * being used by ingest processors or semantic text fields. + *

+ * API name: {@code force} + */ + public final Builder force(@Nullable Boolean value) { + this.force = value; + return this; + } + + /** + * Required - The inference identifier. + *

+ * API name: {@code inference_id} + */ + public final Builder inferenceId(String value) { + this.inferenceId = value; + return this; + } + + /** + * The task type + *

+ * API name: {@code task_type} + */ + public final Builder taskType(@Nullable TaskType value) { + this.taskType = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link DeleteInferenceRequest}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public DeleteInferenceRequest build() { + _checkSingleUse(); + + return new DeleteInferenceRequest(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Endpoint "{@code inference.delete}". + */ + public static final Endpoint _ENDPOINT = new SimpleEndpoint<>( + "es/inference.delete", + + // Request method + request -> { + return "DELETE"; + + }, + + // Request path + request -> { + final int _inferenceId = 1 << 0; + final int _taskType = 1 << 1; + + int propsSet = 0; + + propsSet |= _inferenceId; + if (request.taskType() != null) + propsSet |= _taskType; + + if (propsSet == (_inferenceId)) { + StringBuilder buf = new StringBuilder(); + buf.append("/_inference"); + buf.append("/"); + SimpleEndpoint.pathEncode(request.inferenceId, buf); + return buf.toString(); + } + if (propsSet == (_taskType | _inferenceId)) { + StringBuilder buf = new StringBuilder(); + buf.append("/_inference"); + buf.append("/"); + SimpleEndpoint.pathEncode(request.taskType.jsonValue(), buf); + buf.append("/"); + SimpleEndpoint.pathEncode(request.inferenceId, buf); + return buf.toString(); + } + throw SimpleEndpoint.noPathTemplateFound("path"); + + }, + + // Path parameters + request -> { + Map params = new HashMap<>(); + final int _inferenceId = 1 << 0; + final int _taskType = 1 << 1; + + int propsSet = 0; + + propsSet |= _inferenceId; + if (request.taskType() != null) + propsSet |= _taskType; + + if (propsSet == (_inferenceId)) { + params.put("inferenceId", request.inferenceId); + } + if (propsSet == (_taskType | _inferenceId)) { + params.put("taskType", request.taskType.jsonValue()); + params.put("inferenceId", request.inferenceId); + } + return params; + }, + + // Request parameters + request -> { + Map params = new HashMap<>(); + if (request.dryRun != null) { + params.put("dry_run", String.valueOf(request.dryRun)); + } + if (request.force != null) { + params.put("force", String.valueOf(request.force)); + } + return params; + + }, SimpleEndpoint.emptyMap(), false, DeleteInferenceResponse._DESERIALIZER); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceResponse.java new file mode 100644 index 000000000..1ddee6c97 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/DeleteInferenceResponse.java @@ -0,0 +1,107 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.delete.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class DeleteInferenceResponse extends DeleteInferenceEndpointResult { + // --------------------------------------------------------------------------------------------- + + private DeleteInferenceResponse(Builder builder) { + super(builder); + + } + + public static DeleteInferenceResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link DeleteInferenceResponse}. + */ + + public static class Builder extends DeleteInferenceEndpointResult.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link DeleteInferenceResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public DeleteInferenceResponse build() { + _checkSingleUse(); + + return new DeleteInferenceResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link DeleteInferenceResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, DeleteInferenceResponse::setupDeleteInferenceResponseDeserializer); + + protected static void setupDeleteInferenceResponseDeserializer( + ObjectDeserializer op) { + DeleteInferenceEndpointResult.setupDeleteInferenceEndpointResultDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceAsyncClient.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceAsyncClient.java index 940c51544..5e81a9262 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceAsyncClient.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceAsyncClient.java @@ -320,6 +320,7 @@ public final CompletableFuture put(Function putCohere( return putCohere(fn.apply(new PutCohereRequest.Builder()).build()); } +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") // ----- Endpoint: inference.put_eis /** @@ -731,7 +734,11 @@ public final CompletableFuture putCohere( * Inference Service (EIS). * * @see Documentation +======= + * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-eis.html">Documentation +>>>>>>> c49af58dc (Revert "temp rebase fix") * on elastic.co */ @@ -752,7 +759,11 @@ public CompletableFuture putEis(PutEisRequest request) { * a function that initializes a builder to create the * {@link PutEisRequest} * @see Documentation +======= + * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-eis.html">Documentation +>>>>>>> c49af58dc (Revert "temp rebase fix") * on elastic.co */ @@ -761,6 +772,7 @@ public final CompletableFuture putEis( return putEis(fn.apply(new PutEisRequest.Builder()).build()); } +<<<<<<< HEAD // ----- Endpoint: inference.put_elasticsearch /** @@ -1288,13 +1300,19 @@ public final CompletableFuture putMistral( return putMistral(fn.apply(new PutMistralRequest.Builder()).build()); } +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") // ----- Endpoint: inference.put_openai /** * Create an OpenAI inference endpoint. *

* Create an inference endpoint to perform an inference task with the +<<<<<<< HEAD * openai service or openai compatible APIs. +======= + * openai service. +>>>>>>> c49af58dc (Revert "temp rebase fix") *

* When you create an inference endpoint, the associated machine learning model * is automatically deployed if it is not already running. After creating the @@ -1307,7 +1325,11 @@ public final CompletableFuture putMistral( * consumes significant resources. * * @see Documentation +======= + * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-openai.html">Documentation +>>>>>>> c49af58dc (Revert "temp rebase fix") * on elastic.co */ @@ -1322,7 +1344,11 @@ public CompletableFuture putOpenai(PutOpenaiRequest request) * Create an OpenAI inference endpoint. *

* Create an inference endpoint to perform an inference task with the +<<<<<<< HEAD * openai service or openai compatible APIs. +======= + * openai service. +>>>>>>> c49af58dc (Revert "temp rebase fix") *

* When you create an inference endpoint, the associated machine learning model * is automatically deployed if it is not already running. After creating the @@ -1338,7 +1364,11 @@ public CompletableFuture putOpenai(PutOpenaiRequest request) * a function that initializes a builder to create the * {@link PutOpenaiRequest} * @see Documentation +======= + * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-openai.html">Documentation +>>>>>>> c49af58dc (Revert "temp rebase fix") * on elastic.co */ diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceClient.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceClient.java index b9ac0f07f..b8bf847f7 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceClient.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceClient.java @@ -324,6 +324,7 @@ public final PutResponse put(Function>>>>>> c49af58dc (Revert "temp rebase fix") // ----- Endpoint: inference.put_eis /** @@ -744,7 +747,11 @@ public final PutCohereResponse putCohere(FunctionDocumentation +======= + * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-eis.html">Documentation +>>>>>>> c49af58dc (Revert "temp rebase fix") * on elastic.co */ @@ -765,7 +772,11 @@ public PutEisResponse putEis(PutEisRequest request) throws IOException, Elastics * a function that initializes a builder to create the * {@link PutEisRequest} * @see Documentation +======= + * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-eis.html">Documentation +>>>>>>> c49af58dc (Revert "temp rebase fix") * on elastic.co */ @@ -774,6 +785,7 @@ public final PutEisResponse putEis(Function>>>>>> c49af58dc (Revert "temp rebase fix") // ----- Endpoint: inference.put_openai /** * Create an OpenAI inference endpoint. *

* Create an inference endpoint to perform an inference task with the +<<<<<<< HEAD * openai service or openai compatible APIs. +======= + * openai service. +>>>>>>> c49af58dc (Revert "temp rebase fix") *

* When you create an inference endpoint, the associated machine learning model * is automatically deployed if it is not already running. After creating the @@ -1328,7 +1346,11 @@ public final PutMistralResponse putMistral(FunctionDocumentation +======= + * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-openai.html">Documentation +>>>>>>> c49af58dc (Revert "temp rebase fix") * on elastic.co */ @@ -1343,7 +1365,11 @@ public PutOpenaiResponse putOpenai(PutOpenaiRequest request) throws IOException, * Create an OpenAI inference endpoint. *

* Create an inference endpoint to perform an inference task with the +<<<<<<< HEAD * openai service or openai compatible APIs. +======= + * openai service. +>>>>>>> c49af58dc (Revert "temp rebase fix") *

* When you create an inference endpoint, the associated machine learning model * is automatically deployed if it is not already running. After creating the @@ -1359,7 +1385,11 @@ public PutOpenaiResponse putOpenai(PutOpenaiRequest request) throws IOException, * a function that initializes a builder to create the * {@link PutOpenaiRequest} * @see Documentation +======= + * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-openai.html">Documentation +>>>>>>> c49af58dc (Revert "temp rebase fix") * on elastic.co */ diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/GetInferenceRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/GetInferenceRequest.java new file mode 100644 index 000000000..8a167a202 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/GetInferenceRequest.java @@ -0,0 +1,238 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch._types.RequestBase; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.endpoints.SimpleEndpoint; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.get.Request + +/** + * Get an inference endpoint + * + * @see API + * specification + */ + +public class GetInferenceRequest extends RequestBase { + @Nullable + private final String inferenceId; + + @Nullable + private final TaskType taskType; + + // --------------------------------------------------------------------------------------------- + + private GetInferenceRequest(Builder builder) { + + this.inferenceId = builder.inferenceId; + this.taskType = builder.taskType; + + } + + public static GetInferenceRequest of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * The inference Id + *

+ * API name: {@code inference_id} + */ + @Nullable + public final String inferenceId() { + return this.inferenceId; + } + + /** + * The task type + *

+ * API name: {@code task_type} + */ + @Nullable + public final TaskType taskType() { + return this.taskType; + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link GetInferenceRequest}. + */ + + public static class Builder extends RequestBase.AbstractBuilder + implements + ObjectBuilder { + @Nullable + private String inferenceId; + + @Nullable + private TaskType taskType; + + /** + * The inference Id + *

+ * API name: {@code inference_id} + */ + public final Builder inferenceId(@Nullable String value) { + this.inferenceId = value; + return this; + } + + /** + * The task type + *

+ * API name: {@code task_type} + */ + public final Builder taskType(@Nullable TaskType value) { + this.taskType = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link GetInferenceRequest}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public GetInferenceRequest build() { + _checkSingleUse(); + + return new GetInferenceRequest(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Endpoint "{@code inference.get}". + */ + public static final Endpoint _ENDPOINT = new SimpleEndpoint<>( + "es/inference.get", + + // Request method + request -> { + return "GET"; + + }, + + // Request path + request -> { + final int _inferenceId = 1 << 0; + final int _taskType = 1 << 1; + + int propsSet = 0; + + if (request.inferenceId() != null) + propsSet |= _inferenceId; + if (request.taskType() != null) + propsSet |= _taskType; + + if (propsSet == 0) { + StringBuilder buf = new StringBuilder(); + buf.append("/_inference"); + return buf.toString(); + } + if (propsSet == (_inferenceId)) { + StringBuilder buf = new StringBuilder(); + buf.append("/_inference"); + buf.append("/"); + SimpleEndpoint.pathEncode(request.inferenceId, buf); + return buf.toString(); + } + if (propsSet == (_taskType | _inferenceId)) { + StringBuilder buf = new StringBuilder(); + buf.append("/_inference"); + buf.append("/"); + SimpleEndpoint.pathEncode(request.taskType.jsonValue(), buf); + buf.append("/"); + SimpleEndpoint.pathEncode(request.inferenceId, buf); + return buf.toString(); + } + throw SimpleEndpoint.noPathTemplateFound("path"); + + }, + + // Path parameters + request -> { + Map params = new HashMap<>(); + final int _inferenceId = 1 << 0; + final int _taskType = 1 << 1; + + int propsSet = 0; + + if (request.inferenceId() != null) + propsSet |= _inferenceId; + if (request.taskType() != null) + propsSet |= _taskType; + + if (propsSet == 0) { + } + if (propsSet == (_inferenceId)) { + params.put("inferenceId", request.inferenceId); + } + if (propsSet == (_taskType | _inferenceId)) { + params.put("taskType", request.taskType.jsonValue()); + params.put("inferenceId", request.inferenceId); + } + return params; + }, + + // Request parameters + request -> { + return Collections.emptyMap(); + + }, SimpleEndpoint.emptyMap(), false, GetInferenceResponse._DESERIALIZER); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/GetInferenceResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/GetInferenceResponse.java new file mode 100644 index 000000000..17a5d4458 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/GetInferenceResponse.java @@ -0,0 +1,186 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.get.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class GetInferenceResponse implements JsonpSerializable { + private final List endpoints; + + // --------------------------------------------------------------------------------------------- + + private GetInferenceResponse(Builder builder) { + + this.endpoints = ApiTypeHelper.unmodifiableRequired(builder.endpoints, this, "endpoints"); + + } + + public static GetInferenceResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - API name: {@code endpoints} + */ + public final List endpoints() { + return this.endpoints; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (ApiTypeHelper.isDefined(this.endpoints)) { + generator.writeKey("endpoints"); + generator.writeStartArray(); + for (InferenceEndpointInfo item0 : this.endpoints) { + item0.serialize(generator, mapper); + + } + generator.writeEnd(); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link GetInferenceResponse}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private List endpoints; + + /** + * Required - API name: {@code endpoints} + *

+ * Adds all elements of list to endpoints. + */ + public final Builder endpoints(List list) { + this.endpoints = _listAddAll(this.endpoints, list); + return this; + } + + /** + * Required - API name: {@code endpoints} + *

+ * Adds one or more values to endpoints. + */ + public final Builder endpoints(InferenceEndpointInfo value, InferenceEndpointInfo... values) { + this.endpoints = _listAdd(this.endpoints, value, values); + return this; + } + + /** + * Required - API name: {@code endpoints} + *

+ * Adds a value to endpoints using a builder lambda. + */ + public final Builder endpoints( + Function> fn) { + return endpoints(fn.apply(new InferenceEndpointInfo.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link GetInferenceResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public GetInferenceResponse build() { + _checkSingleUse(); + + return new GetInferenceResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link GetInferenceResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, GetInferenceResponse::setupGetInferenceResponseDeserializer); + + protected static void setupGetInferenceResponseDeserializer(ObjectDeserializer op) { + + op.add(Builder::endpoints, JsonpDeserializer.arrayDeserializer(InferenceEndpointInfo._DESERIALIZER), + "endpoints"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceChunkingSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceChunkingSettings.java new file mode 100644 index 000000000..7f85053c3 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceChunkingSettings.java @@ -0,0 +1,279 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Integer; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference._types.InferenceChunkingSettings + +/** + * Chunking configuration object + * + * @see API + * specification + */ +@JsonpDeserializable +public class InferenceChunkingSettings implements JsonpSerializable { + @Nullable + private final Integer maxChunkSize; + + @Nullable + private final Integer overlap; + + @Nullable + private final Integer sentenceOverlap; + + @Nullable + private final String strategy; + + // --------------------------------------------------------------------------------------------- + + private InferenceChunkingSettings(Builder builder) { + + this.maxChunkSize = builder.maxChunkSize; + this.overlap = builder.overlap; + this.sentenceOverlap = builder.sentenceOverlap; + this.strategy = builder.strategy; + + } + + public static InferenceChunkingSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * The maximum size of a chunk in words. This value cannot be higher than + * 300 or lower than 20 (for sentence + * strategy) or 10 (for word strategy). + *

+ * API name: {@code max_chunk_size} + */ + @Nullable + public final Integer maxChunkSize() { + return this.maxChunkSize; + } + + /** + * The number of overlapping words for chunks. It is applicable only to a + * word chunking strategy. This value cannot be higher than half + * the max_chunk_size value. + *

+ * API name: {@code overlap} + */ + @Nullable + public final Integer overlap() { + return this.overlap; + } + + /** + * The number of overlapping sentences for chunks. It is applicable only for a + * sentence chunking strategy. It can be either 1 or + * 0. + *

+ * API name: {@code sentence_overlap} + */ + @Nullable + public final Integer sentenceOverlap() { + return this.sentenceOverlap; + } + + /** + * The chunking strategy: sentence or word. + *

+ * API name: {@code strategy} + */ + @Nullable + public final String strategy() { + return this.strategy; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.maxChunkSize != null) { + generator.writeKey("max_chunk_size"); + generator.write(this.maxChunkSize); + + } + if (this.overlap != null) { + generator.writeKey("overlap"); + generator.write(this.overlap); + + } + if (this.sentenceOverlap != null) { + generator.writeKey("sentence_overlap"); + generator.write(this.sentenceOverlap); + + } + if (this.strategy != null) { + generator.writeKey("strategy"); + generator.write(this.strategy); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link InferenceChunkingSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private Integer maxChunkSize; + + @Nullable + private Integer overlap; + + @Nullable + private Integer sentenceOverlap; + + @Nullable + private String strategy; + + /** + * The maximum size of a chunk in words. This value cannot be higher than + * 300 or lower than 20 (for sentence + * strategy) or 10 (for word strategy). + *

+ * API name: {@code max_chunk_size} + */ + public final Builder maxChunkSize(@Nullable Integer value) { + this.maxChunkSize = value; + return this; + } + + /** + * The number of overlapping words for chunks. It is applicable only to a + * word chunking strategy. This value cannot be higher than half + * the max_chunk_size value. + *

+ * API name: {@code overlap} + */ + public final Builder overlap(@Nullable Integer value) { + this.overlap = value; + return this; + } + + /** + * The number of overlapping sentences for chunks. It is applicable only for a + * sentence chunking strategy. It can be either 1 or + * 0. + *

+ * API name: {@code sentence_overlap} + */ + public final Builder sentenceOverlap(@Nullable Integer value) { + this.sentenceOverlap = value; + return this; + } + + /** + * The chunking strategy: sentence or word. + *

+ * API name: {@code strategy} + */ + public final Builder strategy(@Nullable String value) { + this.strategy = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link InferenceChunkingSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public InferenceChunkingSettings build() { + _checkSingleUse(); + + return new InferenceChunkingSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link InferenceChunkingSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, InferenceChunkingSettings::setupInferenceChunkingSettingsDeserializer); + + protected static void setupInferenceChunkingSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::maxChunkSize, JsonpDeserializer.integerDeserializer(), "max_chunk_size"); + op.add(Builder::overlap, JsonpDeserializer.integerDeserializer(), "overlap"); + op.add(Builder::sentenceOverlap, JsonpDeserializer.integerDeserializer(), "sentence_overlap"); + op.add(Builder::strategy, JsonpDeserializer.stringDeserializer(), "strategy"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceEndpoint.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceEndpoint.java new file mode 100644 index 000000000..458cd09a8 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceEndpoint.java @@ -0,0 +1,275 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonData; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference._types.InferenceEndpoint + +/** + * Configuration options when storing the inference endpoint + * + * @see API + * specification + */ +@JsonpDeserializable +public class InferenceEndpoint implements JsonpSerializable { + @Nullable + private final InferenceChunkingSettings chunkingSettings; + + private final String service; + + private final JsonData serviceSettings; + + @Nullable + private final JsonData taskSettings; + + // --------------------------------------------------------------------------------------------- + + protected InferenceEndpoint(AbstractBuilder builder) { + + this.chunkingSettings = builder.chunkingSettings; + this.service = ApiTypeHelper.requireNonNull(builder.service, this, "service"); + this.serviceSettings = ApiTypeHelper.requireNonNull(builder.serviceSettings, this, "serviceSettings"); + this.taskSettings = builder.taskSettings; + + } + + public static InferenceEndpoint inferenceEndpointOf(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Chunking configuration object + *

+ * API name: {@code chunking_settings} + */ + @Nullable + public final InferenceChunkingSettings chunkingSettings() { + return this.chunkingSettings; + } + + /** + * Required - The service type + *

+ * API name: {@code service} + */ + public final String service() { + return this.service; + } + + /** + * Required - Settings specific to the service + *

+ * API name: {@code service_settings} + */ + public final JsonData serviceSettings() { + return this.serviceSettings; + } + + /** + * Task settings specific to the service and task type + *

+ * API name: {@code task_settings} + */ + @Nullable + public final JsonData taskSettings() { + return this.taskSettings; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.chunkingSettings != null) { + generator.writeKey("chunking_settings"); + this.chunkingSettings.serialize(generator, mapper); + + } + generator.writeKey("service"); + generator.write(this.service); + + generator.writeKey("service_settings"); + this.serviceSettings.serialize(generator, mapper); + + if (this.taskSettings != null) { + generator.writeKey("task_settings"); + this.taskSettings.serialize(generator, mapper); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link InferenceEndpoint}. + */ + + public static class Builder extends InferenceEndpoint.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link InferenceEndpoint}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public InferenceEndpoint build() { + _checkSingleUse(); + + return new InferenceEndpoint(this); + } + } + + public abstract static class AbstractBuilder> + extends + WithJsonObjectBuilderBase { + @Nullable + private InferenceChunkingSettings chunkingSettings; + + private String service; + + private JsonData serviceSettings; + + @Nullable + private JsonData taskSettings; + + /** + * Chunking configuration object + *

+ * API name: {@code chunking_settings} + */ + public final BuilderT chunkingSettings(@Nullable InferenceChunkingSettings value) { + this.chunkingSettings = value; + return self(); + } + + /** + * Chunking configuration object + *

+ * API name: {@code chunking_settings} + */ + public final BuilderT chunkingSettings( + Function> fn) { + return this.chunkingSettings(fn.apply(new InferenceChunkingSettings.Builder()).build()); + } + + /** + * Required - The service type + *

+ * API name: {@code service} + */ + public final BuilderT service(String value) { + this.service = value; + return self(); + } + + /** + * Required - Settings specific to the service + *

+ * API name: {@code service_settings} + */ + public final BuilderT serviceSettings(JsonData value) { + this.serviceSettings = value; + return self(); + } + + /** + * Task settings specific to the service and task type + *

+ * API name: {@code task_settings} + */ + public final BuilderT taskSettings(@Nullable JsonData value) { + this.taskSettings = value; + return self(); + } + + protected abstract BuilderT self(); + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link InferenceEndpoint} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, InferenceEndpoint::setupInferenceEndpointDeserializer); + + protected static > void setupInferenceEndpointDeserializer( + ObjectDeserializer op) { + + op.add(AbstractBuilder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); + op.add(AbstractBuilder::service, JsonpDeserializer.stringDeserializer(), "service"); + op.add(AbstractBuilder::serviceSettings, JsonData._DESERIALIZER, "service_settings"); + op.add(AbstractBuilder::taskSettings, JsonData._DESERIALIZER, "task_settings"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceEndpointInfo.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceEndpointInfo.java new file mode 100644 index 000000000..9ec75b927 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/InferenceEndpointInfo.java @@ -0,0 +1,182 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference._types.InferenceEndpointInfo + +/** + * Represents an inference endpoint as returned by the GET API + * + * @see API + * specification + */ +@JsonpDeserializable +public class InferenceEndpointInfo extends InferenceEndpoint { + private final String inferenceId; + + private final TaskType taskType; + + // --------------------------------------------------------------------------------------------- + + protected InferenceEndpointInfo(AbstractBuilder builder) { + super(builder); + + this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); + this.taskType = ApiTypeHelper.requireNonNull(builder.taskType, this, "taskType"); + + } + + public static InferenceEndpointInfo inferenceEndpointInfoOf( + Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The inference Id + *

+ * API name: {@code inference_id} + */ + public final String inferenceId() { + return this.inferenceId; + } + + /** + * Required - The task type + *

+ * API name: {@code task_type} + */ + public final TaskType taskType() { + return this.taskType; + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + super.serializeInternal(generator, mapper); + generator.writeKey("inference_id"); + generator.write(this.inferenceId); + + generator.writeKey("task_type"); + this.taskType.serialize(generator, mapper); + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link InferenceEndpointInfo}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link InferenceEndpointInfo}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public InferenceEndpointInfo build() { + _checkSingleUse(); + + return new InferenceEndpointInfo(this); + } + } + + public abstract static class AbstractBuilder> + extends + InferenceEndpoint.AbstractBuilder { + private String inferenceId; + + private TaskType taskType; + + /** + * Required - The inference Id + *

+ * API name: {@code inference_id} + */ + public final BuilderT inferenceId(String value) { + this.inferenceId = value; + return self(); + } + + /** + * Required - The task type + *

+ * API name: {@code task_type} + */ + public final BuilderT taskType(TaskType value) { + this.taskType = value; + return self(); + } + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link InferenceEndpointInfo} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, InferenceEndpointInfo::setupInferenceEndpointInfoDeserializer); + + protected static > void setupInferenceEndpointInfoDeserializer( + ObjectDeserializer op) { + InferenceEndpoint.setupInferenceEndpointDeserializer(op); + op.add(AbstractBuilder::inferenceId, JsonpDeserializer.stringDeserializer(), "inference_id"); + op.add(AbstractBuilder::taskType, TaskType._DESERIALIZER, "task_type"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PostEisChatCompletionRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PostEisChatCompletionRequest.java index 4e9e75981..abe28a1d1 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PostEisChatCompletionRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PostEisChatCompletionRequest.java @@ -21,6 +21,7 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; <<<<<<< HEAD +<<<<<<< HEAD import co.elastic.clients.elasticsearch._types.RequestBase; import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; @@ -30,6 +31,10 @@ import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; >>>>>>> 03828daff (regen from latest spec) +======= +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.ObjectBuilderDeserializer; import co.elastic.clients.json.ObjectDeserializer; import co.elastic.clients.transport.Endpoint; @@ -40,9 +45,12 @@ import co.elastic.clients.util.ObjectBuilder; import jakarta.json.stream.JsonGenerator; <<<<<<< HEAD +<<<<<<< HEAD import jakarta.json.stream.JsonParser; ======= >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import java.lang.String; import java.util.Collections; import java.util.HashMap; @@ -80,6 +88,7 @@ */ @JsonpDeserializable <<<<<<< HEAD +<<<<<<< HEAD public class PostEisChatCompletionRequest extends RequestBase implements JsonpSerializable { private final String eisInferenceId; @@ -93,6 +102,8 @@ private PostEisChatCompletionRequest(Builder builder) { this.chatCompletionRequest = ApiTypeHelper.requireNonNull(builder.chatCompletionRequest, this, "chatCompletionRequest"); ======= +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") public class PostEisChatCompletionRequest extends RequestChatCompletionBase { private final String eisInferenceId; @@ -102,7 +113,10 @@ private PostEisChatCompletionRequest(Builder builder) { super(builder); this.eisInferenceId = ApiTypeHelper.requireNonNull(builder.eisInferenceId, this, "eisInferenceId"); +<<<<<<< HEAD >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") } @@ -119,6 +133,7 @@ public final String eisInferenceId() { return this.eisInferenceId; } +<<<<<<< HEAD <<<<<<< HEAD /** * Required - Request body. @@ -137,26 +152,35 @@ public void serialize(JsonGenerator generator, JsonpMapper mapper) { ======= >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") // --------------------------------------------------------------------------------------------- /** * Builder for {@link PostEisChatCompletionRequest}. */ +<<<<<<< HEAD <<<<<<< HEAD public static class Builder extends RequestBase.AbstractBuilder ======= public static class Builder extends RequestChatCompletionBase.AbstractBuilder >>>>>>> 03828daff (regen from latest spec) +======= + public static class Builder extends RequestChatCompletionBase.AbstractBuilder +>>>>>>> c49af58dc (Revert "temp rebase fix") implements ObjectBuilder { private String eisInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private RequestChatCompletion chatCompletionRequest; ======= >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") /** * Required - The unique identifier of the inference endpoint. *

@@ -167,6 +191,7 @@ public final Builder eisInferenceId(String value) { return this; } +<<<<<<< HEAD <<<<<<< HEAD /** * Required - Request body. @@ -195,6 +220,8 @@ public Builder withJson(JsonParser parser, JsonpMapper mapper) { ======= >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") @Override protected Builder self() { return this; @@ -213,6 +240,7 @@ public PostEisChatCompletionRequest build() { } } +<<<<<<< HEAD <<<<<<< HEAD public static final JsonpDeserializer _DESERIALIZER = createPostEisChatCompletionRequestDeserializer(); protected static JsonpDeserializer createPostEisChatCompletionRequestDeserializer() { @@ -222,6 +250,8 @@ protected static JsonpDeserializer createPostEisCh return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() .chatCompletionRequest(valueDeserializer.deserialize(parser, mapper, event)).build()); ======= +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") // --------------------------------------------------------------------------------------------- /** @@ -234,7 +264,10 @@ protected static void setupPostEisChatCompletionRequestDeserializer( ObjectDeserializer op) { RequestChatCompletionBase.setupRequestChatCompletionBaseDeserializer(op); +<<<<<<< HEAD >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") } // --------------------------------------------------------------------------------------------- diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudRequest.java index 9b059126a..c665dc530 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudRequest.java @@ -22,12 +22,18 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD +======= ======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.elasticsearch.inference.put_alibabacloud.AlibabaCloudServiceSettings; import co.elastic.clients.elasticsearch.inference.put_alibabacloud.AlibabaCloudTaskSettings; import co.elastic.clients.elasticsearch.inference.put_alibabacloud.AlibabaCloudTaskType; import co.elastic.clients.elasticsearch.inference.put_alibabacloud.ServiceType; +<<<<<<< HEAD >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -91,11 +97,15 @@ public class PutAlibabacloudRequest extends RequestBase implements JsonpSerializ @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD private final AlibabaCloudServiceType service; ======= private final ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final AlibabaCloudServiceSettings serviceSettings; @@ -147,11 +157,15 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final AlibabaCloudServiceType service() { ======= public final ServiceType service() { >>>>>>> 03828daff (regen from latest spec) +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -228,11 +242,15 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD private AlibabaCloudServiceType service; ======= private ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private AlibabaCloudServiceSettings serviceSettings; @@ -277,11 +295,15 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(AlibabaCloudServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> 03828daff (regen from latest spec) +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -370,11 +392,15 @@ protected static void setupPutAlibabacloudRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, AlibabaCloudServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> 03828daff (regen from latest spec) +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, AlibabaCloudServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AlibabaCloudTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudResponse.java new file mode 100644 index 000000000..b6c1d6132 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudResponse.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_alibabacloud.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutAlibabacloudResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutAlibabacloudResponse(Builder builder) { + super(builder); + + } + + public static PutAlibabacloudResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutAlibabacloudResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutAlibabacloudResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutAlibabacloudResponse build() { + _checkSingleUse(); + + return new PutAlibabacloudResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutAlibabacloudResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, PutAlibabacloudResponse::setupPutAlibabacloudResponseDeserializer); + + protected static void setupPutAlibabacloudResponseDeserializer( + ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockRequest.java index abd6b0a12..eaff4e191 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockRequest.java @@ -22,12 +22,18 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD +======= ======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.elasticsearch.inference.put_amazonbedrock.AmazonBedrockServiceSettings; import co.elastic.clients.elasticsearch.inference.put_amazonbedrock.AmazonBedrockTaskSettings; import co.elastic.clients.elasticsearch.inference.put_amazonbedrock.AmazonBedrockTaskType; import co.elastic.clients.elasticsearch.inference.put_amazonbedrock.ServiceType; +<<<<<<< HEAD >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -100,11 +106,15 @@ public class PutAmazonbedrockRequest extends RequestBase implements JsonpSeriali @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD private final AmazonBedrockServiceType service; ======= private final ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final AmazonBedrockServiceSettings serviceSettings; @@ -156,11 +166,15 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final AmazonBedrockServiceType service() { ======= public final ServiceType service() { >>>>>>> 03828daff (regen from latest spec) +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -237,11 +251,15 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD private AmazonBedrockServiceType service; ======= private ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private AmazonBedrockServiceSettings serviceSettings; @@ -286,11 +304,15 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(AmazonBedrockServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> 03828daff (regen from latest spec) +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -379,11 +401,15 @@ protected static void setupPutAmazonbedrockRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, AmazonBedrockServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> 03828daff (regen from latest spec) +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, AmazonBedrockServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AmazonBedrockTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockResponse.java new file mode 100644 index 000000000..2d0bc5d53 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockResponse.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_amazonbedrock.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutAmazonbedrockResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutAmazonbedrockResponse(Builder builder) { + super(builder); + + } + + public static PutAmazonbedrockResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutAmazonbedrockResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutAmazonbedrockResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutAmazonbedrockResponse build() { + _checkSingleUse(); + + return new PutAmazonbedrockResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutAmazonbedrockResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, PutAmazonbedrockResponse::setupPutAmazonbedrockResponseDeserializer); + + protected static void setupPutAmazonbedrockResponseDeserializer( + ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicRequest.java index 164826986..ec31225a8 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicRequest.java @@ -22,12 +22,18 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD +======= ======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.elasticsearch.inference.put_anthropic.AnthropicServiceSettings; import co.elastic.clients.elasticsearch.inference.put_anthropic.AnthropicTaskSettings; import co.elastic.clients.elasticsearch.inference.put_anthropic.AnthropicTaskType; import co.elastic.clients.elasticsearch.inference.put_anthropic.ServiceType; +<<<<<<< HEAD >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -90,11 +96,15 @@ public class PutAnthropicRequest extends RequestBase implements JsonpSerializabl @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD private final AnthropicServiceType service; ======= private final ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final AnthropicServiceSettings serviceSettings; @@ -146,11 +156,15 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final AnthropicServiceType service() { ======= public final ServiceType service() { >>>>>>> 03828daff (regen from latest spec) +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -228,11 +242,15 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD private AnthropicServiceType service; ======= private ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private AnthropicServiceSettings serviceSettings; @@ -277,11 +295,15 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(AnthropicServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> 03828daff (regen from latest spec) +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -370,11 +392,15 @@ public PutAnthropicRequest build() { protected static void setupPutAnthropicRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, AnthropicServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> 03828daff (regen from latest spec) +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, AnthropicServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AnthropicTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicResponse.java new file mode 100644 index 000000000..ecf53c22a --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicResponse.java @@ -0,0 +1,107 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_anthropic.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutAnthropicResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutAnthropicResponse(Builder builder) { + super(builder); + + } + + public static PutAnthropicResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutAnthropicResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutAnthropicResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutAnthropicResponse build() { + _checkSingleUse(); + + return new PutAnthropicResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutAnthropicResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, PutAnthropicResponse::setupPutAnthropicResponseDeserializer); + + protected static void setupPutAnthropicResponseDeserializer(ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioRequest.java index df814fdc3..665812792 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioRequest.java @@ -22,12 +22,18 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD +======= ======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.elasticsearch.inference.put_azureaistudio.AzureAiStudioServiceSettings; import co.elastic.clients.elasticsearch.inference.put_azureaistudio.AzureAiStudioTaskSettings; import co.elastic.clients.elasticsearch.inference.put_azureaistudio.AzureAiStudioTaskType; import co.elastic.clients.elasticsearch.inference.put_azureaistudio.ServiceType; +<<<<<<< HEAD >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -91,11 +97,15 @@ public class PutAzureaistudioRequest extends RequestBase implements JsonpSeriali @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD private final AzureAiStudioServiceType service; ======= private final ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final AzureAiStudioServiceSettings serviceSettings; @@ -147,11 +157,15 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final AzureAiStudioServiceType service() { ======= public final ServiceType service() { >>>>>>> 03828daff (regen from latest spec) +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -228,11 +242,15 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD private AzureAiStudioServiceType service; ======= private ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private AzureAiStudioServiceSettings serviceSettings; @@ -277,11 +295,15 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(AzureAiStudioServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> 03828daff (regen from latest spec) +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -370,11 +392,15 @@ protected static void setupPutAzureaistudioRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, AzureAiStudioServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> 03828daff (regen from latest spec) +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, AzureAiStudioServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AzureAiStudioTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioResponse.java new file mode 100644 index 000000000..1edb52050 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioResponse.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_azureaistudio.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutAzureaistudioResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutAzureaistudioResponse(Builder builder) { + super(builder); + + } + + public static PutAzureaistudioResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutAzureaistudioResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutAzureaistudioResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutAzureaistudioResponse build() { + _checkSingleUse(); + + return new PutAzureaistudioResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutAzureaistudioResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, PutAzureaistudioResponse::setupPutAzureaistudioResponseDeserializer); + + protected static void setupPutAzureaistudioResponseDeserializer( + ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiRequest.java index 7d0466626..d258880b2 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiRequest.java @@ -22,12 +22,18 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD +======= ======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.elasticsearch.inference.put_azureopenai.AzureOpenAIServiceSettings; import co.elastic.clients.elasticsearch.inference.put_azureopenai.AzureOpenAITaskSettings; import co.elastic.clients.elasticsearch.inference.put_azureopenai.AzureOpenAITaskType; import co.elastic.clients.elasticsearch.inference.put_azureopenai.ServiceType; +<<<<<<< HEAD >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -106,11 +112,15 @@ public class PutAzureopenaiRequest extends RequestBase implements JsonpSerializa @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD private final AzureOpenAIServiceType service; ======= private final ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final AzureOpenAIServiceSettings serviceSettings; @@ -162,11 +172,15 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final AzureOpenAIServiceType service() { ======= public final ServiceType service() { >>>>>>> 03828daff (regen from latest spec) +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -245,11 +259,15 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD private AzureOpenAIServiceType service; ======= private ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private AzureOpenAIServiceSettings serviceSettings; @@ -294,11 +312,15 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(AzureOpenAIServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> 03828daff (regen from latest spec) +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -388,11 +410,15 @@ public PutAzureopenaiRequest build() { protected static void setupPutAzureopenaiRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, AzureOpenAIServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> 03828daff (regen from latest spec) +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, AzureOpenAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AzureOpenAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiResponse.java new file mode 100644 index 000000000..3674a08b7 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiResponse.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_azureopenai.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutAzureopenaiResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutAzureopenaiResponse(Builder builder) { + super(builder); + + } + + public static PutAzureopenaiResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutAzureopenaiResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutAzureopenaiResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutAzureopenaiResponse build() { + _checkSingleUse(); + + return new PutAzureopenaiResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutAzureopenaiResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, PutAzureopenaiResponse::setupPutAzureopenaiResponseDeserializer); + + protected static void setupPutAzureopenaiResponseDeserializer( + ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereRequest.java index 1f89d910e..4b9150362 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereRequest.java @@ -22,12 +22,18 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD +======= ======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.elasticsearch.inference.put_cohere.CohereServiceSettings; import co.elastic.clients.elasticsearch.inference.put_cohere.CohereTaskSettings; import co.elastic.clients.elasticsearch.inference.put_cohere.CohereTaskType; import co.elastic.clients.elasticsearch.inference.put_cohere.ServiceType; +<<<<<<< HEAD >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -90,11 +96,15 @@ public class PutCohereRequest extends RequestBase implements JsonpSerializable { private final String cohereInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private final CohereServiceType service; ======= private final ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final CohereServiceSettings serviceSettings; @@ -145,11 +155,15 @@ public final String cohereInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final CohereServiceType service() { ======= public final ServiceType service() { >>>>>>> 03828daff (regen from latest spec) +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -226,11 +240,15 @@ public static class Builder extends RequestBase.AbstractBuilder private String cohereInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private CohereServiceType service; ======= private ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private CohereServiceSettings serviceSettings; @@ -275,11 +293,15 @@ public final Builder cohereInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(CohereServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> 03828daff (regen from latest spec) +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -366,11 +388,15 @@ public PutCohereRequest build() { protected static void setupPutCohereRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, CohereServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> 03828daff (regen from latest spec) +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, CohereServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, CohereTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereResponse.java new file mode 100644 index 000000000..8a3dbffeb --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereResponse.java @@ -0,0 +1,106 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_cohere.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutCohereResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutCohereResponse(Builder builder) { + super(builder); + + } + + public static PutCohereResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutCohereResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutCohereResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutCohereResponse build() { + _checkSingleUse(); + + return new PutCohereResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutCohereResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, PutCohereResponse::setupPutCohereResponseDeserializer); + + protected static void setupPutCohereResponseDeserializer(ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisRequest.java index cf752f4e6..dcffa7fe4 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisRequest.java @@ -21,6 +21,12 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_eis.EisServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_eis.EisTaskType; +import co.elastic.clients.elasticsearch.inference.put_eis.ServiceType; +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -70,7 +76,11 @@ public class PutEisRequest extends RequestBase implements JsonpSerializable { private final String eisInferenceId; +<<<<<<< HEAD private final EisServiceType service; +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final EisServiceSettings serviceSettings; @@ -106,7 +116,11 @@ public final String eisInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD public final EisServiceType service() { +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -158,7 +172,11 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { public static class Builder extends RequestBase.AbstractBuilder implements ObjectBuilder { private String eisInferenceId; +<<<<<<< HEAD private EisServiceType service; +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private EisServiceSettings serviceSettings; @@ -180,7 +198,11 @@ public final Builder eisInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(EisServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -247,7 +269,11 @@ public PutEisRequest build() { protected static void setupPutEisRequestDeserializer(ObjectDeserializer op) { +<<<<<<< HEAD op.add(Builder::service, EisServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, EisServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisResponse.java new file mode 100644 index 000000000..04f54e36c --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisResponse.java @@ -0,0 +1,106 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_eis.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutEisResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutEisResponse(Builder builder) { + super(builder); + + } + + public static PutEisResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutEisResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutEisResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutEisResponse build() { + _checkSingleUse(); + + return new PutEisResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutEisResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + PutEisResponse::setupPutEisResponseDeserializer); + + protected static void setupPutEisResponseDeserializer(ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchRequest.java index 3c58201f2..2456383af 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchRequest.java @@ -22,12 +22,18 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD +======= ======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.elasticsearch.inference.put_elasticsearch.ElasticsearchServiceSettings; import co.elastic.clients.elasticsearch.inference.put_elasticsearch.ElasticsearchTaskSettings; import co.elastic.clients.elasticsearch.inference.put_elasticsearch.ElasticsearchTaskType; import co.elastic.clients.elasticsearch.inference.put_elasticsearch.ServiceType; +<<<<<<< HEAD >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -108,11 +114,15 @@ public class PutElasticsearchRequest extends RequestBase implements JsonpSeriali private final String elasticsearchInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private final ElasticsearchServiceType service; ======= private final ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final ElasticsearchServiceSettings serviceSettings; @@ -165,11 +175,15 @@ public final String elasticsearchInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final ElasticsearchServiceType service() { ======= public final ServiceType service() { >>>>>>> 03828daff (regen from latest spec) +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -246,11 +260,15 @@ public static class Builder extends RequestBase.AbstractBuilder private String elasticsearchInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private ElasticsearchServiceType service; ======= private ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private ElasticsearchServiceSettings serviceSettings; @@ -296,11 +314,15 @@ public final Builder elasticsearchInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(ElasticsearchServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> 03828daff (regen from latest spec) +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -389,11 +411,15 @@ protected static void setupPutElasticsearchRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, ElasticsearchServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> 03828daff (regen from latest spec) +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, ElasticsearchServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, ElasticsearchTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchResponse.java new file mode 100644 index 000000000..fcc1ec47b --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchResponse.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_elasticsearch.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutElasticsearchResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutElasticsearchResponse(Builder builder) { + super(builder); + + } + + public static PutElasticsearchResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutElasticsearchResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutElasticsearchResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutElasticsearchResponse build() { + _checkSingleUse(); + + return new PutElasticsearchResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutElasticsearchResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, PutElasticsearchResponse::setupPutElasticsearchResponseDeserializer); + + protected static void setupPutElasticsearchResponseDeserializer( + ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserRequest.java index e2d8c821d..07f990d3b 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserRequest.java @@ -22,11 +22,17 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD ======= import co.elastic.clients.elasticsearch.inference.put_elser.ElserServiceSettings; import co.elastic.clients.elasticsearch.inference.put_elser.ElserTaskType; import co.elastic.clients.elasticsearch.inference.put_elser.ServiceType; >>>>>>> 03828daff (regen from latest spec) +======= +import co.elastic.clients.elasticsearch.inference.put_elser.ElserServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_elser.ElserTaskType; +import co.elastic.clients.elasticsearch.inference.put_elser.ServiceType; +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -110,11 +116,15 @@ public class PutElserRequest extends RequestBase implements JsonpSerializable { private final String elserInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private final ElserServiceType service; ======= private final ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final ElserServiceSettings serviceSettings; @@ -161,11 +171,15 @@ public final String elserInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final ElserServiceType service() { ======= public final ServiceType service() { >>>>>>> 03828daff (regen from latest spec) +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -223,11 +237,15 @@ public static class Builder extends RequestBase.AbstractBuilder impleme private String elserInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private ElserServiceType service; ======= private ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private ElserServiceSettings serviceSettings; @@ -269,11 +287,15 @@ public final Builder elserInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(ElserServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> 03828daff (regen from latest spec) +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -339,11 +361,15 @@ public PutElserRequest build() { protected static void setupPutElserRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, ElserServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> 03828daff (regen from latest spec) +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, ElserServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserResponse.java new file mode 100644 index 000000000..565d8f80b --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserResponse.java @@ -0,0 +1,106 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_elser.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutElserResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutElserResponse(Builder builder) { + super(builder); + + } + + public static PutElserResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutElserResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutElserResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutElserResponse build() { + _checkSingleUse(); + + return new PutElserResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutElserResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + PutElserResponse::setupPutElserResponseDeserializer); + + protected static void setupPutElserResponseDeserializer(ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioRequest.java index e21929848..efe0282e1 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioRequest.java @@ -22,11 +22,17 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD ======= import co.elastic.clients.elasticsearch.inference.put_googleaistudio.GoogleAiStudioServiceSettings; import co.elastic.clients.elasticsearch.inference.put_googleaistudio.GoogleAiStudioTaskType; import co.elastic.clients.elasticsearch.inference.put_googleaistudio.ServiceType; >>>>>>> 03828daff (regen from latest spec) +======= +import co.elastic.clients.elasticsearch.inference.put_googleaistudio.GoogleAiStudioServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_googleaistudio.GoogleAiStudioTaskType; +import co.elastic.clients.elasticsearch.inference.put_googleaistudio.ServiceType; +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -90,11 +96,15 @@ public class PutGoogleaistudioRequest extends RequestBase implements JsonpSerial private final String googleaistudioInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private final GoogleAiServiceType service; ======= private final ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final GoogleAiStudioServiceSettings serviceSettings; @@ -142,11 +152,15 @@ public final String googleaistudioInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final GoogleAiServiceType service() { ======= public final ServiceType service() { >>>>>>> 03828daff (regen from latest spec) +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -206,11 +220,15 @@ public static class Builder extends RequestBase.AbstractBuilder private String googleaistudioInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private GoogleAiServiceType service; ======= private ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private GoogleAiStudioServiceSettings serviceSettings; @@ -252,11 +270,15 @@ public final Builder googleaistudioInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(GoogleAiServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> 03828daff (regen from latest spec) +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -323,11 +345,15 @@ protected static void setupPutGoogleaistudioRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, GoogleAiServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> 03828daff (regen from latest spec) +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, GoogleAiStudioServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioResponse.java new file mode 100644 index 000000000..ec5b9255e --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioResponse.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_googleaistudio.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutGoogleaistudioResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutGoogleaistudioResponse(Builder builder) { + super(builder); + + } + + public static PutGoogleaistudioResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutGoogleaistudioResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutGoogleaistudioResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutGoogleaistudioResponse build() { + _checkSingleUse(); + + return new PutGoogleaistudioResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutGoogleaistudioResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, PutGoogleaistudioResponse::setupPutGoogleaistudioResponseDeserializer); + + protected static void setupPutGoogleaistudioResponseDeserializer( + ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiRequest.java index 3892b1c41..d59779452 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiRequest.java @@ -22,12 +22,18 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD +======= ======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.elasticsearch.inference.put_googlevertexai.GoogleVertexAIServiceSettings; import co.elastic.clients.elasticsearch.inference.put_googlevertexai.GoogleVertexAITaskSettings; import co.elastic.clients.elasticsearch.inference.put_googlevertexai.GoogleVertexAITaskType; import co.elastic.clients.elasticsearch.inference.put_googlevertexai.ServiceType; +<<<<<<< HEAD >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -91,11 +97,15 @@ public class PutGooglevertexaiRequest extends RequestBase implements JsonpSerial private final String googlevertexaiInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private final GoogleVertexAIServiceType service; ======= private final ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final GoogleVertexAIServiceSettings serviceSettings; @@ -147,11 +157,15 @@ public final String googlevertexaiInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final GoogleVertexAIServiceType service() { ======= public final ServiceType service() { >>>>>>> 03828daff (regen from latest spec) +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -228,11 +242,15 @@ public static class Builder extends RequestBase.AbstractBuilder private String googlevertexaiInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private GoogleVertexAIServiceType service; ======= private ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private GoogleVertexAIServiceSettings serviceSettings; @@ -277,11 +295,15 @@ public final Builder googlevertexaiInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(GoogleVertexAIServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> 03828daff (regen from latest spec) +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -370,11 +392,15 @@ protected static void setupPutGooglevertexaiRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, GoogleVertexAIServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> 03828daff (regen from latest spec) +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, GoogleVertexAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, GoogleVertexAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiResponse.java new file mode 100644 index 000000000..8eb2d84cb --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiResponse.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_googlevertexai.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutGooglevertexaiResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutGooglevertexaiResponse(Builder builder) { + super(builder); + + } + + public static PutGooglevertexaiResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutGooglevertexaiResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutGooglevertexaiResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutGooglevertexaiResponse build() { + _checkSingleUse(); + + return new PutGooglevertexaiResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutGooglevertexaiResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, PutGooglevertexaiResponse::setupPutGooglevertexaiResponseDeserializer); + + protected static void setupPutGooglevertexaiResponseDeserializer( + ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceRequest.java index b9978e537..319dfc06c 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceRequest.java @@ -22,11 +22,17 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD ======= import co.elastic.clients.elasticsearch.inference.put_hugging_face.HuggingFaceServiceSettings; import co.elastic.clients.elasticsearch.inference.put_hugging_face.HuggingFaceTaskType; import co.elastic.clients.elasticsearch.inference.put_hugging_face.ServiceType; >>>>>>> 03828daff (regen from latest spec) +======= +import co.elastic.clients.elasticsearch.inference.put_hugging_face.HuggingFaceServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_hugging_face.HuggingFaceTaskType; +import co.elastic.clients.elasticsearch.inference.put_hugging_face.ServiceType; +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -108,11 +114,15 @@ public class PutHuggingFaceRequest extends RequestBase implements JsonpSerializa private final String huggingfaceInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private final HuggingFaceServiceType service; ======= private final ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final HuggingFaceServiceSettings serviceSettings; @@ -160,11 +170,15 @@ public final String huggingfaceInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final HuggingFaceServiceType service() { ======= public final ServiceType service() { >>>>>>> 03828daff (regen from latest spec) +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -224,11 +238,15 @@ public static class Builder extends RequestBase.AbstractBuilder private String huggingfaceInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private HuggingFaceServiceType service; ======= private ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private HuggingFaceServiceSettings serviceSettings; @@ -270,11 +288,15 @@ public final Builder huggingfaceInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(HuggingFaceServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> 03828daff (regen from latest spec) +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -340,11 +362,15 @@ public PutHuggingFaceRequest build() { protected static void setupPutHuggingFaceRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, HuggingFaceServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> 03828daff (regen from latest spec) +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, HuggingFaceServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceResponse.java new file mode 100644 index 000000000..8ed26042f --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceResponse.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_hugging_face.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutHuggingFaceResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutHuggingFaceResponse(Builder builder) { + super(builder); + + } + + public static PutHuggingFaceResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutHuggingFaceResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutHuggingFaceResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutHuggingFaceResponse build() { + _checkSingleUse(); + + return new PutHuggingFaceResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutHuggingFaceResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, PutHuggingFaceResponse::setupPutHuggingFaceResponseDeserializer); + + protected static void setupPutHuggingFaceResponseDeserializer( + ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiRequest.java index c53bd766c..8b0254962 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiRequest.java @@ -22,12 +22,18 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD +======= ======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.elasticsearch.inference.put_jinaai.JinaAIServiceSettings; import co.elastic.clients.elasticsearch.inference.put_jinaai.JinaAITaskSettings; import co.elastic.clients.elasticsearch.inference.put_jinaai.JinaAITaskType; import co.elastic.clients.elasticsearch.inference.put_jinaai.ServiceType; +<<<<<<< HEAD >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -95,11 +101,15 @@ public class PutJinaaiRequest extends RequestBase implements JsonpSerializable { private final String jinaaiInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private final JinaAIServiceType service; ======= private final ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final JinaAIServiceSettings serviceSettings; @@ -150,11 +160,15 @@ public final String jinaaiInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final JinaAIServiceType service() { ======= public final ServiceType service() { >>>>>>> 03828daff (regen from latest spec) +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -231,11 +245,15 @@ public static class Builder extends RequestBase.AbstractBuilder private String jinaaiInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private JinaAIServiceType service; ======= private ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private JinaAIServiceSettings serviceSettings; @@ -280,11 +298,15 @@ public final Builder jinaaiInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(JinaAIServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> 03828daff (regen from latest spec) +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -371,11 +393,15 @@ public PutJinaaiRequest build() { protected static void setupPutJinaaiRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, JinaAIServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> 03828daff (regen from latest spec) +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, JinaAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, JinaAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiResponse.java new file mode 100644 index 000000000..6d40a39ab --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiResponse.java @@ -0,0 +1,106 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_jinaai.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutJinaaiResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutJinaaiResponse(Builder builder) { + super(builder); + + } + + public static PutJinaaiResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutJinaaiResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutJinaaiResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutJinaaiResponse build() { + _checkSingleUse(); + + return new PutJinaaiResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutJinaaiResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, PutJinaaiResponse::setupPutJinaaiResponseDeserializer); + + protected static void setupPutJinaaiResponseDeserializer(ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralRequest.java index ec74bfc03..78a1e639b 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralRequest.java @@ -22,11 +22,17 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD ======= import co.elastic.clients.elasticsearch.inference.put_mistral.MistralServiceSettings; import co.elastic.clients.elasticsearch.inference.put_mistral.MistralTaskType; import co.elastic.clients.elasticsearch.inference.put_mistral.ServiceType; >>>>>>> 03828daff (regen from latest spec) +======= +import co.elastic.clients.elasticsearch.inference.put_mistral.MistralServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_mistral.MistralTaskType; +import co.elastic.clients.elasticsearch.inference.put_mistral.ServiceType; +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -89,11 +95,15 @@ public class PutMistralRequest extends RequestBase implements JsonpSerializable private final String mistralInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private final MistralServiceType service; ======= private final ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final MistralServiceSettings serviceSettings; @@ -140,11 +150,15 @@ public final String mistralInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final MistralServiceType service() { ======= public final ServiceType service() { >>>>>>> 03828daff (regen from latest spec) +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -205,11 +219,15 @@ public static class Builder extends RequestBase.AbstractBuilder private String mistralInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private MistralServiceType service; ======= private ServiceType service; >>>>>>> 03828daff (regen from latest spec) +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private MistralServiceSettings serviceSettings; @@ -251,11 +269,15 @@ public final Builder mistralInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(MistralServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> 03828daff (regen from latest spec) +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -322,11 +344,15 @@ public PutMistralRequest build() { protected static void setupPutMistralRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, MistralServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> 03828daff (regen from latest spec) +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, MistralServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralResponse.java new file mode 100644 index 000000000..6774ddb62 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralResponse.java @@ -0,0 +1,106 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_mistral.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutMistralResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutMistralResponse(Builder builder) { + super(builder); + + } + + public static PutMistralResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutMistralResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutMistralResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutMistralResponse build() { + _checkSingleUse(); + + return new PutMistralResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutMistralResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, PutMistralResponse::setupPutMistralResponseDeserializer); + + protected static void setupPutMistralResponseDeserializer(ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiRequest.java index 2b10fe33f..4b9691858 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiRequest.java @@ -21,6 +21,13 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_openai.OpenAIServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_openai.OpenAITaskSettings; +import co.elastic.clients.elasticsearch.inference.put_openai.OpenAITaskType; +import co.elastic.clients.elasticsearch.inference.put_openai.ServiceType; +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -83,7 +90,11 @@ public class PutOpenaiRequest extends RequestBase implements JsonpSerializable { private final String openaiInferenceId; +<<<<<<< HEAD private final OpenAIServiceType service; +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final OpenAIServiceSettings serviceSettings; @@ -134,7 +145,11 @@ public final String openaiInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD public final OpenAIServiceType service() { +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -213,7 +228,11 @@ public static class Builder extends RequestBase.AbstractBuilder private String openaiInferenceId; +<<<<<<< HEAD private OpenAIServiceType service; +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private OpenAIServiceSettings serviceSettings; @@ -258,7 +277,11 @@ public final Builder openaiInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(OpenAIServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -347,7 +370,11 @@ public PutOpenaiRequest build() { protected static void setupPutOpenaiRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD op.add(Builder::service, OpenAIServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, OpenAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, OpenAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiResponse.java new file mode 100644 index 000000000..cb46d4b17 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiResponse.java @@ -0,0 +1,106 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_openai.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutOpenaiResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutOpenaiResponse(Builder builder) { + super(builder); + + } + + public static PutOpenaiResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutOpenaiResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutOpenaiResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutOpenaiResponse build() { + _checkSingleUse(); + + return new PutOpenaiResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutOpenaiResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, PutOpenaiResponse::setupPutOpenaiResponseDeserializer); + + protected static void setupPutOpenaiResponseDeserializer(ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutRequest.java new file mode 100644 index 000000000..6f734f226 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutRequest.java @@ -0,0 +1,298 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch._types.RequestBase; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.endpoints.SimpleEndpoint; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import java.lang.String; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put.Request + +/** + * Create an inference endpoint. When you create an inference endpoint, the + * associated machine learning model is automatically deployed if it is not + * already running. After creating the endpoint, wait for the model deployment + * to complete before using it. To verify the deployment status, use the get + * trained model statistics API. Look for + * "state": "fully_allocated" in the response + * and ensure that the "allocation_count" matches the + * "target_allocation_count". Avoid creating multiple + * endpoints for the same model unless required, as each endpoint consumes + * significant resources. + *

+ * IMPORTANT: The inference APIs enable you to use certain services, such as + * built-in machine learning models (ELSER, E5), models uploaded through Eland, + * Cohere, OpenAI, Mistral, Azure OpenAI, Google AI Studio, Google Vertex AI, + * Anthropic, Watsonx.ai, or Hugging Face. For built-in models and models + * uploaded through Eland, the inference APIs offer an alternative way to use + * and manage trained models. However, if you do not plan to use the inference + * APIs to use these models or if you want to use non-NLP models, use the + * machine learning trained model APIs. + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutRequest extends RequestBase implements JsonpSerializable { + private final String inferenceId; + + @Nullable + private final TaskType taskType; + + private final InferenceEndpoint inferenceConfig; + + // --------------------------------------------------------------------------------------------- + + private PutRequest(Builder builder) { + + this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); + this.taskType = builder.taskType; + this.inferenceConfig = ApiTypeHelper.requireNonNull(builder.inferenceConfig, this, "inferenceConfig"); + + } + + public static PutRequest of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The inference Id + *

+ * API name: {@code inference_id} + */ + public final String inferenceId() { + return this.inferenceId; + } + + /** + * The task type + *

+ * API name: {@code task_type} + */ + @Nullable + public final TaskType taskType() { + return this.taskType; + } + + /** + * Required - Request body. + */ + public final InferenceEndpoint inferenceConfig() { + return this.inferenceConfig; + } + + /** + * Serialize this value to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + this.inferenceConfig.serialize(generator, mapper); + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutRequest}. + */ + + public static class Builder extends RequestBase.AbstractBuilder implements ObjectBuilder { + private String inferenceId; + + @Nullable + private TaskType taskType; + + private InferenceEndpoint inferenceConfig; + + /** + * Required - The inference Id + *

+ * API name: {@code inference_id} + */ + public final Builder inferenceId(String value) { + this.inferenceId = value; + return this; + } + + /** + * The task type + *

+ * API name: {@code task_type} + */ + public final Builder taskType(@Nullable TaskType value) { + this.taskType = value; + return this; + } + + /** + * Required - Request body. + */ + public final Builder inferenceConfig(InferenceEndpoint value) { + this.inferenceConfig = value; + return this; + } + + /** + * Required - Request body. + */ + public final Builder inferenceConfig(Function> fn) { + return this.inferenceConfig(fn.apply(new InferenceEndpoint.Builder()).build()); + } + + @Override + public Builder withJson(JsonParser parser, JsonpMapper mapper) { + + @SuppressWarnings("unchecked") + InferenceEndpoint value = (InferenceEndpoint) InferenceEndpoint._DESERIALIZER.deserialize(parser, mapper); + return this.inferenceConfig(value); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutRequest}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutRequest build() { + _checkSingleUse(); + + return new PutRequest(this); + } + } + + public static final JsonpDeserializer _DESERIALIZER = createPutRequestDeserializer(); + protected static JsonpDeserializer createPutRequestDeserializer() { + + JsonpDeserializer valueDeserializer = InferenceEndpoint._DESERIALIZER; + + return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() + .inferenceConfig(valueDeserializer.deserialize(parser, mapper, event)).build()); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Endpoint "{@code inference.put}". + */ + public static final Endpoint _ENDPOINT = new SimpleEndpoint<>( + "es/inference.put", + + // Request method + request -> { + return "PUT"; + + }, + + // Request path + request -> { + final int _inferenceId = 1 << 0; + final int _taskType = 1 << 1; + + int propsSet = 0; + + propsSet |= _inferenceId; + if (request.taskType() != null) + propsSet |= _taskType; + + if (propsSet == (_inferenceId)) { + StringBuilder buf = new StringBuilder(); + buf.append("/_inference"); + buf.append("/"); + SimpleEndpoint.pathEncode(request.inferenceId, buf); + return buf.toString(); + } + if (propsSet == (_taskType | _inferenceId)) { + StringBuilder buf = new StringBuilder(); + buf.append("/_inference"); + buf.append("/"); + SimpleEndpoint.pathEncode(request.taskType.jsonValue(), buf); + buf.append("/"); + SimpleEndpoint.pathEncode(request.inferenceId, buf); + return buf.toString(); + } + throw SimpleEndpoint.noPathTemplateFound("path"); + + }, + + // Path parameters + request -> { + Map params = new HashMap<>(); + final int _inferenceId = 1 << 0; + final int _taskType = 1 << 1; + + int propsSet = 0; + + propsSet |= _inferenceId; + if (request.taskType() != null) + propsSet |= _taskType; + + if (propsSet == (_inferenceId)) { + params.put("inferenceId", request.inferenceId); + } + if (propsSet == (_taskType | _inferenceId)) { + params.put("taskType", request.taskType.jsonValue()); + params.put("inferenceId", request.inferenceId); + } + return params; + }, + + // Request parameters + request -> { + return Collections.emptyMap(); + + }, SimpleEndpoint.emptyMap(), true, PutResponse._DESERIALIZER); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutResponse.java new file mode 100644 index 000000000..ec984c519 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutResponse.java @@ -0,0 +1,106 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutResponse(Builder builder) { + super(builder); + + } + + public static PutResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutResponse build() { + _checkSingleUse(); + + return new PutResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + PutResponse::setupPutResponseDeserializer); + + protected static void setupPutResponseDeserializer(ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiRequest.java index d16468247..804dcf3fc 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiRequest.java @@ -21,6 +21,13 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_voyageai.ServiceType; +import co.elastic.clients.elasticsearch.inference.put_voyageai.VoyageAIServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_voyageai.VoyageAITaskSettings; +import co.elastic.clients.elasticsearch.inference.put_voyageai.VoyageAITaskType; +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -74,7 +81,11 @@ public class PutVoyageaiRequest extends RequestBase implements JsonpSerializable @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD private final VoyageAIServiceType service; +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final VoyageAIServiceSettings serviceSettings; @@ -119,7 +130,11 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ +<<<<<<< HEAD public final VoyageAIServiceType service() { +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -203,7 +218,11 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD private VoyageAIServiceType service; +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private VoyageAIServiceSettings serviceSettings; @@ -240,7 +259,11 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(VoyageAIServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -338,7 +361,11 @@ public PutVoyageaiRequest build() { protected static void setupPutVoyageaiRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD op.add(Builder::service, VoyageAIServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, VoyageAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, VoyageAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiResponse.java new file mode 100644 index 000000000..bda8463e7 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiResponse.java @@ -0,0 +1,106 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_voyageai.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutVoyageaiResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutVoyageaiResponse(Builder builder) { + super(builder); + + } + + public static PutVoyageaiResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutVoyageaiResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutVoyageaiResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutVoyageaiResponse build() { + _checkSingleUse(); + + return new PutVoyageaiResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutVoyageaiResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, PutVoyageaiResponse::setupPutVoyageaiResponseDeserializer); + + protected static void setupPutVoyageaiResponseDeserializer(ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxRequest.java index 2529929f7..c54a4df68 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxRequest.java @@ -21,6 +21,12 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; +<<<<<<< HEAD +======= +import co.elastic.clients.elasticsearch.inference.put_watsonx.ServiceType; +import co.elastic.clients.elasticsearch.inference.put_watsonx.WatsonxServiceSettings; +import co.elastic.clients.elasticsearch.inference.put_watsonx.WatsonxTaskType; +>>>>>>> c49af58dc (Revert "temp rebase fix") import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -81,7 +87,11 @@ */ @JsonpDeserializable public class PutWatsonxRequest extends RequestBase implements JsonpSerializable { +<<<<<<< HEAD private final WatsonxServiceType service; +======= + private final ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private final WatsonxServiceSettings serviceSettings; @@ -110,7 +120,11 @@ public static PutWatsonxRequest of(Function * API name: {@code service} */ +<<<<<<< HEAD public final WatsonxServiceType service() { +======= + public final ServiceType service() { +>>>>>>> c49af58dc (Revert "temp rebase fix") return this.service; } @@ -170,7 +184,11 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { public static class Builder extends RequestBase.AbstractBuilder implements ObjectBuilder { +<<<<<<< HEAD private WatsonxServiceType service; +======= + private ServiceType service; +>>>>>>> c49af58dc (Revert "temp rebase fix") private WatsonxServiceSettings serviceSettings; @@ -184,7 +202,11 @@ public static class Builder extends RequestBase.AbstractBuilder *

* API name: {@code service} */ +<<<<<<< HEAD public final Builder service(WatsonxServiceType value) { +======= + public final Builder service(ServiceType value) { +>>>>>>> c49af58dc (Revert "temp rebase fix") this.service = value; return this; } @@ -260,7 +282,11 @@ public PutWatsonxRequest build() { protected static void setupPutWatsonxRequestDeserializer(ObjectDeserializer op) { +<<<<<<< HEAD op.add(Builder::service, WatsonxServiceType._DESERIALIZER, "service"); +======= + op.add(Builder::service, ServiceType._DESERIALIZER, "service"); +>>>>>>> c49af58dc (Revert "temp rebase fix") op.add(Builder::serviceSettings, WatsonxServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxResponse.java new file mode 100644 index 000000000..6bfff7621 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxResponse.java @@ -0,0 +1,106 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_watsonx.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class PutWatsonxResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private PutWatsonxResponse(Builder builder) { + super(builder); + + } + + public static PutWatsonxResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link PutWatsonxResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link PutWatsonxResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public PutWatsonxResponse build() { + _checkSingleUse(); + + return new PutWatsonxResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link PutWatsonxResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, PutWatsonxResponse::setupPutWatsonxResponseDeserializer); + + protected static void setupPutWatsonxResponseDeserializer(ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RankedDocument.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RankedDocument.java new file mode 100644 index 000000000..2cd435013 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RankedDocument.java @@ -0,0 +1,213 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Float; +import java.lang.Integer; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference._types.RankedDocument + +/** + * The rerank result object representing a single ranked document id: the + * original index of the document in the request relevance_score: the + * relevance_score of the document relative to the query text: Optional, the + * text of the document, if requested + * + * @see API + * specification + */ +@JsonpDeserializable +public class RankedDocument implements JsonpSerializable { + private final int index; + + private final float relevanceScore; + + @Nullable + private final String text; + + // --------------------------------------------------------------------------------------------- + + private RankedDocument(Builder builder) { + + this.index = ApiTypeHelper.requireNonNull(builder.index, this, "index"); + this.relevanceScore = ApiTypeHelper.requireNonNull(builder.relevanceScore, this, "relevanceScore"); + this.text = builder.text; + + } + + public static RankedDocument of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - API name: {@code index} + */ + public final int index() { + return this.index; + } + + /** + * Required - API name: {@code relevance_score} + */ + public final float relevanceScore() { + return this.relevanceScore; + } + + /** + * API name: {@code text} + */ + @Nullable + public final String text() { + return this.text; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("index"); + generator.write(this.index); + + generator.writeKey("relevance_score"); + generator.write(this.relevanceScore); + + if (this.text != null) { + generator.writeKey("text"); + generator.write(this.text); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link RankedDocument}. + */ + + public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { + private Integer index; + + private Float relevanceScore; + + @Nullable + private String text; + + /** + * Required - API name: {@code index} + */ + public final Builder index(int value) { + this.index = value; + return this; + } + + /** + * Required - API name: {@code relevance_score} + */ + public final Builder relevanceScore(float value) { + this.relevanceScore = value; + return this; + } + + /** + * API name: {@code text} + */ + public final Builder text(@Nullable String value) { + this.text = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link RankedDocument}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public RankedDocument build() { + _checkSingleUse(); + + return new RankedDocument(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link RankedDocument} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + RankedDocument::setupRankedDocumentDeserializer); + + protected static void setupRankedDocumentDeserializer(ObjectDeserializer op) { + + op.add(Builder::index, JsonpDeserializer.integerDeserializer(), "index"); + op.add(Builder::relevanceScore, JsonpDeserializer.floatDeserializer(), "relevance_score"); + op.add(Builder::text, JsonpDeserializer.stringDeserializer(), "text"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RateLimitSetting.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RateLimitSetting.java new file mode 100644 index 000000000..d26e76129 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RateLimitSetting.java @@ -0,0 +1,163 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference._types.RateLimitSetting + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class RateLimitSetting implements JsonpSerializable { + @Nullable + private final Integer requestsPerMinute; + + // --------------------------------------------------------------------------------------------- + + private RateLimitSetting(Builder builder) { + + this.requestsPerMinute = builder.requestsPerMinute; + + } + + public static RateLimitSetting of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * The number of requests allowed per minute. + *

+ * API name: {@code requests_per_minute} + */ + @Nullable + public final Integer requestsPerMinute() { + return this.requestsPerMinute; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.requestsPerMinute != null) { + generator.writeKey("requests_per_minute"); + generator.write(this.requestsPerMinute); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link RateLimitSetting}. + */ + + public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { + @Nullable + private Integer requestsPerMinute; + + /** + * The number of requests allowed per minute. + *

+ * API name: {@code requests_per_minute} + */ + public final Builder requestsPerMinute(@Nullable Integer value) { + this.requestsPerMinute = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link RateLimitSetting}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public RateLimitSetting build() { + _checkSingleUse(); + + return new RateLimitSetting(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link RateLimitSetting} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + RateLimitSetting::setupRateLimitSettingDeserializer); + + protected static void setupRateLimitSettingDeserializer(ObjectDeserializer op) { + + op.add(Builder::requestsPerMinute, JsonpDeserializer.integerDeserializer(), "requests_per_minute"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RequestChatCompletionBase.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RequestChatCompletionBase.java new file mode 100644 index 000000000..1941152d1 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RequestChatCompletionBase.java @@ -0,0 +1,461 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.elasticsearch._types.RequestBase; +import co.elastic.clients.elasticsearch.inference.chat_completion_unified.CompletionTool; +import co.elastic.clients.elasticsearch.inference.chat_completion_unified.CompletionToolType; +import co.elastic.clients.elasticsearch.inference.chat_completion_unified.Message; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Float; +import java.lang.Long; +import java.lang.String; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference._types.RequestChatCompletionBase + +/** + * + * @see API + * specification + */ + +public abstract class RequestChatCompletionBase extends RequestBase implements JsonpSerializable { + private final List messages; + + @Nullable + private final String model; + + @Nullable + private final Long maxCompletionTokens; + + private final List stop; + + @Nullable + private final Float temperature; + + @Nullable + private final CompletionToolType toolChoice; + + private final List tools; + + @Nullable + private final Float topP; + + // --------------------------------------------------------------------------------------------- + + protected RequestChatCompletionBase(AbstractBuilder builder) { + + this.messages = ApiTypeHelper.unmodifiableRequired(builder.messages, this, "messages"); + this.model = builder.model; + this.maxCompletionTokens = builder.maxCompletionTokens; + this.stop = ApiTypeHelper.unmodifiable(builder.stop); + this.temperature = builder.temperature; + this.toolChoice = builder.toolChoice; + this.tools = ApiTypeHelper.unmodifiable(builder.tools); + this.topP = builder.topP; + + } + + /** + * Required - A list of objects representing the conversation. + *

+ * API name: {@code messages} + */ + public final List messages() { + return this.messages; + } + + /** + * The ID of the model to use. + *

+ * API name: {@code model} + */ + @Nullable + public final String model() { + return this.model; + } + + /** + * The upper bound limit for the number of tokens that can be generated for a + * completion request. + *

+ * API name: {@code max_completion_tokens} + */ + @Nullable + public final Long maxCompletionTokens() { + return this.maxCompletionTokens; + } + + /** + * A sequence of strings to control when the model should stop generating + * additional tokens. + *

+ * API name: {@code stop} + */ + public final List stop() { + return this.stop; + } + + /** + * The sampling temperature to use. + *

+ * API name: {@code temperature} + */ + @Nullable + public final Float temperature() { + return this.temperature; + } + + /** + * Controls which tool is called by the model. + *

+ * API name: {@code tool_choice} + */ + @Nullable + public final CompletionToolType toolChoice() { + return this.toolChoice; + } + + /** + * A list of tools that the model can call. + *

+ * API name: {@code tools} + */ + public final List tools() { + return this.tools; + } + + /** + * Nucleus sampling, an alternative to sampling with temperature. + *

+ * API name: {@code top_p} + */ + @Nullable + public final Float topP() { + return this.topP; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (ApiTypeHelper.isDefined(this.messages)) { + generator.writeKey("messages"); + generator.writeStartArray(); + for (Message item0 : this.messages) { + item0.serialize(generator, mapper); + + } + generator.writeEnd(); + + } + if (this.model != null) { + generator.writeKey("model"); + generator.write(this.model); + + } + if (this.maxCompletionTokens != null) { + generator.writeKey("max_completion_tokens"); + generator.write(this.maxCompletionTokens); + + } + if (ApiTypeHelper.isDefined(this.stop)) { + generator.writeKey("stop"); + generator.writeStartArray(); + for (String item0 : this.stop) { + generator.write(item0); + + } + generator.writeEnd(); + + } + if (this.temperature != null) { + generator.writeKey("temperature"); + generator.write(this.temperature); + + } + if (this.toolChoice != null) { + generator.writeKey("tool_choice"); + this.toolChoice.serialize(generator, mapper); + + } + if (ApiTypeHelper.isDefined(this.tools)) { + generator.writeKey("tools"); + generator.writeStartArray(); + for (CompletionTool item0 : this.tools) { + item0.serialize(generator, mapper); + + } + generator.writeEnd(); + + } + if (this.topP != null) { + generator.writeKey("top_p"); + generator.write(this.topP); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + public abstract static class AbstractBuilder> + extends + RequestBase.AbstractBuilder { + private List messages; + + @Nullable + private String model; + + @Nullable + private Long maxCompletionTokens; + + @Nullable + private List stop; + + @Nullable + private Float temperature; + + @Nullable + private CompletionToolType toolChoice; + + @Nullable + private List tools; + + @Nullable + private Float topP; + + /** + * Required - A list of objects representing the conversation. + *

+ * API name: {@code messages} + *

+ * Adds all elements of list to messages. + */ + public final BuilderT messages(List list) { + this.messages = _listAddAll(this.messages, list); + return self(); + } + + /** + * Required - A list of objects representing the conversation. + *

+ * API name: {@code messages} + *

+ * Adds one or more values to messages. + */ + public final BuilderT messages(Message value, Message... values) { + this.messages = _listAdd(this.messages, value, values); + return self(); + } + + /** + * Required - A list of objects representing the conversation. + *

+ * API name: {@code messages} + *

+ * Adds a value to messages using a builder lambda. + */ + public final BuilderT messages(Function> fn) { + return messages(fn.apply(new Message.Builder()).build()); + } + + /** + * The ID of the model to use. + *

+ * API name: {@code model} + */ + public final BuilderT model(@Nullable String value) { + this.model = value; + return self(); + } + + /** + * The upper bound limit for the number of tokens that can be generated for a + * completion request. + *

+ * API name: {@code max_completion_tokens} + */ + public final BuilderT maxCompletionTokens(@Nullable Long value) { + this.maxCompletionTokens = value; + return self(); + } + + /** + * A sequence of strings to control when the model should stop generating + * additional tokens. + *

+ * API name: {@code stop} + *

+ * Adds all elements of list to stop. + */ + public final BuilderT stop(List list) { + this.stop = _listAddAll(this.stop, list); + return self(); + } + + /** + * A sequence of strings to control when the model should stop generating + * additional tokens. + *

+ * API name: {@code stop} + *

+ * Adds one or more values to stop. + */ + public final BuilderT stop(String value, String... values) { + this.stop = _listAdd(this.stop, value, values); + return self(); + } + + /** + * The sampling temperature to use. + *

+ * API name: {@code temperature} + */ + public final BuilderT temperature(@Nullable Float value) { + this.temperature = value; + return self(); + } + + /** + * Controls which tool is called by the model. + *

+ * API name: {@code tool_choice} + */ + public final BuilderT toolChoice(@Nullable CompletionToolType value) { + this.toolChoice = value; + return self(); + } + + /** + * Controls which tool is called by the model. + *

+ * API name: {@code tool_choice} + */ + public final BuilderT toolChoice(Function> fn) { + return this.toolChoice(fn.apply(new CompletionToolType.Builder()).build()); + } + + /** + * A list of tools that the model can call. + *

+ * API name: {@code tools} + *

+ * Adds all elements of list to tools. + */ + public final BuilderT tools(List list) { + this.tools = _listAddAll(this.tools, list); + return self(); + } + + /** + * A list of tools that the model can call. + *

+ * API name: {@code tools} + *

+ * Adds one or more values to tools. + */ + public final BuilderT tools(CompletionTool value, CompletionTool... values) { + this.tools = _listAdd(this.tools, value, values); + return self(); + } + + /** + * A list of tools that the model can call. + *

+ * API name: {@code tools} + *

+ * Adds a value to tools using a builder lambda. + */ + public final BuilderT tools(Function> fn) { + return tools(fn.apply(new CompletionTool.Builder()).build()); + } + + /** + * Nucleus sampling, an alternative to sampling with temperature. + *

+ * API name: {@code top_p} + */ + public final BuilderT topP(@Nullable Float value) { + this.topP = value; + return self(); + } + + protected abstract BuilderT self(); + + } + + // --------------------------------------------------------------------------------------------- + protected static > void setupRequestChatCompletionBaseDeserializer( + ObjectDeserializer op) { + + op.add(AbstractBuilder::messages, JsonpDeserializer.arrayDeserializer(Message._DESERIALIZER), "messages"); + op.add(AbstractBuilder::model, JsonpDeserializer.stringDeserializer(), "model"); + op.add(AbstractBuilder::maxCompletionTokens, JsonpDeserializer.longDeserializer(), "max_completion_tokens"); + op.add(AbstractBuilder::stop, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), + "stop"); + op.add(AbstractBuilder::temperature, JsonpDeserializer.floatDeserializer(), "temperature"); + op.add(AbstractBuilder::toolChoice, CompletionToolType._DESERIALIZER, "tool_choice"); + op.add(AbstractBuilder::tools, JsonpDeserializer.arrayDeserializer(CompletionTool._DESERIALIZER), "tools"); + op.add(AbstractBuilder::topP, JsonpDeserializer.floatDeserializer(), "top_p"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankRequest.java new file mode 100644 index 000000000..f1f853029 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankRequest.java @@ -0,0 +1,383 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch._types.RequestBase; +import co.elastic.clients.elasticsearch._types.Time; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.endpoints.SimpleEndpoint; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.rerank.Request + +/** + * Perform rereanking inference on the service + * + * @see API + * specification + */ +@JsonpDeserializable +public class RerankRequest extends RequestBase implements JsonpSerializable { + private final String inferenceId; + + private final List input; + + private final String query; + + @Nullable + private final JsonData taskSettings; + + @Nullable + private final Time timeout; + + // --------------------------------------------------------------------------------------------- + + private RerankRequest(Builder builder) { + + this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); + this.input = ApiTypeHelper.unmodifiableRequired(builder.input, this, "input"); + this.query = ApiTypeHelper.requireNonNull(builder.query, this, "query"); + this.taskSettings = builder.taskSettings; + this.timeout = builder.timeout; + + } + + public static RerankRequest of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The unique identifier for the inference endpoint. + *

+ * API name: {@code inference_id} + */ + public final String inferenceId() { + return this.inferenceId; + } + + /** + * Required - The text on which you want to perform the inference task. It can + * be a single string or an array.

+ *

+ * info Inference endpoints for the completion task type currently + * only support a single string as input. + *

+ *
+ *

+ * API name: {@code input} + */ + public final List input() { + return this.input; + } + + /** + * Required - Query input. + *

+ * API name: {@code query} + */ + public final String query() { + return this.query; + } + + /** + * Task settings for the individual inference request. These settings are + * specific to the task type you specified and override the task settings + * specified when initializing the service. + *

+ * API name: {@code task_settings} + */ + @Nullable + public final JsonData taskSettings() { + return this.taskSettings; + } + + /** + * The amount of time to wait for the inference request to complete. + *

+ * API name: {@code timeout} + */ + @Nullable + public final Time timeout() { + return this.timeout; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (ApiTypeHelper.isDefined(this.input)) { + generator.writeKey("input"); + generator.writeStartArray(); + for (String item0 : this.input) { + generator.write(item0); + + } + generator.writeEnd(); + + } + generator.writeKey("query"); + generator.write(this.query); + + if (this.taskSettings != null) { + generator.writeKey("task_settings"); + this.taskSettings.serialize(generator, mapper); + + } + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link RerankRequest}. + */ + + public static class Builder extends RequestBase.AbstractBuilder implements ObjectBuilder { + private String inferenceId; + + private List input; + + private String query; + + @Nullable + private JsonData taskSettings; + + @Nullable + private Time timeout; + + /** + * Required - The unique identifier for the inference endpoint. + *

+ * API name: {@code inference_id} + */ + public final Builder inferenceId(String value) { + this.inferenceId = value; + return this; + } + + /** + * Required - The text on which you want to perform the inference task. It can + * be a single string or an array.

+ *

+ * info Inference endpoints for the completion task type currently + * only support a single string as input. + *

+ *
+ *

+ * API name: {@code input} + *

+ * Adds all elements of list to input. + */ + public final Builder input(List list) { + this.input = _listAddAll(this.input, list); + return this; + } + + /** + * Required - The text on which you want to perform the inference task. It can + * be a single string or an array.

+ *

+ * info Inference endpoints for the completion task type currently + * only support a single string as input. + *

+ *
+ *

+ * API name: {@code input} + *

+ * Adds one or more values to input. + */ + public final Builder input(String value, String... values) { + this.input = _listAdd(this.input, value, values); + return this; + } + + /** + * Required - Query input. + *

+ * API name: {@code query} + */ + public final Builder query(String value) { + this.query = value; + return this; + } + + /** + * Task settings for the individual inference request. These settings are + * specific to the task type you specified and override the task settings + * specified when initializing the service. + *

+ * API name: {@code task_settings} + */ + public final Builder taskSettings(@Nullable JsonData value) { + this.taskSettings = value; + return this; + } + + /** + * The amount of time to wait for the inference request to complete. + *

+ * API name: {@code timeout} + */ + public final Builder timeout(@Nullable Time value) { + this.timeout = value; + return this; + } + + /** + * The amount of time to wait for the inference request to complete. + *

+ * API name: {@code timeout} + */ + public final Builder timeout(Function> fn) { + return this.timeout(fn.apply(new Time.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link RerankRequest}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public RerankRequest build() { + _checkSingleUse(); + + return new RerankRequest(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link RerankRequest} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + RerankRequest::setupRerankRequestDeserializer); + + protected static void setupRerankRequestDeserializer(ObjectDeserializer op) { + + op.add(Builder::input, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), "input"); + op.add(Builder::query, JsonpDeserializer.stringDeserializer(), "query"); + op.add(Builder::taskSettings, JsonData._DESERIALIZER, "task_settings"); + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Endpoint "{@code inference.rerank}". + */ + public static final Endpoint _ENDPOINT = new SimpleEndpoint<>( + "es/inference.rerank", + + // Request method + request -> { + return "POST"; + + }, + + // Request path + request -> { + final int _inferenceId = 1 << 0; + + int propsSet = 0; + + propsSet |= _inferenceId; + + if (propsSet == (_inferenceId)) { + StringBuilder buf = new StringBuilder(); + buf.append("/_inference"); + buf.append("/rerank"); + buf.append("/"); + SimpleEndpoint.pathEncode(request.inferenceId, buf); + return buf.toString(); + } + throw SimpleEndpoint.noPathTemplateFound("path"); + + }, + + // Path parameters + request -> { + Map params = new HashMap<>(); + final int _inferenceId = 1 << 0; + + int propsSet = 0; + + propsSet |= _inferenceId; + + if (propsSet == (_inferenceId)) { + params.put("inferenceId", request.inferenceId); + } + return params; + }, + + // Request parameters + request -> { + Map params = new HashMap<>(); + if (request.timeout != null) { + params.put("timeout", request.timeout._toJsonString()); + } + return params; + + }, SimpleEndpoint.emptyMap(), true, RerankResponse._DESERIALIZER); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankResponse.java new file mode 100644 index 000000000..9cb497631 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankResponse.java @@ -0,0 +1,106 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.rerank.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class RerankResponse extends RerankedInferenceResult { + // --------------------------------------------------------------------------------------------- + + private RerankResponse(Builder builder) { + super(builder); + + } + + public static RerankResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link RerankResponse}. + */ + + public static class Builder extends RerankedInferenceResult.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link RerankResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public RerankResponse build() { + _checkSingleUse(); + + return new RerankResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link RerankResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + RerankResponse::setupRerankResponseDeserializer); + + protected static void setupRerankResponseDeserializer(ObjectDeserializer op) { + RerankedInferenceResult.setupRerankedInferenceResultDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankedInferenceResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankedInferenceResult.java new file mode 100644 index 000000000..62c2f8f6a --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RerankedInferenceResult.java @@ -0,0 +1,156 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference._types.RerankedInferenceResult + +/** + * Defines the response for a rerank request. + * + * @see API + * specification + */ + +public abstract class RerankedInferenceResult implements JsonpSerializable { + private final List rerank; + + // --------------------------------------------------------------------------------------------- + + protected RerankedInferenceResult(AbstractBuilder builder) { + + this.rerank = ApiTypeHelper.unmodifiableRequired(builder.rerank, this, "rerank"); + + } + + /** + * Required - API name: {@code rerank} + */ + public final List rerank() { + return this.rerank; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (ApiTypeHelper.isDefined(this.rerank)) { + generator.writeKey("rerank"); + generator.writeStartArray(); + for (RankedDocument item0 : this.rerank) { + item0.serialize(generator, mapper); + + } + generator.writeEnd(); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + public abstract static class AbstractBuilder> + extends + WithJsonObjectBuilderBase { + private List rerank; + + /** + * Required - API name: {@code rerank} + *

+ * Adds all elements of list to rerank. + */ + public final BuilderT rerank(List list) { + this.rerank = _listAddAll(this.rerank, list); + return self(); + } + + /** + * Required - API name: {@code rerank} + *

+ * Adds one or more values to rerank. + */ + public final BuilderT rerank(RankedDocument value, RankedDocument... values) { + this.rerank = _listAdd(this.rerank, value, values); + return self(); + } + + /** + * Required - API name: {@code rerank} + *

+ * Adds a value to rerank using a builder lambda. + */ + public final BuilderT rerank(Function> fn) { + return rerank(fn.apply(new RankedDocument.Builder()).build()); + } + + protected abstract BuilderT self(); + + } + + // --------------------------------------------------------------------------------------------- + protected static > void setupRerankedInferenceResultDeserializer( + ObjectDeserializer op) { + + op.add(AbstractBuilder::rerank, JsonpDeserializer.arrayDeserializer(RankedDocument._DESERIALIZER), "rerank"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingInferenceResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingInferenceResult.java new file mode 100644 index 000000000..75ef28131 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingInferenceResult.java @@ -0,0 +1,158 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference._types.SparseEmbeddingInferenceResult + +/** + * The response format for the sparse embedding request. + * + * @see API + * specification + */ + +public abstract class SparseEmbeddingInferenceResult implements JsonpSerializable { + private final List sparseEmbedding; + + // --------------------------------------------------------------------------------------------- + + protected SparseEmbeddingInferenceResult(AbstractBuilder builder) { + + this.sparseEmbedding = ApiTypeHelper.unmodifiableRequired(builder.sparseEmbedding, this, "sparseEmbedding"); + + } + + /** + * Required - API name: {@code sparse_embedding} + */ + public final List sparseEmbedding() { + return this.sparseEmbedding; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (ApiTypeHelper.isDefined(this.sparseEmbedding)) { + generator.writeKey("sparse_embedding"); + generator.writeStartArray(); + for (SparseEmbeddingResult item0 : this.sparseEmbedding) { + item0.serialize(generator, mapper); + + } + generator.writeEnd(); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + public abstract static class AbstractBuilder> + extends + WithJsonObjectBuilderBase { + private List sparseEmbedding; + + /** + * Required - API name: {@code sparse_embedding} + *

+ * Adds all elements of list to sparseEmbedding. + */ + public final BuilderT sparseEmbedding(List list) { + this.sparseEmbedding = _listAddAll(this.sparseEmbedding, list); + return self(); + } + + /** + * Required - API name: {@code sparse_embedding} + *

+ * Adds one or more values to sparseEmbedding. + */ + public final BuilderT sparseEmbedding(SparseEmbeddingResult value, SparseEmbeddingResult... values) { + this.sparseEmbedding = _listAdd(this.sparseEmbedding, value, values); + return self(); + } + + /** + * Required - API name: {@code sparse_embedding} + *

+ * Adds a value to sparseEmbedding using a builder lambda. + */ + public final BuilderT sparseEmbedding( + Function> fn) { + return sparseEmbedding(fn.apply(new SparseEmbeddingResult.Builder()).build()); + } + + protected abstract BuilderT self(); + + } + + // --------------------------------------------------------------------------------------------- + protected static > void setupSparseEmbeddingInferenceResultDeserializer( + ObjectDeserializer op) { + + op.add(AbstractBuilder::sparseEmbedding, + JsonpDeserializer.arrayDeserializer(SparseEmbeddingResult._DESERIALIZER), "sparse_embedding"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingRequest.java new file mode 100644 index 000000000..dc311f406 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingRequest.java @@ -0,0 +1,337 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch._types.RequestBase; +import co.elastic.clients.elasticsearch._types.Time; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.endpoints.SimpleEndpoint; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.sparse_embedding.Request + +/** + * Perform sparse embedding inference on the service + * + * @see API + * specification + */ +@JsonpDeserializable +public class SparseEmbeddingRequest extends RequestBase implements JsonpSerializable { + private final String inferenceId; + + private final List input; + + @Nullable + private final JsonData taskSettings; + + @Nullable + private final Time timeout; + + // --------------------------------------------------------------------------------------------- + + private SparseEmbeddingRequest(Builder builder) { + + this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); + this.input = ApiTypeHelper.unmodifiableRequired(builder.input, this, "input"); + this.taskSettings = builder.taskSettings; + this.timeout = builder.timeout; + + } + + public static SparseEmbeddingRequest of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The inference Id + *

+ * API name: {@code inference_id} + */ + public final String inferenceId() { + return this.inferenceId; + } + + /** + * Required - Inference input. Either a string or an array of strings. + *

+ * API name: {@code input} + */ + public final List input() { + return this.input; + } + + /** + * Optional task settings + *

+ * API name: {@code task_settings} + */ + @Nullable + public final JsonData taskSettings() { + return this.taskSettings; + } + + /** + * Specifies the amount of time to wait for the inference request to complete. + *

+ * API name: {@code timeout} + */ + @Nullable + public final Time timeout() { + return this.timeout; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (ApiTypeHelper.isDefined(this.input)) { + generator.writeKey("input"); + generator.writeStartArray(); + for (String item0 : this.input) { + generator.write(item0); + + } + generator.writeEnd(); + + } + if (this.taskSettings != null) { + generator.writeKey("task_settings"); + this.taskSettings.serialize(generator, mapper); + + } + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link SparseEmbeddingRequest}. + */ + + public static class Builder extends RequestBase.AbstractBuilder + implements + ObjectBuilder { + private String inferenceId; + + private List input; + + @Nullable + private JsonData taskSettings; + + @Nullable + private Time timeout; + + /** + * Required - The inference Id + *

+ * API name: {@code inference_id} + */ + public final Builder inferenceId(String value) { + this.inferenceId = value; + return this; + } + + /** + * Required - Inference input. Either a string or an array of strings. + *

+ * API name: {@code input} + *

+ * Adds all elements of list to input. + */ + public final Builder input(List list) { + this.input = _listAddAll(this.input, list); + return this; + } + + /** + * Required - Inference input. Either a string or an array of strings. + *

+ * API name: {@code input} + *

+ * Adds one or more values to input. + */ + public final Builder input(String value, String... values) { + this.input = _listAdd(this.input, value, values); + return this; + } + + /** + * Optional task settings + *

+ * API name: {@code task_settings} + */ + public final Builder taskSettings(@Nullable JsonData value) { + this.taskSettings = value; + return this; + } + + /** + * Specifies the amount of time to wait for the inference request to complete. + *

+ * API name: {@code timeout} + */ + public final Builder timeout(@Nullable Time value) { + this.timeout = value; + return this; + } + + /** + * Specifies the amount of time to wait for the inference request to complete. + *

+ * API name: {@code timeout} + */ + public final Builder timeout(Function> fn) { + return this.timeout(fn.apply(new Time.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link SparseEmbeddingRequest}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public SparseEmbeddingRequest build() { + _checkSingleUse(); + + return new SparseEmbeddingRequest(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link SparseEmbeddingRequest} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, SparseEmbeddingRequest::setupSparseEmbeddingRequestDeserializer); + + protected static void setupSparseEmbeddingRequestDeserializer( + ObjectDeserializer op) { + + op.add(Builder::input, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), "input"); + op.add(Builder::taskSettings, JsonData._DESERIALIZER, "task_settings"); + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Endpoint "{@code inference.sparse_embedding}". + */ + public static final Endpoint _ENDPOINT = new SimpleEndpoint<>( + "es/inference.sparse_embedding", + + // Request method + request -> { + return "POST"; + + }, + + // Request path + request -> { + final int _inferenceId = 1 << 0; + + int propsSet = 0; + + propsSet |= _inferenceId; + + if (propsSet == (_inferenceId)) { + StringBuilder buf = new StringBuilder(); + buf.append("/_inference"); + buf.append("/sparse_embedding"); + buf.append("/"); + SimpleEndpoint.pathEncode(request.inferenceId, buf); + return buf.toString(); + } + throw SimpleEndpoint.noPathTemplateFound("path"); + + }, + + // Path parameters + request -> { + Map params = new HashMap<>(); + final int _inferenceId = 1 << 0; + + int propsSet = 0; + + propsSet |= _inferenceId; + + if (propsSet == (_inferenceId)) { + params.put("inferenceId", request.inferenceId); + } + return params; + }, + + // Request parameters + request -> { + Map params = new HashMap<>(); + if (request.timeout != null) { + params.put("timeout", request.timeout._toJsonString()); + } + return params; + + }, SimpleEndpoint.emptyMap(), true, SparseEmbeddingResponse._DESERIALIZER); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingResponse.java new file mode 100644 index 000000000..17be5993e --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingResponse.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.sparse_embedding.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class SparseEmbeddingResponse extends SparseEmbeddingInferenceResult { + // --------------------------------------------------------------------------------------------- + + private SparseEmbeddingResponse(Builder builder) { + super(builder); + + } + + public static SparseEmbeddingResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link SparseEmbeddingResponse}. + */ + + public static class Builder extends SparseEmbeddingInferenceResult.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link SparseEmbeddingResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public SparseEmbeddingResponse build() { + _checkSingleUse(); + + return new SparseEmbeddingResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link SparseEmbeddingResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, SparseEmbeddingResponse::setupSparseEmbeddingResponseDeserializer); + + protected static void setupSparseEmbeddingResponseDeserializer( + ObjectDeserializer op) { + SparseEmbeddingInferenceResult.setupSparseEmbeddingInferenceResultDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingResult.java new file mode 100644 index 000000000..7538e4951 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/SparseEmbeddingResult.java @@ -0,0 +1,180 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Float; +import java.lang.String; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference._types.SparseEmbeddingResult + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class SparseEmbeddingResult implements JsonpSerializable { + private final Map embedding; + + // --------------------------------------------------------------------------------------------- + + private SparseEmbeddingResult(Builder builder) { + + this.embedding = ApiTypeHelper.unmodifiableRequired(builder.embedding, this, "embedding"); + + } + + public static SparseEmbeddingResult of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - API name: {@code embedding} + */ + public final Map embedding() { + return this.embedding; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (ApiTypeHelper.isDefined(this.embedding)) { + generator.writeKey("embedding"); + generator.writeStartObject(); + for (Map.Entry item0 : this.embedding.entrySet()) { + generator.writeKey(item0.getKey()); + generator.write(item0.getValue()); + + } + generator.writeEnd(); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link SparseEmbeddingResult}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private Map embedding; + + /** + * Required - API name: {@code embedding} + *

+ * Adds all entries of map to embedding. + */ + public final Builder embedding(Map map) { + this.embedding = _mapPutAll(this.embedding, map); + return this; + } + + /** + * Required - API name: {@code embedding} + *

+ * Adds an entry to embedding. + */ + public final Builder embedding(String key, Float value) { + this.embedding = _mapPut(this.embedding, key, value); + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link SparseEmbeddingResult}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public SparseEmbeddingResult build() { + _checkSingleUse(); + + return new SparseEmbeddingResult(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link SparseEmbeddingResult} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, SparseEmbeddingResult::setupSparseEmbeddingResultDeserializer); + + protected static void setupSparseEmbeddingResultDeserializer(ObjectDeserializer op) { + + op.add(Builder::embedding, JsonpDeserializer.stringMapDeserializer(JsonpDeserializer.floatDeserializer()), + "embedding"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/StreamCompletionRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/StreamCompletionRequest.java new file mode 100644 index 000000000..fe389c828 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/StreamCompletionRequest.java @@ -0,0 +1,327 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch._types.RequestBase; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.endpoints.BinaryEndpoint; +import co.elastic.clients.transport.endpoints.BinaryResponse; +import co.elastic.clients.transport.endpoints.SimpleEndpoint; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.stream_completion.Request + +/** + * Perform streaming inference. Get real-time responses for completion tasks by + * delivering answers incrementally, reducing response times during computation. + * This API works only with the completion task type. + *

+ * IMPORTANT: The inference APIs enable you to use certain services, such as + * built-in machine learning models (ELSER, E5), models uploaded through Eland, + * Cohere, OpenAI, Azure, Google AI Studio, Google Vertex AI, Anthropic, + * Watsonx.ai, or Hugging Face. For built-in models and models uploaded through + * Eland, the inference APIs offer an alternative way to use and manage trained + * models. However, if you do not plan to use the inference APIs to use these + * models or if you want to use non-NLP models, use the machine learning trained + * model APIs. + *

+ * This API requires the monitor_inference cluster privilege (the + * built-in inference_admin and inference_user roles + * grant this privilege). You must use a client that supports streaming. + * + * @see API + * specification + */ +@JsonpDeserializable +public class StreamCompletionRequest extends RequestBase implements JsonpSerializable { + private final String inferenceId; + + private final List input; + + @Nullable + private final JsonData taskSettings; + + // --------------------------------------------------------------------------------------------- + + private StreamCompletionRequest(Builder builder) { + + this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); + this.input = ApiTypeHelper.unmodifiableRequired(builder.input, this, "input"); + this.taskSettings = builder.taskSettings; + + } + + public static StreamCompletionRequest of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The unique identifier for the inference endpoint. + *

+ * API name: {@code inference_id} + */ + public final String inferenceId() { + return this.inferenceId; + } + + /** + * Required - The text on which you want to perform the inference task. It can + * be a single string or an array. + *

+ * NOTE: Inference endpoints for the completion task type currently only support + * a single string as input. + *

+ * API name: {@code input} + */ + public final List input() { + return this.input; + } + + /** + * Optional task settings + *

+ * API name: {@code task_settings} + */ + @Nullable + public final JsonData taskSettings() { + return this.taskSettings; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (ApiTypeHelper.isDefined(this.input)) { + generator.writeKey("input"); + generator.writeStartArray(); + for (String item0 : this.input) { + generator.write(item0); + + } + generator.writeEnd(); + + } + if (this.taskSettings != null) { + generator.writeKey("task_settings"); + this.taskSettings.serialize(generator, mapper); + + } + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link StreamCompletionRequest}. + */ + + public static class Builder extends RequestBase.AbstractBuilder + implements + ObjectBuilder { + private String inferenceId; + + private List input; + + @Nullable + private JsonData taskSettings; + + /** + * Required - The unique identifier for the inference endpoint. + *

+ * API name: {@code inference_id} + */ + public final Builder inferenceId(String value) { + this.inferenceId = value; + return this; + } + + /** + * Required - The text on which you want to perform the inference task. It can + * be a single string or an array. + *

+ * NOTE: Inference endpoints for the completion task type currently only support + * a single string as input. + *

+ * API name: {@code input} + *

+ * Adds all elements of list to input. + */ + public final Builder input(List list) { + this.input = _listAddAll(this.input, list); + return this; + } + + /** + * Required - The text on which you want to perform the inference task. It can + * be a single string or an array. + *

+ * NOTE: Inference endpoints for the completion task type currently only support + * a single string as input. + *

+ * API name: {@code input} + *

+ * Adds one or more values to input. + */ + public final Builder input(String value, String... values) { + this.input = _listAdd(this.input, value, values); + return this; + } + + /** + * Optional task settings + *

+ * API name: {@code task_settings} + */ + public final Builder taskSettings(@Nullable JsonData value) { + this.taskSettings = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link StreamCompletionRequest}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public StreamCompletionRequest build() { + _checkSingleUse(); + + return new StreamCompletionRequest(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link StreamCompletionRequest} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, StreamCompletionRequest::setupStreamCompletionRequestDeserializer); + + protected static void setupStreamCompletionRequestDeserializer( + ObjectDeserializer op) { + + op.add(Builder::input, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), "input"); + op.add(Builder::taskSettings, JsonData._DESERIALIZER, "task_settings"); + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Endpoint "{@code inference.stream_completion}". + */ + public static final Endpoint _ENDPOINT = new BinaryEndpoint<>( + "es/inference.stream_completion", + + // Request method + request -> { + return "POST"; + + }, + + // Request path + request -> { + final int _inferenceId = 1 << 0; + + int propsSet = 0; + + propsSet |= _inferenceId; + + if (propsSet == (_inferenceId)) { + StringBuilder buf = new StringBuilder(); + buf.append("/_inference"); + buf.append("/completion"); + buf.append("/"); + SimpleEndpoint.pathEncode(request.inferenceId, buf); + buf.append("/_stream"); + return buf.toString(); + } + throw SimpleEndpoint.noPathTemplateFound("path"); + + }, + + // Path parameters + request -> { + Map params = new HashMap<>(); + final int _inferenceId = 1 << 0; + + int propsSet = 0; + + propsSet |= _inferenceId; + + if (propsSet == (_inferenceId)) { + params.put("inferenceId", request.inferenceId); + } + return params; + }, + + // Request parameters + request -> { + return Collections.emptyMap(); + + }, SimpleEndpoint.emptyMap(), true, null); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TaskType.java new file mode 100644 index 000000000..6b1fbab65 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TaskType.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum TaskType implements JsonEnum { + SparseEmbedding("sparse_embedding"), + + TextEmbedding("text_embedding"), + + Rerank("rerank"), + + Completion("completion"), + + ChatCompletion("chat_completion"), + + ; + + private final String jsonValue; + + TaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>(TaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingByteResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingByteResult.java new file mode 100644 index 000000000..2143fa6c4 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingByteResult.java @@ -0,0 +1,180 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Number; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference._types.TextEmbeddingByteResult + +/** + * The text embedding result object for byte representation + * + * @see API + * specification + */ +@JsonpDeserializable +public class TextEmbeddingByteResult implements JsonpSerializable { + private final List embedding; + + // --------------------------------------------------------------------------------------------- + + private TextEmbeddingByteResult(Builder builder) { + + this.embedding = ApiTypeHelper.unmodifiableRequired(builder.embedding, this, "embedding"); + + } + + public static TextEmbeddingByteResult of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - API name: {@code embedding} + */ + public final List embedding() { + return this.embedding; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (ApiTypeHelper.isDefined(this.embedding)) { + generator.writeKey("embedding"); + generator.writeStartArray(); + for (Number item0 : this.embedding) { + generator.write(item0.doubleValue()); + + } + generator.writeEnd(); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link TextEmbeddingByteResult}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private List embedding; + + /** + * Required - API name: {@code embedding} + *

+ * Adds all elements of list to embedding. + */ + public final Builder embedding(List list) { + this.embedding = _listAddAll(this.embedding, list); + return this; + } + + /** + * Required - API name: {@code embedding} + *

+ * Adds one or more values to embedding. + */ + public final Builder embedding(Number value, Number... values) { + this.embedding = _listAdd(this.embedding, value, values); + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link TextEmbeddingByteResult}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public TextEmbeddingByteResult build() { + _checkSingleUse(); + + return new TextEmbeddingByteResult(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link TextEmbeddingByteResult} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, TextEmbeddingByteResult::setupTextEmbeddingByteResultDeserializer); + + protected static void setupTextEmbeddingByteResultDeserializer( + ObjectDeserializer op) { + + op.add(Builder::embedding, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.numberDeserializer()), + "embedding"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResult.java new file mode 100644 index 000000000..0bd25d6d6 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResult.java @@ -0,0 +1,284 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.TaggedUnion; +import co.elastic.clients.util.TaggedUnionUtils; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Object; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference._types.TextEmbeddingInferenceResult + +/** + * TextEmbeddingInferenceResult is an aggregation of mutually exclusive + * text_embedding variants + * + * @see API + * specification + */ +@JsonpDeserializable +public class TextEmbeddingInferenceResult + implements + TaggedUnion, + JsonpSerializable { + + /** + * {@link TextEmbeddingInferenceResult} variant kinds. + * + * @see API + * specification + */ + + public enum Kind implements JsonEnum { + TextEmbeddingBytes("text_embedding_bytes"), + + TextEmbeddingBits("text_embedding_bits"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + Kind(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + } + + private final Kind _kind; + private final Object _value; + + @Override + public final Kind _kind() { + return _kind; + } + + @Override + public final Object _get() { + return _value; + } + + public TextEmbeddingInferenceResult(TextEmbeddingInferenceResultVariant value) { + + this._kind = ApiTypeHelper.requireNonNull(value._textEmbeddingInferenceResultKind(), this, ""); + this._value = ApiTypeHelper.requireNonNull(value, this, ""); + + } + + private TextEmbeddingInferenceResult(Builder builder) { + + this._kind = ApiTypeHelper.requireNonNull(builder._kind, builder, ""); + this._value = ApiTypeHelper.requireNonNull(builder._value, builder, ""); + + } + + public static TextEmbeddingInferenceResult of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Is this variant instance of kind {@code text_embedding_bytes}? + */ + public boolean isTextEmbeddingBytes() { + return _kind == Kind.TextEmbeddingBytes; + } + + /** + * Get the {@code text_embedding_bytes} variant value. + * + * @throws IllegalStateException + * if the current variant is not of the {@code text_embedding_bytes} + * kind. + */ + public List textEmbeddingBytes() { + return TaggedUnionUtils.get(this, Kind.TextEmbeddingBytes); + } + + /** + * Is this variant instance of kind {@code text_embedding_bits}? + */ + public boolean isTextEmbeddingBits() { + return _kind == Kind.TextEmbeddingBits; + } + + /** + * Get the {@code text_embedding_bits} variant value. + * + * @throws IllegalStateException + * if the current variant is not of the {@code text_embedding_bits} + * kind. + */ + public List textEmbeddingBits() { + return TaggedUnionUtils.get(this, Kind.TextEmbeddingBits); + } + + /** + * Is this variant instance of kind {@code text_embedding}? + */ + public boolean isTextEmbedding() { + return _kind == Kind.TextEmbedding; + } + + /** + * Get the {@code text_embedding} variant value. + * + * @throws IllegalStateException + * if the current variant is not of the {@code text_embedding} kind. + */ + public List textEmbedding() { + return TaggedUnionUtils.get(this, Kind.TextEmbedding); + } + + @Override + @SuppressWarnings("unchecked") + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeStartObject(); + + generator.writeKey(_kind.jsonValue()); + if (_value instanceof JsonpSerializable) { + ((JsonpSerializable) _value).serialize(generator, mapper); + } else { + switch (_kind) { + case TextEmbeddingBytes : + generator.writeStartArray(); + for (TextEmbeddingByteResult item0 : ((List) this._value)) { + item0.serialize(generator, mapper); + + } + generator.writeEnd(); + + break; + case TextEmbeddingBits : + generator.writeStartArray(); + for (TextEmbeddingByteResult item0 : ((List) this._value)) { + item0.serialize(generator, mapper); + + } + generator.writeEnd(); + + break; + case TextEmbedding : + generator.writeStartArray(); + for (TextEmbeddingResult item0 : ((List) this._value)) { + item0.serialize(generator, mapper); + + } + generator.writeEnd(); + + break; + } + } + + generator.writeEnd(); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private Kind _kind; + private Object _value; + + @Override + protected Builder self() { + return this; + } + public ObjectBuilder textEmbeddingBytes(List v) { + this._kind = Kind.TextEmbeddingBytes; + this._value = v; + return this; + } + + public ObjectBuilder textEmbeddingBits(List v) { + this._kind = Kind.TextEmbeddingBits; + this._value = v; + return this; + } + + public ObjectBuilder textEmbedding(List v) { + this._kind = Kind.TextEmbedding; + this._value = v; + return this; + } + + public TextEmbeddingInferenceResult build() { + _checkSingleUse(); + return new TextEmbeddingInferenceResult(this); + } + + } + + protected static void setupTextEmbeddingInferenceResultDeserializer(ObjectDeserializer op) { + + op.add(Builder::textEmbeddingBytes, JsonpDeserializer.arrayDeserializer(TextEmbeddingByteResult._DESERIALIZER), + "text_embedding_bytes"); + op.add(Builder::textEmbeddingBits, JsonpDeserializer.arrayDeserializer(TextEmbeddingByteResult._DESERIALIZER), + "text_embedding_bits"); + op.add(Builder::textEmbedding, JsonpDeserializer.arrayDeserializer(TextEmbeddingResult._DESERIALIZER), + "text_embedding"); + + } + + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy( + Builder::new, TextEmbeddingInferenceResult::setupTextEmbeddingInferenceResultDeserializer, Builder::build); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResultBuilders.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResultBuilders.java new file mode 100644 index 000000000..076daddd4 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResultBuilders.java @@ -0,0 +1,53 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.util.ObjectBuilder; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * Builders for {@link TextEmbeddingInferenceResult} variants. + *

+ * Variants text_embedding_bytes, text_embedding_bits, + * text_embedding are not available here as they don't have a + * dedicated class. Use {@link TextEmbeddingInferenceResult}'s builder for + * these. + * + */ +public class TextEmbeddingInferenceResultBuilders { + private TextEmbeddingInferenceResultBuilders() { + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResultVariant.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResultVariant.java new file mode 100644 index 000000000..6b3ade5ea --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingInferenceResultVariant.java @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * Base interface for {@link TextEmbeddingInferenceResult} variants. + */ +public interface TextEmbeddingInferenceResultVariant { + + TextEmbeddingInferenceResult.Kind _textEmbeddingInferenceResultKind(); + + default TextEmbeddingInferenceResult _toTextEmbeddingInferenceResult() { + return new TextEmbeddingInferenceResult(this); + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingRequest.java new file mode 100644 index 000000000..042082f7f --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingRequest.java @@ -0,0 +1,336 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch._types.RequestBase; +import co.elastic.clients.elasticsearch._types.Time; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.endpoints.SimpleEndpoint; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.text_embedding.Request + +/** + * Perform text embedding inference on the service + * + * @see API + * specification + */ +@JsonpDeserializable +public class TextEmbeddingRequest extends RequestBase implements JsonpSerializable { + private final String inferenceId; + + private final List input; + + @Nullable + private final JsonData taskSettings; + + @Nullable + private final Time timeout; + + // --------------------------------------------------------------------------------------------- + + private TextEmbeddingRequest(Builder builder) { + + this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); + this.input = ApiTypeHelper.unmodifiableRequired(builder.input, this, "input"); + this.taskSettings = builder.taskSettings; + this.timeout = builder.timeout; + + } + + public static TextEmbeddingRequest of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The inference Id + *

+ * API name: {@code inference_id} + */ + public final String inferenceId() { + return this.inferenceId; + } + + /** + * Required - Inference input. Either a string or an array of strings. + *

+ * API name: {@code input} + */ + public final List input() { + return this.input; + } + + /** + * Optional task settings + *

+ * API name: {@code task_settings} + */ + @Nullable + public final JsonData taskSettings() { + return this.taskSettings; + } + + /** + * Specifies the amount of time to wait for the inference request to complete. + *

+ * API name: {@code timeout} + */ + @Nullable + public final Time timeout() { + return this.timeout; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (ApiTypeHelper.isDefined(this.input)) { + generator.writeKey("input"); + generator.writeStartArray(); + for (String item0 : this.input) { + generator.write(item0); + + } + generator.writeEnd(); + + } + if (this.taskSettings != null) { + generator.writeKey("task_settings"); + this.taskSettings.serialize(generator, mapper); + + } + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link TextEmbeddingRequest}. + */ + + public static class Builder extends RequestBase.AbstractBuilder + implements + ObjectBuilder { + private String inferenceId; + + private List input; + + @Nullable + private JsonData taskSettings; + + @Nullable + private Time timeout; + + /** + * Required - The inference Id + *

+ * API name: {@code inference_id} + */ + public final Builder inferenceId(String value) { + this.inferenceId = value; + return this; + } + + /** + * Required - Inference input. Either a string or an array of strings. + *

+ * API name: {@code input} + *

+ * Adds all elements of list to input. + */ + public final Builder input(List list) { + this.input = _listAddAll(this.input, list); + return this; + } + + /** + * Required - Inference input. Either a string or an array of strings. + *

+ * API name: {@code input} + *

+ * Adds one or more values to input. + */ + public final Builder input(String value, String... values) { + this.input = _listAdd(this.input, value, values); + return this; + } + + /** + * Optional task settings + *

+ * API name: {@code task_settings} + */ + public final Builder taskSettings(@Nullable JsonData value) { + this.taskSettings = value; + return this; + } + + /** + * Specifies the amount of time to wait for the inference request to complete. + *

+ * API name: {@code timeout} + */ + public final Builder timeout(@Nullable Time value) { + this.timeout = value; + return this; + } + + /** + * Specifies the amount of time to wait for the inference request to complete. + *

+ * API name: {@code timeout} + */ + public final Builder timeout(Function> fn) { + return this.timeout(fn.apply(new Time.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link TextEmbeddingRequest}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public TextEmbeddingRequest build() { + _checkSingleUse(); + + return new TextEmbeddingRequest(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link TextEmbeddingRequest} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, TextEmbeddingRequest::setupTextEmbeddingRequestDeserializer); + + protected static void setupTextEmbeddingRequestDeserializer(ObjectDeserializer op) { + + op.add(Builder::input, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), "input"); + op.add(Builder::taskSettings, JsonData._DESERIALIZER, "task_settings"); + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Endpoint "{@code inference.text_embedding}". + */ + public static final Endpoint _ENDPOINT = new SimpleEndpoint<>( + "es/inference.text_embedding", + + // Request method + request -> { + return "POST"; + + }, + + // Request path + request -> { + final int _inferenceId = 1 << 0; + + int propsSet = 0; + + propsSet |= _inferenceId; + + if (propsSet == (_inferenceId)) { + StringBuilder buf = new StringBuilder(); + buf.append("/_inference"); + buf.append("/text_embedding"); + buf.append("/"); + SimpleEndpoint.pathEncode(request.inferenceId, buf); + return buf.toString(); + } + throw SimpleEndpoint.noPathTemplateFound("path"); + + }, + + // Path parameters + request -> { + Map params = new HashMap<>(); + final int _inferenceId = 1 << 0; + + int propsSet = 0; + + propsSet |= _inferenceId; + + if (propsSet == (_inferenceId)) { + params.put("inferenceId", request.inferenceId); + } + return params; + }, + + // Request parameters + request -> { + Map params = new HashMap<>(); + if (request.timeout != null) { + params.put("timeout", request.timeout._toJsonString()); + } + return params; + + }, SimpleEndpoint.emptyMap(), true, TextEmbeddingResponse._DESERIALIZER); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResponse.java index 6672e9c9a..d3e855c1e 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResponse.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResponse.java @@ -60,13 +60,21 @@ */ @JsonpDeserializable public class TextEmbeddingResponse implements JsonpSerializable { +<<<<<<< HEAD private final TextEmbeddingInferenceResult inferenceResult; +======= + private final TextEmbeddingInferenceResult valueBody; +>>>>>>> c49af58dc (Revert "temp rebase fix") // --------------------------------------------------------------------------------------------- private TextEmbeddingResponse(Builder builder) { +<<<<<<< HEAD this.inferenceResult = ApiTypeHelper.requireNonNull(builder.inferenceResult, this, "inferenceResult"); +======= + this.valueBody = ApiTypeHelper.requireNonNull(builder.valueBody, this, "valueBody"); +>>>>>>> c49af58dc (Revert "temp rebase fix") } @@ -77,15 +85,24 @@ public static TextEmbeddingResponse of(Function>>>>>> c49af58dc (Revert "temp rebase fix") } /** * Serialize this value to JSON. */ public void serialize(JsonGenerator generator, JsonpMapper mapper) { +<<<<<<< HEAD this.inferenceResult.serialize(generator, mapper); +======= + this.valueBody.serialize(generator, mapper); +>>>>>>> c49af58dc (Revert "temp rebase fix") } @@ -103,29 +120,49 @@ public String toString() { public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { +<<<<<<< HEAD private TextEmbeddingInferenceResult inferenceResult; +======= + private TextEmbeddingInferenceResult valueBody; +>>>>>>> c49af58dc (Revert "temp rebase fix") /** * Required - Response value. */ +<<<<<<< HEAD public final Builder inferenceResult(TextEmbeddingInferenceResult value) { this.inferenceResult = value; +======= + public final Builder valueBody(TextEmbeddingInferenceResult value) { + this.valueBody = value; +>>>>>>> c49af58dc (Revert "temp rebase fix") return this; } /** * Required - Response value. */ +<<<<<<< HEAD public final Builder inferenceResult( Function> fn) { return this.inferenceResult(fn.apply(new TextEmbeddingInferenceResult.Builder()).build()); +======= + public final Builder valueBody( + Function> fn) { + return this.valueBody(fn.apply(new TextEmbeddingInferenceResult.Builder()).build()); +>>>>>>> c49af58dc (Revert "temp rebase fix") } /** * Required - Response value. */ +<<<<<<< HEAD public final Builder inferenceResult(TextEmbeddingInferenceResultVariant value) { this.inferenceResult = value._toTextEmbeddingInferenceResult(); +======= + public final Builder valueBody(TextEmbeddingInferenceResultVariant value) { + this.valueBody = value._toTextEmbeddingInferenceResult(); +>>>>>>> c49af58dc (Revert "temp rebase fix") return this; } @@ -135,7 +172,11 @@ public Builder withJson(JsonParser parser, JsonpMapper mapper) { @SuppressWarnings("unchecked") TextEmbeddingInferenceResult value = (TextEmbeddingInferenceResult) TextEmbeddingInferenceResult._DESERIALIZER .deserialize(parser, mapper); +<<<<<<< HEAD return this.inferenceResult(value); +======= + return this.valueBody(value); +>>>>>>> c49af58dc (Revert "temp rebase fix") } @Override @@ -162,7 +203,11 @@ protected static JsonpDeserializer createTextEmbeddingRes JsonpDeserializer valueDeserializer = TextEmbeddingInferenceResult._DESERIALIZER; return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() +<<<<<<< HEAD .inferenceResult(valueDeserializer.deserialize(parser, mapper, event)).build()); +======= + .valueBody(valueDeserializer.deserialize(parser, mapper, event)).build()); +>>>>>>> c49af58dc (Revert "temp rebase fix") } } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResult.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResult.java new file mode 100644 index 000000000..a237a6945 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResult.java @@ -0,0 +1,179 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Float; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference._types.TextEmbeddingResult + +/** + * The text embedding result object + * + * @see API + * specification + */ +@JsonpDeserializable +public class TextEmbeddingResult implements JsonpSerializable { + private final List embedding; + + // --------------------------------------------------------------------------------------------- + + private TextEmbeddingResult(Builder builder) { + + this.embedding = ApiTypeHelper.unmodifiableRequired(builder.embedding, this, "embedding"); + + } + + public static TextEmbeddingResult of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - API name: {@code embedding} + */ + public final List embedding() { + return this.embedding; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (ApiTypeHelper.isDefined(this.embedding)) { + generator.writeKey("embedding"); + generator.writeStartArray(); + for (Float item0 : this.embedding) { + generator.write(item0); + + } + generator.writeEnd(); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link TextEmbeddingResult}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private List embedding; + + /** + * Required - API name: {@code embedding} + *

+ * Adds all elements of list to embedding. + */ + public final Builder embedding(List list) { + this.embedding = _listAddAll(this.embedding, list); + return this; + } + + /** + * Required - API name: {@code embedding} + *

+ * Adds one or more values to embedding. + */ + public final Builder embedding(Float value, Float... values) { + this.embedding = _listAdd(this.embedding, value, values); + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link TextEmbeddingResult}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public TextEmbeddingResult build() { + _checkSingleUse(); + + return new TextEmbeddingResult(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link TextEmbeddingResult} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, TextEmbeddingResult::setupTextEmbeddingResultDeserializer); + + protected static void setupTextEmbeddingResultDeserializer(ObjectDeserializer op) { + + op.add(Builder::embedding, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.floatDeserializer()), + "embedding"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/UpdateInferenceRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/UpdateInferenceRequest.java new file mode 100644 index 000000000..e210ed71f --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/UpdateInferenceRequest.java @@ -0,0 +1,298 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch._types.RequestBase; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.transport.Endpoint; +import co.elastic.clients.transport.endpoints.SimpleEndpoint; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonParser; +import java.lang.String; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.update.Request + +/** + * Update an inference endpoint. + *

+ * Modify task_settings, secrets (within + * service_settings), or num_allocations for an + * inference endpoint, depending on the specific endpoint service and + * task_type. + *

+ * IMPORTANT: The inference APIs enable you to use certain services, such as + * built-in machine learning models (ELSER, E5), models uploaded through Eland, + * Cohere, OpenAI, Azure, Google AI Studio, Google Vertex AI, Anthropic, + * Watsonx.ai, or Hugging Face. For built-in models and models uploaded through + * Eland, the inference APIs offer an alternative way to use and manage trained + * models. However, if you do not plan to use the inference APIs to use these + * models or if you want to use non-NLP models, use the machine learning trained + * model APIs. + * + * @see API + * specification + */ +@JsonpDeserializable +public class UpdateInferenceRequest extends RequestBase implements JsonpSerializable { + private final String inferenceId; + + @Nullable + private final TaskType taskType; + + private final InferenceEndpoint inferenceConfig; + + // --------------------------------------------------------------------------------------------- + + private UpdateInferenceRequest(Builder builder) { + + this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); + this.taskType = builder.taskType; + this.inferenceConfig = ApiTypeHelper.requireNonNull(builder.inferenceConfig, this, "inferenceConfig"); + + } + + public static UpdateInferenceRequest of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The unique identifier of the inference endpoint. + *

+ * API name: {@code inference_id} + */ + public final String inferenceId() { + return this.inferenceId; + } + + /** + * The type of inference task that the model performs. + *

+ * API name: {@code task_type} + */ + @Nullable + public final TaskType taskType() { + return this.taskType; + } + + /** + * Required - Request body. + */ + public final InferenceEndpoint inferenceConfig() { + return this.inferenceConfig; + } + + /** + * Serialize this value to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + this.inferenceConfig.serialize(generator, mapper); + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link UpdateInferenceRequest}. + */ + + public static class Builder extends RequestBase.AbstractBuilder + implements + ObjectBuilder { + private String inferenceId; + + @Nullable + private TaskType taskType; + + private InferenceEndpoint inferenceConfig; + + /** + * Required - The unique identifier of the inference endpoint. + *

+ * API name: {@code inference_id} + */ + public final Builder inferenceId(String value) { + this.inferenceId = value; + return this; + } + + /** + * The type of inference task that the model performs. + *

+ * API name: {@code task_type} + */ + public final Builder taskType(@Nullable TaskType value) { + this.taskType = value; + return this; + } + + /** + * Required - Request body. + */ + public final Builder inferenceConfig(InferenceEndpoint value) { + this.inferenceConfig = value; + return this; + } + + /** + * Required - Request body. + */ + public final Builder inferenceConfig(Function> fn) { + return this.inferenceConfig(fn.apply(new InferenceEndpoint.Builder()).build()); + } + + @Override + public Builder withJson(JsonParser parser, JsonpMapper mapper) { + + @SuppressWarnings("unchecked") + InferenceEndpoint value = (InferenceEndpoint) InferenceEndpoint._DESERIALIZER.deserialize(parser, mapper); + return this.inferenceConfig(value); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link UpdateInferenceRequest}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public UpdateInferenceRequest build() { + _checkSingleUse(); + + return new UpdateInferenceRequest(this); + } + } + + public static final JsonpDeserializer _DESERIALIZER = createUpdateInferenceRequestDeserializer(); + protected static JsonpDeserializer createUpdateInferenceRequestDeserializer() { + + JsonpDeserializer valueDeserializer = InferenceEndpoint._DESERIALIZER; + + return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() + .inferenceConfig(valueDeserializer.deserialize(parser, mapper, event)).build()); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Endpoint "{@code inference.update}". + */ + public static final Endpoint _ENDPOINT = new SimpleEndpoint<>( + "es/inference.update", + + // Request method + request -> { + return "PUT"; + + }, + + // Request path + request -> { + final int _inferenceId = 1 << 0; + final int _taskType = 1 << 1; + + int propsSet = 0; + + propsSet |= _inferenceId; + if (request.taskType() != null) + propsSet |= _taskType; + + if (propsSet == (_inferenceId)) { + StringBuilder buf = new StringBuilder(); + buf.append("/_inference"); + buf.append("/"); + SimpleEndpoint.pathEncode(request.inferenceId, buf); + buf.append("/_update"); + return buf.toString(); + } + if (propsSet == (_taskType | _inferenceId)) { + StringBuilder buf = new StringBuilder(); + buf.append("/_inference"); + buf.append("/"); + SimpleEndpoint.pathEncode(request.taskType.jsonValue(), buf); + buf.append("/"); + SimpleEndpoint.pathEncode(request.inferenceId, buf); + buf.append("/_update"); + return buf.toString(); + } + throw SimpleEndpoint.noPathTemplateFound("path"); + + }, + + // Path parameters + request -> { + Map params = new HashMap<>(); + final int _inferenceId = 1 << 0; + final int _taskType = 1 << 1; + + int propsSet = 0; + + propsSet |= _inferenceId; + if (request.taskType() != null) + propsSet |= _taskType; + + if (propsSet == (_inferenceId)) { + params.put("inferenceId", request.inferenceId); + } + if (propsSet == (_taskType | _inferenceId)) { + params.put("taskType", request.taskType.jsonValue()); + params.put("inferenceId", request.inferenceId); + } + return params; + }, + + // Request parameters + request -> { + return Collections.emptyMap(); + + }, SimpleEndpoint.emptyMap(), true, UpdateInferenceResponse._DESERIALIZER); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/UpdateInferenceResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/UpdateInferenceResponse.java new file mode 100644 index 000000000..2979876ac --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/UpdateInferenceResponse.java @@ -0,0 +1,107 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import jakarta.json.stream.JsonGenerator; +import java.util.Objects; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.update.Response + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class UpdateInferenceResponse extends InferenceEndpointInfo { + // --------------------------------------------------------------------------------------------- + + private UpdateInferenceResponse(Builder builder) { + super(builder); + + } + + public static UpdateInferenceResponse of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link UpdateInferenceResponse}. + */ + + public static class Builder extends InferenceEndpointInfo.AbstractBuilder + implements + ObjectBuilder { + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link UpdateInferenceResponse}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public UpdateInferenceResponse build() { + _checkSingleUse(); + + return new UpdateInferenceResponse(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link UpdateInferenceResponse} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, UpdateInferenceResponse::setupUpdateInferenceResponseDeserializer); + + protected static void setupUpdateInferenceResponseDeserializer( + ObjectDeserializer op) { + InferenceEndpointInfo.setupInferenceEndpointInfoDeserializer(op); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionTool.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionTool.java new file mode 100644 index 000000000..52a84d62a --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionTool.java @@ -0,0 +1,197 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.chat_completion_unified; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.chat_completion_unified.CompletionTool + +/** + * A list of tools that the model can call. + * + * @see API + * specification + */ +@JsonpDeserializable +public class CompletionTool implements JsonpSerializable { + private final String type; + + private final CompletionToolFunction function; + + // --------------------------------------------------------------------------------------------- + + private CompletionTool(Builder builder) { + + this.type = ApiTypeHelper.requireNonNull(builder.type, this, "type"); + this.function = ApiTypeHelper.requireNonNull(builder.function, this, "function"); + + } + + public static CompletionTool of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The type of tool. + *

+ * API name: {@code type} + */ + public final String type() { + return this.type; + } + + /** + * Required - The function definition. + *

+ * API name: {@code function} + */ + public final CompletionToolFunction function() { + return this.function; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("type"); + generator.write(this.type); + + generator.writeKey("function"); + this.function.serialize(generator, mapper); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link CompletionTool}. + */ + + public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { + private String type; + + private CompletionToolFunction function; + + /** + * Required - The type of tool. + *

+ * API name: {@code type} + */ + public final Builder type(String value) { + this.type = value; + return this; + } + + /** + * Required - The function definition. + *

+ * API name: {@code function} + */ + public final Builder function(CompletionToolFunction value) { + this.function = value; + return this; + } + + /** + * Required - The function definition. + *

+ * API name: {@code function} + */ + public final Builder function( + Function> fn) { + return this.function(fn.apply(new CompletionToolFunction.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link CompletionTool}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public CompletionTool build() { + _checkSingleUse(); + + return new CompletionTool(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link CompletionTool} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + CompletionTool::setupCompletionToolDeserializer); + + protected static void setupCompletionToolDeserializer(ObjectDeserializer op) { + + op.add(Builder::type, JsonpDeserializer.stringDeserializer(), "type"); + op.add(Builder::function, CompletionToolFunction._DESERIALIZER, "function"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolChoice.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolChoice.java new file mode 100644 index 000000000..dbad642e6 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolChoice.java @@ -0,0 +1,199 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.chat_completion_unified; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.chat_completion_unified.CompletionToolChoice + +/** + * Controls which tool is called by the model. + * + * @see API + * specification + */ +@JsonpDeserializable +public class CompletionToolChoice implements JsonpSerializable { + private final String type; + + private final CompletionToolChoiceFunction function; + + // --------------------------------------------------------------------------------------------- + + private CompletionToolChoice(Builder builder) { + + this.type = ApiTypeHelper.requireNonNull(builder.type, this, "type"); + this.function = ApiTypeHelper.requireNonNull(builder.function, this, "function"); + + } + + public static CompletionToolChoice of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The type of the tool. + *

+ * API name: {@code type} + */ + public final String type() { + return this.type; + } + + /** + * Required - The tool choice function. + *

+ * API name: {@code function} + */ + public final CompletionToolChoiceFunction function() { + return this.function; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("type"); + generator.write(this.type); + + generator.writeKey("function"); + this.function.serialize(generator, mapper); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link CompletionToolChoice}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String type; + + private CompletionToolChoiceFunction function; + + /** + * Required - The type of the tool. + *

+ * API name: {@code type} + */ + public final Builder type(String value) { + this.type = value; + return this; + } + + /** + * Required - The tool choice function. + *

+ * API name: {@code function} + */ + public final Builder function(CompletionToolChoiceFunction value) { + this.function = value; + return this; + } + + /** + * Required - The tool choice function. + *

+ * API name: {@code function} + */ + public final Builder function( + Function> fn) { + return this.function(fn.apply(new CompletionToolChoiceFunction.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link CompletionToolChoice}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public CompletionToolChoice build() { + _checkSingleUse(); + + return new CompletionToolChoice(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link CompletionToolChoice} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, CompletionToolChoice::setupCompletionToolChoiceDeserializer); + + protected static void setupCompletionToolChoiceDeserializer(ObjectDeserializer op) { + + op.add(Builder::type, JsonpDeserializer.stringDeserializer(), "type"); + op.add(Builder::function, CompletionToolChoiceFunction._DESERIALIZER, "function"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolChoiceFunction.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolChoiceFunction.java new file mode 100644 index 000000000..3678e4a20 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolChoiceFunction.java @@ -0,0 +1,162 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.chat_completion_unified; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.chat_completion_unified.CompletionToolChoiceFunction + +/** + * The tool choice function. + * + * @see API + * specification + */ +@JsonpDeserializable +public class CompletionToolChoiceFunction implements JsonpSerializable { + private final String name; + + // --------------------------------------------------------------------------------------------- + + private CompletionToolChoiceFunction(Builder builder) { + + this.name = ApiTypeHelper.requireNonNull(builder.name, this, "name"); + + } + + public static CompletionToolChoiceFunction of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The name of the function to call. + *

+ * API name: {@code name} + */ + public final String name() { + return this.name; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("name"); + generator.write(this.name); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link CompletionToolChoiceFunction}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String name; + + /** + * Required - The name of the function to call. + *

+ * API name: {@code name} + */ + public final Builder name(String value) { + this.name = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link CompletionToolChoiceFunction}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public CompletionToolChoiceFunction build() { + _checkSingleUse(); + + return new CompletionToolChoiceFunction(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link CompletionToolChoiceFunction} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, CompletionToolChoiceFunction::setupCompletionToolChoiceFunctionDeserializer); + + protected static void setupCompletionToolChoiceFunctionDeserializer( + ObjectDeserializer op) { + + op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolFunction.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolFunction.java new file mode 100644 index 000000000..30ed3b41d --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolFunction.java @@ -0,0 +1,268 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.chat_completion_unified; + +import co.elastic.clients.json.JsonData; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.chat_completion_unified.CompletionToolFunction + +/** + * The completion tool function definition. + * + * @see API + * specification + */ +@JsonpDeserializable +public class CompletionToolFunction implements JsonpSerializable { + @Nullable + private final String description; + + private final String name; + + @Nullable + private final JsonData parameters; + + @Nullable + private final Boolean strict; + + // --------------------------------------------------------------------------------------------- + + private CompletionToolFunction(Builder builder) { + + this.description = builder.description; + this.name = ApiTypeHelper.requireNonNull(builder.name, this, "name"); + this.parameters = builder.parameters; + this.strict = builder.strict; + + } + + public static CompletionToolFunction of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * A description of what the function does. This is used by the model to choose + * when and how to call the function. + *

+ * API name: {@code description} + */ + @Nullable + public final String description() { + return this.description; + } + + /** + * Required - The name of the function. + *

+ * API name: {@code name} + */ + public final String name() { + return this.name; + } + + /** + * The parameters the functional accepts. This should be formatted as a JSON + * object. + *

+ * API name: {@code parameters} + */ + @Nullable + public final JsonData parameters() { + return this.parameters; + } + + /** + * Whether to enable schema adherence when generating the function call. + *

+ * API name: {@code strict} + */ + @Nullable + public final Boolean strict() { + return this.strict; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.description != null) { + generator.writeKey("description"); + generator.write(this.description); + + } + generator.writeKey("name"); + generator.write(this.name); + + if (this.parameters != null) { + generator.writeKey("parameters"); + this.parameters.serialize(generator, mapper); + + } + if (this.strict != null) { + generator.writeKey("strict"); + generator.write(this.strict); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link CompletionToolFunction}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private String description; + + private String name; + + @Nullable + private JsonData parameters; + + @Nullable + private Boolean strict; + + /** + * A description of what the function does. This is used by the model to choose + * when and how to call the function. + *

+ * API name: {@code description} + */ + public final Builder description(@Nullable String value) { + this.description = value; + return this; + } + + /** + * Required - The name of the function. + *

+ * API name: {@code name} + */ + public final Builder name(String value) { + this.name = value; + return this; + } + + /** + * The parameters the functional accepts. This should be formatted as a JSON + * object. + *

+ * API name: {@code parameters} + */ + public final Builder parameters(@Nullable JsonData value) { + this.parameters = value; + return this; + } + + /** + * Whether to enable schema adherence when generating the function call. + *

+ * API name: {@code strict} + */ + public final Builder strict(@Nullable Boolean value) { + this.strict = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link CompletionToolFunction}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public CompletionToolFunction build() { + _checkSingleUse(); + + return new CompletionToolFunction(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link CompletionToolFunction} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, CompletionToolFunction::setupCompletionToolFunctionDeserializer); + + protected static void setupCompletionToolFunctionDeserializer( + ObjectDeserializer op) { + + op.add(Builder::description, JsonpDeserializer.stringDeserializer(), "description"); + op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); + op.add(Builder::parameters, JsonData._DESERIALIZER, "parameters"); + op.add(Builder::strict, JsonpDeserializer.booleanDeserializer(), "strict"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolType.java new file mode 100644 index 000000000..08db50b98 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolType.java @@ -0,0 +1,191 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.chat_completion_unified; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.json.UnionDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.ObjectBuilderBase; +import co.elastic.clients.util.TaggedUnion; +import co.elastic.clients.util.TaggedUnionUtils; +import jakarta.json.stream.JsonGenerator; +import java.lang.Object; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.chat_completion_unified.CompletionToolType + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class CompletionToolType implements TaggedUnion, JsonpSerializable { + + public enum Kind { + Object, String + + } + + private final Kind _kind; + private final Object _value; + + @Override + public final Kind _kind() { + return _kind; + } + + @Override + public final Object _get() { + return _value; + } + + private CompletionToolType(Kind kind, Object value) { + this._kind = kind; + this._value = value; + } + + private CompletionToolType(Builder builder) { + + this._kind = ApiTypeHelper.requireNonNull(builder._kind, builder, ""); + this._value = ApiTypeHelper.requireNonNull(builder._value, builder, ""); + + } + + public static CompletionToolType of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Is this variant instance of kind {@code object}? + */ + public boolean isObject() { + return _kind == Kind.Object; + } + + /** + * Get the {@code object} variant value. + * + * @throws IllegalStateException + * if the current variant is not of the {@code object} kind. + */ + public CompletionToolChoice object() { + return TaggedUnionUtils.get(this, Kind.Object); + } + + /** + * Is this variant instance of kind {@code string}? + */ + public boolean isString() { + return _kind == Kind.String; + } + + /** + * Get the {@code string} variant value. + * + * @throws IllegalStateException + * if the current variant is not of the {@code string} kind. + */ + public String string() { + return TaggedUnionUtils.get(this, Kind.String); + } + + @Override + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + if (_value instanceof JsonpSerializable) { + ((JsonpSerializable) _value).serialize(generator, mapper); + } else { + switch (_kind) { + case String : + generator.write(((String) this._value)); + + break; + } + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + public static class Builder extends ObjectBuilderBase implements ObjectBuilder { + private Kind _kind; + private Object _value; + + public ObjectBuilder object(CompletionToolChoice v) { + this._kind = Kind.Object; + this._value = v; + return this; + } + + public ObjectBuilder object( + Function> fn) { + return this.object(fn.apply(new CompletionToolChoice.Builder()).build()); + } + + public ObjectBuilder string(String v) { + this._kind = Kind.String; + this._value = v; + return this; + } + + public CompletionToolType build() { + _checkSingleUse(); + return new CompletionToolType(this); + } + + } + + private static JsonpDeserializer buildCompletionToolTypeDeserializer() { + return new UnionDeserializer.Builder(CompletionToolType::new, false) + .addMember(Kind.Object, CompletionToolChoice._DESERIALIZER) + .addMember(Kind.String, JsonpDeserializer.stringDeserializer()).build(); + } + + public static final JsonpDeserializer _DESERIALIZER = JsonpDeserializer + .lazy(CompletionToolType::buildCompletionToolTypeDeserializer); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolTypeBuilders.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolTypeBuilders.java new file mode 100644 index 000000000..6cb75d6af --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolTypeBuilders.java @@ -0,0 +1,59 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.chat_completion_unified; + +import co.elastic.clients.util.ObjectBuilder; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * Builders for {@link CompletionToolType} variants. + *

+ * Variants string are not available here as they don't have a + * dedicated class. Use {@link CompletionToolType}'s builder for these. + * + */ +public class CompletionToolTypeBuilders { + private CompletionToolTypeBuilders() { + } + + /** + * Creates a builder for the {@link CompletionToolChoice object} + * {@code CompletionToolType} variant. + */ + public static CompletionToolChoice.Builder object() { + return new CompletionToolChoice.Builder(); + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ContentObject.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ContentObject.java new file mode 100644 index 000000000..c834649ee --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ContentObject.java @@ -0,0 +1,187 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.chat_completion_unified; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.chat_completion_unified.ContentObject + +/** + * An object style representation of a single portion of a conversation. + * + * @see API + * specification + */ +@JsonpDeserializable +public class ContentObject implements JsonpSerializable { + private final String text; + + private final String type; + + // --------------------------------------------------------------------------------------------- + + private ContentObject(Builder builder) { + + this.text = ApiTypeHelper.requireNonNull(builder.text, this, "text"); + this.type = ApiTypeHelper.requireNonNull(builder.type, this, "type"); + + } + + public static ContentObject of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The text content. + *

+ * API name: {@code text} + */ + public final String text() { + return this.text; + } + + /** + * Required - The type of content. + *

+ * API name: {@code type} + */ + public final String type() { + return this.type; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("text"); + generator.write(this.text); + + generator.writeKey("type"); + generator.write(this.type); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link ContentObject}. + */ + + public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { + private String text; + + private String type; + + /** + * Required - The text content. + *

+ * API name: {@code text} + */ + public final Builder text(String value) { + this.text = value; + return this; + } + + /** + * Required - The type of content. + *

+ * API name: {@code type} + */ + public final Builder type(String value) { + this.type = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link ContentObject}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public ContentObject build() { + _checkSingleUse(); + + return new ContentObject(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link ContentObject} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + ContentObject::setupContentObjectDeserializer); + + protected static void setupContentObjectDeserializer(ObjectDeserializer op) { + + op.add(Builder::text, JsonpDeserializer.stringDeserializer(), "text"); + op.add(Builder::type, JsonpDeserializer.stringDeserializer(), "type"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/Message.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/Message.java new file mode 100644 index 000000000..dcde249d1 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/Message.java @@ -0,0 +1,297 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.chat_completion_unified; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.chat_completion_unified.Message + +/** + * An object representing part of the conversation. + * + * @see API + * specification + */ +@JsonpDeserializable +public class Message implements JsonpSerializable { + @Nullable + private final MessageContent content; + + private final String role; + + @Nullable + private final String toolCallId; + + private final List toolCalls; + + // --------------------------------------------------------------------------------------------- + + private Message(Builder builder) { + + this.content = builder.content; + this.role = ApiTypeHelper.requireNonNull(builder.role, this, "role"); + this.toolCallId = builder.toolCallId; + this.toolCalls = ApiTypeHelper.unmodifiable(builder.toolCalls); + + } + + public static Message of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * The content of the message. + *

+ * API name: {@code content} + */ + @Nullable + public final MessageContent content() { + return this.content; + } + + /** + * Required - The role of the message author. + *

+ * API name: {@code role} + */ + public final String role() { + return this.role; + } + + /** + * The tool call that this message is responding to. + *

+ * API name: {@code tool_call_id} + */ + @Nullable + public final String toolCallId() { + return this.toolCallId; + } + + /** + * The tool calls generated by the model. + *

+ * API name: {@code tool_calls} + */ + public final List toolCalls() { + return this.toolCalls; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.content != null) { + generator.writeKey("content"); + this.content.serialize(generator, mapper); + + } + generator.writeKey("role"); + generator.write(this.role); + + if (this.toolCallId != null) { + generator.writeKey("tool_call_id"); + generator.write(this.toolCallId); + + } + if (ApiTypeHelper.isDefined(this.toolCalls)) { + generator.writeKey("tool_calls"); + generator.writeStartArray(); + for (ToolCall item0 : this.toolCalls) { + item0.serialize(generator, mapper); + + } + generator.writeEnd(); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link Message}. + */ + + public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { + @Nullable + private MessageContent content; + + private String role; + + @Nullable + private String toolCallId; + + @Nullable + private List toolCalls; + + /** + * The content of the message. + *

+ * API name: {@code content} + */ + public final Builder content(@Nullable MessageContent value) { + this.content = value; + return this; + } + + /** + * The content of the message. + *

+ * API name: {@code content} + */ + public final Builder content(Function> fn) { + return this.content(fn.apply(new MessageContent.Builder()).build()); + } + + /** + * Required - The role of the message author. + *

+ * API name: {@code role} + */ + public final Builder role(String value) { + this.role = value; + return this; + } + + /** + * The tool call that this message is responding to. + *

+ * API name: {@code tool_call_id} + */ + public final Builder toolCallId(@Nullable String value) { + this.toolCallId = value; + return this; + } + + /** + * The tool calls generated by the model. + *

+ * API name: {@code tool_calls} + *

+ * Adds all elements of list to toolCalls. + */ + public final Builder toolCalls(List list) { + this.toolCalls = _listAddAll(this.toolCalls, list); + return this; + } + + /** + * The tool calls generated by the model. + *

+ * API name: {@code tool_calls} + *

+ * Adds one or more values to toolCalls. + */ + public final Builder toolCalls(ToolCall value, ToolCall... values) { + this.toolCalls = _listAdd(this.toolCalls, value, values); + return this; + } + + /** + * The tool calls generated by the model. + *

+ * API name: {@code tool_calls} + *

+ * Adds a value to toolCalls using a builder lambda. + */ + public final Builder toolCalls(Function> fn) { + return toolCalls(fn.apply(new ToolCall.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link Message}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public Message build() { + _checkSingleUse(); + + return new Message(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link Message} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + Message::setupMessageDeserializer); + + protected static void setupMessageDeserializer(ObjectDeserializer op) { + + op.add(Builder::content, MessageContent._DESERIALIZER, "content"); + op.add(Builder::role, JsonpDeserializer.stringDeserializer(), "role"); + op.add(Builder::toolCallId, JsonpDeserializer.stringDeserializer(), "tool_call_id"); + op.add(Builder::toolCalls, JsonpDeserializer.arrayDeserializer(ToolCall._DESERIALIZER), "tool_calls"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/MessageContent.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/MessageContent.java new file mode 100644 index 000000000..893600091 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/MessageContent.java @@ -0,0 +1,196 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.chat_completion_unified; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.json.UnionDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.ObjectBuilderBase; +import co.elastic.clients.util.TaggedUnion; +import co.elastic.clients.util.TaggedUnionUtils; +import jakarta.json.stream.JsonGenerator; +import java.lang.Object; +import java.lang.String; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.chat_completion_unified.MessageContent + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class MessageContent implements TaggedUnion, JsonpSerializable { + + public enum Kind { + Object, String + + } + + private final Kind _kind; + private final Object _value; + + @Override + public final Kind _kind() { + return _kind; + } + + @Override + public final Object _get() { + return _value; + } + + private MessageContent(Kind kind, Object value) { + this._kind = kind; + this._value = value; + } + + private MessageContent(Builder builder) { + + this._kind = ApiTypeHelper.requireNonNull(builder._kind, builder, ""); + this._value = ApiTypeHelper.requireNonNull(builder._value, builder, ""); + + } + + public static MessageContent of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Is this variant instance of kind {@code object}? + */ + public boolean isObject() { + return _kind == Kind.Object; + } + + /** + * Get the {@code object} variant value. + * + * @throws IllegalStateException + * if the current variant is not of the {@code object} kind. + */ + public List object() { + return TaggedUnionUtils.get(this, Kind.Object); + } + + /** + * Is this variant instance of kind {@code string}? + */ + public boolean isString() { + return _kind == Kind.String; + } + + /** + * Get the {@code string} variant value. + * + * @throws IllegalStateException + * if the current variant is not of the {@code string} kind. + */ + public String string() { + return TaggedUnionUtils.get(this, Kind.String); + } + + @Override + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + if (_value instanceof JsonpSerializable) { + ((JsonpSerializable) _value).serialize(generator, mapper); + } else { + switch (_kind) { + case Object : + generator.writeStartArray(); + for (ContentObject item0 : ((List) this._value)) { + item0.serialize(generator, mapper); + + } + generator.writeEnd(); + + break; + case String : + generator.write(((String) this._value)); + + break; + } + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + public static class Builder extends ObjectBuilderBase implements ObjectBuilder { + private Kind _kind; + private Object _value; + + public ObjectBuilder object(List v) { + this._kind = Kind.Object; + this._value = v; + return this; + } + + public ObjectBuilder string(String v) { + this._kind = Kind.String; + this._value = v; + return this; + } + + public MessageContent build() { + _checkSingleUse(); + return new MessageContent(this); + } + + } + + private static JsonpDeserializer buildMessageContentDeserializer() { + return new UnionDeserializer.Builder(MessageContent::new, false) + .addMember(Kind.Object, JsonpDeserializer.arrayDeserializer(ContentObject._DESERIALIZER)) + .addMember(Kind.String, JsonpDeserializer.stringDeserializer()).build(); + } + + public static final JsonpDeserializer _DESERIALIZER = JsonpDeserializer + .lazy(MessageContent::buildMessageContentDeserializer); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/MessageContentBuilders.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/MessageContentBuilders.java new file mode 100644 index 000000000..04cb0c5c9 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/MessageContentBuilders.java @@ -0,0 +1,52 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.chat_completion_unified; + +import co.elastic.clients.util.ObjectBuilder; +import java.util.function.Function; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * Builders for {@link MessageContent} variants. + *

+ * Variants object, string are not available here as + * they don't have a dedicated class. Use {@link MessageContent}'s builder for + * these. + * + */ +public class MessageContentBuilders { + private MessageContentBuilders() { + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ToolCall.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ToolCall.java new file mode 100644 index 000000000..c557d9dd9 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ToolCall.java @@ -0,0 +1,224 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.chat_completion_unified; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.chat_completion_unified.ToolCall + +/** + * A tool call generated by the model. + * + * @see API + * specification + */ +@JsonpDeserializable +public class ToolCall implements JsonpSerializable { + private final String id; + + private final ToolCallFunction function; + + private final String type; + + // --------------------------------------------------------------------------------------------- + + private ToolCall(Builder builder) { + + this.id = ApiTypeHelper.requireNonNull(builder.id, this, "id"); + this.function = ApiTypeHelper.requireNonNull(builder.function, this, "function"); + this.type = ApiTypeHelper.requireNonNull(builder.type, this, "type"); + + } + + public static ToolCall of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The identifier of the tool call. + *

+ * API name: {@code id} + */ + public final String id() { + return this.id; + } + + /** + * Required - The function that the model called. + *

+ * API name: {@code function} + */ + public final ToolCallFunction function() { + return this.function; + } + + /** + * Required - The type of the tool call. + *

+ * API name: {@code type} + */ + public final String type() { + return this.type; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("id"); + generator.write(this.id); + + generator.writeKey("function"); + this.function.serialize(generator, mapper); + + generator.writeKey("type"); + generator.write(this.type); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link ToolCall}. + */ + + public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { + private String id; + + private ToolCallFunction function; + + private String type; + + /** + * Required - The identifier of the tool call. + *

+ * API name: {@code id} + */ + public final Builder id(String value) { + this.id = value; + return this; + } + + /** + * Required - The function that the model called. + *

+ * API name: {@code function} + */ + public final Builder function(ToolCallFunction value) { + this.function = value; + return this; + } + + /** + * Required - The function that the model called. + *

+ * API name: {@code function} + */ + public final Builder function(Function> fn) { + return this.function(fn.apply(new ToolCallFunction.Builder()).build()); + } + + /** + * Required - The type of the tool call. + *

+ * API name: {@code type} + */ + public final Builder type(String value) { + this.type = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link ToolCall}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public ToolCall build() { + _checkSingleUse(); + + return new ToolCall(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link ToolCall} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + ToolCall::setupToolCallDeserializer); + + protected static void setupToolCallDeserializer(ObjectDeserializer op) { + + op.add(Builder::id, JsonpDeserializer.stringDeserializer(), "id"); + op.add(Builder::function, ToolCallFunction._DESERIALIZER, "function"); + op.add(Builder::type, JsonpDeserializer.stringDeserializer(), "type"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ToolCallFunction.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ToolCallFunction.java new file mode 100644 index 000000000..21cfd5237 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ToolCallFunction.java @@ -0,0 +1,187 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.chat_completion_unified; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.chat_completion_unified.ToolCallFunction + +/** + * The function that the model called. + * + * @see API + * specification + */ +@JsonpDeserializable +public class ToolCallFunction implements JsonpSerializable { + private final String arguments; + + private final String name; + + // --------------------------------------------------------------------------------------------- + + private ToolCallFunction(Builder builder) { + + this.arguments = ApiTypeHelper.requireNonNull(builder.arguments, this, "arguments"); + this.name = ApiTypeHelper.requireNonNull(builder.name, this, "name"); + + } + + public static ToolCallFunction of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The arguments to call the function with in JSON format. + *

+ * API name: {@code arguments} + */ + public final String arguments() { + return this.arguments; + } + + /** + * Required - The name of the function to call. + *

+ * API name: {@code name} + */ + public final String name() { + return this.name; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("arguments"); + generator.write(this.arguments); + + generator.writeKey("name"); + generator.write(this.name); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link ToolCallFunction}. + */ + + public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { + private String arguments; + + private String name; + + /** + * Required - The arguments to call the function with in JSON format. + *

+ * API name: {@code arguments} + */ + public final Builder arguments(String value) { + this.arguments = value; + return this; + } + + /** + * Required - The name of the function to call. + *

+ * API name: {@code name} + */ + public final Builder name(String value) { + this.name = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link ToolCallFunction}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public ToolCallFunction build() { + _checkSingleUse(); + + return new ToolCallFunction(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link ToolCallFunction} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + ToolCallFunction::setupToolCallFunctionDeserializer); + + protected static void setupToolCallFunctionDeserializer(ObjectDeserializer op) { + + op.add(Builder::arguments, JsonpDeserializer.stringDeserializer(), "arguments"); + op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudServiceSettings.java new file mode 100644 index 000000000..55d8c7ef9 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudServiceSettings.java @@ -0,0 +1,344 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_alibabacloud; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_alibabacloud.AlibabaCloudServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AlibabaCloudServiceSettings implements JsonpSerializable { + private final String apiKey; + + private final String host; + + @Nullable + private final RateLimitSetting rateLimit; + + private final String serviceId; + + private final String workspace; + + // --------------------------------------------------------------------------------------------- + + private AlibabaCloudServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.host = ApiTypeHelper.requireNonNull(builder.host, this, "host"); + this.rateLimit = builder.rateLimit; + this.serviceId = ApiTypeHelper.requireNonNull(builder.serviceId, this, "serviceId"); + this.workspace = ApiTypeHelper.requireNonNull(builder.workspace, this, "workspace"); + + } + + public static AlibabaCloudServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid API key for the AlibabaCloud AI Search API. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * Required - The name of the host address used for the inference task. You can + * find the host address in the API keys section of the documentation. + *

+ * API name: {@code host} + */ + public final String host() { + return this.host; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * AlibabaCloud AI Search. By default, the alibabacloud-ai-search + * service sets the number of requests allowed per minute to 1000. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Required - The name of the model service to use for the inference task. The + * following service IDs are available for the completion task: + *

    + *
  • ops-qwen-turbo
  • + *
  • qwen-turbo
  • + *
  • qwen-plus
  • + *
  • qwen-max ÷ qwen-max-longcontext
  • + *
+ *

+ * The following service ID is available for the rerank task: + *

    + *
  • ops-bge-reranker-larger
  • + *
+ *

+ * The following service ID is available for the sparse_embedding + * task: + *

    + *
  • ops-text-sparse-embedding-001
  • + *
+ *

+ * The following service IDs are available for the text_embedding + * task: + *

+ * ops-text-embedding-001 ops-text-embedding-zh-001 + * ops-text-embedding-en-001 ops-text-embedding-002 + *

+ * API name: {@code service_id} + */ + public final String serviceId() { + return this.serviceId; + } + + /** + * Required - The name of the workspace used for the inference task. + *

+ * API name: {@code workspace} + */ + public final String workspace() { + return this.workspace; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + generator.writeKey("host"); + generator.write(this.host); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + generator.writeKey("service_id"); + generator.write(this.serviceId); + + generator.writeKey("workspace"); + generator.write(this.workspace); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AlibabaCloudServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + private String host; + + @Nullable + private RateLimitSetting rateLimit; + + private String serviceId; + + private String workspace; + + /** + * Required - A valid API key for the AlibabaCloud AI Search API. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * Required - The name of the host address used for the inference task. You can + * find the host address in the API keys section of the documentation. + *

+ * API name: {@code host} + */ + public final Builder host(String value) { + this.host = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * AlibabaCloud AI Search. By default, the alibabacloud-ai-search + * service sets the number of requests allowed per minute to 1000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * AlibabaCloud AI Search. By default, the alibabacloud-ai-search + * service sets the number of requests allowed per minute to 1000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * Required - The name of the model service to use for the inference task. The + * following service IDs are available for the completion task: + *

    + *
  • ops-qwen-turbo
  • + *
  • qwen-turbo
  • + *
  • qwen-plus
  • + *
  • qwen-max ÷ qwen-max-longcontext
  • + *
+ *

+ * The following service ID is available for the rerank task: + *

    + *
  • ops-bge-reranker-larger
  • + *
+ *

+ * The following service ID is available for the sparse_embedding + * task: + *

    + *
  • ops-text-sparse-embedding-001
  • + *
+ *

+ * The following service IDs are available for the text_embedding + * task: + *

+ * ops-text-embedding-001 ops-text-embedding-zh-001 + * ops-text-embedding-en-001 ops-text-embedding-002 + *

+ * API name: {@code service_id} + */ + public final Builder serviceId(String value) { + this.serviceId = value; + return this; + } + + /** + * Required - The name of the workspace used for the inference task. + *

+ * API name: {@code workspace} + */ + public final Builder workspace(String value) { + this.workspace = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AlibabaCloudServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AlibabaCloudServiceSettings build() { + _checkSingleUse(); + + return new AlibabaCloudServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AlibabaCloudServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AlibabaCloudServiceSettings::setupAlibabaCloudServiceSettingsDeserializer); + + protected static void setupAlibabaCloudServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::host, JsonpDeserializer.stringDeserializer(), "host"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::serviceId, JsonpDeserializer.stringDeserializer(), "service_id"); + op.add(Builder::workspace, JsonpDeserializer.stringDeserializer(), "workspace"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskSettings.java new file mode 100644 index 000000000..288d3e0d1 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskSettings.java @@ -0,0 +1,218 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_alibabacloud; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_alibabacloud.AlibabaCloudTaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AlibabaCloudTaskSettings implements JsonpSerializable { + @Nullable + private final String inputType; + + @Nullable + private final Boolean returnToken; + + // --------------------------------------------------------------------------------------------- + + private AlibabaCloudTaskSettings(Builder builder) { + + this.inputType = builder.inputType; + this.returnToken = builder.returnToken; + + } + + public static AlibabaCloudTaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * For a sparse_embedding or text_embedding task, + * specify the type of input passed to the model. Valid values are: + *

    + *
  • ingest for storing document embeddings in a vector + * database.
  • + *
  • search for storing embeddings of search queries run against + * a vector database to find relevant documents.
  • + *
+ *

+ * API name: {@code input_type} + */ + @Nullable + public final String inputType() { + return this.inputType; + } + + /** + * For a sparse_embedding task, it affects whether the token name + * will be returned in the response. It defaults to false, which + * means only the token ID will be returned in the response. + *

+ * API name: {@code return_token} + */ + @Nullable + public final Boolean returnToken() { + return this.returnToken; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.inputType != null) { + generator.writeKey("input_type"); + generator.write(this.inputType); + + } + if (this.returnToken != null) { + generator.writeKey("return_token"); + generator.write(this.returnToken); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AlibabaCloudTaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private String inputType; + + @Nullable + private Boolean returnToken; + + /** + * For a sparse_embedding or text_embedding task, + * specify the type of input passed to the model. Valid values are: + *

    + *
  • ingest for storing document embeddings in a vector + * database.
  • + *
  • search for storing embeddings of search queries run against + * a vector database to find relevant documents.
  • + *
+ *

+ * API name: {@code input_type} + */ + public final Builder inputType(@Nullable String value) { + this.inputType = value; + return this; + } + + /** + * For a sparse_embedding task, it affects whether the token name + * will be returned in the response. It defaults to false, which + * means only the token ID will be returned in the response. + *

+ * API name: {@code return_token} + */ + public final Builder returnToken(@Nullable Boolean value) { + this.returnToken = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AlibabaCloudTaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AlibabaCloudTaskSettings build() { + _checkSingleUse(); + + return new AlibabaCloudTaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AlibabaCloudTaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AlibabaCloudTaskSettings::setupAlibabaCloudTaskSettingsDeserializer); + + protected static void setupAlibabaCloudTaskSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::inputType, JsonpDeserializer.stringDeserializer(), "input_type"); + op.add(Builder::returnToken, JsonpDeserializer.booleanDeserializer(), "return_token"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskType.java new file mode 100644 index 000000000..8adf946a1 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskType.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_alibabacloud; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum AlibabaCloudTaskType implements JsonEnum { + Completion("completion"), + + Rerank("rerank"), + + SpaceEmbedding("space_embedding"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + AlibabaCloudTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + AlibabaCloudTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/ServiceType.java new file mode 100644 index 000000000..010f0bfdf --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_alibabacloud; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + AlibabacloudAiSearch("alibabacloud-ai-search"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockServiceSettings.java new file mode 100644 index 000000000..06417819f --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockServiceSettings.java @@ -0,0 +1,371 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_amazonbedrock; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_amazonbedrock.AmazonBedrockServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AmazonBedrockServiceSettings implements JsonpSerializable { + private final String accessKey; + + private final String model; + + @Nullable + private final String provider; + + private final String region; + + @Nullable + private final RateLimitSetting rateLimit; + + private final String secretKey; + + // --------------------------------------------------------------------------------------------- + + private AmazonBedrockServiceSettings(Builder builder) { + + this.accessKey = ApiTypeHelper.requireNonNull(builder.accessKey, this, "accessKey"); + this.model = ApiTypeHelper.requireNonNull(builder.model, this, "model"); + this.provider = builder.provider; + this.region = ApiTypeHelper.requireNonNull(builder.region, this, "region"); + this.rateLimit = builder.rateLimit; + this.secretKey = ApiTypeHelper.requireNonNull(builder.secretKey, this, "secretKey"); + + } + + public static AmazonBedrockServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid AWS access key that has permissions to use Amazon Bedrock + * and access to models for inference requests. + *

+ * API name: {@code access_key} + */ + public final String accessKey() { + return this.accessKey; + } + + /** + * Required - The base model ID or an ARN to a custom model based on a + * foundational model. The base model IDs can be found in the Amazon Bedrock + * documentation. Note that the model ID must be available for the provider + * chosen and your IAM user must have access to the model. + *

+ * API name: {@code model} + */ + public final String model() { + return this.model; + } + + /** + * The model provider for your deployment. Note that some providers may support + * only certain task types. Supported providers include: + *

    + *
  • amazontitan - available for text_embedding and + * completion task types
  • + *
  • anthropic - available for completion task type + * only
  • + *
  • ai21labs - available for completion task type + * only
  • + *
  • cohere - available for text_embedding and + * completion task types
  • + *
  • meta - available for completion task type + * only
  • + *
  • mistral - available for completion task type + * only
  • + *
+ *

+ * API name: {@code provider} + */ + @Nullable + public final String provider() { + return this.provider; + } + + /** + * Required - The region that your model or ARN is deployed in. The list of + * available regions per model can be found in the Amazon Bedrock documentation. + *

+ * API name: {@code region} + */ + public final String region() { + return this.region; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Watsonx. By default, the watsonxai service sets the number of + * requests allowed per minute to 120. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Required - A valid AWS secret key that is paired with the + * access_key. For informationg about creating and managing access + * and secret keys, refer to the AWS documentation. + *

+ * API name: {@code secret_key} + */ + public final String secretKey() { + return this.secretKey; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("access_key"); + generator.write(this.accessKey); + + generator.writeKey("model"); + generator.write(this.model); + + if (this.provider != null) { + generator.writeKey("provider"); + generator.write(this.provider); + + } + generator.writeKey("region"); + generator.write(this.region); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + generator.writeKey("secret_key"); + generator.write(this.secretKey); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AmazonBedrockServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String accessKey; + + private String model; + + @Nullable + private String provider; + + private String region; + + @Nullable + private RateLimitSetting rateLimit; + + private String secretKey; + + /** + * Required - A valid AWS access key that has permissions to use Amazon Bedrock + * and access to models for inference requests. + *

+ * API name: {@code access_key} + */ + public final Builder accessKey(String value) { + this.accessKey = value; + return this; + } + + /** + * Required - The base model ID or an ARN to a custom model based on a + * foundational model. The base model IDs can be found in the Amazon Bedrock + * documentation. Note that the model ID must be available for the provider + * chosen and your IAM user must have access to the model. + *

+ * API name: {@code model} + */ + public final Builder model(String value) { + this.model = value; + return this; + } + + /** + * The model provider for your deployment. Note that some providers may support + * only certain task types. Supported providers include: + *

    + *
  • amazontitan - available for text_embedding and + * completion task types
  • + *
  • anthropic - available for completion task type + * only
  • + *
  • ai21labs - available for completion task type + * only
  • + *
  • cohere - available for text_embedding and + * completion task types
  • + *
  • meta - available for completion task type + * only
  • + *
  • mistral - available for completion task type + * only
  • + *
+ *

+ * API name: {@code provider} + */ + public final Builder provider(@Nullable String value) { + this.provider = value; + return this; + } + + /** + * Required - The region that your model or ARN is deployed in. The list of + * available regions per model can be found in the Amazon Bedrock documentation. + *

+ * API name: {@code region} + */ + public final Builder region(String value) { + this.region = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Watsonx. By default, the watsonxai service sets the number of + * requests allowed per minute to 120. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Watsonx. By default, the watsonxai service sets the number of + * requests allowed per minute to 120. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * Required - A valid AWS secret key that is paired with the + * access_key. For informationg about creating and managing access + * and secret keys, refer to the AWS documentation. + *

+ * API name: {@code secret_key} + */ + public final Builder secretKey(String value) { + this.secretKey = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AmazonBedrockServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AmazonBedrockServiceSettings build() { + _checkSingleUse(); + + return new AmazonBedrockServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AmazonBedrockServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AmazonBedrockServiceSettings::setupAmazonBedrockServiceSettingsDeserializer); + + protected static void setupAmazonBedrockServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::accessKey, JsonpDeserializer.stringDeserializer(), "access_key"); + op.add(Builder::model, JsonpDeserializer.stringDeserializer(), "model"); + op.add(Builder::provider, JsonpDeserializer.stringDeserializer(), "provider"); + op.add(Builder::region, JsonpDeserializer.stringDeserializer(), "region"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::secretKey, JsonpDeserializer.stringDeserializer(), "secret_key"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskSettings.java new file mode 100644 index 000000000..3ada2fc38 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskSettings.java @@ -0,0 +1,292 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_amazonbedrock; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Float; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_amazonbedrock.AmazonBedrockTaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AmazonBedrockTaskSettings implements JsonpSerializable { + @Nullable + private final Integer maxNewTokens; + + @Nullable + private final Float temperature; + + @Nullable + private final Float topK; + + @Nullable + private final Float topP; + + // --------------------------------------------------------------------------------------------- + + private AmazonBedrockTaskSettings(Builder builder) { + + this.maxNewTokens = builder.maxNewTokens; + this.temperature = builder.temperature; + this.topK = builder.topK; + this.topP = builder.topP; + + } + + public static AmazonBedrockTaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * For a completion task, it sets the maximum number for the output + * tokens to be generated. + *

+ * API name: {@code max_new_tokens} + */ + @Nullable + public final Integer maxNewTokens() { + return this.maxNewTokens; + } + + /** + * For a completion task, it is a number between 0.0 and 1.0 that + * controls the apparent creativity of the results. At temperature 0.0 the model + * is most deterministic, at temperature 1.0 most random. It should not be used + * if top_p or top_k is specified. + *

+ * API name: {@code temperature} + */ + @Nullable + public final Float temperature() { + return this.temperature; + } + + /** + * For a completion task, it limits samples to the top-K most + * likely words, balancing coherence and variability. It is only available for + * anthropic, cohere, and mistral providers. It is an alternative to + * temperature; it should not be used if temperature + * is specified. + *

+ * API name: {@code top_k} + */ + @Nullable + public final Float topK() { + return this.topK; + } + + /** + * For a completion task, it is a number in the range of 0.0 to + * 1.0, to eliminate low-probability tokens. Top-p uses nucleus sampling to + * select top tokens whose sum of likelihoods does not exceed a certain value, + * ensuring both variety and coherence. It is an alternative to + * temperature; it should not be used if temperature + * is specified. + *

+ * API name: {@code top_p} + */ + @Nullable + public final Float topP() { + return this.topP; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.maxNewTokens != null) { + generator.writeKey("max_new_tokens"); + generator.write(this.maxNewTokens); + + } + if (this.temperature != null) { + generator.writeKey("temperature"); + generator.write(this.temperature); + + } + if (this.topK != null) { + generator.writeKey("top_k"); + generator.write(this.topK); + + } + if (this.topP != null) { + generator.writeKey("top_p"); + generator.write(this.topP); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AmazonBedrockTaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private Integer maxNewTokens; + + @Nullable + private Float temperature; + + @Nullable + private Float topK; + + @Nullable + private Float topP; + + /** + * For a completion task, it sets the maximum number for the output + * tokens to be generated. + *

+ * API name: {@code max_new_tokens} + */ + public final Builder maxNewTokens(@Nullable Integer value) { + this.maxNewTokens = value; + return this; + } + + /** + * For a completion task, it is a number between 0.0 and 1.0 that + * controls the apparent creativity of the results. At temperature 0.0 the model + * is most deterministic, at temperature 1.0 most random. It should not be used + * if top_p or top_k is specified. + *

+ * API name: {@code temperature} + */ + public final Builder temperature(@Nullable Float value) { + this.temperature = value; + return this; + } + + /** + * For a completion task, it limits samples to the top-K most + * likely words, balancing coherence and variability. It is only available for + * anthropic, cohere, and mistral providers. It is an alternative to + * temperature; it should not be used if temperature + * is specified. + *

+ * API name: {@code top_k} + */ + public final Builder topK(@Nullable Float value) { + this.topK = value; + return this; + } + + /** + * For a completion task, it is a number in the range of 0.0 to + * 1.0, to eliminate low-probability tokens. Top-p uses nucleus sampling to + * select top tokens whose sum of likelihoods does not exceed a certain value, + * ensuring both variety and coherence. It is an alternative to + * temperature; it should not be used if temperature + * is specified. + *

+ * API name: {@code top_p} + */ + public final Builder topP(@Nullable Float value) { + this.topP = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AmazonBedrockTaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AmazonBedrockTaskSettings build() { + _checkSingleUse(); + + return new AmazonBedrockTaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AmazonBedrockTaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AmazonBedrockTaskSettings::setupAmazonBedrockTaskSettingsDeserializer); + + protected static void setupAmazonBedrockTaskSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::maxNewTokens, JsonpDeserializer.integerDeserializer(), "max_new_tokens"); + op.add(Builder::temperature, JsonpDeserializer.floatDeserializer(), "temperature"); + op.add(Builder::topK, JsonpDeserializer.floatDeserializer(), "top_k"); + op.add(Builder::topP, JsonpDeserializer.floatDeserializer(), "top_p"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskType.java new file mode 100644 index 000000000..67d56cc4f --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskType.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_amazonbedrock; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum AmazonBedrockTaskType implements JsonEnum { + Completion("completion"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + AmazonBedrockTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + AmazonBedrockTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/ServiceType.java new file mode 100644 index 000000000..417d4e7c7 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_amazonbedrock; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Amazonbedrock("amazonbedrock"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicServiceSettings.java new file mode 100644 index 000000000..fd1133481 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicServiceSettings.java @@ -0,0 +1,241 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_anthropic; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_anthropic.AnthropicServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AnthropicServiceSettings implements JsonpSerializable { + private final String apiKey; + + private final String modelId; + + @Nullable + private final RateLimitSetting rateLimit; + + // --------------------------------------------------------------------------------------------- + + private AnthropicServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); + this.rateLimit = builder.rateLimit; + + } + + public static AnthropicServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid API key for the Anthropic API. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * Anthropic documentation for the list of supported models. + *

+ * API name: {@code model_id} + */ + public final String modelId() { + return this.modelId; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Anthropic. By default, the anthropic service sets the number of + * requests allowed per minute to 50. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + generator.writeKey("model_id"); + generator.write(this.modelId); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AnthropicServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + private String modelId; + + @Nullable + private RateLimitSetting rateLimit; + + /** + * Required - A valid API key for the Anthropic API. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * Anthropic documentation for the list of supported models. + *

+ * API name: {@code model_id} + */ + public final Builder modelId(String value) { + this.modelId = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Anthropic. By default, the anthropic service sets the number of + * requests allowed per minute to 50. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Anthropic. By default, the anthropic service sets the number of + * requests allowed per minute to 50. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AnthropicServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AnthropicServiceSettings build() { + _checkSingleUse(); + + return new AnthropicServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AnthropicServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AnthropicServiceSettings::setupAnthropicServiceSettingsDeserializer); + + protected static void setupAnthropicServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskSettings.java new file mode 100644 index 000000000..cababb804 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskSettings.java @@ -0,0 +1,283 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_anthropic; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Float; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_anthropic.AnthropicTaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AnthropicTaskSettings implements JsonpSerializable { + private final int maxTokens; + + @Nullable + private final Float temperature; + + @Nullable + private final Integer topK; + + @Nullable + private final Float topP; + + // --------------------------------------------------------------------------------------------- + + private AnthropicTaskSettings(Builder builder) { + + this.maxTokens = ApiTypeHelper.requireNonNull(builder.maxTokens, this, "maxTokens"); + this.temperature = builder.temperature; + this.topK = builder.topK; + this.topP = builder.topP; + + } + + public static AnthropicTaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - For a completion task, it is the maximum number of + * tokens to generate before stopping. + *

+ * API name: {@code max_tokens} + */ + public final int maxTokens() { + return this.maxTokens; + } + + /** + * For a completion task, it is the amount of randomness injected + * into the response. For more details about the supported range, refer to + * Anthropic documentation. + *

+ * API name: {@code temperature} + */ + @Nullable + public final Float temperature() { + return this.temperature; + } + + /** + * For a completion task, it specifies to only sample from the top + * K options for each subsequent token. It is recommended for advanced use cases + * only. You usually only need to use temperature. + *

+ * API name: {@code top_k} + */ + @Nullable + public final Integer topK() { + return this.topK; + } + + /** + * For a completion task, it specifies to use Anthropic's nucleus + * sampling. In nucleus sampling, Anthropic computes the cumulative distribution + * over all the options for each subsequent token in decreasing probability + * order and cuts it off once it reaches the specified probability. You should + * either alter temperature or top_p, but not both. It + * is recommended for advanced use cases only. You usually only need to use + * temperature. + *

+ * API name: {@code top_p} + */ + @Nullable + public final Float topP() { + return this.topP; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("max_tokens"); + generator.write(this.maxTokens); + + if (this.temperature != null) { + generator.writeKey("temperature"); + generator.write(this.temperature); + + } + if (this.topK != null) { + generator.writeKey("top_k"); + generator.write(this.topK); + + } + if (this.topP != null) { + generator.writeKey("top_p"); + generator.write(this.topP); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AnthropicTaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private Integer maxTokens; + + @Nullable + private Float temperature; + + @Nullable + private Integer topK; + + @Nullable + private Float topP; + + /** + * Required - For a completion task, it is the maximum number of + * tokens to generate before stopping. + *

+ * API name: {@code max_tokens} + */ + public final Builder maxTokens(int value) { + this.maxTokens = value; + return this; + } + + /** + * For a completion task, it is the amount of randomness injected + * into the response. For more details about the supported range, refer to + * Anthropic documentation. + *

+ * API name: {@code temperature} + */ + public final Builder temperature(@Nullable Float value) { + this.temperature = value; + return this; + } + + /** + * For a completion task, it specifies to only sample from the top + * K options for each subsequent token. It is recommended for advanced use cases + * only. You usually only need to use temperature. + *

+ * API name: {@code top_k} + */ + public final Builder topK(@Nullable Integer value) { + this.topK = value; + return this; + } + + /** + * For a completion task, it specifies to use Anthropic's nucleus + * sampling. In nucleus sampling, Anthropic computes the cumulative distribution + * over all the options for each subsequent token in decreasing probability + * order and cuts it off once it reaches the specified probability. You should + * either alter temperature or top_p, but not both. It + * is recommended for advanced use cases only. You usually only need to use + * temperature. + *

+ * API name: {@code top_p} + */ + public final Builder topP(@Nullable Float value) { + this.topP = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AnthropicTaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AnthropicTaskSettings build() { + _checkSingleUse(); + + return new AnthropicTaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AnthropicTaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AnthropicTaskSettings::setupAnthropicTaskSettingsDeserializer); + + protected static void setupAnthropicTaskSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::maxTokens, JsonpDeserializer.integerDeserializer(), "max_tokens"); + op.add(Builder::temperature, JsonpDeserializer.floatDeserializer(), "temperature"); + op.add(Builder::topK, JsonpDeserializer.integerDeserializer(), "top_k"); + op.add(Builder::topP, JsonpDeserializer.floatDeserializer(), "top_p"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskType.java new file mode 100644 index 000000000..4599e9d31 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_anthropic; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum AnthropicTaskType implements JsonEnum { + Completion("completion"), + + ; + + private final String jsonValue; + + AnthropicTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + AnthropicTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/ServiceType.java new file mode 100644 index 000000000..2d6288747 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_anthropic; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Anthropic("anthropic"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioServiceSettings.java new file mode 100644 index 000000000..a407ad66b --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioServiceSettings.java @@ -0,0 +1,353 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_azureaistudio; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_azureaistudio.AzureAiStudioServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AzureAiStudioServiceSettings implements JsonpSerializable { + private final String apiKey; + + private final String endpointType; + + private final String target; + + private final String provider; + + @Nullable + private final RateLimitSetting rateLimit; + + // --------------------------------------------------------------------------------------------- + + private AzureAiStudioServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.endpointType = ApiTypeHelper.requireNonNull(builder.endpointType, this, "endpointType"); + this.target = ApiTypeHelper.requireNonNull(builder.target, this, "target"); + this.provider = ApiTypeHelper.requireNonNull(builder.provider, this, "provider"); + this.rateLimit = builder.rateLimit; + + } + + public static AzureAiStudioServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid API key of your Azure AI Studio model deployment. This key + * can be found on the overview page for your deployment in the management + * section of your Azure AI Studio account. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * Required - The type of endpoint that is available for deployment through + * Azure AI Studio: token or realtime. The + * token endpoint type is for "pay as you go" endpoints + * that are billed per token. The realtime endpoint type is for + * "real-time" endpoints that are billed per hour of usage. + *

+ * API name: {@code endpoint_type} + */ + public final String endpointType() { + return this.endpointType; + } + + /** + * Required - The target URL of your Azure AI Studio model deployment. This can + * be found on the overview page for your deployment in the management section + * of your Azure AI Studio account. + *

+ * API name: {@code target} + */ + public final String target() { + return this.target; + } + + /** + * Required - The model provider for your deployment. Note that some providers + * may support only certain task types. Supported providers include: + *

    + *
  • cohere - available for text_embedding and + * completion task types
  • + *
  • databricks - available for completion task type + * only
  • + *
  • meta - available for completion task type + * only
  • + *
  • microsoft_phi - available for completion task + * type only
  • + *
  • mistral - available for completion task type + * only
  • + *
  • openai - available for text_embedding and + * completion task types
  • + *
+ *

+ * API name: {@code provider} + */ + public final String provider() { + return this.provider; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Azure AI Studio. By default, the azureaistudio service sets the + * number of requests allowed per minute to 240. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + generator.writeKey("endpoint_type"); + generator.write(this.endpointType); + + generator.writeKey("target"); + generator.write(this.target); + + generator.writeKey("provider"); + generator.write(this.provider); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AzureAiStudioServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + private String endpointType; + + private String target; + + private String provider; + + @Nullable + private RateLimitSetting rateLimit; + + /** + * Required - A valid API key of your Azure AI Studio model deployment. This key + * can be found on the overview page for your deployment in the management + * section of your Azure AI Studio account. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * Required - The type of endpoint that is available for deployment through + * Azure AI Studio: token or realtime. The + * token endpoint type is for "pay as you go" endpoints + * that are billed per token. The realtime endpoint type is for + * "real-time" endpoints that are billed per hour of usage. + *

+ * API name: {@code endpoint_type} + */ + public final Builder endpointType(String value) { + this.endpointType = value; + return this; + } + + /** + * Required - The target URL of your Azure AI Studio model deployment. This can + * be found on the overview page for your deployment in the management section + * of your Azure AI Studio account. + *

+ * API name: {@code target} + */ + public final Builder target(String value) { + this.target = value; + return this; + } + + /** + * Required - The model provider for your deployment. Note that some providers + * may support only certain task types. Supported providers include: + *

    + *
  • cohere - available for text_embedding and + * completion task types
  • + *
  • databricks - available for completion task type + * only
  • + *
  • meta - available for completion task type + * only
  • + *
  • microsoft_phi - available for completion task + * type only
  • + *
  • mistral - available for completion task type + * only
  • + *
  • openai - available for text_embedding and + * completion task types
  • + *
+ *

+ * API name: {@code provider} + */ + public final Builder provider(String value) { + this.provider = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Azure AI Studio. By default, the azureaistudio service sets the + * number of requests allowed per minute to 240. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Azure AI Studio. By default, the azureaistudio service sets the + * number of requests allowed per minute to 240. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AzureAiStudioServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AzureAiStudioServiceSettings build() { + _checkSingleUse(); + + return new AzureAiStudioServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AzureAiStudioServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AzureAiStudioServiceSettings::setupAzureAiStudioServiceSettingsDeserializer); + + protected static void setupAzureAiStudioServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::endpointType, JsonpDeserializer.stringDeserializer(), "endpoint_type"); + op.add(Builder::target, JsonpDeserializer.stringDeserializer(), "target"); + op.add(Builder::provider, JsonpDeserializer.stringDeserializer(), "provider"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskSettings.java new file mode 100644 index 000000000..df846c062 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskSettings.java @@ -0,0 +1,320 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_azureaistudio; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Float; +import java.lang.Integer; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_azureaistudio.AzureAiStudioTaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AzureAiStudioTaskSettings implements JsonpSerializable { + @Nullable + private final Float doSample; + + @Nullable + private final Integer maxNewTokens; + + @Nullable + private final Float temperature; + + @Nullable + private final Float topP; + + @Nullable + private final String user; + + // --------------------------------------------------------------------------------------------- + + private AzureAiStudioTaskSettings(Builder builder) { + + this.doSample = builder.doSample; + this.maxNewTokens = builder.maxNewTokens; + this.temperature = builder.temperature; + this.topP = builder.topP; + this.user = builder.user; + + } + + public static AzureAiStudioTaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * For a completion task, instruct the inference process to perform + * sampling. It has no effect unless temperature or + * top_p is specified. + *

+ * API name: {@code do_sample} + */ + @Nullable + public final Float doSample() { + return this.doSample; + } + + /** + * For a completion task, provide a hint for the maximum number of + * output tokens to be generated. + *

+ * API name: {@code max_new_tokens} + */ + @Nullable + public final Integer maxNewTokens() { + return this.maxNewTokens; + } + + /** + * For a completion task, control the apparent creativity of + * generated completions with a sampling temperature. It must be a number in the + * range of 0.0 to 2.0. It should not be used if top_p is + * specified. + *

+ * API name: {@code temperature} + */ + @Nullable + public final Float temperature() { + return this.temperature; + } + + /** + * For a completion task, make the model consider the results of + * the tokens with nucleus sampling probability. It is an alternative value to + * temperature and must be a number in the range of 0.0 to 2.0. It + * should not be used if temperature is specified. + *

+ * API name: {@code top_p} + */ + @Nullable + public final Float topP() { + return this.topP; + } + + /** + * For a text_embedding task, specify the user issuing the request. + * This information can be used for abuse detection. + *

+ * API name: {@code user} + */ + @Nullable + public final String user() { + return this.user; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.doSample != null) { + generator.writeKey("do_sample"); + generator.write(this.doSample); + + } + if (this.maxNewTokens != null) { + generator.writeKey("max_new_tokens"); + generator.write(this.maxNewTokens); + + } + if (this.temperature != null) { + generator.writeKey("temperature"); + generator.write(this.temperature); + + } + if (this.topP != null) { + generator.writeKey("top_p"); + generator.write(this.topP); + + } + if (this.user != null) { + generator.writeKey("user"); + generator.write(this.user); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AzureAiStudioTaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private Float doSample; + + @Nullable + private Integer maxNewTokens; + + @Nullable + private Float temperature; + + @Nullable + private Float topP; + + @Nullable + private String user; + + /** + * For a completion task, instruct the inference process to perform + * sampling. It has no effect unless temperature or + * top_p is specified. + *

+ * API name: {@code do_sample} + */ + public final Builder doSample(@Nullable Float value) { + this.doSample = value; + return this; + } + + /** + * For a completion task, provide a hint for the maximum number of + * output tokens to be generated. + *

+ * API name: {@code max_new_tokens} + */ + public final Builder maxNewTokens(@Nullable Integer value) { + this.maxNewTokens = value; + return this; + } + + /** + * For a completion task, control the apparent creativity of + * generated completions with a sampling temperature. It must be a number in the + * range of 0.0 to 2.0. It should not be used if top_p is + * specified. + *

+ * API name: {@code temperature} + */ + public final Builder temperature(@Nullable Float value) { + this.temperature = value; + return this; + } + + /** + * For a completion task, make the model consider the results of + * the tokens with nucleus sampling probability. It is an alternative value to + * temperature and must be a number in the range of 0.0 to 2.0. It + * should not be used if temperature is specified. + *

+ * API name: {@code top_p} + */ + public final Builder topP(@Nullable Float value) { + this.topP = value; + return this; + } + + /** + * For a text_embedding task, specify the user issuing the request. + * This information can be used for abuse detection. + *

+ * API name: {@code user} + */ + public final Builder user(@Nullable String value) { + this.user = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AzureAiStudioTaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AzureAiStudioTaskSettings build() { + _checkSingleUse(); + + return new AzureAiStudioTaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AzureAiStudioTaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AzureAiStudioTaskSettings::setupAzureAiStudioTaskSettingsDeserializer); + + protected static void setupAzureAiStudioTaskSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::doSample, JsonpDeserializer.floatDeserializer(), "do_sample"); + op.add(Builder::maxNewTokens, JsonpDeserializer.integerDeserializer(), "max_new_tokens"); + op.add(Builder::temperature, JsonpDeserializer.floatDeserializer(), "temperature"); + op.add(Builder::topP, JsonpDeserializer.floatDeserializer(), "top_p"); + op.add(Builder::user, JsonpDeserializer.stringDeserializer(), "user"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskType.java new file mode 100644 index 000000000..7a8b074fe --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskType.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_azureaistudio; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum AzureAiStudioTaskType implements JsonEnum { + Completion("completion"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + AzureAiStudioTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + AzureAiStudioTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/ServiceType.java new file mode 100644 index 000000000..5e3b80f0e --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_azureaistudio; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Azureaistudio("azureaistudio"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAIServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAIServiceSettings.java new file mode 100644 index 000000000..849f7bee6 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAIServiceSettings.java @@ -0,0 +1,368 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_azureopenai; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_azureopenai.AzureOpenAIServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AzureOpenAIServiceSettings implements JsonpSerializable { + @Nullable + private final String apiKey; + + private final String apiVersion; + + private final String deploymentId; + + @Nullable + private final String entraId; + + @Nullable + private final RateLimitSetting rateLimit; + + private final String resourceName; + + // --------------------------------------------------------------------------------------------- + + private AzureOpenAIServiceSettings(Builder builder) { + + this.apiKey = builder.apiKey; + this.apiVersion = ApiTypeHelper.requireNonNull(builder.apiVersion, this, "apiVersion"); + this.deploymentId = ApiTypeHelper.requireNonNull(builder.deploymentId, this, "deploymentId"); + this.entraId = builder.entraId; + this.rateLimit = builder.rateLimit; + this.resourceName = ApiTypeHelper.requireNonNull(builder.resourceName, this, "resourceName"); + + } + + public static AzureOpenAIServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * A valid API key for your Azure OpenAI account. You must specify either + * api_key or entra_id. If you do not provide either + * or you provide both, you will receive an error when you try to create your + * model. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + @Nullable + public final String apiKey() { + return this.apiKey; + } + + /** + * Required - The Azure API version ID to use. It is recommended to use the + * latest supported non-preview version. + *

+ * API name: {@code api_version} + */ + public final String apiVersion() { + return this.apiVersion; + } + + /** + * Required - The deployment name of your deployed models. Your Azure OpenAI + * deployments can be found though the Azure OpenAI Studio portal that is linked + * to your subscription. + *

+ * API name: {@code deployment_id} + */ + public final String deploymentId() { + return this.deploymentId; + } + + /** + * A valid Microsoft Entra token. You must specify either api_key + * or entra_id. If you do not provide either or you provide both, + * you will receive an error when you try to create your model. + *

+ * API name: {@code entra_id} + */ + @Nullable + public final String entraId() { + return this.entraId; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Azure. The azureopenai service sets a default number of requests + * allowed per minute depending on the task type. For + * text_embedding, it is set to 1440. For + * completion, it is set to 120. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Required - The name of your Azure OpenAI resource. You can find this from the + * list of resources in the Azure Portal for your subscription. + *

+ * API name: {@code resource_name} + */ + public final String resourceName() { + return this.resourceName; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.apiKey != null) { + generator.writeKey("api_key"); + generator.write(this.apiKey); + + } + generator.writeKey("api_version"); + generator.write(this.apiVersion); + + generator.writeKey("deployment_id"); + generator.write(this.deploymentId); + + if (this.entraId != null) { + generator.writeKey("entra_id"); + generator.write(this.entraId); + + } + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + generator.writeKey("resource_name"); + generator.write(this.resourceName); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AzureOpenAIServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private String apiKey; + + private String apiVersion; + + private String deploymentId; + + @Nullable + private String entraId; + + @Nullable + private RateLimitSetting rateLimit; + + private String resourceName; + + /** + * A valid API key for your Azure OpenAI account. You must specify either + * api_key or entra_id. If you do not provide either + * or you provide both, you will receive an error when you try to create your + * model. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(@Nullable String value) { + this.apiKey = value; + return this; + } + + /** + * Required - The Azure API version ID to use. It is recommended to use the + * latest supported non-preview version. + *

+ * API name: {@code api_version} + */ + public final Builder apiVersion(String value) { + this.apiVersion = value; + return this; + } + + /** + * Required - The deployment name of your deployed models. Your Azure OpenAI + * deployments can be found though the Azure OpenAI Studio portal that is linked + * to your subscription. + *

+ * API name: {@code deployment_id} + */ + public final Builder deploymentId(String value) { + this.deploymentId = value; + return this; + } + + /** + * A valid Microsoft Entra token. You must specify either api_key + * or entra_id. If you do not provide either or you provide both, + * you will receive an error when you try to create your model. + *

+ * API name: {@code entra_id} + */ + public final Builder entraId(@Nullable String value) { + this.entraId = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Azure. The azureopenai service sets a default number of requests + * allowed per minute depending on the task type. For + * text_embedding, it is set to 1440. For + * completion, it is set to 120. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Azure. The azureopenai service sets a default number of requests + * allowed per minute depending on the task type. For + * text_embedding, it is set to 1440. For + * completion, it is set to 120. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * Required - The name of your Azure OpenAI resource. You can find this from the + * list of resources in the Azure Portal for your subscription. + *

+ * API name: {@code resource_name} + */ + public final Builder resourceName(String value) { + this.resourceName = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AzureOpenAIServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AzureOpenAIServiceSettings build() { + _checkSingleUse(); + + return new AzureOpenAIServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AzureOpenAIServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AzureOpenAIServiceSettings::setupAzureOpenAIServiceSettingsDeserializer); + + protected static void setupAzureOpenAIServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::apiVersion, JsonpDeserializer.stringDeserializer(), "api_version"); + op.add(Builder::deploymentId, JsonpDeserializer.stringDeserializer(), "deployment_id"); + op.add(Builder::entraId, JsonpDeserializer.stringDeserializer(), "entra_id"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::resourceName, JsonpDeserializer.stringDeserializer(), "resource_name"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAITaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAITaskType.java new file mode 100644 index 000000000..4c6414276 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAITaskType.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_azureopenai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum AzureOpenAITaskType implements JsonEnum { + Completion("completion"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + AzureOpenAITaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + AzureOpenAITaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/ServiceType.java new file mode 100644 index 000000000..c27837b69 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_azureopenai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Azureopenai("azureopenai"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereServiceSettings.java new file mode 100644 index 000000000..86c1c9e24 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereServiceSettings.java @@ -0,0 +1,363 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_cohere; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_cohere.CohereServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class CohereServiceSettings implements JsonpSerializable { + private final String apiKey; + + @Nullable + private final EmbeddingType embeddingType; + + @Nullable + private final String modelId; + + @Nullable + private final RateLimitSetting rateLimit; + + @Nullable + private final SimilarityType similarity; + + // --------------------------------------------------------------------------------------------- + + private CohereServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.embeddingType = builder.embeddingType; + this.modelId = builder.modelId; + this.rateLimit = builder.rateLimit; + this.similarity = builder.similarity; + + } + + public static CohereServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid API key for your Cohere account. You can find or create + * your Cohere API keys on the Cohere API key settings page. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * For a text_embedding task, the types of embeddings you want to + * get back. Use byte for signed int8 embeddings (this is a synonym + * of int8). Use float for the default float + * embeddings. Use int8 for signed int8 embeddings. + *

+ * API name: {@code embedding_type} + */ + @Nullable + public final EmbeddingType embeddingType() { + return this.embeddingType; + } + + /** + * For a completion, rerank, or + * text_embedding task, the name of the model to use for the + * inference task. + *

+ *

+ * The default value for a text embedding task is + * embed-english-v2.0. + *

+ * API name: {@code model_id} + */ + @Nullable + public final String modelId() { + return this.modelId; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Cohere. By default, the cohere service sets the number of + * requests allowed per minute to 10000. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * The similarity measure. If the embedding_type is + * float, the default value is dot_product. If the + * embedding_type is int8 or byte, the + * default value is cosine. + *

+ * API name: {@code similarity} + */ + @Nullable + public final SimilarityType similarity() { + return this.similarity; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + if (this.embeddingType != null) { + generator.writeKey("embedding_type"); + this.embeddingType.serialize(generator, mapper); + } + if (this.modelId != null) { + generator.writeKey("model_id"); + generator.write(this.modelId); + + } + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + if (this.similarity != null) { + generator.writeKey("similarity"); + this.similarity.serialize(generator, mapper); + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link CohereServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + @Nullable + private EmbeddingType embeddingType; + + @Nullable + private String modelId; + + @Nullable + private RateLimitSetting rateLimit; + + @Nullable + private SimilarityType similarity; + + /** + * Required - A valid API key for your Cohere account. You can find or create + * your Cohere API keys on the Cohere API key settings page. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * For a text_embedding task, the types of embeddings you want to + * get back. Use byte for signed int8 embeddings (this is a synonym + * of int8). Use float for the default float + * embeddings. Use int8 for signed int8 embeddings. + *

+ * API name: {@code embedding_type} + */ + public final Builder embeddingType(@Nullable EmbeddingType value) { + this.embeddingType = value; + return this; + } + + /** + * For a completion, rerank, or + * text_embedding task, the name of the model to use for the + * inference task. + *

+ *

+ * The default value for a text embedding task is + * embed-english-v2.0. + *

+ * API name: {@code model_id} + */ + public final Builder modelId(@Nullable String value) { + this.modelId = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Cohere. By default, the cohere service sets the number of + * requests allowed per minute to 10000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Cohere. By default, the cohere service sets the number of + * requests allowed per minute to 10000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * The similarity measure. If the embedding_type is + * float, the default value is dot_product. If the + * embedding_type is int8 or byte, the + * default value is cosine. + *

+ * API name: {@code similarity} + */ + public final Builder similarity(@Nullable SimilarityType value) { + this.similarity = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link CohereServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public CohereServiceSettings build() { + _checkSingleUse(); + + return new CohereServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link CohereServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, CohereServiceSettings::setupCohereServiceSettingsDeserializer); + + protected static void setupCohereServiceSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::embeddingType, EmbeddingType._DESERIALIZER, "embedding_type"); + op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::similarity, SimilarityType._DESERIALIZER, "similarity"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskSettings.java new file mode 100644 index 000000000..77947b3ee --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskSettings.java @@ -0,0 +1,317 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_cohere; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_cohere.CohereTaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class CohereTaskSettings implements JsonpSerializable { + @Nullable + private final InputType inputType; + + @Nullable + private final Boolean returnDocuments; + + @Nullable + private final Integer topN; + + @Nullable + private final TruncateType truncate; + + // --------------------------------------------------------------------------------------------- + + private CohereTaskSettings(Builder builder) { + + this.inputType = builder.inputType; + this.returnDocuments = builder.returnDocuments; + this.topN = builder.topN; + this.truncate = builder.truncate; + + } + + public static CohereTaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * For a text_embedding task, the type of input passed to the + * model. Valid values are: + *

    + *
  • classification: Use it for embeddings passed through a text + * classifier.
  • + *
  • clustering: Use it for the embeddings run through a + * clustering algorithm.
  • + *
  • ingest: Use it for storing document embeddings in a vector + * database.
  • + *
  • search: Use it for storing embeddings of search queries run + * against a vector database to find relevant documents.
  • + *
+ *

+ * IMPORTANT: The input_type field is required when using embedding + * models v3 and higher. + *

+ * API name: {@code input_type} + */ + @Nullable + public final InputType inputType() { + return this.inputType; + } + + /** + * For a rerank task, return doc text within the results. + *

+ * API name: {@code return_documents} + */ + @Nullable + public final Boolean returnDocuments() { + return this.returnDocuments; + } + + /** + * For a rerank task, the number of most relevant documents to + * return. It defaults to the number of the documents. If this inference + * endpoint is used in a text_similarity_reranker retriever query + * and top_n is set, it must be greater than or equal to + * rank_window_size in the query. + *

+ * API name: {@code top_n} + */ + @Nullable + public final Integer topN() { + return this.topN; + } + + /** + * For a text_embedding task, the method to handle inputs longer + * than the maximum token length. Valid values are: + *

    + *
  • END: When the input exceeds the maximum input token length, + * the end of the input is discarded.
  • + *
  • NONE: When the input exceeds the maximum input token length, + * an error is returned.
  • + *
  • START: When the input exceeds the maximum input token + * length, the start of the input is discarded.
  • + *
+ *

+ * API name: {@code truncate} + */ + @Nullable + public final TruncateType truncate() { + return this.truncate; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.inputType != null) { + generator.writeKey("input_type"); + this.inputType.serialize(generator, mapper); + } + if (this.returnDocuments != null) { + generator.writeKey("return_documents"); + generator.write(this.returnDocuments); + + } + if (this.topN != null) { + generator.writeKey("top_n"); + generator.write(this.topN); + + } + if (this.truncate != null) { + generator.writeKey("truncate"); + this.truncate.serialize(generator, mapper); + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link CohereTaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private InputType inputType; + + @Nullable + private Boolean returnDocuments; + + @Nullable + private Integer topN; + + @Nullable + private TruncateType truncate; + + /** + * For a text_embedding task, the type of input passed to the + * model. Valid values are: + *

    + *
  • classification: Use it for embeddings passed through a text + * classifier.
  • + *
  • clustering: Use it for the embeddings run through a + * clustering algorithm.
  • + *
  • ingest: Use it for storing document embeddings in a vector + * database.
  • + *
  • search: Use it for storing embeddings of search queries run + * against a vector database to find relevant documents.
  • + *
+ *

+ * IMPORTANT: The input_type field is required when using embedding + * models v3 and higher. + *

+ * API name: {@code input_type} + */ + public final Builder inputType(@Nullable InputType value) { + this.inputType = value; + return this; + } + + /** + * For a rerank task, return doc text within the results. + *

+ * API name: {@code return_documents} + */ + public final Builder returnDocuments(@Nullable Boolean value) { + this.returnDocuments = value; + return this; + } + + /** + * For a rerank task, the number of most relevant documents to + * return. It defaults to the number of the documents. If this inference + * endpoint is used in a text_similarity_reranker retriever query + * and top_n is set, it must be greater than or equal to + * rank_window_size in the query. + *

+ * API name: {@code top_n} + */ + public final Builder topN(@Nullable Integer value) { + this.topN = value; + return this; + } + + /** + * For a text_embedding task, the method to handle inputs longer + * than the maximum token length. Valid values are: + *

    + *
  • END: When the input exceeds the maximum input token length, + * the end of the input is discarded.
  • + *
  • NONE: When the input exceeds the maximum input token length, + * an error is returned.
  • + *
  • START: When the input exceeds the maximum input token + * length, the start of the input is discarded.
  • + *
+ *

+ * API name: {@code truncate} + */ + public final Builder truncate(@Nullable TruncateType value) { + this.truncate = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link CohereTaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public CohereTaskSettings build() { + _checkSingleUse(); + + return new CohereTaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link CohereTaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, CohereTaskSettings::setupCohereTaskSettingsDeserializer); + + protected static void setupCohereTaskSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::inputType, InputType._DESERIALIZER, "input_type"); + op.add(Builder::returnDocuments, JsonpDeserializer.booleanDeserializer(), "return_documents"); + op.add(Builder::topN, JsonpDeserializer.integerDeserializer(), "top_n"); + op.add(Builder::truncate, TruncateType._DESERIALIZER, "truncate"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskType.java new file mode 100644 index 000000000..81025c4aa --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskType.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_cohere; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum CohereTaskType implements JsonEnum { + Completion("completion"), + + Rerank("rerank"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + CohereTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + CohereTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/EmbeddingType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/EmbeddingType.java new file mode 100644 index 000000000..0527144d6 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/EmbeddingType.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_cohere; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum EmbeddingType implements JsonEnum { + Byte("byte"), + + Float("float"), + + Int8("int8"), + + ; + + private final String jsonValue; + + EmbeddingType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + EmbeddingType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/InputType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/InputType.java new file mode 100644 index 000000000..e4ff40c8f --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/InputType.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_cohere; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum InputType implements JsonEnum { + Classification("classification"), + + Clustering("clustering"), + + Ingest("ingest"), + + Search("search"), + + ; + + private final String jsonValue; + + InputType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + InputType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/ServiceType.java new file mode 100644 index 000000000..ff717e85a --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_cohere; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Cohere("cohere"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/SimilarityType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/SimilarityType.java new file mode 100644 index 000000000..651346c62 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/SimilarityType.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_cohere; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum SimilarityType implements JsonEnum { + Cosine("cosine"), + + DotProduct("dot_product"), + + L2Norm("l2_norm"), + + ; + + private final String jsonValue; + + SimilarityType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + SimilarityType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/TruncateType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/TruncateType.java new file mode 100644 index 000000000..b3f7691cd --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/TruncateType.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_cohere; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum TruncateType implements JsonEnum { + End("END"), + + None("NONE"), + + Start("START"), + + ; + + private final String jsonValue; + + TruncateType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + TruncateType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/EisServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/EisServiceSettings.java new file mode 100644 index 000000000..56c3ec63f --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/EisServiceSettings.java @@ -0,0 +1,210 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_eis; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_eis.EisServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class EisServiceSettings implements JsonpSerializable { + private final String modelId; + + @Nullable + private final RateLimitSetting rateLimit; + + // --------------------------------------------------------------------------------------------- + + private EisServiceSettings(Builder builder) { + + this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); + this.rateLimit = builder.rateLimit; + + } + + public static EisServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The name of the model to use for the inference task. + *

+ * API name: {@code model_id} + */ + public final String modelId() { + return this.modelId; + } + + /** + * This setting helps to minimize the number of rate limit errors returned. By + * default, the elastic service sets the number of requests allowed + * per minute to 240 in case of chat_completion. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("model_id"); + generator.write(this.modelId); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link EisServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String modelId; + + @Nullable + private RateLimitSetting rateLimit; + + /** + * Required - The name of the model to use for the inference task. + *

+ * API name: {@code model_id} + */ + public final Builder modelId(String value) { + this.modelId = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned. By + * default, the elastic service sets the number of requests allowed + * per minute to 240 in case of chat_completion. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned. By + * default, the elastic service sets the number of requests allowed + * per minute to 240 in case of chat_completion. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link EisServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public EisServiceSettings build() { + _checkSingleUse(); + + return new EisServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link EisServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, EisServiceSettings::setupEisServiceSettingsDeserializer); + + protected static void setupEisServiceSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/EisTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/EisTaskType.java new file mode 100644 index 000000000..59d10e58b --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/EisTaskType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_eis; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum EisTaskType implements JsonEnum { + ChatCompletion("chat_completion"), + + ; + + private final String jsonValue; + + EisTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + EisTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/ServiceType.java new file mode 100644 index 000000000..ecb074488 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_eis; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Elastic("elastic"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/AdaptiveAllocations.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/AdaptiveAllocations.java new file mode 100644 index 000000000..b5c60a2ae --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/AdaptiveAllocations.java @@ -0,0 +1,236 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_elasticsearch; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_elasticsearch.AdaptiveAllocations + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AdaptiveAllocations implements JsonpSerializable { + @Nullable + private final Boolean enabled; + + @Nullable + private final Integer maxNumberOfAllocations; + + @Nullable + private final Integer minNumberOfAllocations; + + // --------------------------------------------------------------------------------------------- + + private AdaptiveAllocations(Builder builder) { + + this.enabled = builder.enabled; + this.maxNumberOfAllocations = builder.maxNumberOfAllocations; + this.minNumberOfAllocations = builder.minNumberOfAllocations; + + } + + public static AdaptiveAllocations of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Turn on adaptive_allocations. + *

+ * API name: {@code enabled} + */ + @Nullable + public final Boolean enabled() { + return this.enabled; + } + + /** + * The maximum number of allocations to scale to. If set, it must be greater + * than or equal to min_number_of_allocations. + *

+ * API name: {@code max_number_of_allocations} + */ + @Nullable + public final Integer maxNumberOfAllocations() { + return this.maxNumberOfAllocations; + } + + /** + * The minimum number of allocations to scale to. If set, it must be greater + * than or equal to 0. If not defined, the deployment scales to 0. + *

+ * API name: {@code min_number_of_allocations} + */ + @Nullable + public final Integer minNumberOfAllocations() { + return this.minNumberOfAllocations; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.enabled != null) { + generator.writeKey("enabled"); + generator.write(this.enabled); + + } + if (this.maxNumberOfAllocations != null) { + generator.writeKey("max_number_of_allocations"); + generator.write(this.maxNumberOfAllocations); + + } + if (this.minNumberOfAllocations != null) { + generator.writeKey("min_number_of_allocations"); + generator.write(this.minNumberOfAllocations); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AdaptiveAllocations}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private Boolean enabled; + + @Nullable + private Integer maxNumberOfAllocations; + + @Nullable + private Integer minNumberOfAllocations; + + /** + * Turn on adaptive_allocations. + *

+ * API name: {@code enabled} + */ + public final Builder enabled(@Nullable Boolean value) { + this.enabled = value; + return this; + } + + /** + * The maximum number of allocations to scale to. If set, it must be greater + * than or equal to min_number_of_allocations. + *

+ * API name: {@code max_number_of_allocations} + */ + public final Builder maxNumberOfAllocations(@Nullable Integer value) { + this.maxNumberOfAllocations = value; + return this; + } + + /** + * The minimum number of allocations to scale to. If set, it must be greater + * than or equal to 0. If not defined, the deployment scales to 0. + *

+ * API name: {@code min_number_of_allocations} + */ + public final Builder minNumberOfAllocations(@Nullable Integer value) { + this.minNumberOfAllocations = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AdaptiveAllocations}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AdaptiveAllocations build() { + _checkSingleUse(); + + return new AdaptiveAllocations(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AdaptiveAllocations} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AdaptiveAllocations::setupAdaptiveAllocationsDeserializer); + + protected static void setupAdaptiveAllocationsDeserializer(ObjectDeserializer op) { + + op.add(Builder::enabled, JsonpDeserializer.booleanDeserializer(), "enabled"); + op.add(Builder::maxNumberOfAllocations, JsonpDeserializer.integerDeserializer(), "max_number_of_allocations"); + op.add(Builder::minNumberOfAllocations, JsonpDeserializer.integerDeserializer(), "min_number_of_allocations"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchServiceSettings.java new file mode 100644 index 000000000..e9e60d46a --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchServiceSettings.java @@ -0,0 +1,342 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_elasticsearch; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Integer; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_elasticsearch.ElasticsearchServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class ElasticsearchServiceSettings implements JsonpSerializable { + @Nullable + private final AdaptiveAllocations adaptiveAllocations; + + @Nullable + private final String deploymentId; + + private final String modelId; + + @Nullable + private final Integer numAllocations; + + private final int numThreads; + + // --------------------------------------------------------------------------------------------- + + private ElasticsearchServiceSettings(Builder builder) { + + this.adaptiveAllocations = builder.adaptiveAllocations; + this.deploymentId = builder.deploymentId; + this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); + this.numAllocations = builder.numAllocations; + this.numThreads = ApiTypeHelper.requireNonNull(builder.numThreads, this, "numThreads"); + + } + + public static ElasticsearchServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Adaptive allocations configuration details. If enabled is true, + * the number of allocations of the model is set based on the current load the + * process gets. When the load is high, a new model allocation is automatically + * created, respecting the value of max_number_of_allocations if + * it's set. When the load is low, a model allocation is automatically removed, + * respecting the value of min_number_of_allocations if it's set. + * If enabled is true, do not set the number of allocations + * manually. + *

+ * API name: {@code adaptive_allocations} + */ + @Nullable + public final AdaptiveAllocations adaptiveAllocations() { + return this.adaptiveAllocations; + } + + /** + * The deployment identifier for a trained model deployment. When + * deployment_id is used the model_id is optional. + *

+ * API name: {@code deployment_id} + */ + @Nullable + public final String deploymentId() { + return this.deploymentId; + } + + /** + * Required - The name of the model to use for the inference task. It can be the + * ID of a built-in model (for example, .multilingual-e5-small for + * E5) or a text embedding model that was uploaded by using the Eland client. + *

+ * API name: {@code model_id} + */ + public final String modelId() { + return this.modelId; + } + + /** + * The total number of allocations that are assigned to the model across machine + * learning nodes. Increasing this value generally increases the throughput. If + * adaptive allocations are enabled, do not set this value because it's + * automatically set. + *

+ * API name: {@code num_allocations} + */ + @Nullable + public final Integer numAllocations() { + return this.numAllocations; + } + + /** + * Required - The number of threads used by each model allocation during + * inference. This setting generally increases the speed per inference request. + * The inference process is a compute-bound process; + * threads_per_allocations must not exceed the number of available + * allocated processors per node. The value must be a power of 2. The maximum + * value is 32. + *

+ * API name: {@code num_threads} + */ + public final int numThreads() { + return this.numThreads; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.adaptiveAllocations != null) { + generator.writeKey("adaptive_allocations"); + this.adaptiveAllocations.serialize(generator, mapper); + + } + if (this.deploymentId != null) { + generator.writeKey("deployment_id"); + generator.write(this.deploymentId); + + } + generator.writeKey("model_id"); + generator.write(this.modelId); + + if (this.numAllocations != null) { + generator.writeKey("num_allocations"); + generator.write(this.numAllocations); + + } + generator.writeKey("num_threads"); + generator.write(this.numThreads); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link ElasticsearchServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private AdaptiveAllocations adaptiveAllocations; + + @Nullable + private String deploymentId; + + private String modelId; + + @Nullable + private Integer numAllocations; + + private Integer numThreads; + + /** + * Adaptive allocations configuration details. If enabled is true, + * the number of allocations of the model is set based on the current load the + * process gets. When the load is high, a new model allocation is automatically + * created, respecting the value of max_number_of_allocations if + * it's set. When the load is low, a model allocation is automatically removed, + * respecting the value of min_number_of_allocations if it's set. + * If enabled is true, do not set the number of allocations + * manually. + *

+ * API name: {@code adaptive_allocations} + */ + public final Builder adaptiveAllocations(@Nullable AdaptiveAllocations value) { + this.adaptiveAllocations = value; + return this; + } + + /** + * Adaptive allocations configuration details. If enabled is true, + * the number of allocations of the model is set based on the current load the + * process gets. When the load is high, a new model allocation is automatically + * created, respecting the value of max_number_of_allocations if + * it's set. When the load is low, a model allocation is automatically removed, + * respecting the value of min_number_of_allocations if it's set. + * If enabled is true, do not set the number of allocations + * manually. + *

+ * API name: {@code adaptive_allocations} + */ + public final Builder adaptiveAllocations( + Function> fn) { + return this.adaptiveAllocations(fn.apply(new AdaptiveAllocations.Builder()).build()); + } + + /** + * The deployment identifier for a trained model deployment. When + * deployment_id is used the model_id is optional. + *

+ * API name: {@code deployment_id} + */ + public final Builder deploymentId(@Nullable String value) { + this.deploymentId = value; + return this; + } + + /** + * Required - The name of the model to use for the inference task. It can be the + * ID of a built-in model (for example, .multilingual-e5-small for + * E5) or a text embedding model that was uploaded by using the Eland client. + *

+ * API name: {@code model_id} + */ + public final Builder modelId(String value) { + this.modelId = value; + return this; + } + + /** + * The total number of allocations that are assigned to the model across machine + * learning nodes. Increasing this value generally increases the throughput. If + * adaptive allocations are enabled, do not set this value because it's + * automatically set. + *

+ * API name: {@code num_allocations} + */ + public final Builder numAllocations(@Nullable Integer value) { + this.numAllocations = value; + return this; + } + + /** + * Required - The number of threads used by each model allocation during + * inference. This setting generally increases the speed per inference request. + * The inference process is a compute-bound process; + * threads_per_allocations must not exceed the number of available + * allocated processors per node. The value must be a power of 2. The maximum + * value is 32. + *

+ * API name: {@code num_threads} + */ + public final Builder numThreads(int value) { + this.numThreads = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link ElasticsearchServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public ElasticsearchServiceSettings build() { + _checkSingleUse(); + + return new ElasticsearchServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link ElasticsearchServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, ElasticsearchServiceSettings::setupElasticsearchServiceSettingsDeserializer); + + protected static void setupElasticsearchServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::adaptiveAllocations, AdaptiveAllocations._DESERIALIZER, "adaptive_allocations"); + op.add(Builder::deploymentId, JsonpDeserializer.stringDeserializer(), "deployment_id"); + op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); + op.add(Builder::numAllocations, JsonpDeserializer.integerDeserializer(), "num_allocations"); + op.add(Builder::numThreads, JsonpDeserializer.integerDeserializer(), "num_threads"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskSettings.java new file mode 100644 index 000000000..085c5faad --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskSettings.java @@ -0,0 +1,168 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_elasticsearch; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_elasticsearch.ElasticsearchTaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class ElasticsearchTaskSettings implements JsonpSerializable { + @Nullable + private final Boolean returnDocuments; + + // --------------------------------------------------------------------------------------------- + + private ElasticsearchTaskSettings(Builder builder) { + + this.returnDocuments = builder.returnDocuments; + + } + + public static ElasticsearchTaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * For a rerank task, return the document instead of only the + * index. + *

+ * API name: {@code return_documents} + */ + @Nullable + public final Boolean returnDocuments() { + return this.returnDocuments; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.returnDocuments != null) { + generator.writeKey("return_documents"); + generator.write(this.returnDocuments); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link ElasticsearchTaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private Boolean returnDocuments; + + /** + * For a rerank task, return the document instead of only the + * index. + *

+ * API name: {@code return_documents} + */ + public final Builder returnDocuments(@Nullable Boolean value) { + this.returnDocuments = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link ElasticsearchTaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public ElasticsearchTaskSettings build() { + _checkSingleUse(); + + return new ElasticsearchTaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link ElasticsearchTaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, ElasticsearchTaskSettings::setupElasticsearchTaskSettingsDeserializer); + + protected static void setupElasticsearchTaskSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::returnDocuments, JsonpDeserializer.booleanDeserializer(), "return_documents"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskType.java new file mode 100644 index 000000000..bdd5a9230 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskType.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_elasticsearch; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ElasticsearchTaskType implements JsonEnum { + Rerank("rerank"), + + SparseEmbedding("sparse_embedding"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + ElasticsearchTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ElasticsearchTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ServiceType.java new file mode 100644 index 000000000..623a65181 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_elasticsearch; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Elasticsearch("elasticsearch"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/AdaptiveAllocations.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/AdaptiveAllocations.java new file mode 100644 index 000000000..3facca41b --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/AdaptiveAllocations.java @@ -0,0 +1,236 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_elser; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_elser.AdaptiveAllocations + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class AdaptiveAllocations implements JsonpSerializable { + @Nullable + private final Boolean enabled; + + @Nullable + private final Integer maxNumberOfAllocations; + + @Nullable + private final Integer minNumberOfAllocations; + + // --------------------------------------------------------------------------------------------- + + private AdaptiveAllocations(Builder builder) { + + this.enabled = builder.enabled; + this.maxNumberOfAllocations = builder.maxNumberOfAllocations; + this.minNumberOfAllocations = builder.minNumberOfAllocations; + + } + + public static AdaptiveAllocations of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Turn on adaptive_allocations. + *

+ * API name: {@code enabled} + */ + @Nullable + public final Boolean enabled() { + return this.enabled; + } + + /** + * The maximum number of allocations to scale to. If set, it must be greater + * than or equal to min_number_of_allocations. + *

+ * API name: {@code max_number_of_allocations} + */ + @Nullable + public final Integer maxNumberOfAllocations() { + return this.maxNumberOfAllocations; + } + + /** + * The minimum number of allocations to scale to. If set, it must be greater + * than or equal to 0. If not defined, the deployment scales to 0. + *

+ * API name: {@code min_number_of_allocations} + */ + @Nullable + public final Integer minNumberOfAllocations() { + return this.minNumberOfAllocations; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.enabled != null) { + generator.writeKey("enabled"); + generator.write(this.enabled); + + } + if (this.maxNumberOfAllocations != null) { + generator.writeKey("max_number_of_allocations"); + generator.write(this.maxNumberOfAllocations); + + } + if (this.minNumberOfAllocations != null) { + generator.writeKey("min_number_of_allocations"); + generator.write(this.minNumberOfAllocations); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link AdaptiveAllocations}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private Boolean enabled; + + @Nullable + private Integer maxNumberOfAllocations; + + @Nullable + private Integer minNumberOfAllocations; + + /** + * Turn on adaptive_allocations. + *

+ * API name: {@code enabled} + */ + public final Builder enabled(@Nullable Boolean value) { + this.enabled = value; + return this; + } + + /** + * The maximum number of allocations to scale to. If set, it must be greater + * than or equal to min_number_of_allocations. + *

+ * API name: {@code max_number_of_allocations} + */ + public final Builder maxNumberOfAllocations(@Nullable Integer value) { + this.maxNumberOfAllocations = value; + return this; + } + + /** + * The minimum number of allocations to scale to. If set, it must be greater + * than or equal to 0. If not defined, the deployment scales to 0. + *

+ * API name: {@code min_number_of_allocations} + */ + public final Builder minNumberOfAllocations(@Nullable Integer value) { + this.minNumberOfAllocations = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link AdaptiveAllocations}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public AdaptiveAllocations build() { + _checkSingleUse(); + + return new AdaptiveAllocations(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link AdaptiveAllocations} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, AdaptiveAllocations::setupAdaptiveAllocationsDeserializer); + + protected static void setupAdaptiveAllocationsDeserializer(ObjectDeserializer op) { + + op.add(Builder::enabled, JsonpDeserializer.booleanDeserializer(), "enabled"); + op.add(Builder::maxNumberOfAllocations, JsonpDeserializer.integerDeserializer(), "max_number_of_allocations"); + op.add(Builder::minNumberOfAllocations, JsonpDeserializer.integerDeserializer(), "min_number_of_allocations"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserServiceSettings.java new file mode 100644 index 000000000..5cee104ba --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserServiceSettings.java @@ -0,0 +1,280 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_elser; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_elser.ElserServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class ElserServiceSettings implements JsonpSerializable { + @Nullable + private final AdaptiveAllocations adaptiveAllocations; + + private final int numAllocations; + + private final int numThreads; + + // --------------------------------------------------------------------------------------------- + + private ElserServiceSettings(Builder builder) { + + this.adaptiveAllocations = builder.adaptiveAllocations; + this.numAllocations = ApiTypeHelper.requireNonNull(builder.numAllocations, this, "numAllocations"); + this.numThreads = ApiTypeHelper.requireNonNull(builder.numThreads, this, "numThreads"); + + } + + public static ElserServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Adaptive allocations configuration details. If enabled is true, + * the number of allocations of the model is set based on the current load the + * process gets. When the load is high, a new model allocation is automatically + * created, respecting the value of max_number_of_allocations if + * it's set. When the load is low, a model allocation is automatically removed, + * respecting the value of min_number_of_allocations if it's set. + * If enabled is true, do not set the number of allocations + * manually. + *

+ * API name: {@code adaptive_allocations} + */ + @Nullable + public final AdaptiveAllocations adaptiveAllocations() { + return this.adaptiveAllocations; + } + + /** + * Required - The total number of allocations this model is assigned across + * machine learning nodes. Increasing this value generally increases the + * throughput. If adaptive allocations is enabled, do not set this value because + * it's automatically set. + *

+ * API name: {@code num_allocations} + */ + public final int numAllocations() { + return this.numAllocations; + } + + /** + * Required - The number of threads used by each model allocation during + * inference. Increasing this value generally increases the speed per inference + * request. The inference process is a compute-bound process; + * threads_per_allocations must not exceed the number of available + * allocated processors per node. The value must be a power of 2. The maximum + * value is 32.

+ *

+ * info If you want to optimize your ELSER endpoint for ingest, set the number + * of threads to 1. If you want to optimize your ELSER endpoint for search, set + * the number of threads to greater than 1. + *

+ *
+ *

+ * API name: {@code num_threads} + */ + public final int numThreads() { + return this.numThreads; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.adaptiveAllocations != null) { + generator.writeKey("adaptive_allocations"); + this.adaptiveAllocations.serialize(generator, mapper); + + } + generator.writeKey("num_allocations"); + generator.write(this.numAllocations); + + generator.writeKey("num_threads"); + generator.write(this.numThreads); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link ElserServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private AdaptiveAllocations adaptiveAllocations; + + private Integer numAllocations; + + private Integer numThreads; + + /** + * Adaptive allocations configuration details. If enabled is true, + * the number of allocations of the model is set based on the current load the + * process gets. When the load is high, a new model allocation is automatically + * created, respecting the value of max_number_of_allocations if + * it's set. When the load is low, a model allocation is automatically removed, + * respecting the value of min_number_of_allocations if it's set. + * If enabled is true, do not set the number of allocations + * manually. + *

+ * API name: {@code adaptive_allocations} + */ + public final Builder adaptiveAllocations(@Nullable AdaptiveAllocations value) { + this.adaptiveAllocations = value; + return this; + } + + /** + * Adaptive allocations configuration details. If enabled is true, + * the number of allocations of the model is set based on the current load the + * process gets. When the load is high, a new model allocation is automatically + * created, respecting the value of max_number_of_allocations if + * it's set. When the load is low, a model allocation is automatically removed, + * respecting the value of min_number_of_allocations if it's set. + * If enabled is true, do not set the number of allocations + * manually. + *

+ * API name: {@code adaptive_allocations} + */ + public final Builder adaptiveAllocations( + Function> fn) { + return this.adaptiveAllocations(fn.apply(new AdaptiveAllocations.Builder()).build()); + } + + /** + * Required - The total number of allocations this model is assigned across + * machine learning nodes. Increasing this value generally increases the + * throughput. If adaptive allocations is enabled, do not set this value because + * it's automatically set. + *

+ * API name: {@code num_allocations} + */ + public final Builder numAllocations(int value) { + this.numAllocations = value; + return this; + } + + /** + * Required - The number of threads used by each model allocation during + * inference. Increasing this value generally increases the speed per inference + * request. The inference process is a compute-bound process; + * threads_per_allocations must not exceed the number of available + * allocated processors per node. The value must be a power of 2. The maximum + * value is 32.

+ *

+ * info If you want to optimize your ELSER endpoint for ingest, set the number + * of threads to 1. If you want to optimize your ELSER endpoint for search, set + * the number of threads to greater than 1. + *

+ *
+ *

+ * API name: {@code num_threads} + */ + public final Builder numThreads(int value) { + this.numThreads = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link ElserServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public ElserServiceSettings build() { + _checkSingleUse(); + + return new ElserServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link ElserServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, ElserServiceSettings::setupElserServiceSettingsDeserializer); + + protected static void setupElserServiceSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::adaptiveAllocations, AdaptiveAllocations._DESERIALIZER, "adaptive_allocations"); + op.add(Builder::numAllocations, JsonpDeserializer.integerDeserializer(), "num_allocations"); + op.add(Builder::numThreads, JsonpDeserializer.integerDeserializer(), "num_threads"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserTaskType.java new file mode 100644 index 000000000..b06065905 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserTaskType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_elser; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ElserTaskType implements JsonEnum { + SparseEmbedding("sparse_embedding"), + + ; + + private final String jsonValue; + + ElserTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ElserTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioServiceSettings.java new file mode 100644 index 000000000..9fa3878c5 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioServiceSettings.java @@ -0,0 +1,241 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_googleaistudio; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_googleaistudio.GoogleAiStudioServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class GoogleAiStudioServiceSettings implements JsonpSerializable { + private final String apiKey; + + private final String modelId; + + @Nullable + private final RateLimitSetting rateLimit; + + // --------------------------------------------------------------------------------------------- + + private GoogleAiStudioServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); + this.rateLimit = builder.rateLimit; + + } + + public static GoogleAiStudioServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid API key of your Google Gemini account. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * Google documentation for the list of supported models. + *

+ * API name: {@code model_id} + */ + public final String modelId() { + return this.modelId; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Google AI Studio. By default, the googleaistudio service sets + * the number of requests allowed per minute to 360. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + generator.writeKey("model_id"); + generator.write(this.modelId); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link GoogleAiStudioServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + private String modelId; + + @Nullable + private RateLimitSetting rateLimit; + + /** + * Required - A valid API key of your Google Gemini account. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * Google documentation for the list of supported models. + *

+ * API name: {@code model_id} + */ + public final Builder modelId(String value) { + this.modelId = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Google AI Studio. By default, the googleaistudio service sets + * the number of requests allowed per minute to 360. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Google AI Studio. By default, the googleaistudio service sets + * the number of requests allowed per minute to 360. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link GoogleAiStudioServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public GoogleAiStudioServiceSettings build() { + _checkSingleUse(); + + return new GoogleAiStudioServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link GoogleAiStudioServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, GoogleAiStudioServiceSettings::setupGoogleAiStudioServiceSettingsDeserializer); + + protected static void setupGoogleAiStudioServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioTaskType.java new file mode 100644 index 000000000..7c9fa04ea --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioTaskType.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_googleaistudio; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum GoogleAiStudioTaskType implements JsonEnum { + Completion("completion"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + GoogleAiStudioTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + GoogleAiStudioTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/ServiceType.java new file mode 100644 index 000000000..cc2d8aca2 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_googleaistudio; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Googleaistudio("googleaistudio"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAIServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAIServiceSettings.java new file mode 100644 index 000000000..8482cbdfa --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAIServiceSettings.java @@ -0,0 +1,300 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_googlevertexai; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_googlevertexai.GoogleVertexAIServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class GoogleVertexAIServiceSettings implements JsonpSerializable { + private final String location; + + private final String modelId; + + private final String projectId; + + @Nullable + private final RateLimitSetting rateLimit; + + private final String serviceAccountJson; + + // --------------------------------------------------------------------------------------------- + + private GoogleVertexAIServiceSettings(Builder builder) { + + this.location = ApiTypeHelper.requireNonNull(builder.location, this, "location"); + this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); + this.projectId = ApiTypeHelper.requireNonNull(builder.projectId, this, "projectId"); + this.rateLimit = builder.rateLimit; + this.serviceAccountJson = ApiTypeHelper.requireNonNull(builder.serviceAccountJson, this, "serviceAccountJson"); + + } + + public static GoogleVertexAIServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - The name of the location to use for the inference task. Refer to + * the Google documentation for the list of supported locations. + *

+ * API name: {@code location} + */ + public final String location() { + return this.location; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * Google documentation for the list of supported models. + *

+ * API name: {@code model_id} + */ + public final String modelId() { + return this.modelId; + } + + /** + * Required - The name of the project to use for the inference task. + *

+ * API name: {@code project_id} + */ + public final String projectId() { + return this.projectId; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Google Vertex AI. By default, the googlevertexai service sets + * the number of requests allowed per minute to 30.000. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Required - A valid service account in JSON format for the Google Vertex AI + * API. + *

+ * API name: {@code service_account_json} + */ + public final String serviceAccountJson() { + return this.serviceAccountJson; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("location"); + generator.write(this.location); + + generator.writeKey("model_id"); + generator.write(this.modelId); + + generator.writeKey("project_id"); + generator.write(this.projectId); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + generator.writeKey("service_account_json"); + generator.write(this.serviceAccountJson); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link GoogleVertexAIServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String location; + + private String modelId; + + private String projectId; + + @Nullable + private RateLimitSetting rateLimit; + + private String serviceAccountJson; + + /** + * Required - The name of the location to use for the inference task. Refer to + * the Google documentation for the list of supported locations. + *

+ * API name: {@code location} + */ + public final Builder location(String value) { + this.location = value; + return this; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * Google documentation for the list of supported models. + *

+ * API name: {@code model_id} + */ + public final Builder modelId(String value) { + this.modelId = value; + return this; + } + + /** + * Required - The name of the project to use for the inference task. + *

+ * API name: {@code project_id} + */ + public final Builder projectId(String value) { + this.projectId = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Google Vertex AI. By default, the googlevertexai service sets + * the number of requests allowed per minute to 30.000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Google Vertex AI. By default, the googlevertexai service sets + * the number of requests allowed per minute to 30.000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * Required - A valid service account in JSON format for the Google Vertex AI + * API. + *

+ * API name: {@code service_account_json} + */ + public final Builder serviceAccountJson(String value) { + this.serviceAccountJson = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link GoogleVertexAIServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public GoogleVertexAIServiceSettings build() { + _checkSingleUse(); + + return new GoogleVertexAIServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link GoogleVertexAIServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, GoogleVertexAIServiceSettings::setupGoogleVertexAIServiceSettingsDeserializer); + + protected static void setupGoogleVertexAIServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::location, JsonpDeserializer.stringDeserializer(), "location"); + op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); + op.add(Builder::projectId, JsonpDeserializer.stringDeserializer(), "project_id"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::serviceAccountJson, JsonpDeserializer.stringDeserializer(), "service_account_json"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskSettings.java new file mode 100644 index 000000000..99ea25c03 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskSettings.java @@ -0,0 +1,204 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_googlevertexai; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_googlevertexai.GoogleVertexAITaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class GoogleVertexAITaskSettings implements JsonpSerializable { + @Nullable + private final Boolean autoTruncate; + + @Nullable + private final Integer topN; + + // --------------------------------------------------------------------------------------------- + + private GoogleVertexAITaskSettings(Builder builder) { + + this.autoTruncate = builder.autoTruncate; + this.topN = builder.topN; + + } + + public static GoogleVertexAITaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * For a text_embedding task, truncate inputs longer than the + * maximum token length automatically. + *

+ * API name: {@code auto_truncate} + */ + @Nullable + public final Boolean autoTruncate() { + return this.autoTruncate; + } + + /** + * For a rerank task, the number of the top N documents that should + * be returned. + *

+ * API name: {@code top_n} + */ + @Nullable + public final Integer topN() { + return this.topN; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.autoTruncate != null) { + generator.writeKey("auto_truncate"); + generator.write(this.autoTruncate); + + } + if (this.topN != null) { + generator.writeKey("top_n"); + generator.write(this.topN); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link GoogleVertexAITaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private Boolean autoTruncate; + + @Nullable + private Integer topN; + + /** + * For a text_embedding task, truncate inputs longer than the + * maximum token length automatically. + *

+ * API name: {@code auto_truncate} + */ + public final Builder autoTruncate(@Nullable Boolean value) { + this.autoTruncate = value; + return this; + } + + /** + * For a rerank task, the number of the top N documents that should + * be returned. + *

+ * API name: {@code top_n} + */ + public final Builder topN(@Nullable Integer value) { + this.topN = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link GoogleVertexAITaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public GoogleVertexAITaskSettings build() { + _checkSingleUse(); + + return new GoogleVertexAITaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link GoogleVertexAITaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, GoogleVertexAITaskSettings::setupGoogleVertexAITaskSettingsDeserializer); + + protected static void setupGoogleVertexAITaskSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::autoTruncate, JsonpDeserializer.booleanDeserializer(), "auto_truncate"); + op.add(Builder::topN, JsonpDeserializer.integerDeserializer(), "top_n"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskType.java new file mode 100644 index 000000000..4b1859642 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskType.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_googlevertexai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum GoogleVertexAITaskType implements JsonEnum { + Rerank("rerank"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + GoogleVertexAITaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + GoogleVertexAITaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/ServiceType.java new file mode 100644 index 000000000..65b054f2e --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_googlevertexai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Googlevertexai("googlevertexai"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceServiceSettings.java new file mode 100644 index 000000000..07464ac58 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceServiceSettings.java @@ -0,0 +1,252 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_hugging_face; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_hugging_face.HuggingFaceServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class HuggingFaceServiceSettings implements JsonpSerializable { + private final String apiKey; + + @Nullable + private final RateLimitSetting rateLimit; + + private final String url; + + // --------------------------------------------------------------------------------------------- + + private HuggingFaceServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.rateLimit = builder.rateLimit; + this.url = ApiTypeHelper.requireNonNull(builder.url, this, "url"); + + } + + public static HuggingFaceServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid access token for your HuggingFace account. You can create + * or find your access tokens on the HuggingFace settings page. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Hugging Face. By default, the hugging_face service sets the + * number of requests allowed per minute to 3000. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Required - The URL endpoint to use for the requests. + *

+ * API name: {@code url} + */ + public final String url() { + return this.url; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + generator.writeKey("url"); + generator.write(this.url); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link HuggingFaceServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + @Nullable + private RateLimitSetting rateLimit; + + private String url; + + /** + * Required - A valid access token for your HuggingFace account. You can create + * or find your access tokens on the HuggingFace settings page. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Hugging Face. By default, the hugging_face service sets the + * number of requests allowed per minute to 3000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Hugging Face. By default, the hugging_face service sets the + * number of requests allowed per minute to 3000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * Required - The URL endpoint to use for the requests. + *

+ * API name: {@code url} + */ + public final Builder url(String value) { + this.url = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link HuggingFaceServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public HuggingFaceServiceSettings build() { + _checkSingleUse(); + + return new HuggingFaceServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link HuggingFaceServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, HuggingFaceServiceSettings::setupHuggingFaceServiceSettingsDeserializer); + + protected static void setupHuggingFaceServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::url, JsonpDeserializer.stringDeserializer(), "url"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceTaskType.java new file mode 100644 index 000000000..3a36ada42 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceTaskType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_hugging_face; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum HuggingFaceTaskType implements JsonEnum { + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + HuggingFaceTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + HuggingFaceTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/ServiceType.java new file mode 100644 index 000000000..870661dba --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_hugging_face; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + HuggingFace("hugging_face"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAIServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAIServiceSettings.java new file mode 100644 index 000000000..26f5e7643 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAIServiceSettings.java @@ -0,0 +1,297 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_jinaai; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_jinaai.JinaAIServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class JinaAIServiceSettings implements JsonpSerializable { + private final String apiKey; + + @Nullable + private final String modelId; + + @Nullable + private final RateLimitSetting rateLimit; + + @Nullable + private final SimilarityType similarity; + + // --------------------------------------------------------------------------------------------- + + private JinaAIServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.modelId = builder.modelId; + this.rateLimit = builder.rateLimit; + this.similarity = builder.similarity; + + } + + public static JinaAIServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid API key of your JinaAI account. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * The name of the model to use for the inference task. For a + * rerank task, it is required. For a text_embedding + * task, it is optional. + *

+ * API name: {@code model_id} + */ + @Nullable + public final String modelId() { + return this.modelId; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * JinaAI. By default, the jinaai service sets the number of + * requests allowed per minute to 2000 for all task types. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * For a text_embedding task, the similarity measure. One of + * cosine, dot_product, l2_norm. The default values varies with the embedding + * type. For example, a float embedding type uses a dot_product + * similarity measure by default. + *

+ * API name: {@code similarity} + */ + @Nullable + public final SimilarityType similarity() { + return this.similarity; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + if (this.modelId != null) { + generator.writeKey("model_id"); + generator.write(this.modelId); + + } + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + if (this.similarity != null) { + generator.writeKey("similarity"); + this.similarity.serialize(generator, mapper); + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link JinaAIServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + @Nullable + private String modelId; + + @Nullable + private RateLimitSetting rateLimit; + + @Nullable + private SimilarityType similarity; + + /** + * Required - A valid API key of your JinaAI account. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * The name of the model to use for the inference task. For a + * rerank task, it is required. For a text_embedding + * task, it is optional. + *

+ * API name: {@code model_id} + */ + public final Builder modelId(@Nullable String value) { + this.modelId = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * JinaAI. By default, the jinaai service sets the number of + * requests allowed per minute to 2000 for all task types. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * JinaAI. By default, the jinaai service sets the number of + * requests allowed per minute to 2000 for all task types. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * For a text_embedding task, the similarity measure. One of + * cosine, dot_product, l2_norm. The default values varies with the embedding + * type. For example, a float embedding type uses a dot_product + * similarity measure by default. + *

+ * API name: {@code similarity} + */ + public final Builder similarity(@Nullable SimilarityType value) { + this.similarity = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link JinaAIServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public JinaAIServiceSettings build() { + _checkSingleUse(); + + return new JinaAIServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link JinaAIServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, JinaAIServiceSettings::setupJinaAIServiceSettingsDeserializer); + + protected static void setupJinaAIServiceSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::similarity, SimilarityType._DESERIALIZER, "similarity"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskSettings.java new file mode 100644 index 000000000..25888bdce --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskSettings.java @@ -0,0 +1,261 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_jinaai; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.lang.Integer; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_jinaai.JinaAITaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class JinaAITaskSettings implements JsonpSerializable { + @Nullable + private final Boolean returnDocuments; + + @Nullable + private final TextEmbeddingTask task; + + @Nullable + private final Integer topN; + + // --------------------------------------------------------------------------------------------- + + private JinaAITaskSettings(Builder builder) { + + this.returnDocuments = builder.returnDocuments; + this.task = builder.task; + this.topN = builder.topN; + + } + + public static JinaAITaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * For a rerank task, return the doc text within the results. + *

+ * API name: {@code return_documents} + */ + @Nullable + public final Boolean returnDocuments() { + return this.returnDocuments; + } + + /** + * For a text_embedding task, the task passed to the model. Valid + * values are: + *

    + *
  • classification: Use it for embeddings passed through a text + * classifier.
  • + *
  • clustering: Use it for the embeddings run through a + * clustering algorithm.
  • + *
  • ingest: Use it for storing document embeddings in a vector + * database.
  • + *
  • search: Use it for storing embeddings of search queries run + * against a vector database to find relevant documents.
  • + *
+ *

+ * API name: {@code task} + */ + @Nullable + public final TextEmbeddingTask task() { + return this.task; + } + + /** + * For a rerank task, the number of most relevant documents to + * return. It defaults to the number of the documents. If this inference + * endpoint is used in a text_similarity_reranker retriever query + * and top_n is set, it must be greater than or equal to + * rank_window_size in the query. + *

+ * API name: {@code top_n} + */ + @Nullable + public final Integer topN() { + return this.topN; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.returnDocuments != null) { + generator.writeKey("return_documents"); + generator.write(this.returnDocuments); + + } + if (this.task != null) { + generator.writeKey("task"); + this.task.serialize(generator, mapper); + } + if (this.topN != null) { + generator.writeKey("top_n"); + generator.write(this.topN); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link JinaAITaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private Boolean returnDocuments; + + @Nullable + private TextEmbeddingTask task; + + @Nullable + private Integer topN; + + /** + * For a rerank task, return the doc text within the results. + *

+ * API name: {@code return_documents} + */ + public final Builder returnDocuments(@Nullable Boolean value) { + this.returnDocuments = value; + return this; + } + + /** + * For a text_embedding task, the task passed to the model. Valid + * values are: + *

    + *
  • classification: Use it for embeddings passed through a text + * classifier.
  • + *
  • clustering: Use it for the embeddings run through a + * clustering algorithm.
  • + *
  • ingest: Use it for storing document embeddings in a vector + * database.
  • + *
  • search: Use it for storing embeddings of search queries run + * against a vector database to find relevant documents.
  • + *
+ *

+ * API name: {@code task} + */ + public final Builder task(@Nullable TextEmbeddingTask value) { + this.task = value; + return this; + } + + /** + * For a rerank task, the number of most relevant documents to + * return. It defaults to the number of the documents. If this inference + * endpoint is used in a text_similarity_reranker retriever query + * and top_n is set, it must be greater than or equal to + * rank_window_size in the query. + *

+ * API name: {@code top_n} + */ + public final Builder topN(@Nullable Integer value) { + this.topN = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link JinaAITaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public JinaAITaskSettings build() { + _checkSingleUse(); + + return new JinaAITaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link JinaAITaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, JinaAITaskSettings::setupJinaAITaskSettingsDeserializer); + + protected static void setupJinaAITaskSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::returnDocuments, JsonpDeserializer.booleanDeserializer(), "return_documents"); + op.add(Builder::task, TextEmbeddingTask._DESERIALIZER, "task"); + op.add(Builder::topN, JsonpDeserializer.integerDeserializer(), "top_n"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskType.java new file mode 100644 index 000000000..0d8771a24 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskType.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_jinaai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum JinaAITaskType implements JsonEnum { + Rerank("rerank"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + JinaAITaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + JinaAITaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/ServiceType.java new file mode 100644 index 000000000..f9df9ea40 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_jinaai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Jinaai("jinaai"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/SimilarityType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/SimilarityType.java new file mode 100644 index 000000000..970051384 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/SimilarityType.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_jinaai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum SimilarityType implements JsonEnum { + Cosine("cosine"), + + DotProduct("dot_product"), + + L2Norm("l2_norm"), + + ; + + private final String jsonValue; + + SimilarityType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + SimilarityType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/TextEmbeddingTask.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/TextEmbeddingTask.java new file mode 100644 index 000000000..1a1667667 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/TextEmbeddingTask.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_jinaai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum TextEmbeddingTask implements JsonEnum { + Classification("classification"), + + Clustering("clustering"), + + Ingest("ingest"), + + Search("search"), + + ; + + private final String jsonValue; + + TextEmbeddingTask(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + TextEmbeddingTask.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralServiceSettings.java new file mode 100644 index 000000000..fbcc888ec --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralServiceSettings.java @@ -0,0 +1,289 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_mistral; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Integer; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_mistral.MistralServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class MistralServiceSettings implements JsonpSerializable { + private final String apiKey; + + @Nullable + private final Integer maxInputTokens; + + private final String model; + + @Nullable + private final RateLimitSetting rateLimit; + + // --------------------------------------------------------------------------------------------- + + private MistralServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.maxInputTokens = builder.maxInputTokens; + this.model = ApiTypeHelper.requireNonNull(builder.model, this, "model"); + this.rateLimit = builder.rateLimit; + + } + + public static MistralServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid API key of your Mistral account. You can find your Mistral + * API keys or you can create a new one on the API Keys page. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * The maximum number of tokens per input before chunking occurs. + *

+ * API name: {@code max_input_tokens} + */ + @Nullable + public final Integer maxInputTokens() { + return this.maxInputTokens; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * Mistral models documentation for the list of available text embedding models. + *

+ * API name: {@code model} + */ + public final String model() { + return this.model; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * the Mistral API. By default, the mistral service sets the number + * of requests allowed per minute to 240. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + if (this.maxInputTokens != null) { + generator.writeKey("max_input_tokens"); + generator.write(this.maxInputTokens); + + } + generator.writeKey("model"); + generator.write(this.model); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link MistralServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + @Nullable + private Integer maxInputTokens; + + private String model; + + @Nullable + private RateLimitSetting rateLimit; + + /** + * Required - A valid API key of your Mistral account. You can find your Mistral + * API keys or you can create a new one on the API Keys page. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * The maximum number of tokens per input before chunking occurs. + *

+ * API name: {@code max_input_tokens} + */ + public final Builder maxInputTokens(@Nullable Integer value) { + this.maxInputTokens = value; + return this; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * Mistral models documentation for the list of available text embedding models. + *

+ * API name: {@code model} + */ + public final Builder model(String value) { + this.model = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * the Mistral API. By default, the mistral service sets the number + * of requests allowed per minute to 240. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * the Mistral API. By default, the mistral service sets the number + * of requests allowed per minute to 240. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link MistralServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public MistralServiceSettings build() { + _checkSingleUse(); + + return new MistralServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link MistralServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, MistralServiceSettings::setupMistralServiceSettingsDeserializer); + + protected static void setupMistralServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::maxInputTokens, JsonpDeserializer.integerDeserializer(), "max_input_tokens"); + op.add(Builder::model, JsonpDeserializer.stringDeserializer(), "model"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralTaskType.java new file mode 100644 index 000000000..94c34e12c --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralTaskType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_mistral; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum MistralTaskType implements JsonEnum { + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + MistralTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + MistralTaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/ServiceType.java new file mode 100644 index 000000000..36f555841 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_mistral; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Mistral("mistral"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAIServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAIServiceSettings.java new file mode 100644 index 000000000..8d4fa4222 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAIServiceSettings.java @@ -0,0 +1,368 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_openai; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Integer; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_openai.OpenAIServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class OpenAIServiceSettings implements JsonpSerializable { + private final String apiKey; + + @Nullable + private final Integer dimensions; + + private final String modelId; + + @Nullable + private final String organizationId; + + @Nullable + private final RateLimitSetting rateLimit; + + @Nullable + private final String url; + + // --------------------------------------------------------------------------------------------- + + private OpenAIServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.dimensions = builder.dimensions; + this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); + this.organizationId = builder.organizationId; + this.rateLimit = builder.rateLimit; + this.url = builder.url; + + } + + public static OpenAIServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid API key of your OpenAI account. You can find your OpenAI + * API keys in your OpenAI account under the API keys section. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * The number of dimensions the resulting output embeddings should have. It is + * supported only in text-embedding-3 and later models. If it is + * not set, the OpenAI defined default for the model is used. + *

+ * API name: {@code dimensions} + */ + @Nullable + public final Integer dimensions() { + return this.dimensions; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * OpenAI documentation for the list of available text embedding models. + *

+ * API name: {@code model_id} + */ + public final String modelId() { + return this.modelId; + } + + /** + * The unique identifier for your organization. You can find the Organization ID + * in your OpenAI account under Settings > Organizations. + *

+ * API name: {@code organization_id} + */ + @Nullable + public final String organizationId() { + return this.organizationId; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * OpenAI. The openai service sets a default number of requests + * allowed per minute depending on the task type. For + * text_embedding, it is set to 3000. For + * completion, it is set to 500. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * The URL endpoint to use for the requests. It can be changed for testing + * purposes. + *

+ * API name: {@code url} + */ + @Nullable + public final String url() { + return this.url; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + if (this.dimensions != null) { + generator.writeKey("dimensions"); + generator.write(this.dimensions); + + } + generator.writeKey("model_id"); + generator.write(this.modelId); + + if (this.organizationId != null) { + generator.writeKey("organization_id"); + generator.write(this.organizationId); + + } + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + if (this.url != null) { + generator.writeKey("url"); + generator.write(this.url); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link OpenAIServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + @Nullable + private Integer dimensions; + + private String modelId; + + @Nullable + private String organizationId; + + @Nullable + private RateLimitSetting rateLimit; + + @Nullable + private String url; + + /** + * Required - A valid API key of your OpenAI account. You can find your OpenAI + * API keys in your OpenAI account under the API keys section. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * The number of dimensions the resulting output embeddings should have. It is + * supported only in text-embedding-3 and later models. If it is + * not set, the OpenAI defined default for the model is used. + *

+ * API name: {@code dimensions} + */ + public final Builder dimensions(@Nullable Integer value) { + this.dimensions = value; + return this; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * OpenAI documentation for the list of available text embedding models. + *

+ * API name: {@code model_id} + */ + public final Builder modelId(String value) { + this.modelId = value; + return this; + } + + /** + * The unique identifier for your organization. You can find the Organization ID + * in your OpenAI account under Settings > Organizations. + *

+ * API name: {@code organization_id} + */ + public final Builder organizationId(@Nullable String value) { + this.organizationId = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * OpenAI. The openai service sets a default number of requests + * allowed per minute depending on the task type. For + * text_embedding, it is set to 3000. For + * completion, it is set to 500. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * OpenAI. The openai service sets a default number of requests + * allowed per minute depending on the task type. For + * text_embedding, it is set to 3000. For + * completion, it is set to 500. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * The URL endpoint to use for the requests. It can be changed for testing + * purposes. + *

+ * API name: {@code url} + */ + public final Builder url(@Nullable String value) { + this.url = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link OpenAIServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public OpenAIServiceSettings build() { + _checkSingleUse(); + + return new OpenAIServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link OpenAIServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, OpenAIServiceSettings::setupOpenAIServiceSettingsDeserializer); + + protected static void setupOpenAIServiceSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::dimensions, JsonpDeserializer.integerDeserializer(), "dimensions"); + op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); + op.add(Builder::organizationId, JsonpDeserializer.stringDeserializer(), "organization_id"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::url, JsonpDeserializer.stringDeserializer(), "url"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAITaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAITaskSettings.java new file mode 100644 index 000000000..e80616c0b --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAITaskSettings.java @@ -0,0 +1,169 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_openai; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_openai.OpenAITaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class OpenAITaskSettings implements JsonpSerializable { + @Nullable + private final String user; + + // --------------------------------------------------------------------------------------------- + + private OpenAITaskSettings(Builder builder) { + + this.user = builder.user; + + } + + public static OpenAITaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * For a completion or text_embedding task, specify + * the user issuing the request. This information can be used for abuse + * detection. + *

+ * API name: {@code user} + */ + @Nullable + public final String user() { + return this.user; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.user != null) { + generator.writeKey("user"); + generator.write(this.user); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link OpenAITaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private String user; + + /** + * For a completion or text_embedding task, specify + * the user issuing the request. This information can be used for abuse + * detection. + *

+ * API name: {@code user} + */ + public final Builder user(@Nullable String value) { + this.user = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link OpenAITaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public OpenAITaskSettings build() { + _checkSingleUse(); + + return new OpenAITaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link OpenAITaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, OpenAITaskSettings::setupOpenAITaskSettingsDeserializer); + + protected static void setupOpenAITaskSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::user, JsonpDeserializer.stringDeserializer(), "user"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAITaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAITaskType.java new file mode 100644 index 000000000..12c8b6c5b --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAITaskType.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_openai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum OpenAITaskType implements JsonEnum { + ChatCompletion("chat_completion"), + + Completion("completion"), + + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + OpenAITaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + OpenAITaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java new file mode 100644 index 000000000..451b2e64a --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java @@ -0,0 +1,77 @@ +/* + * 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. + */ + +<<<<<<<< HEAD:java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/ServiceType.java +package co.elastic.clients.elasticsearch.inference.put_voyageai; +======== +package co.elastic.clients.elasticsearch.inference.put_openai; +>>>>>>>> c86960dc6 (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API +======== + * "../../doc-files/api-spec.html#inference.put_openai.ServiceType">API +>>>>>>>> c86960dc6 (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { +<<<<<<<< HEAD:java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/ServiceType.java + Voyageai("voyageai"), +======== + Openai("openai"), +>>>>>>>> c86960dc6 (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/ServiceType.java new file mode 100644 index 000000000..ad66756ad --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_voyageai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Voyageai("voyageai"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAIServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAIServiceSettings.java new file mode 100644 index 000000000..5b3c7c0ce --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAIServiceSettings.java @@ -0,0 +1,303 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_voyageai; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Float; +import java.lang.Integer; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_voyageai.VoyageAIServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class VoyageAIServiceSettings implements JsonpSerializable { + @Nullable + private final Integer dimensions; + + private final String modelId; + + @Nullable + private final RateLimitSetting rateLimit; + + @Nullable + private final Float embeddingType; + + // --------------------------------------------------------------------------------------------- + + private VoyageAIServiceSettings(Builder builder) { + + this.dimensions = builder.dimensions; + this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); + this.rateLimit = builder.rateLimit; + this.embeddingType = builder.embeddingType; + + } + + public static VoyageAIServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * The number of dimensions for resulting output embeddings. This setting maps + * to output_dimension in the VoyageAI documentation. Only for the + * text_embedding task type. + *

+ * API name: {@code dimensions} + */ + @Nullable + public final Integer dimensions() { + return this.dimensions; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * VoyageAI documentation for the list of available text embedding and rerank + * models. + *

+ * API name: {@code model_id} + */ + public final String modelId() { + return this.modelId; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * VoyageAI. The voyageai service sets a default number of requests + * allowed per minute depending on the task type. For both + * text_embedding and rerank, it is set to + * 2000. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * The data type for the embeddings to be returned. This setting maps to + * output_dtype in the VoyageAI documentation. Permitted values: + * float, int8, bit. int8 is a synonym of byte in the + * VoyageAI documentation. bit is a synonym of binary + * in the VoyageAI documentation. Only for the text_embedding task + * type. + *

+ * API name: {@code embedding_type} + */ + @Nullable + public final Float embeddingType() { + return this.embeddingType; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.dimensions != null) { + generator.writeKey("dimensions"); + generator.write(this.dimensions); + + } + generator.writeKey("model_id"); + generator.write(this.modelId); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + if (this.embeddingType != null) { + generator.writeKey("embedding_type"); + generator.write(this.embeddingType); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link VoyageAIServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private Integer dimensions; + + private String modelId; + + @Nullable + private RateLimitSetting rateLimit; + + @Nullable + private Float embeddingType; + + /** + * The number of dimensions for resulting output embeddings. This setting maps + * to output_dimension in the VoyageAI documentation. Only for the + * text_embedding task type. + *

+ * API name: {@code dimensions} + */ + public final Builder dimensions(@Nullable Integer value) { + this.dimensions = value; + return this; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * VoyageAI documentation for the list of available text embedding and rerank + * models. + *

+ * API name: {@code model_id} + */ + public final Builder modelId(String value) { + this.modelId = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * VoyageAI. The voyageai service sets a default number of requests + * allowed per minute depending on the task type. For both + * text_embedding and rerank, it is set to + * 2000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * VoyageAI. The voyageai service sets a default number of requests + * allowed per minute depending on the task type. For both + * text_embedding and rerank, it is set to + * 2000. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * The data type for the embeddings to be returned. This setting maps to + * output_dtype in the VoyageAI documentation. Permitted values: + * float, int8, bit. int8 is a synonym of byte in the + * VoyageAI documentation. bit is a synonym of binary + * in the VoyageAI documentation. Only for the text_embedding task + * type. + *

+ * API name: {@code embedding_type} + */ + public final Builder embeddingType(@Nullable Float value) { + this.embeddingType = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link VoyageAIServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public VoyageAIServiceSettings build() { + _checkSingleUse(); + + return new VoyageAIServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link VoyageAIServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, VoyageAIServiceSettings::setupVoyageAIServiceSettingsDeserializer); + + protected static void setupVoyageAIServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::dimensions, JsonpDeserializer.integerDeserializer(), "dimensions"); + op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::embeddingType, JsonpDeserializer.floatDeserializer(), "embedding_type"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAITaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAITaskSettings.java new file mode 100644 index 000000000..de5db0b54 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAITaskSettings.java @@ -0,0 +1,278 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_voyageai; + +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.Boolean; +import java.lang.Integer; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_voyageai.VoyageAITaskSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class VoyageAITaskSettings implements JsonpSerializable { + @Nullable + private final String inputType; + + @Nullable + private final Boolean returnDocuments; + + @Nullable + private final Integer topK; + + @Nullable + private final Boolean truncation; + + // --------------------------------------------------------------------------------------------- + + private VoyageAITaskSettings(Builder builder) { + + this.inputType = builder.inputType; + this.returnDocuments = builder.returnDocuments; + this.topK = builder.topK; + this.truncation = builder.truncation; + + } + + public static VoyageAITaskSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Type of the input text. Permitted values: ingest (maps to + * document in the VoyageAI documentation), search + * (maps to query in the VoyageAI documentation). Only for the + * text_embedding task type. + *

+ * API name: {@code input_type} + */ + @Nullable + public final String inputType() { + return this.inputType; + } + + /** + * Whether to return the source documents in the response. Only for the + * rerank task type. + *

+ * API name: {@code return_documents} + */ + @Nullable + public final Boolean returnDocuments() { + return this.returnDocuments; + } + + /** + * The number of most relevant documents to return. If not specified, the + * reranking results of all documents will be returned. Only for the + * rerank task type. + *

+ * API name: {@code top_k} + */ + @Nullable + public final Integer topK() { + return this.topK; + } + + /** + * Whether to truncate the input texts to fit within the context length. + *

+ * API name: {@code truncation} + */ + @Nullable + public final Boolean truncation() { + return this.truncation; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.inputType != null) { + generator.writeKey("input_type"); + generator.write(this.inputType); + + } + if (this.returnDocuments != null) { + generator.writeKey("return_documents"); + generator.write(this.returnDocuments); + + } + if (this.topK != null) { + generator.writeKey("top_k"); + generator.write(this.topK); + + } + if (this.truncation != null) { + generator.writeKey("truncation"); + generator.write(this.truncation); + + } + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link VoyageAITaskSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + @Nullable + private String inputType; + + @Nullable + private Boolean returnDocuments; + + @Nullable + private Integer topK; + + @Nullable + private Boolean truncation; + + /** + * Type of the input text. Permitted values: ingest (maps to + * document in the VoyageAI documentation), search + * (maps to query in the VoyageAI documentation). Only for the + * text_embedding task type. + *

+ * API name: {@code input_type} + */ + public final Builder inputType(@Nullable String value) { + this.inputType = value; + return this; + } + + /** + * Whether to return the source documents in the response. Only for the + * rerank task type. + *

+ * API name: {@code return_documents} + */ + public final Builder returnDocuments(@Nullable Boolean value) { + this.returnDocuments = value; + return this; + } + + /** + * The number of most relevant documents to return. If not specified, the + * reranking results of all documents will be returned. Only for the + * rerank task type. + *

+ * API name: {@code top_k} + */ + public final Builder topK(@Nullable Integer value) { + this.topK = value; + return this; + } + + /** + * Whether to truncate the input texts to fit within the context length. + *

+ * API name: {@code truncation} + */ + public final Builder truncation(@Nullable Boolean value) { + this.truncation = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link VoyageAITaskSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public VoyageAITaskSettings build() { + _checkSingleUse(); + + return new VoyageAITaskSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link VoyageAITaskSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, VoyageAITaskSettings::setupVoyageAITaskSettingsDeserializer); + + protected static void setupVoyageAITaskSettingsDeserializer(ObjectDeserializer op) { + + op.add(Builder::inputType, JsonpDeserializer.stringDeserializer(), "input_type"); + op.add(Builder::returnDocuments, JsonpDeserializer.booleanDeserializer(), "return_documents"); + op.add(Builder::topK, JsonpDeserializer.integerDeserializer(), "top_k"); + op.add(Builder::truncation, JsonpDeserializer.booleanDeserializer(), "truncation"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAITaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAITaskType.java new file mode 100644 index 000000000..efe36056a --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAITaskType.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_voyageai; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum VoyageAITaskType implements JsonEnum { + TextEmbedding("text_embedding"), + + Rerank("rerank"), + + ; + + private final String jsonValue; + + VoyageAITaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + VoyageAITaskType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/ServiceType.java new file mode 100644 index 000000000..a5f8ddbb4 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/ServiceType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_watsonx; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum ServiceType implements JsonEnum { + Watsonxai("watsonxai"), + + ; + + private final String jsonValue; + + ServiceType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + ServiceType.values()); +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/WatsonxServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/WatsonxServiceSettings.java new file mode 100644 index 000000000..f43664eea --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/WatsonxServiceSettings.java @@ -0,0 +1,346 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_watsonx; + +import co.elastic.clients.elasticsearch.inference.RateLimitSetting; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; +import co.elastic.clients.json.JsonpUtils; +import co.elastic.clients.json.ObjectBuilderDeserializer; +import co.elastic.clients.json.ObjectDeserializer; +import co.elastic.clients.util.ApiTypeHelper; +import co.elastic.clients.util.ObjectBuilder; +import co.elastic.clients.util.WithJsonObjectBuilderBase; +import jakarta.json.stream.JsonGenerator; +import java.lang.String; +import java.util.Objects; +import java.util.function.Function; +import javax.annotation.Nullable; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +// typedef: inference.put_watsonx.WatsonxServiceSettings + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public class WatsonxServiceSettings implements JsonpSerializable { + private final String apiKey; + + private final String apiVersion; + + private final String modelId; + + private final String projectId; + + @Nullable + private final RateLimitSetting rateLimit; + + private final String url; + + // --------------------------------------------------------------------------------------------- + + private WatsonxServiceSettings(Builder builder) { + + this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); + this.apiVersion = ApiTypeHelper.requireNonNull(builder.apiVersion, this, "apiVersion"); + this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); + this.projectId = ApiTypeHelper.requireNonNull(builder.projectId, this, "projectId"); + this.rateLimit = builder.rateLimit; + this.url = ApiTypeHelper.requireNonNull(builder.url, this, "url"); + + } + + public static WatsonxServiceSettings of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Required - A valid API key of your Watsonx account. You can find your Watsonx + * API keys or you can create a new one on the API keys page. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final String apiKey() { + return this.apiKey; + } + + /** + * Required - A version parameter that takes a version date in the format of + * YYYY-MM-DD. For the active version data parameters, refer to the + * Wastonx documentation. + *

+ * API name: {@code api_version} + */ + public final String apiVersion() { + return this.apiVersion; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * IBM Embedding Models section in the Watsonx documentation for the list of + * available text embedding models. + *

+ * API name: {@code model_id} + */ + public final String modelId() { + return this.modelId; + } + + /** + * Required - The identifier of the IBM Cloud project to use for the inference + * task. + *

+ * API name: {@code project_id} + */ + public final String projectId() { + return this.projectId; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Watsonx. By default, the watsonxai service sets the number of + * requests allowed per minute to 120. + *

+ * API name: {@code rate_limit} + */ + @Nullable + public final RateLimitSetting rateLimit() { + return this.rateLimit; + } + + /** + * Required - The URL of the inference endpoint that you created on Watsonx. + *

+ * API name: {@code url} + */ + public final String url() { + return this.url; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + generator.writeKey("api_key"); + generator.write(this.apiKey); + + generator.writeKey("api_version"); + generator.write(this.apiVersion); + + generator.writeKey("model_id"); + generator.write(this.modelId); + + generator.writeKey("project_id"); + generator.write(this.projectId); + + if (this.rateLimit != null) { + generator.writeKey("rate_limit"); + this.rateLimit.serialize(generator, mapper); + + } + generator.writeKey("url"); + generator.write(this.url); + + } + + @Override + public String toString() { + return JsonpUtils.toString(this); + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link WatsonxServiceSettings}. + */ + + public static class Builder extends WithJsonObjectBuilderBase + implements + ObjectBuilder { + private String apiKey; + + private String apiVersion; + + private String modelId; + + private String projectId; + + @Nullable + private RateLimitSetting rateLimit; + + private String url; + + /** + * Required - A valid API key of your Watsonx account. You can find your Watsonx + * API keys or you can create a new one on the API keys page. + *

+ * IMPORTANT: You need to provide the API key only once, during the inference + * model creation. The get inference endpoint API does not retrieve your API + * key. After creating the inference model, you cannot change the associated API + * key. If you want to use a different API key, delete the inference model and + * recreate it with the same name and the updated API key. + *

+ * API name: {@code api_key} + */ + public final Builder apiKey(String value) { + this.apiKey = value; + return this; + } + + /** + * Required - A version parameter that takes a version date in the format of + * YYYY-MM-DD. For the active version data parameters, refer to the + * Wastonx documentation. + *

+ * API name: {@code api_version} + */ + public final Builder apiVersion(String value) { + this.apiVersion = value; + return this; + } + + /** + * Required - The name of the model to use for the inference task. Refer to the + * IBM Embedding Models section in the Watsonx documentation for the list of + * available text embedding models. + *

+ * API name: {@code model_id} + */ + public final Builder modelId(String value) { + this.modelId = value; + return this; + } + + /** + * Required - The identifier of the IBM Cloud project to use for the inference + * task. + *

+ * API name: {@code project_id} + */ + public final Builder projectId(String value) { + this.projectId = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Watsonx. By default, the watsonxai service sets the number of + * requests allowed per minute to 120. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(@Nullable RateLimitSetting value) { + this.rateLimit = value; + return this; + } + + /** + * This setting helps to minimize the number of rate limit errors returned from + * Watsonx. By default, the watsonxai service sets the number of + * requests allowed per minute to 120. + *

+ * API name: {@code rate_limit} + */ + public final Builder rateLimit(Function> fn) { + return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); + } + + /** + * Required - The URL of the inference endpoint that you created on Watsonx. + *

+ * API name: {@code url} + */ + public final Builder url(String value) { + this.url = value; + return this; + } + + @Override + protected Builder self() { + return this; + } + + /** + * Builds a {@link WatsonxServiceSettings}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public WatsonxServiceSettings build() { + _checkSingleUse(); + + return new WatsonxServiceSettings(this); + } + } + + // --------------------------------------------------------------------------------------------- + + /** + * Json deserializer for {@link WatsonxServiceSettings} + */ + public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer + .lazy(Builder::new, WatsonxServiceSettings::setupWatsonxServiceSettingsDeserializer); + + protected static void setupWatsonxServiceSettingsDeserializer( + ObjectDeserializer op) { + + op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); + op.add(Builder::apiVersion, JsonpDeserializer.stringDeserializer(), "api_version"); + op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); + op.add(Builder::projectId, JsonpDeserializer.stringDeserializer(), "project_id"); + op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); + op.add(Builder::url, JsonpDeserializer.stringDeserializer(), "url"); + + } + +} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/WatsonxTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/WatsonxTaskType.java new file mode 100644 index 000000000..2a702f6e5 --- /dev/null +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/WatsonxTaskType.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package co.elastic.clients.elasticsearch.inference.put_watsonx; + +import co.elastic.clients.json.JsonEnum; +import co.elastic.clients.json.JsonpDeserializable; +import co.elastic.clients.json.JsonpDeserializer; + +//---------------------------------------------------------------- +// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. +//---------------------------------------------------------------- +// +// This code is generated from the Elasticsearch API specification +// at https://github.com/elastic/elasticsearch-specification +// +// Manual updates to this file will be lost when the code is +// re-generated. +// +// If you find a property that is missing or wrongly typed, please +// open an issue or a PR on the API specification repository. +// +//---------------------------------------------------------------- + +/** + * + * @see API + * specification + */ +@JsonpDeserializable +public enum WatsonxTaskType implements JsonEnum { + TextEmbedding("text_embedding"), + + ; + + private final String jsonValue; + + WatsonxTaskType(String jsonValue) { + this.jsonValue = jsonValue; + } + + public String jsonValue() { + return this.jsonValue; + } + + public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( + WatsonxTaskType.values()); +} From cd4964a466b17e1591672467123dbc74c5d1e0c8 Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Mon, 31 Mar 2025 17:08:39 +0200 Subject: [PATCH 36/38] [codegen] update to latest spec and generator --- .../ElasticsearchAsyncClient.java | 7 + .../elasticsearch/ElasticsearchClient.java | 7 + .../elasticsearch/doc-files/api-spec.html | 15 + .../ChatCompletionUnifiedRequest.java | 49 +- .../elasticsearch/inference/EisTaskType.java | 10 + .../ElasticsearchInferenceAsyncClient.java | 36 ++ .../ElasticsearchInferenceClient.java | 36 ++ .../PostEisChatCompletionRequest.java | 63 ++- .../inference/PutAlibabacloudRequest.java | 23 + .../inference/PutAmazonbedrockRequest.java | 23 + .../inference/PutAnthropicRequest.java | 23 + .../inference/PutAzureaistudioRequest.java | 23 + .../inference/PutAzureopenaiRequest.java | 23 + .../inference/PutCohereRequest.java | 23 + .../inference/PutEisRequest.java | 23 + .../inference/PutElasticsearchRequest.java | 23 + .../inference/PutElserRequest.java | 23 + .../inference/PutGoogleaistudioRequest.java | 23 + .../inference/PutGooglevertexaiRequest.java | 23 + .../inference/PutHuggingFaceRequest.java | 23 + .../inference/PutJinaaiRequest.java | 23 + .../inference/PutMistralRequest.java | 23 + .../inference/PutOpenaiRequest.java | 23 + .../inference/PutVoyageaiRequest.java | 23 + .../inference/PutWatsonxRequest.java | 23 + .../inference/RequestChatCompletionBase.java | 461 ------------------ .../inference/TextEmbeddingResponse.java | 45 ++ .../CompletionTool.java | 197 -------- .../CompletionToolChoice.java | 199 -------- .../CompletionToolChoiceFunction.java | 162 ------ .../CompletionToolFunction.java | 268 ---------- .../CompletionToolType.java | 191 -------- .../CompletionToolTypeBuilders.java | 59 --- .../ContentObject.java | 187 ------- .../chat_completion_unified/Message.java | 297 ----------- .../MessageContent.java | 196 -------- .../MessageContentBuilders.java | 52 -- .../chat_completion_unified/ToolCall.java | 224 --------- .../ToolCallFunction.java | 187 ------- .../AlibabaCloudServiceSettings.java | 344 ------------- .../AlibabaCloudTaskSettings.java | 218 --------- .../AlibabaCloudTaskType.java | 71 --- .../put_alibabacloud/ServiceType.java | 65 --- .../AmazonBedrockServiceSettings.java | 371 -------------- .../AmazonBedrockTaskSettings.java | 292 ----------- .../AmazonBedrockTaskType.java | 67 --- .../put_amazonbedrock/ServiceType.java | 65 --- .../AnthropicServiceSettings.java | 241 --------- .../put_anthropic/AnthropicTaskSettings.java | 283 ----------- .../put_anthropic/AnthropicTaskType.java | 65 --- .../inference/put_anthropic/ServiceType.java | 65 --- .../AzureAiStudioServiceSettings.java | 353 -------------- .../AzureAiStudioTaskSettings.java | 320 ------------ .../AzureAiStudioTaskType.java | 67 --- .../put_azureaistudio/ServiceType.java | 65 --- .../AzureOpenAIServiceSettings.java | 368 -------------- .../put_azureopenai/AzureOpenAITaskType.java | 67 --- .../put_azureopenai/ServiceType.java | 65 --- .../put_cohere/CohereServiceSettings.java | 363 -------------- .../put_cohere/CohereTaskSettings.java | 317 ------------ .../inference/put_cohere/CohereTaskType.java | 69 --- .../inference/put_cohere/EmbeddingType.java | 69 --- .../inference/put_cohere/InputType.java | 71 --- .../inference/put_cohere/ServiceType.java | 65 --- .../inference/put_cohere/SimilarityType.java | 69 --- .../inference/put_cohere/TruncateType.java | 69 --- .../inference/put_eis/EisServiceSettings.java | 210 -------- .../inference/put_eis/EisTaskType.java | 65 --- .../inference/put_eis/ServiceType.java | 65 --- .../AdaptiveAllocations.java | 236 --------- .../ElasticsearchServiceSettings.java | 342 ------------- .../ElasticsearchTaskSettings.java | 168 ------- .../ElasticsearchTaskType.java | 69 --- .../put_elasticsearch/ServiceType.java | 65 --- .../put_elser/AdaptiveAllocations.java | 236 --------- .../put_elser/ElserServiceSettings.java | 280 ----------- .../inference/put_elser/ElserTaskType.java | 65 --- .../GoogleAiStudioServiceSettings.java | 241 --------- .../GoogleAiStudioTaskType.java | 67 --- .../put_googleaistudio/ServiceType.java | 65 --- .../GoogleVertexAIServiceSettings.java | 300 ------------ .../GoogleVertexAITaskSettings.java | 204 -------- .../GoogleVertexAITaskType.java | 67 --- .../put_googlevertexai/ServiceType.java | 65 --- .../HuggingFaceServiceSettings.java | 252 ---------- .../put_hugging_face/HuggingFaceTaskType.java | 65 --- .../put_hugging_face/ServiceType.java | 65 --- .../put_jinaai/JinaAIServiceSettings.java | 297 ----------- .../put_jinaai/JinaAITaskSettings.java | 261 ---------- .../inference/put_jinaai/JinaAITaskType.java | 67 --- .../inference/put_jinaai/ServiceType.java | 65 --- .../inference/put_jinaai/SimilarityType.java | 69 --- .../put_jinaai/TextEmbeddingTask.java | 71 --- .../put_mistral/MistralServiceSettings.java | 289 ----------- .../put_mistral/MistralTaskType.java | 65 --- .../inference/put_mistral/ServiceType.java | 65 --- .../put_openai/OpenAIServiceSettings.java | 368 -------------- .../put_openai/OpenAITaskSettings.java | 169 ------- .../inference/put_openai/OpenAITaskType.java | 69 --- .../inference/put_openai/ServiceType.java | 77 --- .../inference/put_voyageai/ServiceType.java | 65 --- .../put_voyageai/VoyageAIServiceSettings.java | 303 ------------ .../put_voyageai/VoyageAITaskSettings.java | 278 ----------- .../put_voyageai/VoyageAITaskType.java | 67 --- .../inference/put_watsonx/ServiceType.java | 65 --- .../put_watsonx/WatsonxServiceSettings.java | 346 ------------- .../put_watsonx/WatsonxTaskType.java | 65 --- 107 files changed, 646 insertions(+), 13550 deletions(-) delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RequestChatCompletionBase.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionTool.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolChoice.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolChoiceFunction.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolFunction.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolTypeBuilders.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ContentObject.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/Message.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/MessageContent.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/MessageContentBuilders.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ToolCall.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ToolCallFunction.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAIServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAITaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/EmbeddingType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/InputType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/SimilarityType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/TruncateType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/EisServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/EisTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/AdaptiveAllocations.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/AdaptiveAllocations.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAIServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAIServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/SimilarityType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/TextEmbeddingTask.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralTaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAIServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAITaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAITaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAIServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAITaskSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAITaskType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/ServiceType.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/WatsonxServiceSettings.java delete mode 100644 java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/WatsonxTaskType.java diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java index 0d6e56a29..30f7ae8b5 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchAsyncClient.java @@ -180,12 +180,19 @@ */ public class ElasticsearchAsyncClient extends ApiClient { + /** + * Creates a client from a {@link ElasticsearchTransportConfig.Default}} + * configuration created with an inline lambda expression. + */ public static ElasticsearchAsyncClient of( Function fn) { return new ElasticsearchAsyncClient( fn.apply(new ElasticsearchTransportConfig.Builder()).build().buildTransport()); } + /** + * Creates a client from an {@link ElasticsearchTransportConfig}. + */ public ElasticsearchAsyncClient(ElasticsearchTransportConfig config) { this(config.buildTransport()); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java index e571b6f8f..271d40c24 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java @@ -181,11 +181,18 @@ */ public class ElasticsearchClient extends ApiClient { + /** + * Creates a client from a {@link ElasticsearchTransportConfig.Default}} + * configuration created with an inline lambda expression. + */ public static ElasticsearchClient of( Function fn) { return new ElasticsearchClient(fn.apply(new ElasticsearchTransportConfig.Builder()).build().buildTransport()); } + /** + * Creates a client from an {@link ElasticsearchTransportConfig}. + */ public ElasticsearchClient(ElasticsearchTransportConfig config) { this(config.buildTransport()); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/doc-files/api-spec.html b/java-client/src/main/java/co/elastic/clients/elasticsearch/doc-files/api-spec.html index b18eab292..4cd9caa47 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/doc-files/api-spec.html +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/doc-files/api-spec.html @@ -27,10 +27,14 @@ '_global.create.Response': '_global/create/CreateResponse.ts#L22-L25', '_global.delete.Request': '_global/delete/DeleteRequest.ts#L34-L146', <<<<<<< HEAD +<<<<<<< HEAD '_global.delete.Response': '_global/delete/DeleteResponse.ts#L22-L35', ======= '_global.delete.Response': '_global/delete/DeleteResponse.ts#L22-L34', >>>>>>> 03828daff (regen from latest spec) +======= +'_global.delete.Response': '_global/delete/DeleteResponse.ts#L22-L35', +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) '_global.delete_by_query.Request': '_global/delete_by_query/DeleteByQueryRequest.ts#L36-L314', '_global.delete_by_query.Response': '_global/delete_by_query/DeleteByQueryResponse.ts#L26-L88', '_global.delete_by_query_rethrottle.Request': '_global/delete_by_query_rethrottle/DeleteByQueryRethrottleRequest.ts#L24-L55', @@ -1813,6 +1817,9 @@ 'inference._types.TextEmbeddingInferenceResult': 'inference/_types/Results.ts#L67-L75', 'inference._types.TextEmbeddingResult': 'inference/_types/Results.ts#L60-L65', <<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) 'inference._types.ToolCall': 'inference/_types/CommonTypes.ts#L112-L128', 'inference._types.ToolCallFunction': 'inference/_types/CommonTypes.ts#L98-L110', 'inference._types.VoyageAIServiceSettings': 'inference/_types/CommonTypes.ts#L1075-L1106', @@ -1824,6 +1831,7 @@ 'inference._types.WatsonxTaskType': 'inference/_types/CommonTypes.ts#L1182-L1184', 'inference.chat_completion_unified.Request': 'inference/chat_completion_unified/UnifiedRequest.ts#L24-L53', 'inference.chat_completion_unified.Response': 'inference/chat_completion_unified/UnifiedResponse.ts#L22-L25', +<<<<<<< HEAD ======= 'inference.chat_completion_unified.CompletionTool': 'inference/chat_completion_unified/UnifiedRequest.ts#L180-L192', 'inference.chat_completion_unified.CompletionToolChoice': 'inference/chat_completion_unified/UnifiedRequest.ts#L143-L155', @@ -1838,6 +1846,8 @@ 'inference.chat_completion_unified.ToolCall': 'inference/chat_completion_unified/UnifiedRequest.ts#L87-L103', 'inference.chat_completion_unified.ToolCallFunction': 'inference/chat_completion_unified/UnifiedRequest.ts#L73-L85', >>>>>>> 03828daff (regen from latest spec) +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) 'inference.completion.Request': 'inference/completion/CompletionRequest.ts#L25-L63', 'inference.completion.Response': 'inference/completion/CompletionResponse.ts#L22-L25', 'inference.delete.Request': 'inference/delete/DeleteRequest.ts#L24-L66', @@ -1845,12 +1855,17 @@ 'inference.get.Request': 'inference/get/GetRequest.ts#L24-L56', 'inference.get.Response': 'inference/get/GetResponse.ts#L22-L26', <<<<<<< HEAD +<<<<<<< HEAD 'inference.post_eis_chat_completion.Request': 'inference/post_eis_chat_completion/PostEisChatCompletionRequest.ts#L23-L48', 'inference.post_eis_chat_completion.Response': 'inference/post_eis_chat_completion/PostEisChatCompletionResponse.ts#L22-L25', ======= 'inference.post_eis_chat_completion.Request': 'inference/post_eis_chat_completion/PostEisChatCompletionRequest.ts#L23-L46', 'inference.post_eis_chat_completion.Response': 'inference/post_eis_chat_completion/PostEisChatCompletionResponse.ts#L22-L24', >>>>>>> 03828daff (regen from latest spec) +======= +'inference.post_eis_chat_completion.Request': 'inference/post_eis_chat_completion/PostEisChatCompletionRequest.ts#L23-L48', +'inference.post_eis_chat_completion.Response': 'inference/post_eis_chat_completion/PostEisChatCompletionResponse.ts#L22-L25', +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) 'inference.put.Request': 'inference/put/PutRequest.ts#L25-L65', 'inference.put.Response': 'inference/put/PutResponse.ts#L22-L25', 'inference.put_alibabacloud.Request': 'inference/put_alibabacloud/PutAlibabaCloudRequest.ts#L30-L83', diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ChatCompletionUnifiedRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ChatCompletionUnifiedRequest.java index a75c98530..8b44188a6 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ChatCompletionUnifiedRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ChatCompletionUnifiedRequest.java @@ -20,9 +20,12 @@ package co.elastic.clients.elasticsearch.inference; import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch._types.RequestBase; import co.elastic.clients.elasticsearch._types.Time; import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; +import co.elastic.clients.json.JsonpMapper; +import co.elastic.clients.json.JsonpSerializable; import co.elastic.clients.json.ObjectBuilderDeserializer; import co.elastic.clients.json.ObjectDeserializer; import co.elastic.clients.transport.Endpoint; @@ -34,11 +37,15 @@ import jakarta.json.stream.JsonGenerator; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD import jakarta.json.stream.JsonParser; ======= >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +import jakarta.json.stream.JsonParser; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import java.lang.String; import java.util.HashMap; import java.util.Map; @@ -71,12 +78,13 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") * specification */ @JsonpDeserializable -public class ChatCompletionUnifiedRequest extends RequestChatCompletionBase { +public class ChatCompletionUnifiedRequest extends RequestBase implements JsonpSerializable { private final String inferenceId; @Nullable private final Time timeout; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private final RequestChatCompletion chatCompletionRequest; @@ -85,14 +93,18 @@ public class ChatCompletionUnifiedRequest extends RequestChatCompletionBase { >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final RequestChatCompletion chatCompletionRequest; + +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // --------------------------------------------------------------------------------------------- private ChatCompletionUnifiedRequest(Builder builder) { - super(builder); this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); this.timeout = builder.timeout; <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD this.chatCompletionRequest = ApiTypeHelper.requireNonNull(builder.chatCompletionRequest, this, "chatCompletionRequest"); @@ -100,6 +112,10 @@ private ChatCompletionUnifiedRequest(Builder builder) { >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + this.chatCompletionRequest = ApiTypeHelper.requireNonNull(builder.chatCompletionRequest, this, + "chatCompletionRequest"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } @@ -128,6 +144,9 @@ public final Time timeout() { <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) /** * Required - Request body. */ @@ -143,17 +162,20 @@ public void serialize(JsonGenerator generator, JsonpMapper mapper) { } +<<<<<<< HEAD ======= >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // --------------------------------------------------------------------------------------------- /** * Builder for {@link ChatCompletionUnifiedRequest}. */ - public static class Builder extends RequestChatCompletionBase.AbstractBuilder + public static class Builder extends RequestBase.AbstractBuilder implements ObjectBuilder { private String inferenceId; @@ -161,6 +183,7 @@ public static class Builder extends RequestChatCompletionBase.AbstractBuilder>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private RequestChatCompletion chatCompletionRequest; + +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) /** * Required - The inference Id *

@@ -200,6 +227,9 @@ public final Builder timeout(Function> fn) { <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) /** * Required - Request body. */ @@ -225,10 +255,13 @@ public Builder withJson(JsonParser parser, JsonpMapper mapper) { return this.chatCompletionRequest(value); } +<<<<<<< HEAD ======= >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) @Override protected Builder self() { return this; @@ -247,6 +280,7 @@ public ChatCompletionUnifiedRequest build() { } } +<<<<<<< HEAD <<<<<<< HEAD public static final JsonpDeserializer _DESERIALIZER = createChatCompletionUnifiedRequestDeserializer(); protected static JsonpDeserializer createChatCompletionUnifiedRequestDeserializer() { @@ -275,6 +309,15 @@ protected static void setupChatCompletionUnifiedRequestDeserializer( ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public static final JsonpDeserializer _DESERIALIZER = createChatCompletionUnifiedRequestDeserializer(); + protected static JsonpDeserializer createChatCompletionUnifiedRequestDeserializer() { + + JsonpDeserializer valueDeserializer = RequestChatCompletion._DESERIALIZER; + + return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() + .chatCompletionRequest(valueDeserializer.deserialize(parser, mapper, event)).build()); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } // --------------------------------------------------------------------------------------------- diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java index e86fae2b4..8c6278aa1 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java @@ -17,6 +17,7 @@ * under the License. */ +<<<<<<< HEAD <<<<<<< HEAD:java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java package co.elastic.clients.elasticsearch.inference; ======= @@ -26,6 +27,9 @@ package co.elastic.clients.elasticsearch.inference.put_openai; >>>>>>>> c86960dc6 (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java >>>>>>> 03828daff (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java +======= +package co.elastic.clients.elasticsearch.inference; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonEnum; import co.elastic.clients.json.JsonpDeserializable; @@ -48,13 +52,17 @@ >>>>>>>> c86960dc6 (regen from latest spec):java-client/src/main/java/co/elastic /** * +<<<<<<< HEAD <<<<<<< HEAD:java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * @see API * specification */ @JsonpDeserializable public enum EisTaskType implements JsonEnum { ChatCompletion("chat_completion"), +<<<<<<< HEAD ======= * @see >>>>>>> c86960dc6 (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java >>>>>>> 03828daff (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) ; diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceAsyncClient.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceAsyncClient.java index 5e81a9262..ea4611142 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceAsyncClient.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceAsyncClient.java @@ -321,6 +321,9 @@ public final CompletableFuture put(Function>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // ----- Endpoint: inference.put_alibabacloud /** @@ -723,8 +726,11 @@ public final CompletableFuture putCohere( return putCohere(fn.apply(new PutCohereRequest.Builder()).build()); } +<<<<<<< HEAD ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // ----- Endpoint: inference.put_eis /** @@ -734,11 +740,15 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") * Inference Service (EIS). * * @see Documentation ======= * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-eis.html">Documentation >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + * "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-eis">Documentation +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * on elastic.co */ @@ -759,11 +769,15 @@ public CompletableFuture putEis(PutEisRequest request) { * a function that initializes a builder to create the * {@link PutEisRequest} * @see Documentation ======= * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-eis.html">Documentation >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + * "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-eis">Documentation +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * on elastic.co */ @@ -773,6 +787,9 @@ public final CompletableFuture putEis( } <<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // ----- Endpoint: inference.put_elasticsearch /** @@ -1300,19 +1317,26 @@ public final CompletableFuture putMistral( return putMistral(fn.apply(new PutMistralRequest.Builder()).build()); } +<<<<<<< HEAD ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // ----- Endpoint: inference.put_openai /** * Create an OpenAI inference endpoint. *

* Create an inference endpoint to perform an inference task with the +<<<<<<< HEAD <<<<<<< HEAD * openai service or openai compatible APIs. ======= * openai service. >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + * openai service or openai compatible APIs. +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) *

* When you create an inference endpoint, the associated machine learning model * is automatically deployed if it is not already running. After creating the @@ -1325,11 +1349,15 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") * consumes significant resources. * * @see Documentation ======= * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-openai.html">Documentation >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + * "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-openai">Documentation +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * on elastic.co */ @@ -1344,11 +1372,15 @@ public CompletableFuture putOpenai(PutOpenaiRequest request) * Create an OpenAI inference endpoint. *

* Create an inference endpoint to perform an inference task with the +<<<<<<< HEAD <<<<<<< HEAD * openai service or openai compatible APIs. ======= * openai service. >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + * openai service or openai compatible APIs. +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) *

* When you create an inference endpoint, the associated machine learning model * is automatically deployed if it is not already running. After creating the @@ -1364,11 +1396,15 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") * a function that initializes a builder to create the * {@link PutOpenaiRequest} * @see Documentation ======= * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-openai.html">Documentation >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + * "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-openai">Documentation +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * on elastic.co */ diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceClient.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceClient.java index b8bf847f7..e0d5adb10 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceClient.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceClient.java @@ -325,6 +325,9 @@ public final PutResponse put(Function>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // ----- Endpoint: inference.put_alibabacloud /** @@ -736,8 +739,11 @@ public final PutCohereResponse putCohere(Function>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // ----- Endpoint: inference.put_eis /** @@ -747,11 +753,15 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") * Inference Service (EIS). * * @see Documentation ======= * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-eis.html">Documentation >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + * "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-eis">Documentation +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * on elastic.co */ @@ -772,11 +782,15 @@ public PutEisResponse putEis(PutEisRequest request) throws IOException, Elastics * a function that initializes a builder to create the * {@link PutEisRequest} * @see Documentation ======= * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-eis.html">Documentation >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + * "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-eis">Documentation +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * on elastic.co */ @@ -786,6 +800,9 @@ public final PutEisResponse putEis(Function>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // ----- Endpoint: inference.put_elasticsearch /** @@ -1321,19 +1338,26 @@ public final PutMistralResponse putMistral(Function>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // ----- Endpoint: inference.put_openai /** * Create an OpenAI inference endpoint. *

* Create an inference endpoint to perform an inference task with the +<<<<<<< HEAD <<<<<<< HEAD * openai service or openai compatible APIs. ======= * openai service. >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + * openai service or openai compatible APIs. +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) *

* When you create an inference endpoint, the associated machine learning model * is automatically deployed if it is not already running. After creating the @@ -1346,11 +1370,15 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") * consumes significant resources. * * @see Documentation ======= * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-openai.html">Documentation >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + * "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-openai">Documentation +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * on elastic.co */ @@ -1365,11 +1393,15 @@ public PutOpenaiResponse putOpenai(PutOpenaiRequest request) throws IOException, * Create an OpenAI inference endpoint. *

* Create an inference endpoint to perform an inference task with the +<<<<<<< HEAD <<<<<<< HEAD * openai service or openai compatible APIs. ======= * openai service. >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + * openai service or openai compatible APIs. +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) *

* When you create an inference endpoint, the associated machine learning model * is automatically deployed if it is not already running. After creating the @@ -1385,11 +1417,15 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") * a function that initializes a builder to create the * {@link PutOpenaiRequest} * @see Documentation ======= * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-openai.html">Documentation >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + * "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-openai">Documentation +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * on elastic.co */ diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PostEisChatCompletionRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PostEisChatCompletionRequest.java index abe28a1d1..56c847756 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PostEisChatCompletionRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PostEisChatCompletionRequest.java @@ -22,11 +22,15 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.elasticsearch._types.RequestBase; import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; import co.elastic.clients.json.JsonpSerializable; +<<<<<<< HEAD ======= import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; @@ -35,6 +39,8 @@ import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.ObjectBuilderDeserializer; import co.elastic.clients.json.ObjectDeserializer; import co.elastic.clients.transport.Endpoint; @@ -46,11 +52,15 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") import jakarta.json.stream.JsonGenerator; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD import jakarta.json.stream.JsonParser; ======= >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +import jakarta.json.stream.JsonParser; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import java.lang.String; import java.util.Collections; import java.util.HashMap; @@ -89,6 +99,7 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") @JsonpDeserializable <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD public class PostEisChatCompletionRequest extends RequestBase implements JsonpSerializable { private final String eisInferenceId; @@ -105,18 +116,27 @@ private PostEisChatCompletionRequest(Builder builder) { ======= >>>>>>> c49af58dc (Revert "temp rebase fix") public class PostEisChatCompletionRequest extends RequestChatCompletionBase { +======= +public class PostEisChatCompletionRequest extends RequestBase implements JsonpSerializable { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final String eisInferenceId; + private final RequestChatCompletion chatCompletionRequest; + // --------------------------------------------------------------------------------------------- private PostEisChatCompletionRequest(Builder builder) { - super(builder); this.eisInferenceId = ApiTypeHelper.requireNonNull(builder.eisInferenceId, this, "eisInferenceId"); <<<<<<< HEAD +<<<<<<< HEAD >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + this.chatCompletionRequest = ApiTypeHelper.requireNonNull(builder.chatCompletionRequest, this, + "chatCompletionRequest"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } @@ -135,6 +155,9 @@ public final String eisInferenceId() { <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) /** * Required - Request body. */ @@ -150,16 +173,20 @@ public void serialize(JsonGenerator generator, JsonpMapper mapper) { } +<<<<<<< HEAD ======= >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // --------------------------------------------------------------------------------------------- /** * Builder for {@link PostEisChatCompletionRequest}. */ +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD public static class Builder extends RequestBase.AbstractBuilder @@ -169,10 +196,14 @@ public static class Builder extends RequestChatCompletionBase.AbstractBuilder >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public static class Builder extends RequestBase.AbstractBuilder +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) implements ObjectBuilder { private String eisInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private RequestChatCompletion chatCompletionRequest; @@ -181,6 +212,10 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private RequestChatCompletion chatCompletionRequest; + +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) /** * Required - The unique identifier of the inference endpoint. *

@@ -193,6 +228,9 @@ public final Builder eisInferenceId(String value) { <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) /** * Required - Request body. */ @@ -218,10 +256,13 @@ public Builder withJson(JsonParser parser, JsonpMapper mapper) { return this.chatCompletionRequest(value); } +<<<<<<< HEAD ======= >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) @Override protected Builder self() { return this; @@ -240,6 +281,7 @@ public PostEisChatCompletionRequest build() { } } +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD public static final JsonpDeserializer _DESERIALIZER = createPostEisChatCompletionRequestDeserializer(); @@ -253,21 +295,22 @@ protected static JsonpDeserializer createPostEisCh ======= >>>>>>> c49af58dc (Revert "temp rebase fix") // --------------------------------------------------------------------------------------------- +======= + public static final JsonpDeserializer _DESERIALIZER = createPostEisChatCompletionRequestDeserializer(); + protected static JsonpDeserializer createPostEisChatCompletionRequestDeserializer() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) - /** - * Json deserializer for {@link PostEisChatCompletionRequest} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, PostEisChatCompletionRequest::setupPostEisChatCompletionRequestDeserializer); - - protected static void setupPostEisChatCompletionRequestDeserializer( - ObjectDeserializer op) { - RequestChatCompletionBase.setupRequestChatCompletionBaseDeserializer(op); + JsonpDeserializer valueDeserializer = RequestChatCompletion._DESERIALIZER; +<<<<<<< HEAD <<<<<<< HEAD >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() + .chatCompletionRequest(valueDeserializer.deserialize(parser, mapper, event)).build()); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } // --------------------------------------------------------------------------------------------- diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudRequest.java index c665dc530..bc4d55475 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudRequest.java @@ -23,6 +23,7 @@ import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= ======= >>>>>>> c49af58dc (Revert "temp rebase fix") @@ -34,6 +35,8 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -97,6 +100,7 @@ public class PutAlibabacloudRequest extends RequestBase implements JsonpSerializ @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private final AlibabaCloudServiceType service; @@ -106,6 +110,9 @@ public class PutAlibabacloudRequest extends RequestBase implements JsonpSerializ ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final AlibabaCloudServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final AlibabaCloudServiceSettings serviceSettings; @@ -158,6 +165,7 @@ public final InferenceChunkingSettings chunkingSettings() { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final AlibabaCloudServiceType service() { ======= @@ -166,6 +174,9 @@ public final ServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final AlibabaCloudServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -242,6 +253,7 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private AlibabaCloudServiceType service; @@ -251,6 +263,9 @@ public static class Builder extends RequestBase.AbstractBuilder ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private AlibabaCloudServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private AlibabaCloudServiceSettings serviceSettings; @@ -296,6 +311,7 @@ public final Builder chunkingSettings( * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(AlibabaCloudServiceType value) { ======= @@ -304,6 +320,9 @@ public final Builder service(ServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(AlibabaCloudServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -393,6 +412,7 @@ protected static void setupPutAlibabacloudRequestDeserializer( op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, AlibabaCloudServiceType._DESERIALIZER, "service"); ======= @@ -401,6 +421,9 @@ protected static void setupPutAlibabacloudRequestDeserializer( ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, AlibabaCloudServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, AlibabaCloudServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AlibabaCloudTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockRequest.java index eaff4e191..fe53c4bc7 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockRequest.java @@ -23,6 +23,7 @@ import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= ======= >>>>>>> c49af58dc (Revert "temp rebase fix") @@ -34,6 +35,8 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -106,6 +109,7 @@ public class PutAmazonbedrockRequest extends RequestBase implements JsonpSeriali @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private final AmazonBedrockServiceType service; @@ -115,6 +119,9 @@ public class PutAmazonbedrockRequest extends RequestBase implements JsonpSeriali ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final AmazonBedrockServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final AmazonBedrockServiceSettings serviceSettings; @@ -167,6 +174,7 @@ public final InferenceChunkingSettings chunkingSettings() { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final AmazonBedrockServiceType service() { ======= @@ -175,6 +183,9 @@ public final ServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final AmazonBedrockServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -251,6 +262,7 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private AmazonBedrockServiceType service; @@ -260,6 +272,9 @@ public static class Builder extends RequestBase.AbstractBuilder ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private AmazonBedrockServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private AmazonBedrockServiceSettings serviceSettings; @@ -305,6 +320,7 @@ public final Builder chunkingSettings( * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(AmazonBedrockServiceType value) { ======= @@ -313,6 +329,9 @@ public final Builder service(ServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(AmazonBedrockServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -402,6 +421,7 @@ protected static void setupPutAmazonbedrockRequestDeserializer( op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, AmazonBedrockServiceType._DESERIALIZER, "service"); ======= @@ -410,6 +430,9 @@ protected static void setupPutAmazonbedrockRequestDeserializer( ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, AmazonBedrockServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, AmazonBedrockServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AmazonBedrockTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicRequest.java index ec31225a8..564d81bb7 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicRequest.java @@ -23,6 +23,7 @@ import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= ======= >>>>>>> c49af58dc (Revert "temp rebase fix") @@ -34,6 +35,8 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -96,6 +99,7 @@ public class PutAnthropicRequest extends RequestBase implements JsonpSerializabl @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private final AnthropicServiceType service; @@ -105,6 +109,9 @@ public class PutAnthropicRequest extends RequestBase implements JsonpSerializabl ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final AnthropicServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final AnthropicServiceSettings serviceSettings; @@ -157,6 +164,7 @@ public final InferenceChunkingSettings chunkingSettings() { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final AnthropicServiceType service() { ======= @@ -165,6 +173,9 @@ public final ServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final AnthropicServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -242,6 +253,7 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private AnthropicServiceType service; @@ -251,6 +263,9 @@ public static class Builder extends RequestBase.AbstractBuilder ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private AnthropicServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private AnthropicServiceSettings serviceSettings; @@ -296,6 +311,7 @@ public final Builder chunkingSettings( * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(AnthropicServiceType value) { ======= @@ -304,6 +320,9 @@ public final Builder service(ServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(AnthropicServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -393,6 +412,7 @@ protected static void setupPutAnthropicRequestDeserializer(ObjectDeserializer>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, AnthropicServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, AnthropicServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AnthropicTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioRequest.java index 665812792..6c84a9940 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioRequest.java @@ -23,6 +23,7 @@ import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= ======= >>>>>>> c49af58dc (Revert "temp rebase fix") @@ -34,6 +35,8 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -97,6 +100,7 @@ public class PutAzureaistudioRequest extends RequestBase implements JsonpSeriali @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private final AzureAiStudioServiceType service; @@ -106,6 +110,9 @@ public class PutAzureaistudioRequest extends RequestBase implements JsonpSeriali ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final AzureAiStudioServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final AzureAiStudioServiceSettings serviceSettings; @@ -158,6 +165,7 @@ public final InferenceChunkingSettings chunkingSettings() { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final AzureAiStudioServiceType service() { ======= @@ -166,6 +174,9 @@ public final ServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final AzureAiStudioServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -242,6 +253,7 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private AzureAiStudioServiceType service; @@ -251,6 +263,9 @@ public static class Builder extends RequestBase.AbstractBuilder ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private AzureAiStudioServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private AzureAiStudioServiceSettings serviceSettings; @@ -296,6 +311,7 @@ public final Builder chunkingSettings( * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(AzureAiStudioServiceType value) { ======= @@ -304,6 +320,9 @@ public final Builder service(ServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(AzureAiStudioServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -393,6 +412,7 @@ protected static void setupPutAzureaistudioRequestDeserializer( op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, AzureAiStudioServiceType._DESERIALIZER, "service"); ======= @@ -401,6 +421,9 @@ protected static void setupPutAzureaistudioRequestDeserializer( ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, AzureAiStudioServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, AzureAiStudioServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AzureAiStudioTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiRequest.java index d258880b2..0eb1d17e7 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiRequest.java @@ -23,6 +23,7 @@ import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= ======= >>>>>>> c49af58dc (Revert "temp rebase fix") @@ -34,6 +35,8 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -112,6 +115,7 @@ public class PutAzureopenaiRequest extends RequestBase implements JsonpSerializa @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private final AzureOpenAIServiceType service; @@ -121,6 +125,9 @@ public class PutAzureopenaiRequest extends RequestBase implements JsonpSerializa ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final AzureOpenAIServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final AzureOpenAIServiceSettings serviceSettings; @@ -173,6 +180,7 @@ public final InferenceChunkingSettings chunkingSettings() { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final AzureOpenAIServiceType service() { ======= @@ -181,6 +189,9 @@ public final ServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final AzureOpenAIServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -259,6 +270,7 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private AzureOpenAIServiceType service; @@ -268,6 +280,9 @@ public static class Builder extends RequestBase.AbstractBuilder ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private AzureOpenAIServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private AzureOpenAIServiceSettings serviceSettings; @@ -313,6 +328,7 @@ public final Builder chunkingSettings( * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(AzureOpenAIServiceType value) { ======= @@ -321,6 +337,9 @@ public final Builder service(ServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(AzureOpenAIServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -411,6 +430,7 @@ protected static void setupPutAzureopenaiRequestDeserializer(ObjectDeserializer< op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, AzureOpenAIServiceType._DESERIALIZER, "service"); ======= @@ -419,6 +439,9 @@ protected static void setupPutAzureopenaiRequestDeserializer(ObjectDeserializer< ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, AzureOpenAIServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, AzureOpenAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AzureOpenAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereRequest.java index 4b9150362..9c75cf425 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereRequest.java @@ -23,6 +23,7 @@ import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= ======= >>>>>>> c49af58dc (Revert "temp rebase fix") @@ -34,6 +35,8 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -96,6 +99,7 @@ public class PutCohereRequest extends RequestBase implements JsonpSerializable { private final String cohereInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private final CohereServiceType service; @@ -105,6 +109,9 @@ public class PutCohereRequest extends RequestBase implements JsonpSerializable { ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final CohereServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final CohereServiceSettings serviceSettings; @@ -156,6 +163,7 @@ public final String cohereInferenceId() { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final CohereServiceType service() { ======= @@ -164,6 +172,9 @@ public final ServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final CohereServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -240,6 +251,7 @@ public static class Builder extends RequestBase.AbstractBuilder private String cohereInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private CohereServiceType service; @@ -249,6 +261,9 @@ public static class Builder extends RequestBase.AbstractBuilder ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private CohereServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private CohereServiceSettings serviceSettings; @@ -294,6 +309,7 @@ public final Builder cohereInferenceId(String value) { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(CohereServiceType value) { ======= @@ -302,6 +318,9 @@ public final Builder service(ServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(CohereServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -389,6 +408,7 @@ protected static void setupPutCohereRequestDeserializer(ObjectDeserializer>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, CohereServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, CohereServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, CohereTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisRequest.java index dcffa7fe4..29e105d3e 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisRequest.java @@ -22,11 +22,14 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD ======= import co.elastic.clients.elasticsearch.inference.put_eis.EisServiceSettings; import co.elastic.clients.elasticsearch.inference.put_eis.EisTaskType; import co.elastic.clients.elasticsearch.inference.put_eis.ServiceType; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -76,11 +79,15 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") public class PutEisRequest extends RequestBase implements JsonpSerializable { private final String eisInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private final EisServiceType service; ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final EisServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final EisServiceSettings serviceSettings; @@ -116,11 +123,15 @@ public final String eisInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final EisServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final EisServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -172,11 +183,15 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { public static class Builder extends RequestBase.AbstractBuilder implements ObjectBuilder { private String eisInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private EisServiceType service; ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private EisServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private EisServiceSettings serviceSettings; @@ -198,11 +213,15 @@ public final Builder eisInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(EisServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(EisServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -269,11 +288,15 @@ public PutEisRequest build() { protected static void setupPutEisRequestDeserializer(ObjectDeserializer op) { +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, EisServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, EisServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, EisServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchRequest.java index 2456383af..512fcb38d 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchRequest.java @@ -23,6 +23,7 @@ import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= ======= >>>>>>> c49af58dc (Revert "temp rebase fix") @@ -34,6 +35,8 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -114,6 +117,7 @@ public class PutElasticsearchRequest extends RequestBase implements JsonpSeriali private final String elasticsearchInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private final ElasticsearchServiceType service; @@ -123,6 +127,9 @@ public class PutElasticsearchRequest extends RequestBase implements JsonpSeriali ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final ElasticsearchServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final ElasticsearchServiceSettings serviceSettings; @@ -176,6 +183,7 @@ public final String elasticsearchInferenceId() { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final ElasticsearchServiceType service() { ======= @@ -184,6 +192,9 @@ public final ServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final ElasticsearchServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -260,6 +271,7 @@ public static class Builder extends RequestBase.AbstractBuilder private String elasticsearchInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private ElasticsearchServiceType service; @@ -269,6 +281,9 @@ public static class Builder extends RequestBase.AbstractBuilder ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private ElasticsearchServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private ElasticsearchServiceSettings serviceSettings; @@ -315,6 +330,7 @@ public final Builder elasticsearchInferenceId(String value) { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(ElasticsearchServiceType value) { ======= @@ -323,6 +339,9 @@ public final Builder service(ServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(ElasticsearchServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -412,6 +431,7 @@ protected static void setupPutElasticsearchRequestDeserializer( op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, ElasticsearchServiceType._DESERIALIZER, "service"); ======= @@ -420,6 +440,9 @@ protected static void setupPutElasticsearchRequestDeserializer( ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, ElasticsearchServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, ElasticsearchServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, ElasticsearchTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserRequest.java index 07f990d3b..d28b829d7 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserRequest.java @@ -23,6 +23,7 @@ import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= import co.elastic.clients.elasticsearch.inference.put_elser.ElserServiceSettings; import co.elastic.clients.elasticsearch.inference.put_elser.ElserTaskType; @@ -33,6 +34,8 @@ import co.elastic.clients.elasticsearch.inference.put_elser.ElserTaskType; import co.elastic.clients.elasticsearch.inference.put_elser.ServiceType; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -116,6 +119,7 @@ public class PutElserRequest extends RequestBase implements JsonpSerializable { private final String elserInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private final ElserServiceType service; @@ -125,6 +129,9 @@ public class PutElserRequest extends RequestBase implements JsonpSerializable { ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final ElserServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final ElserServiceSettings serviceSettings; @@ -172,6 +179,7 @@ public final String elserInferenceId() { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final ElserServiceType service() { ======= @@ -180,6 +188,9 @@ public final ServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final ElserServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -237,6 +248,7 @@ public static class Builder extends RequestBase.AbstractBuilder impleme private String elserInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private ElserServiceType service; @@ -246,6 +258,9 @@ public static class Builder extends RequestBase.AbstractBuilder impleme ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private ElserServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private ElserServiceSettings serviceSettings; @@ -288,6 +303,7 @@ public final Builder elserInferenceId(String value) { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(ElserServiceType value) { ======= @@ -296,6 +312,9 @@ public final Builder service(ServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(ElserServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -362,6 +381,7 @@ protected static void setupPutElserRequestDeserializer(ObjectDeserializer>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, ElserServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, ElserServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioRequest.java index efe0282e1..185eec74e 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioRequest.java @@ -23,6 +23,7 @@ import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= import co.elastic.clients.elasticsearch.inference.put_googleaistudio.GoogleAiStudioServiceSettings; import co.elastic.clients.elasticsearch.inference.put_googleaistudio.GoogleAiStudioTaskType; @@ -33,6 +34,8 @@ import co.elastic.clients.elasticsearch.inference.put_googleaistudio.GoogleAiStudioTaskType; import co.elastic.clients.elasticsearch.inference.put_googleaistudio.ServiceType; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -96,6 +99,7 @@ public class PutGoogleaistudioRequest extends RequestBase implements JsonpSerial private final String googleaistudioInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private final GoogleAiServiceType service; @@ -105,6 +109,9 @@ public class PutGoogleaistudioRequest extends RequestBase implements JsonpSerial ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final GoogleAiServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final GoogleAiStudioServiceSettings serviceSettings; @@ -153,6 +160,7 @@ public final String googleaistudioInferenceId() { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final GoogleAiServiceType service() { ======= @@ -161,6 +169,9 @@ public final ServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final GoogleAiServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -220,6 +231,7 @@ public static class Builder extends RequestBase.AbstractBuilder private String googleaistudioInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private GoogleAiServiceType service; @@ -229,6 +241,9 @@ public static class Builder extends RequestBase.AbstractBuilder ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private GoogleAiServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private GoogleAiStudioServiceSettings serviceSettings; @@ -271,6 +286,7 @@ public final Builder googleaistudioInferenceId(String value) { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(GoogleAiServiceType value) { ======= @@ -279,6 +295,9 @@ public final Builder service(ServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(GoogleAiServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -346,6 +365,7 @@ protected static void setupPutGoogleaistudioRequestDeserializer( op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, GoogleAiServiceType._DESERIALIZER, "service"); ======= @@ -354,6 +374,9 @@ protected static void setupPutGoogleaistudioRequestDeserializer( ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, GoogleAiServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, GoogleAiStudioServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiRequest.java index d59779452..808122ab7 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiRequest.java @@ -23,6 +23,7 @@ import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= ======= >>>>>>> c49af58dc (Revert "temp rebase fix") @@ -34,6 +35,8 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -97,6 +100,7 @@ public class PutGooglevertexaiRequest extends RequestBase implements JsonpSerial private final String googlevertexaiInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private final GoogleVertexAIServiceType service; @@ -106,6 +110,9 @@ public class PutGooglevertexaiRequest extends RequestBase implements JsonpSerial ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final GoogleVertexAIServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final GoogleVertexAIServiceSettings serviceSettings; @@ -158,6 +165,7 @@ public final String googlevertexaiInferenceId() { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final GoogleVertexAIServiceType service() { ======= @@ -166,6 +174,9 @@ public final ServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final GoogleVertexAIServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -242,6 +253,7 @@ public static class Builder extends RequestBase.AbstractBuilder private String googlevertexaiInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private GoogleVertexAIServiceType service; @@ -251,6 +263,9 @@ public static class Builder extends RequestBase.AbstractBuilder ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private GoogleVertexAIServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private GoogleVertexAIServiceSettings serviceSettings; @@ -296,6 +311,7 @@ public final Builder googlevertexaiInferenceId(String value) { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(GoogleVertexAIServiceType value) { ======= @@ -304,6 +320,9 @@ public final Builder service(ServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(GoogleVertexAIServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -393,6 +412,7 @@ protected static void setupPutGooglevertexaiRequestDeserializer( op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, GoogleVertexAIServiceType._DESERIALIZER, "service"); ======= @@ -401,6 +421,9 @@ protected static void setupPutGooglevertexaiRequestDeserializer( ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, GoogleVertexAIServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, GoogleVertexAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, GoogleVertexAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceRequest.java index 319dfc06c..072cc78e7 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceRequest.java @@ -23,6 +23,7 @@ import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= import co.elastic.clients.elasticsearch.inference.put_hugging_face.HuggingFaceServiceSettings; import co.elastic.clients.elasticsearch.inference.put_hugging_face.HuggingFaceTaskType; @@ -33,6 +34,8 @@ import co.elastic.clients.elasticsearch.inference.put_hugging_face.HuggingFaceTaskType; import co.elastic.clients.elasticsearch.inference.put_hugging_face.ServiceType; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -114,6 +117,7 @@ public class PutHuggingFaceRequest extends RequestBase implements JsonpSerializa private final String huggingfaceInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private final HuggingFaceServiceType service; @@ -123,6 +127,9 @@ public class PutHuggingFaceRequest extends RequestBase implements JsonpSerializa ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final HuggingFaceServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final HuggingFaceServiceSettings serviceSettings; @@ -171,6 +178,7 @@ public final String huggingfaceInferenceId() { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final HuggingFaceServiceType service() { ======= @@ -179,6 +187,9 @@ public final ServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final HuggingFaceServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -238,6 +249,7 @@ public static class Builder extends RequestBase.AbstractBuilder private String huggingfaceInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private HuggingFaceServiceType service; @@ -247,6 +259,9 @@ public static class Builder extends RequestBase.AbstractBuilder ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private HuggingFaceServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private HuggingFaceServiceSettings serviceSettings; @@ -289,6 +304,7 @@ public final Builder huggingfaceInferenceId(String value) { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(HuggingFaceServiceType value) { ======= @@ -297,6 +313,9 @@ public final Builder service(ServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(HuggingFaceServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -363,6 +382,7 @@ protected static void setupPutHuggingFaceRequestDeserializer(ObjectDeserializer< op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, HuggingFaceServiceType._DESERIALIZER, "service"); ======= @@ -371,6 +391,9 @@ protected static void setupPutHuggingFaceRequestDeserializer(ObjectDeserializer< ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, HuggingFaceServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, HuggingFaceServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiRequest.java index 8b0254962..b7aff29fa 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiRequest.java @@ -23,6 +23,7 @@ import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= ======= >>>>>>> c49af58dc (Revert "temp rebase fix") @@ -34,6 +35,8 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") >>>>>>> 03828daff (regen from latest spec) ======= >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -101,6 +104,7 @@ public class PutJinaaiRequest extends RequestBase implements JsonpSerializable { private final String jinaaiInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private final JinaAIServiceType service; @@ -110,6 +114,9 @@ public class PutJinaaiRequest extends RequestBase implements JsonpSerializable { ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final JinaAIServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final JinaAIServiceSettings serviceSettings; @@ -161,6 +168,7 @@ public final String jinaaiInferenceId() { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final JinaAIServiceType service() { ======= @@ -169,6 +177,9 @@ public final ServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final JinaAIServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -245,6 +256,7 @@ public static class Builder extends RequestBase.AbstractBuilder private String jinaaiInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private JinaAIServiceType service; @@ -254,6 +266,9 @@ public static class Builder extends RequestBase.AbstractBuilder ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private JinaAIServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private JinaAIServiceSettings serviceSettings; @@ -299,6 +314,7 @@ public final Builder jinaaiInferenceId(String value) { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(JinaAIServiceType value) { ======= @@ -307,6 +323,9 @@ public final Builder service(ServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(JinaAIServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -394,6 +413,7 @@ protected static void setupPutJinaaiRequestDeserializer(ObjectDeserializer>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, JinaAIServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, JinaAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, JinaAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralRequest.java index 78a1e639b..81b494927 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralRequest.java @@ -23,6 +23,7 @@ import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= import co.elastic.clients.elasticsearch.inference.put_mistral.MistralServiceSettings; import co.elastic.clients.elasticsearch.inference.put_mistral.MistralTaskType; @@ -33,6 +34,8 @@ import co.elastic.clients.elasticsearch.inference.put_mistral.MistralTaskType; import co.elastic.clients.elasticsearch.inference.put_mistral.ServiceType; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -95,6 +98,7 @@ public class PutMistralRequest extends RequestBase implements JsonpSerializable private final String mistralInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private final MistralServiceType service; @@ -104,6 +108,9 @@ public class PutMistralRequest extends RequestBase implements JsonpSerializable ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final MistralServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final MistralServiceSettings serviceSettings; @@ -151,6 +158,7 @@ public final String mistralInferenceId() { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final MistralServiceType service() { ======= @@ -159,6 +167,9 @@ public final ServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final MistralServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -219,6 +230,7 @@ public static class Builder extends RequestBase.AbstractBuilder private String mistralInferenceId; +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD private MistralServiceType service; @@ -228,6 +240,9 @@ public static class Builder extends RequestBase.AbstractBuilder ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private MistralServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private MistralServiceSettings serviceSettings; @@ -270,6 +285,7 @@ public final Builder mistralInferenceId(String value) { * API name: {@code service} */ <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(MistralServiceType value) { ======= @@ -278,6 +294,9 @@ public final Builder service(ServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(MistralServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -345,6 +364,7 @@ protected static void setupPutMistralRequestDeserializer(ObjectDeserializer>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, MistralServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, MistralServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiRequest.java index 4b9691858..73e6c00e9 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiRequest.java @@ -22,12 +22,15 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD ======= import co.elastic.clients.elasticsearch.inference.put_openai.OpenAIServiceSettings; import co.elastic.clients.elasticsearch.inference.put_openai.OpenAITaskSettings; import co.elastic.clients.elasticsearch.inference.put_openai.OpenAITaskType; import co.elastic.clients.elasticsearch.inference.put_openai.ServiceType; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -90,11 +93,15 @@ public class PutOpenaiRequest extends RequestBase implements JsonpSerializable { private final String openaiInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private final OpenAIServiceType service; ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final OpenAIServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final OpenAIServiceSettings serviceSettings; @@ -145,11 +152,15 @@ public final String openaiInferenceId() { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final OpenAIServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final OpenAIServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -228,11 +239,15 @@ public static class Builder extends RequestBase.AbstractBuilder private String openaiInferenceId; +<<<<<<< HEAD <<<<<<< HEAD private OpenAIServiceType service; ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private OpenAIServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private OpenAIServiceSettings serviceSettings; @@ -277,11 +292,15 @@ public final Builder openaiInferenceId(String value) { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(OpenAIServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(OpenAIServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -370,11 +389,15 @@ public PutOpenaiRequest build() { protected static void setupPutOpenaiRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, OpenAIServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, OpenAIServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, OpenAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, OpenAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiRequest.java index 804dcf3fc..97bfbea2e 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiRequest.java @@ -22,12 +22,15 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD ======= import co.elastic.clients.elasticsearch.inference.put_voyageai.ServiceType; import co.elastic.clients.elasticsearch.inference.put_voyageai.VoyageAIServiceSettings; import co.elastic.clients.elasticsearch.inference.put_voyageai.VoyageAITaskSettings; import co.elastic.clients.elasticsearch.inference.put_voyageai.VoyageAITaskType; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -81,11 +84,15 @@ public class PutVoyageaiRequest extends RequestBase implements JsonpSerializable @Nullable private final InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD private final VoyageAIServiceType service; ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final VoyageAIServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final VoyageAIServiceSettings serviceSettings; @@ -130,11 +137,15 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final VoyageAIServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final VoyageAIServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -218,11 +229,15 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; +<<<<<<< HEAD <<<<<<< HEAD private VoyageAIServiceType service; ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private VoyageAIServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private VoyageAIServiceSettings serviceSettings; @@ -259,11 +274,15 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(VoyageAIServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(VoyageAIServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -361,11 +380,15 @@ public PutVoyageaiRequest build() { protected static void setupPutVoyageaiRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, VoyageAIServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, VoyageAIServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, VoyageAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, VoyageAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxRequest.java index c54a4df68..05e3d282a 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxRequest.java @@ -22,11 +22,14 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; <<<<<<< HEAD +<<<<<<< HEAD ======= import co.elastic.clients.elasticsearch.inference.put_watsonx.ServiceType; import co.elastic.clients.elasticsearch.inference.put_watsonx.WatsonxServiceSettings; import co.elastic.clients.elasticsearch.inference.put_watsonx.WatsonxTaskType; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -87,11 +90,15 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") */ @JsonpDeserializable public class PutWatsonxRequest extends RequestBase implements JsonpSerializable { +<<<<<<< HEAD <<<<<<< HEAD private final WatsonxServiceType service; ======= private final ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final WatsonxServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final WatsonxServiceSettings serviceSettings; @@ -120,11 +127,15 @@ public static PutWatsonxRequest of(Function * API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final WatsonxServiceType service() { ======= public final ServiceType service() { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final WatsonxServiceType service() { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -184,11 +195,15 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { public static class Builder extends RequestBase.AbstractBuilder implements ObjectBuilder { +<<<<<<< HEAD <<<<<<< HEAD private WatsonxServiceType service; ======= private ServiceType service; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private WatsonxServiceType service; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private WatsonxServiceSettings serviceSettings; @@ -202,11 +217,15 @@ >>>>>>> c49af58dc (Revert "temp rebase fix") *

* API name: {@code service} */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder service(WatsonxServiceType value) { ======= public final Builder service(ServiceType value) { >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder service(WatsonxServiceType value) { +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -282,11 +301,15 @@ public PutWatsonxRequest build() { protected static void setupPutWatsonxRequestDeserializer(ObjectDeserializer op) { +<<<<<<< HEAD <<<<<<< HEAD op.add(Builder::service, WatsonxServiceType._DESERIALIZER, "service"); ======= op.add(Builder::service, ServiceType._DESERIALIZER, "service"); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + op.add(Builder::service, WatsonxServiceType._DESERIALIZER, "service"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, WatsonxServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RequestChatCompletionBase.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RequestChatCompletionBase.java deleted file mode 100644 index 1941152d1..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/RequestChatCompletionBase.java +++ /dev/null @@ -1,461 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference; - -import co.elastic.clients.elasticsearch._types.RequestBase; -import co.elastic.clients.elasticsearch.inference.chat_completion_unified.CompletionTool; -import co.elastic.clients.elasticsearch.inference.chat_completion_unified.CompletionToolType; -import co.elastic.clients.elasticsearch.inference.chat_completion_unified.Message; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Float; -import java.lang.Long; -import java.lang.String; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference._types.RequestChatCompletionBase - -/** - * - * @see API - * specification - */ - -public abstract class RequestChatCompletionBase extends RequestBase implements JsonpSerializable { - private final List messages; - - @Nullable - private final String model; - - @Nullable - private final Long maxCompletionTokens; - - private final List stop; - - @Nullable - private final Float temperature; - - @Nullable - private final CompletionToolType toolChoice; - - private final List tools; - - @Nullable - private final Float topP; - - // --------------------------------------------------------------------------------------------- - - protected RequestChatCompletionBase(AbstractBuilder builder) { - - this.messages = ApiTypeHelper.unmodifiableRequired(builder.messages, this, "messages"); - this.model = builder.model; - this.maxCompletionTokens = builder.maxCompletionTokens; - this.stop = ApiTypeHelper.unmodifiable(builder.stop); - this.temperature = builder.temperature; - this.toolChoice = builder.toolChoice; - this.tools = ApiTypeHelper.unmodifiable(builder.tools); - this.topP = builder.topP; - - } - - /** - * Required - A list of objects representing the conversation. - *

- * API name: {@code messages} - */ - public final List messages() { - return this.messages; - } - - /** - * The ID of the model to use. - *

- * API name: {@code model} - */ - @Nullable - public final String model() { - return this.model; - } - - /** - * The upper bound limit for the number of tokens that can be generated for a - * completion request. - *

- * API name: {@code max_completion_tokens} - */ - @Nullable - public final Long maxCompletionTokens() { - return this.maxCompletionTokens; - } - - /** - * A sequence of strings to control when the model should stop generating - * additional tokens. - *

- * API name: {@code stop} - */ - public final List stop() { - return this.stop; - } - - /** - * The sampling temperature to use. - *

- * API name: {@code temperature} - */ - @Nullable - public final Float temperature() { - return this.temperature; - } - - /** - * Controls which tool is called by the model. - *

- * API name: {@code tool_choice} - */ - @Nullable - public final CompletionToolType toolChoice() { - return this.toolChoice; - } - - /** - * A list of tools that the model can call. - *

- * API name: {@code tools} - */ - public final List tools() { - return this.tools; - } - - /** - * Nucleus sampling, an alternative to sampling with temperature. - *

- * API name: {@code top_p} - */ - @Nullable - public final Float topP() { - return this.topP; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (ApiTypeHelper.isDefined(this.messages)) { - generator.writeKey("messages"); - generator.writeStartArray(); - for (Message item0 : this.messages) { - item0.serialize(generator, mapper); - - } - generator.writeEnd(); - - } - if (this.model != null) { - generator.writeKey("model"); - generator.write(this.model); - - } - if (this.maxCompletionTokens != null) { - generator.writeKey("max_completion_tokens"); - generator.write(this.maxCompletionTokens); - - } - if (ApiTypeHelper.isDefined(this.stop)) { - generator.writeKey("stop"); - generator.writeStartArray(); - for (String item0 : this.stop) { - generator.write(item0); - - } - generator.writeEnd(); - - } - if (this.temperature != null) { - generator.writeKey("temperature"); - generator.write(this.temperature); - - } - if (this.toolChoice != null) { - generator.writeKey("tool_choice"); - this.toolChoice.serialize(generator, mapper); - - } - if (ApiTypeHelper.isDefined(this.tools)) { - generator.writeKey("tools"); - generator.writeStartArray(); - for (CompletionTool item0 : this.tools) { - item0.serialize(generator, mapper); - - } - generator.writeEnd(); - - } - if (this.topP != null) { - generator.writeKey("top_p"); - generator.write(this.topP); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - public abstract static class AbstractBuilder> - extends - RequestBase.AbstractBuilder { - private List messages; - - @Nullable - private String model; - - @Nullable - private Long maxCompletionTokens; - - @Nullable - private List stop; - - @Nullable - private Float temperature; - - @Nullable - private CompletionToolType toolChoice; - - @Nullable - private List tools; - - @Nullable - private Float topP; - - /** - * Required - A list of objects representing the conversation. - *

- * API name: {@code messages} - *

- * Adds all elements of list to messages. - */ - public final BuilderT messages(List list) { - this.messages = _listAddAll(this.messages, list); - return self(); - } - - /** - * Required - A list of objects representing the conversation. - *

- * API name: {@code messages} - *

- * Adds one or more values to messages. - */ - public final BuilderT messages(Message value, Message... values) { - this.messages = _listAdd(this.messages, value, values); - return self(); - } - - /** - * Required - A list of objects representing the conversation. - *

- * API name: {@code messages} - *

- * Adds a value to messages using a builder lambda. - */ - public final BuilderT messages(Function> fn) { - return messages(fn.apply(new Message.Builder()).build()); - } - - /** - * The ID of the model to use. - *

- * API name: {@code model} - */ - public final BuilderT model(@Nullable String value) { - this.model = value; - return self(); - } - - /** - * The upper bound limit for the number of tokens that can be generated for a - * completion request. - *

- * API name: {@code max_completion_tokens} - */ - public final BuilderT maxCompletionTokens(@Nullable Long value) { - this.maxCompletionTokens = value; - return self(); - } - - /** - * A sequence of strings to control when the model should stop generating - * additional tokens. - *

- * API name: {@code stop} - *

- * Adds all elements of list to stop. - */ - public final BuilderT stop(List list) { - this.stop = _listAddAll(this.stop, list); - return self(); - } - - /** - * A sequence of strings to control when the model should stop generating - * additional tokens. - *

- * API name: {@code stop} - *

- * Adds one or more values to stop. - */ - public final BuilderT stop(String value, String... values) { - this.stop = _listAdd(this.stop, value, values); - return self(); - } - - /** - * The sampling temperature to use. - *

- * API name: {@code temperature} - */ - public final BuilderT temperature(@Nullable Float value) { - this.temperature = value; - return self(); - } - - /** - * Controls which tool is called by the model. - *

- * API name: {@code tool_choice} - */ - public final BuilderT toolChoice(@Nullable CompletionToolType value) { - this.toolChoice = value; - return self(); - } - - /** - * Controls which tool is called by the model. - *

- * API name: {@code tool_choice} - */ - public final BuilderT toolChoice(Function> fn) { - return this.toolChoice(fn.apply(new CompletionToolType.Builder()).build()); - } - - /** - * A list of tools that the model can call. - *

- * API name: {@code tools} - *

- * Adds all elements of list to tools. - */ - public final BuilderT tools(List list) { - this.tools = _listAddAll(this.tools, list); - return self(); - } - - /** - * A list of tools that the model can call. - *

- * API name: {@code tools} - *

- * Adds one or more values to tools. - */ - public final BuilderT tools(CompletionTool value, CompletionTool... values) { - this.tools = _listAdd(this.tools, value, values); - return self(); - } - - /** - * A list of tools that the model can call. - *

- * API name: {@code tools} - *

- * Adds a value to tools using a builder lambda. - */ - public final BuilderT tools(Function> fn) { - return tools(fn.apply(new CompletionTool.Builder()).build()); - } - - /** - * Nucleus sampling, an alternative to sampling with temperature. - *

- * API name: {@code top_p} - */ - public final BuilderT topP(@Nullable Float value) { - this.topP = value; - return self(); - } - - protected abstract BuilderT self(); - - } - - // --------------------------------------------------------------------------------------------- - protected static > void setupRequestChatCompletionBaseDeserializer( - ObjectDeserializer op) { - - op.add(AbstractBuilder::messages, JsonpDeserializer.arrayDeserializer(Message._DESERIALIZER), "messages"); - op.add(AbstractBuilder::model, JsonpDeserializer.stringDeserializer(), "model"); - op.add(AbstractBuilder::maxCompletionTokens, JsonpDeserializer.longDeserializer(), "max_completion_tokens"); - op.add(AbstractBuilder::stop, JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()), - "stop"); - op.add(AbstractBuilder::temperature, JsonpDeserializer.floatDeserializer(), "temperature"); - op.add(AbstractBuilder::toolChoice, CompletionToolType._DESERIALIZER, "tool_choice"); - op.add(AbstractBuilder::tools, JsonpDeserializer.arrayDeserializer(CompletionTool._DESERIALIZER), "tools"); - op.add(AbstractBuilder::topP, JsonpDeserializer.floatDeserializer(), "top_p"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResponse.java index d3e855c1e..d0811ab69 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResponse.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResponse.java @@ -60,21 +60,29 @@ */ @JsonpDeserializable public class TextEmbeddingResponse implements JsonpSerializable { +<<<<<<< HEAD <<<<<<< HEAD private final TextEmbeddingInferenceResult inferenceResult; ======= private final TextEmbeddingInferenceResult valueBody; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private final TextEmbeddingInferenceResult inferenceResult; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // --------------------------------------------------------------------------------------------- private TextEmbeddingResponse(Builder builder) { +<<<<<<< HEAD <<<<<<< HEAD this.inferenceResult = ApiTypeHelper.requireNonNull(builder.inferenceResult, this, "inferenceResult"); ======= this.valueBody = ApiTypeHelper.requireNonNull(builder.valueBody, this, "valueBody"); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + this.inferenceResult = ApiTypeHelper.requireNonNull(builder.inferenceResult, this, "inferenceResult"); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } @@ -85,6 +93,7 @@ public static TextEmbeddingResponse of(Function>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final TextEmbeddingInferenceResult inferenceResult() { + return this.inferenceResult; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } /** * Serialize this value to JSON. */ public void serialize(JsonGenerator generator, JsonpMapper mapper) { +<<<<<<< HEAD <<<<<<< HEAD this.inferenceResult.serialize(generator, mapper); ======= this.valueBody.serialize(generator, mapper); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + this.inferenceResult.serialize(generator, mapper); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } @@ -120,15 +137,20 @@ public String toString() { public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { +<<<<<<< HEAD <<<<<<< HEAD private TextEmbeddingInferenceResult inferenceResult; ======= private TextEmbeddingInferenceResult valueBody; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + private TextEmbeddingInferenceResult inferenceResult; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) /** * Required - Response value. */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder inferenceResult(TextEmbeddingInferenceResult value) { this.inferenceResult = value; @@ -136,12 +158,17 @@ public final Builder inferenceResult(TextEmbeddingInferenceResult value) { public final Builder valueBody(TextEmbeddingInferenceResult value) { this.valueBody = value; >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder inferenceResult(TextEmbeddingInferenceResult value) { + this.inferenceResult = value; +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this; } /** * Required - Response value. */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder inferenceResult( Function> fn) { @@ -151,11 +178,17 @@ public final Builder valueBody( Function> fn) { return this.valueBody(fn.apply(new TextEmbeddingInferenceResult.Builder()).build()); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder inferenceResult( + Function> fn) { + return this.inferenceResult(fn.apply(new TextEmbeddingInferenceResult.Builder()).build()); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } /** * Required - Response value. */ +<<<<<<< HEAD <<<<<<< HEAD public final Builder inferenceResult(TextEmbeddingInferenceResultVariant value) { this.inferenceResult = value._toTextEmbeddingInferenceResult(); @@ -163,6 +196,10 @@ public final Builder inferenceResult(TextEmbeddingInferenceResultVariant value) public final Builder valueBody(TextEmbeddingInferenceResultVariant value) { this.valueBody = value._toTextEmbeddingInferenceResult(); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + public final Builder inferenceResult(TextEmbeddingInferenceResultVariant value) { + this.inferenceResult = value._toTextEmbeddingInferenceResult(); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this; } @@ -172,11 +209,15 @@ public Builder withJson(JsonParser parser, JsonpMapper mapper) { @SuppressWarnings("unchecked") TextEmbeddingInferenceResult value = (TextEmbeddingInferenceResult) TextEmbeddingInferenceResult._DESERIALIZER .deserialize(parser, mapper); +<<<<<<< HEAD <<<<<<< HEAD return this.inferenceResult(value); ======= return this.valueBody(value); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + return this.inferenceResult(value); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } @Override @@ -203,11 +244,15 @@ protected static JsonpDeserializer createTextEmbeddingRes JsonpDeserializer valueDeserializer = TextEmbeddingInferenceResult._DESERIALIZER; return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() +<<<<<<< HEAD <<<<<<< HEAD .inferenceResult(valueDeserializer.deserialize(parser, mapper, event)).build()); ======= .valueBody(valueDeserializer.deserialize(parser, mapper, event)).build()); >>>>>>> c49af58dc (Revert "temp rebase fix") +======= + .inferenceResult(valueDeserializer.deserialize(parser, mapper, event)).build()); +>>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionTool.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionTool.java deleted file mode 100644 index 52a84d62a..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionTool.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.chat_completion_unified; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.chat_completion_unified.CompletionTool - -/** - * A list of tools that the model can call. - * - * @see API - * specification - */ -@JsonpDeserializable -public class CompletionTool implements JsonpSerializable { - private final String type; - - private final CompletionToolFunction function; - - // --------------------------------------------------------------------------------------------- - - private CompletionTool(Builder builder) { - - this.type = ApiTypeHelper.requireNonNull(builder.type, this, "type"); - this.function = ApiTypeHelper.requireNonNull(builder.function, this, "function"); - - } - - public static CompletionTool of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The type of tool. - *

- * API name: {@code type} - */ - public final String type() { - return this.type; - } - - /** - * Required - The function definition. - *

- * API name: {@code function} - */ - public final CompletionToolFunction function() { - return this.function; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("type"); - generator.write(this.type); - - generator.writeKey("function"); - this.function.serialize(generator, mapper); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link CompletionTool}. - */ - - public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { - private String type; - - private CompletionToolFunction function; - - /** - * Required - The type of tool. - *

- * API name: {@code type} - */ - public final Builder type(String value) { - this.type = value; - return this; - } - - /** - * Required - The function definition. - *

- * API name: {@code function} - */ - public final Builder function(CompletionToolFunction value) { - this.function = value; - return this; - } - - /** - * Required - The function definition. - *

- * API name: {@code function} - */ - public final Builder function( - Function> fn) { - return this.function(fn.apply(new CompletionToolFunction.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link CompletionTool}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public CompletionTool build() { - _checkSingleUse(); - - return new CompletionTool(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link CompletionTool} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, - CompletionTool::setupCompletionToolDeserializer); - - protected static void setupCompletionToolDeserializer(ObjectDeserializer op) { - - op.add(Builder::type, JsonpDeserializer.stringDeserializer(), "type"); - op.add(Builder::function, CompletionToolFunction._DESERIALIZER, "function"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolChoice.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolChoice.java deleted file mode 100644 index dbad642e6..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolChoice.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.chat_completion_unified; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.chat_completion_unified.CompletionToolChoice - -/** - * Controls which tool is called by the model. - * - * @see API - * specification - */ -@JsonpDeserializable -public class CompletionToolChoice implements JsonpSerializable { - private final String type; - - private final CompletionToolChoiceFunction function; - - // --------------------------------------------------------------------------------------------- - - private CompletionToolChoice(Builder builder) { - - this.type = ApiTypeHelper.requireNonNull(builder.type, this, "type"); - this.function = ApiTypeHelper.requireNonNull(builder.function, this, "function"); - - } - - public static CompletionToolChoice of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The type of the tool. - *

- * API name: {@code type} - */ - public final String type() { - return this.type; - } - - /** - * Required - The tool choice function. - *

- * API name: {@code function} - */ - public final CompletionToolChoiceFunction function() { - return this.function; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("type"); - generator.write(this.type); - - generator.writeKey("function"); - this.function.serialize(generator, mapper); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link CompletionToolChoice}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String type; - - private CompletionToolChoiceFunction function; - - /** - * Required - The type of the tool. - *

- * API name: {@code type} - */ - public final Builder type(String value) { - this.type = value; - return this; - } - - /** - * Required - The tool choice function. - *

- * API name: {@code function} - */ - public final Builder function(CompletionToolChoiceFunction value) { - this.function = value; - return this; - } - - /** - * Required - The tool choice function. - *

- * API name: {@code function} - */ - public final Builder function( - Function> fn) { - return this.function(fn.apply(new CompletionToolChoiceFunction.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link CompletionToolChoice}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public CompletionToolChoice build() { - _checkSingleUse(); - - return new CompletionToolChoice(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link CompletionToolChoice} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, CompletionToolChoice::setupCompletionToolChoiceDeserializer); - - protected static void setupCompletionToolChoiceDeserializer(ObjectDeserializer op) { - - op.add(Builder::type, JsonpDeserializer.stringDeserializer(), "type"); - op.add(Builder::function, CompletionToolChoiceFunction._DESERIALIZER, "function"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolChoiceFunction.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolChoiceFunction.java deleted file mode 100644 index 3678e4a20..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolChoiceFunction.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.chat_completion_unified; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.chat_completion_unified.CompletionToolChoiceFunction - -/** - * The tool choice function. - * - * @see API - * specification - */ -@JsonpDeserializable -public class CompletionToolChoiceFunction implements JsonpSerializable { - private final String name; - - // --------------------------------------------------------------------------------------------- - - private CompletionToolChoiceFunction(Builder builder) { - - this.name = ApiTypeHelper.requireNonNull(builder.name, this, "name"); - - } - - public static CompletionToolChoiceFunction of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The name of the function to call. - *

- * API name: {@code name} - */ - public final String name() { - return this.name; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("name"); - generator.write(this.name); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link CompletionToolChoiceFunction}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String name; - - /** - * Required - The name of the function to call. - *

- * API name: {@code name} - */ - public final Builder name(String value) { - this.name = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link CompletionToolChoiceFunction}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public CompletionToolChoiceFunction build() { - _checkSingleUse(); - - return new CompletionToolChoiceFunction(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link CompletionToolChoiceFunction} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, CompletionToolChoiceFunction::setupCompletionToolChoiceFunctionDeserializer); - - protected static void setupCompletionToolChoiceFunctionDeserializer( - ObjectDeserializer op) { - - op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolFunction.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolFunction.java deleted file mode 100644 index 30ed3b41d..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolFunction.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.chat_completion_unified; - -import co.elastic.clients.json.JsonData; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.chat_completion_unified.CompletionToolFunction - -/** - * The completion tool function definition. - * - * @see API - * specification - */ -@JsonpDeserializable -public class CompletionToolFunction implements JsonpSerializable { - @Nullable - private final String description; - - private final String name; - - @Nullable - private final JsonData parameters; - - @Nullable - private final Boolean strict; - - // --------------------------------------------------------------------------------------------- - - private CompletionToolFunction(Builder builder) { - - this.description = builder.description; - this.name = ApiTypeHelper.requireNonNull(builder.name, this, "name"); - this.parameters = builder.parameters; - this.strict = builder.strict; - - } - - public static CompletionToolFunction of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * A description of what the function does. This is used by the model to choose - * when and how to call the function. - *

- * API name: {@code description} - */ - @Nullable - public final String description() { - return this.description; - } - - /** - * Required - The name of the function. - *

- * API name: {@code name} - */ - public final String name() { - return this.name; - } - - /** - * The parameters the functional accepts. This should be formatted as a JSON - * object. - *

- * API name: {@code parameters} - */ - @Nullable - public final JsonData parameters() { - return this.parameters; - } - - /** - * Whether to enable schema adherence when generating the function call. - *

- * API name: {@code strict} - */ - @Nullable - public final Boolean strict() { - return this.strict; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.description != null) { - generator.writeKey("description"); - generator.write(this.description); - - } - generator.writeKey("name"); - generator.write(this.name); - - if (this.parameters != null) { - generator.writeKey("parameters"); - this.parameters.serialize(generator, mapper); - - } - if (this.strict != null) { - generator.writeKey("strict"); - generator.write(this.strict); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link CompletionToolFunction}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private String description; - - private String name; - - @Nullable - private JsonData parameters; - - @Nullable - private Boolean strict; - - /** - * A description of what the function does. This is used by the model to choose - * when and how to call the function. - *

- * API name: {@code description} - */ - public final Builder description(@Nullable String value) { - this.description = value; - return this; - } - - /** - * Required - The name of the function. - *

- * API name: {@code name} - */ - public final Builder name(String value) { - this.name = value; - return this; - } - - /** - * The parameters the functional accepts. This should be formatted as a JSON - * object. - *

- * API name: {@code parameters} - */ - public final Builder parameters(@Nullable JsonData value) { - this.parameters = value; - return this; - } - - /** - * Whether to enable schema adherence when generating the function call. - *

- * API name: {@code strict} - */ - public final Builder strict(@Nullable Boolean value) { - this.strict = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link CompletionToolFunction}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public CompletionToolFunction build() { - _checkSingleUse(); - - return new CompletionToolFunction(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link CompletionToolFunction} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, CompletionToolFunction::setupCompletionToolFunctionDeserializer); - - protected static void setupCompletionToolFunctionDeserializer( - ObjectDeserializer op) { - - op.add(Builder::description, JsonpDeserializer.stringDeserializer(), "description"); - op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); - op.add(Builder::parameters, JsonData._DESERIALIZER, "parameters"); - op.add(Builder::strict, JsonpDeserializer.booleanDeserializer(), "strict"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolType.java deleted file mode 100644 index 08db50b98..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolType.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.chat_completion_unified; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.json.UnionDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.ObjectBuilderBase; -import co.elastic.clients.util.TaggedUnion; -import co.elastic.clients.util.TaggedUnionUtils; -import jakarta.json.stream.JsonGenerator; -import java.lang.Object; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.chat_completion_unified.CompletionToolType - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class CompletionToolType implements TaggedUnion, JsonpSerializable { - - public enum Kind { - Object, String - - } - - private final Kind _kind; - private final Object _value; - - @Override - public final Kind _kind() { - return _kind; - } - - @Override - public final Object _get() { - return _value; - } - - private CompletionToolType(Kind kind, Object value) { - this._kind = kind; - this._value = value; - } - - private CompletionToolType(Builder builder) { - - this._kind = ApiTypeHelper.requireNonNull(builder._kind, builder, ""); - this._value = ApiTypeHelper.requireNonNull(builder._value, builder, ""); - - } - - public static CompletionToolType of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Is this variant instance of kind {@code object}? - */ - public boolean isObject() { - return _kind == Kind.Object; - } - - /** - * Get the {@code object} variant value. - * - * @throws IllegalStateException - * if the current variant is not of the {@code object} kind. - */ - public CompletionToolChoice object() { - return TaggedUnionUtils.get(this, Kind.Object); - } - - /** - * Is this variant instance of kind {@code string}? - */ - public boolean isString() { - return _kind == Kind.String; - } - - /** - * Get the {@code string} variant value. - * - * @throws IllegalStateException - * if the current variant is not of the {@code string} kind. - */ - public String string() { - return TaggedUnionUtils.get(this, Kind.String); - } - - @Override - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - if (_value instanceof JsonpSerializable) { - ((JsonpSerializable) _value).serialize(generator, mapper); - } else { - switch (_kind) { - case String : - generator.write(((String) this._value)); - - break; - } - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - public static class Builder extends ObjectBuilderBase implements ObjectBuilder { - private Kind _kind; - private Object _value; - - public ObjectBuilder object(CompletionToolChoice v) { - this._kind = Kind.Object; - this._value = v; - return this; - } - - public ObjectBuilder object( - Function> fn) { - return this.object(fn.apply(new CompletionToolChoice.Builder()).build()); - } - - public ObjectBuilder string(String v) { - this._kind = Kind.String; - this._value = v; - return this; - } - - public CompletionToolType build() { - _checkSingleUse(); - return new CompletionToolType(this); - } - - } - - private static JsonpDeserializer buildCompletionToolTypeDeserializer() { - return new UnionDeserializer.Builder(CompletionToolType::new, false) - .addMember(Kind.Object, CompletionToolChoice._DESERIALIZER) - .addMember(Kind.String, JsonpDeserializer.stringDeserializer()).build(); - } - - public static final JsonpDeserializer _DESERIALIZER = JsonpDeserializer - .lazy(CompletionToolType::buildCompletionToolTypeDeserializer); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolTypeBuilders.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolTypeBuilders.java deleted file mode 100644 index 6cb75d6af..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/CompletionToolTypeBuilders.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.chat_completion_unified; - -import co.elastic.clients.util.ObjectBuilder; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * Builders for {@link CompletionToolType} variants. - *

- * Variants string are not available here as they don't have a - * dedicated class. Use {@link CompletionToolType}'s builder for these. - * - */ -public class CompletionToolTypeBuilders { - private CompletionToolTypeBuilders() { - } - - /** - * Creates a builder for the {@link CompletionToolChoice object} - * {@code CompletionToolType} variant. - */ - public static CompletionToolChoice.Builder object() { - return new CompletionToolChoice.Builder(); - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ContentObject.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ContentObject.java deleted file mode 100644 index c834649ee..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ContentObject.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.chat_completion_unified; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.chat_completion_unified.ContentObject - -/** - * An object style representation of a single portion of a conversation. - * - * @see API - * specification - */ -@JsonpDeserializable -public class ContentObject implements JsonpSerializable { - private final String text; - - private final String type; - - // --------------------------------------------------------------------------------------------- - - private ContentObject(Builder builder) { - - this.text = ApiTypeHelper.requireNonNull(builder.text, this, "text"); - this.type = ApiTypeHelper.requireNonNull(builder.type, this, "type"); - - } - - public static ContentObject of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The text content. - *

- * API name: {@code text} - */ - public final String text() { - return this.text; - } - - /** - * Required - The type of content. - *

- * API name: {@code type} - */ - public final String type() { - return this.type; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("text"); - generator.write(this.text); - - generator.writeKey("type"); - generator.write(this.type); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link ContentObject}. - */ - - public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { - private String text; - - private String type; - - /** - * Required - The text content. - *

- * API name: {@code text} - */ - public final Builder text(String value) { - this.text = value; - return this; - } - - /** - * Required - The type of content. - *

- * API name: {@code type} - */ - public final Builder type(String value) { - this.type = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link ContentObject}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public ContentObject build() { - _checkSingleUse(); - - return new ContentObject(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link ContentObject} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, - ContentObject::setupContentObjectDeserializer); - - protected static void setupContentObjectDeserializer(ObjectDeserializer op) { - - op.add(Builder::text, JsonpDeserializer.stringDeserializer(), "text"); - op.add(Builder::type, JsonpDeserializer.stringDeserializer(), "type"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/Message.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/Message.java deleted file mode 100644 index dcde249d1..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/Message.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.chat_completion_unified; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.chat_completion_unified.Message - -/** - * An object representing part of the conversation. - * - * @see API - * specification - */ -@JsonpDeserializable -public class Message implements JsonpSerializable { - @Nullable - private final MessageContent content; - - private final String role; - - @Nullable - private final String toolCallId; - - private final List toolCalls; - - // --------------------------------------------------------------------------------------------- - - private Message(Builder builder) { - - this.content = builder.content; - this.role = ApiTypeHelper.requireNonNull(builder.role, this, "role"); - this.toolCallId = builder.toolCallId; - this.toolCalls = ApiTypeHelper.unmodifiable(builder.toolCalls); - - } - - public static Message of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * The content of the message. - *

- * API name: {@code content} - */ - @Nullable - public final MessageContent content() { - return this.content; - } - - /** - * Required - The role of the message author. - *

- * API name: {@code role} - */ - public final String role() { - return this.role; - } - - /** - * The tool call that this message is responding to. - *

- * API name: {@code tool_call_id} - */ - @Nullable - public final String toolCallId() { - return this.toolCallId; - } - - /** - * The tool calls generated by the model. - *

- * API name: {@code tool_calls} - */ - public final List toolCalls() { - return this.toolCalls; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.content != null) { - generator.writeKey("content"); - this.content.serialize(generator, mapper); - - } - generator.writeKey("role"); - generator.write(this.role); - - if (this.toolCallId != null) { - generator.writeKey("tool_call_id"); - generator.write(this.toolCallId); - - } - if (ApiTypeHelper.isDefined(this.toolCalls)) { - generator.writeKey("tool_calls"); - generator.writeStartArray(); - for (ToolCall item0 : this.toolCalls) { - item0.serialize(generator, mapper); - - } - generator.writeEnd(); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link Message}. - */ - - public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { - @Nullable - private MessageContent content; - - private String role; - - @Nullable - private String toolCallId; - - @Nullable - private List toolCalls; - - /** - * The content of the message. - *

- * API name: {@code content} - */ - public final Builder content(@Nullable MessageContent value) { - this.content = value; - return this; - } - - /** - * The content of the message. - *

- * API name: {@code content} - */ - public final Builder content(Function> fn) { - return this.content(fn.apply(new MessageContent.Builder()).build()); - } - - /** - * Required - The role of the message author. - *

- * API name: {@code role} - */ - public final Builder role(String value) { - this.role = value; - return this; - } - - /** - * The tool call that this message is responding to. - *

- * API name: {@code tool_call_id} - */ - public final Builder toolCallId(@Nullable String value) { - this.toolCallId = value; - return this; - } - - /** - * The tool calls generated by the model. - *

- * API name: {@code tool_calls} - *

- * Adds all elements of list to toolCalls. - */ - public final Builder toolCalls(List list) { - this.toolCalls = _listAddAll(this.toolCalls, list); - return this; - } - - /** - * The tool calls generated by the model. - *

- * API name: {@code tool_calls} - *

- * Adds one or more values to toolCalls. - */ - public final Builder toolCalls(ToolCall value, ToolCall... values) { - this.toolCalls = _listAdd(this.toolCalls, value, values); - return this; - } - - /** - * The tool calls generated by the model. - *

- * API name: {@code tool_calls} - *

- * Adds a value to toolCalls using a builder lambda. - */ - public final Builder toolCalls(Function> fn) { - return toolCalls(fn.apply(new ToolCall.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link Message}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public Message build() { - _checkSingleUse(); - - return new Message(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link Message} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, - Message::setupMessageDeserializer); - - protected static void setupMessageDeserializer(ObjectDeserializer op) { - - op.add(Builder::content, MessageContent._DESERIALIZER, "content"); - op.add(Builder::role, JsonpDeserializer.stringDeserializer(), "role"); - op.add(Builder::toolCallId, JsonpDeserializer.stringDeserializer(), "tool_call_id"); - op.add(Builder::toolCalls, JsonpDeserializer.arrayDeserializer(ToolCall._DESERIALIZER), "tool_calls"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/MessageContent.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/MessageContent.java deleted file mode 100644 index 893600091..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/MessageContent.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.chat_completion_unified; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.json.UnionDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.ObjectBuilderBase; -import co.elastic.clients.util.TaggedUnion; -import co.elastic.clients.util.TaggedUnionUtils; -import jakarta.json.stream.JsonGenerator; -import java.lang.Object; -import java.lang.String; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.chat_completion_unified.MessageContent - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class MessageContent implements TaggedUnion, JsonpSerializable { - - public enum Kind { - Object, String - - } - - private final Kind _kind; - private final Object _value; - - @Override - public final Kind _kind() { - return _kind; - } - - @Override - public final Object _get() { - return _value; - } - - private MessageContent(Kind kind, Object value) { - this._kind = kind; - this._value = value; - } - - private MessageContent(Builder builder) { - - this._kind = ApiTypeHelper.requireNonNull(builder._kind, builder, ""); - this._value = ApiTypeHelper.requireNonNull(builder._value, builder, ""); - - } - - public static MessageContent of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Is this variant instance of kind {@code object}? - */ - public boolean isObject() { - return _kind == Kind.Object; - } - - /** - * Get the {@code object} variant value. - * - * @throws IllegalStateException - * if the current variant is not of the {@code object} kind. - */ - public List object() { - return TaggedUnionUtils.get(this, Kind.Object); - } - - /** - * Is this variant instance of kind {@code string}? - */ - public boolean isString() { - return _kind == Kind.String; - } - - /** - * Get the {@code string} variant value. - * - * @throws IllegalStateException - * if the current variant is not of the {@code string} kind. - */ - public String string() { - return TaggedUnionUtils.get(this, Kind.String); - } - - @Override - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - if (_value instanceof JsonpSerializable) { - ((JsonpSerializable) _value).serialize(generator, mapper); - } else { - switch (_kind) { - case Object : - generator.writeStartArray(); - for (ContentObject item0 : ((List) this._value)) { - item0.serialize(generator, mapper); - - } - generator.writeEnd(); - - break; - case String : - generator.write(((String) this._value)); - - break; - } - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - public static class Builder extends ObjectBuilderBase implements ObjectBuilder { - private Kind _kind; - private Object _value; - - public ObjectBuilder object(List v) { - this._kind = Kind.Object; - this._value = v; - return this; - } - - public ObjectBuilder string(String v) { - this._kind = Kind.String; - this._value = v; - return this; - } - - public MessageContent build() { - _checkSingleUse(); - return new MessageContent(this); - } - - } - - private static JsonpDeserializer buildMessageContentDeserializer() { - return new UnionDeserializer.Builder(MessageContent::new, false) - .addMember(Kind.Object, JsonpDeserializer.arrayDeserializer(ContentObject._DESERIALIZER)) - .addMember(Kind.String, JsonpDeserializer.stringDeserializer()).build(); - } - - public static final JsonpDeserializer _DESERIALIZER = JsonpDeserializer - .lazy(MessageContent::buildMessageContentDeserializer); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/MessageContentBuilders.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/MessageContentBuilders.java deleted file mode 100644 index 04cb0c5c9..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/MessageContentBuilders.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.chat_completion_unified; - -import co.elastic.clients.util.ObjectBuilder; -import java.util.function.Function; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * Builders for {@link MessageContent} variants. - *

- * Variants object, string are not available here as - * they don't have a dedicated class. Use {@link MessageContent}'s builder for - * these. - * - */ -public class MessageContentBuilders { - private MessageContentBuilders() { - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ToolCall.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ToolCall.java deleted file mode 100644 index c557d9dd9..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ToolCall.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.chat_completion_unified; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.chat_completion_unified.ToolCall - -/** - * A tool call generated by the model. - * - * @see API - * specification - */ -@JsonpDeserializable -public class ToolCall implements JsonpSerializable { - private final String id; - - private final ToolCallFunction function; - - private final String type; - - // --------------------------------------------------------------------------------------------- - - private ToolCall(Builder builder) { - - this.id = ApiTypeHelper.requireNonNull(builder.id, this, "id"); - this.function = ApiTypeHelper.requireNonNull(builder.function, this, "function"); - this.type = ApiTypeHelper.requireNonNull(builder.type, this, "type"); - - } - - public static ToolCall of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The identifier of the tool call. - *

- * API name: {@code id} - */ - public final String id() { - return this.id; - } - - /** - * Required - The function that the model called. - *

- * API name: {@code function} - */ - public final ToolCallFunction function() { - return this.function; - } - - /** - * Required - The type of the tool call. - *

- * API name: {@code type} - */ - public final String type() { - return this.type; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("id"); - generator.write(this.id); - - generator.writeKey("function"); - this.function.serialize(generator, mapper); - - generator.writeKey("type"); - generator.write(this.type); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link ToolCall}. - */ - - public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { - private String id; - - private ToolCallFunction function; - - private String type; - - /** - * Required - The identifier of the tool call. - *

- * API name: {@code id} - */ - public final Builder id(String value) { - this.id = value; - return this; - } - - /** - * Required - The function that the model called. - *

- * API name: {@code function} - */ - public final Builder function(ToolCallFunction value) { - this.function = value; - return this; - } - - /** - * Required - The function that the model called. - *

- * API name: {@code function} - */ - public final Builder function(Function> fn) { - return this.function(fn.apply(new ToolCallFunction.Builder()).build()); - } - - /** - * Required - The type of the tool call. - *

- * API name: {@code type} - */ - public final Builder type(String value) { - this.type = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link ToolCall}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public ToolCall build() { - _checkSingleUse(); - - return new ToolCall(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link ToolCall} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, - ToolCall::setupToolCallDeserializer); - - protected static void setupToolCallDeserializer(ObjectDeserializer op) { - - op.add(Builder::id, JsonpDeserializer.stringDeserializer(), "id"); - op.add(Builder::function, ToolCallFunction._DESERIALIZER, "function"); - op.add(Builder::type, JsonpDeserializer.stringDeserializer(), "type"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ToolCallFunction.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ToolCallFunction.java deleted file mode 100644 index 21cfd5237..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/chat_completion_unified/ToolCallFunction.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.chat_completion_unified; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.chat_completion_unified.ToolCallFunction - -/** - * The function that the model called. - * - * @see API - * specification - */ -@JsonpDeserializable -public class ToolCallFunction implements JsonpSerializable { - private final String arguments; - - private final String name; - - // --------------------------------------------------------------------------------------------- - - private ToolCallFunction(Builder builder) { - - this.arguments = ApiTypeHelper.requireNonNull(builder.arguments, this, "arguments"); - this.name = ApiTypeHelper.requireNonNull(builder.name, this, "name"); - - } - - public static ToolCallFunction of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The arguments to call the function with in JSON format. - *

- * API name: {@code arguments} - */ - public final String arguments() { - return this.arguments; - } - - /** - * Required - The name of the function to call. - *

- * API name: {@code name} - */ - public final String name() { - return this.name; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("arguments"); - generator.write(this.arguments); - - generator.writeKey("name"); - generator.write(this.name); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link ToolCallFunction}. - */ - - public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { - private String arguments; - - private String name; - - /** - * Required - The arguments to call the function with in JSON format. - *

- * API name: {@code arguments} - */ - public final Builder arguments(String value) { - this.arguments = value; - return this; - } - - /** - * Required - The name of the function to call. - *

- * API name: {@code name} - */ - public final Builder name(String value) { - this.name = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link ToolCallFunction}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public ToolCallFunction build() { - _checkSingleUse(); - - return new ToolCallFunction(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link ToolCallFunction} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, - ToolCallFunction::setupToolCallFunctionDeserializer); - - protected static void setupToolCallFunctionDeserializer(ObjectDeserializer op) { - - op.add(Builder::arguments, JsonpDeserializer.stringDeserializer(), "arguments"); - op.add(Builder::name, JsonpDeserializer.stringDeserializer(), "name"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudServiceSettings.java deleted file mode 100644 index 55d8c7ef9..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudServiceSettings.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_alibabacloud; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_alibabacloud.AlibabaCloudServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AlibabaCloudServiceSettings implements JsonpSerializable { - private final String apiKey; - - private final String host; - - @Nullable - private final RateLimitSetting rateLimit; - - private final String serviceId; - - private final String workspace; - - // --------------------------------------------------------------------------------------------- - - private AlibabaCloudServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.host = ApiTypeHelper.requireNonNull(builder.host, this, "host"); - this.rateLimit = builder.rateLimit; - this.serviceId = ApiTypeHelper.requireNonNull(builder.serviceId, this, "serviceId"); - this.workspace = ApiTypeHelper.requireNonNull(builder.workspace, this, "workspace"); - - } - - public static AlibabaCloudServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid API key for the AlibabaCloud AI Search API. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * Required - The name of the host address used for the inference task. You can - * find the host address in the API keys section of the documentation. - *

- * API name: {@code host} - */ - public final String host() { - return this.host; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * AlibabaCloud AI Search. By default, the alibabacloud-ai-search - * service sets the number of requests allowed per minute to 1000. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Required - The name of the model service to use for the inference task. The - * following service IDs are available for the completion task: - *

    - *
  • ops-qwen-turbo
  • - *
  • qwen-turbo
  • - *
  • qwen-plus
  • - *
  • qwen-max ÷ qwen-max-longcontext
  • - *
- *

- * The following service ID is available for the rerank task: - *

    - *
  • ops-bge-reranker-larger
  • - *
- *

- * The following service ID is available for the sparse_embedding - * task: - *

    - *
  • ops-text-sparse-embedding-001
  • - *
- *

- * The following service IDs are available for the text_embedding - * task: - *

- * ops-text-embedding-001 ops-text-embedding-zh-001 - * ops-text-embedding-en-001 ops-text-embedding-002 - *

- * API name: {@code service_id} - */ - public final String serviceId() { - return this.serviceId; - } - - /** - * Required - The name of the workspace used for the inference task. - *

- * API name: {@code workspace} - */ - public final String workspace() { - return this.workspace; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - generator.writeKey("host"); - generator.write(this.host); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - generator.writeKey("service_id"); - generator.write(this.serviceId); - - generator.writeKey("workspace"); - generator.write(this.workspace); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AlibabaCloudServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - private String host; - - @Nullable - private RateLimitSetting rateLimit; - - private String serviceId; - - private String workspace; - - /** - * Required - A valid API key for the AlibabaCloud AI Search API. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * Required - The name of the host address used for the inference task. You can - * find the host address in the API keys section of the documentation. - *

- * API name: {@code host} - */ - public final Builder host(String value) { - this.host = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * AlibabaCloud AI Search. By default, the alibabacloud-ai-search - * service sets the number of requests allowed per minute to 1000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * AlibabaCloud AI Search. By default, the alibabacloud-ai-search - * service sets the number of requests allowed per minute to 1000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * Required - The name of the model service to use for the inference task. The - * following service IDs are available for the completion task: - *

    - *
  • ops-qwen-turbo
  • - *
  • qwen-turbo
  • - *
  • qwen-plus
  • - *
  • qwen-max ÷ qwen-max-longcontext
  • - *
- *

- * The following service ID is available for the rerank task: - *

    - *
  • ops-bge-reranker-larger
  • - *
- *

- * The following service ID is available for the sparse_embedding - * task: - *

    - *
  • ops-text-sparse-embedding-001
  • - *
- *

- * The following service IDs are available for the text_embedding - * task: - *

- * ops-text-embedding-001 ops-text-embedding-zh-001 - * ops-text-embedding-en-001 ops-text-embedding-002 - *

- * API name: {@code service_id} - */ - public final Builder serviceId(String value) { - this.serviceId = value; - return this; - } - - /** - * Required - The name of the workspace used for the inference task. - *

- * API name: {@code workspace} - */ - public final Builder workspace(String value) { - this.workspace = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AlibabaCloudServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AlibabaCloudServiceSettings build() { - _checkSingleUse(); - - return new AlibabaCloudServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AlibabaCloudServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AlibabaCloudServiceSettings::setupAlibabaCloudServiceSettingsDeserializer); - - protected static void setupAlibabaCloudServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::host, JsonpDeserializer.stringDeserializer(), "host"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::serviceId, JsonpDeserializer.stringDeserializer(), "service_id"); - op.add(Builder::workspace, JsonpDeserializer.stringDeserializer(), "workspace"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskSettings.java deleted file mode 100644 index 288d3e0d1..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskSettings.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_alibabacloud; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_alibabacloud.AlibabaCloudTaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AlibabaCloudTaskSettings implements JsonpSerializable { - @Nullable - private final String inputType; - - @Nullable - private final Boolean returnToken; - - // --------------------------------------------------------------------------------------------- - - private AlibabaCloudTaskSettings(Builder builder) { - - this.inputType = builder.inputType; - this.returnToken = builder.returnToken; - - } - - public static AlibabaCloudTaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * For a sparse_embedding or text_embedding task, - * specify the type of input passed to the model. Valid values are: - *

    - *
  • ingest for storing document embeddings in a vector - * database.
  • - *
  • search for storing embeddings of search queries run against - * a vector database to find relevant documents.
  • - *
- *

- * API name: {@code input_type} - */ - @Nullable - public final String inputType() { - return this.inputType; - } - - /** - * For a sparse_embedding task, it affects whether the token name - * will be returned in the response. It defaults to false, which - * means only the token ID will be returned in the response. - *

- * API name: {@code return_token} - */ - @Nullable - public final Boolean returnToken() { - return this.returnToken; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.inputType != null) { - generator.writeKey("input_type"); - generator.write(this.inputType); - - } - if (this.returnToken != null) { - generator.writeKey("return_token"); - generator.write(this.returnToken); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AlibabaCloudTaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private String inputType; - - @Nullable - private Boolean returnToken; - - /** - * For a sparse_embedding or text_embedding task, - * specify the type of input passed to the model. Valid values are: - *

    - *
  • ingest for storing document embeddings in a vector - * database.
  • - *
  • search for storing embeddings of search queries run against - * a vector database to find relevant documents.
  • - *
- *

- * API name: {@code input_type} - */ - public final Builder inputType(@Nullable String value) { - this.inputType = value; - return this; - } - - /** - * For a sparse_embedding task, it affects whether the token name - * will be returned in the response. It defaults to false, which - * means only the token ID will be returned in the response. - *

- * API name: {@code return_token} - */ - public final Builder returnToken(@Nullable Boolean value) { - this.returnToken = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AlibabaCloudTaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AlibabaCloudTaskSettings build() { - _checkSingleUse(); - - return new AlibabaCloudTaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AlibabaCloudTaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AlibabaCloudTaskSettings::setupAlibabaCloudTaskSettingsDeserializer); - - protected static void setupAlibabaCloudTaskSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::inputType, JsonpDeserializer.stringDeserializer(), "input_type"); - op.add(Builder::returnToken, JsonpDeserializer.booleanDeserializer(), "return_token"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskType.java deleted file mode 100644 index 8adf946a1..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/AlibabaCloudTaskType.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_alibabacloud; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum AlibabaCloudTaskType implements JsonEnum { - Completion("completion"), - - Rerank("rerank"), - - SpaceEmbedding("space_embedding"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - AlibabaCloudTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - AlibabaCloudTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/ServiceType.java deleted file mode 100644 index 010f0bfdf..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_alibabacloud/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_alibabacloud; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - AlibabacloudAiSearch("alibabacloud-ai-search"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockServiceSettings.java deleted file mode 100644 index 06417819f..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockServiceSettings.java +++ /dev/null @@ -1,371 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_amazonbedrock; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_amazonbedrock.AmazonBedrockServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AmazonBedrockServiceSettings implements JsonpSerializable { - private final String accessKey; - - private final String model; - - @Nullable - private final String provider; - - private final String region; - - @Nullable - private final RateLimitSetting rateLimit; - - private final String secretKey; - - // --------------------------------------------------------------------------------------------- - - private AmazonBedrockServiceSettings(Builder builder) { - - this.accessKey = ApiTypeHelper.requireNonNull(builder.accessKey, this, "accessKey"); - this.model = ApiTypeHelper.requireNonNull(builder.model, this, "model"); - this.provider = builder.provider; - this.region = ApiTypeHelper.requireNonNull(builder.region, this, "region"); - this.rateLimit = builder.rateLimit; - this.secretKey = ApiTypeHelper.requireNonNull(builder.secretKey, this, "secretKey"); - - } - - public static AmazonBedrockServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid AWS access key that has permissions to use Amazon Bedrock - * and access to models for inference requests. - *

- * API name: {@code access_key} - */ - public final String accessKey() { - return this.accessKey; - } - - /** - * Required - The base model ID or an ARN to a custom model based on a - * foundational model. The base model IDs can be found in the Amazon Bedrock - * documentation. Note that the model ID must be available for the provider - * chosen and your IAM user must have access to the model. - *

- * API name: {@code model} - */ - public final String model() { - return this.model; - } - - /** - * The model provider for your deployment. Note that some providers may support - * only certain task types. Supported providers include: - *

    - *
  • amazontitan - available for text_embedding and - * completion task types
  • - *
  • anthropic - available for completion task type - * only
  • - *
  • ai21labs - available for completion task type - * only
  • - *
  • cohere - available for text_embedding and - * completion task types
  • - *
  • meta - available for completion task type - * only
  • - *
  • mistral - available for completion task type - * only
  • - *
- *

- * API name: {@code provider} - */ - @Nullable - public final String provider() { - return this.provider; - } - - /** - * Required - The region that your model or ARN is deployed in. The list of - * available regions per model can be found in the Amazon Bedrock documentation. - *

- * API name: {@code region} - */ - public final String region() { - return this.region; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Watsonx. By default, the watsonxai service sets the number of - * requests allowed per minute to 120. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Required - A valid AWS secret key that is paired with the - * access_key. For informationg about creating and managing access - * and secret keys, refer to the AWS documentation. - *

- * API name: {@code secret_key} - */ - public final String secretKey() { - return this.secretKey; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("access_key"); - generator.write(this.accessKey); - - generator.writeKey("model"); - generator.write(this.model); - - if (this.provider != null) { - generator.writeKey("provider"); - generator.write(this.provider); - - } - generator.writeKey("region"); - generator.write(this.region); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - generator.writeKey("secret_key"); - generator.write(this.secretKey); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AmazonBedrockServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String accessKey; - - private String model; - - @Nullable - private String provider; - - private String region; - - @Nullable - private RateLimitSetting rateLimit; - - private String secretKey; - - /** - * Required - A valid AWS access key that has permissions to use Amazon Bedrock - * and access to models for inference requests. - *

- * API name: {@code access_key} - */ - public final Builder accessKey(String value) { - this.accessKey = value; - return this; - } - - /** - * Required - The base model ID or an ARN to a custom model based on a - * foundational model. The base model IDs can be found in the Amazon Bedrock - * documentation. Note that the model ID must be available for the provider - * chosen and your IAM user must have access to the model. - *

- * API name: {@code model} - */ - public final Builder model(String value) { - this.model = value; - return this; - } - - /** - * The model provider for your deployment. Note that some providers may support - * only certain task types. Supported providers include: - *

    - *
  • amazontitan - available for text_embedding and - * completion task types
  • - *
  • anthropic - available for completion task type - * only
  • - *
  • ai21labs - available for completion task type - * only
  • - *
  • cohere - available for text_embedding and - * completion task types
  • - *
  • meta - available for completion task type - * only
  • - *
  • mistral - available for completion task type - * only
  • - *
- *

- * API name: {@code provider} - */ - public final Builder provider(@Nullable String value) { - this.provider = value; - return this; - } - - /** - * Required - The region that your model or ARN is deployed in. The list of - * available regions per model can be found in the Amazon Bedrock documentation. - *

- * API name: {@code region} - */ - public final Builder region(String value) { - this.region = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Watsonx. By default, the watsonxai service sets the number of - * requests allowed per minute to 120. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Watsonx. By default, the watsonxai service sets the number of - * requests allowed per minute to 120. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * Required - A valid AWS secret key that is paired with the - * access_key. For informationg about creating and managing access - * and secret keys, refer to the AWS documentation. - *

- * API name: {@code secret_key} - */ - public final Builder secretKey(String value) { - this.secretKey = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AmazonBedrockServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AmazonBedrockServiceSettings build() { - _checkSingleUse(); - - return new AmazonBedrockServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AmazonBedrockServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AmazonBedrockServiceSettings::setupAmazonBedrockServiceSettingsDeserializer); - - protected static void setupAmazonBedrockServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::accessKey, JsonpDeserializer.stringDeserializer(), "access_key"); - op.add(Builder::model, JsonpDeserializer.stringDeserializer(), "model"); - op.add(Builder::provider, JsonpDeserializer.stringDeserializer(), "provider"); - op.add(Builder::region, JsonpDeserializer.stringDeserializer(), "region"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::secretKey, JsonpDeserializer.stringDeserializer(), "secret_key"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskSettings.java deleted file mode 100644 index 3ada2fc38..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskSettings.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_amazonbedrock; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Float; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_amazonbedrock.AmazonBedrockTaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AmazonBedrockTaskSettings implements JsonpSerializable { - @Nullable - private final Integer maxNewTokens; - - @Nullable - private final Float temperature; - - @Nullable - private final Float topK; - - @Nullable - private final Float topP; - - // --------------------------------------------------------------------------------------------- - - private AmazonBedrockTaskSettings(Builder builder) { - - this.maxNewTokens = builder.maxNewTokens; - this.temperature = builder.temperature; - this.topK = builder.topK; - this.topP = builder.topP; - - } - - public static AmazonBedrockTaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * For a completion task, it sets the maximum number for the output - * tokens to be generated. - *

- * API name: {@code max_new_tokens} - */ - @Nullable - public final Integer maxNewTokens() { - return this.maxNewTokens; - } - - /** - * For a completion task, it is a number between 0.0 and 1.0 that - * controls the apparent creativity of the results. At temperature 0.0 the model - * is most deterministic, at temperature 1.0 most random. It should not be used - * if top_p or top_k is specified. - *

- * API name: {@code temperature} - */ - @Nullable - public final Float temperature() { - return this.temperature; - } - - /** - * For a completion task, it limits samples to the top-K most - * likely words, balancing coherence and variability. It is only available for - * anthropic, cohere, and mistral providers. It is an alternative to - * temperature; it should not be used if temperature - * is specified. - *

- * API name: {@code top_k} - */ - @Nullable - public final Float topK() { - return this.topK; - } - - /** - * For a completion task, it is a number in the range of 0.0 to - * 1.0, to eliminate low-probability tokens. Top-p uses nucleus sampling to - * select top tokens whose sum of likelihoods does not exceed a certain value, - * ensuring both variety and coherence. It is an alternative to - * temperature; it should not be used if temperature - * is specified. - *

- * API name: {@code top_p} - */ - @Nullable - public final Float topP() { - return this.topP; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.maxNewTokens != null) { - generator.writeKey("max_new_tokens"); - generator.write(this.maxNewTokens); - - } - if (this.temperature != null) { - generator.writeKey("temperature"); - generator.write(this.temperature); - - } - if (this.topK != null) { - generator.writeKey("top_k"); - generator.write(this.topK); - - } - if (this.topP != null) { - generator.writeKey("top_p"); - generator.write(this.topP); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AmazonBedrockTaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private Integer maxNewTokens; - - @Nullable - private Float temperature; - - @Nullable - private Float topK; - - @Nullable - private Float topP; - - /** - * For a completion task, it sets the maximum number for the output - * tokens to be generated. - *

- * API name: {@code max_new_tokens} - */ - public final Builder maxNewTokens(@Nullable Integer value) { - this.maxNewTokens = value; - return this; - } - - /** - * For a completion task, it is a number between 0.0 and 1.0 that - * controls the apparent creativity of the results. At temperature 0.0 the model - * is most deterministic, at temperature 1.0 most random. It should not be used - * if top_p or top_k is specified. - *

- * API name: {@code temperature} - */ - public final Builder temperature(@Nullable Float value) { - this.temperature = value; - return this; - } - - /** - * For a completion task, it limits samples to the top-K most - * likely words, balancing coherence and variability. It is only available for - * anthropic, cohere, and mistral providers. It is an alternative to - * temperature; it should not be used if temperature - * is specified. - *

- * API name: {@code top_k} - */ - public final Builder topK(@Nullable Float value) { - this.topK = value; - return this; - } - - /** - * For a completion task, it is a number in the range of 0.0 to - * 1.0, to eliminate low-probability tokens. Top-p uses nucleus sampling to - * select top tokens whose sum of likelihoods does not exceed a certain value, - * ensuring both variety and coherence. It is an alternative to - * temperature; it should not be used if temperature - * is specified. - *

- * API name: {@code top_p} - */ - public final Builder topP(@Nullable Float value) { - this.topP = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AmazonBedrockTaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AmazonBedrockTaskSettings build() { - _checkSingleUse(); - - return new AmazonBedrockTaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AmazonBedrockTaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AmazonBedrockTaskSettings::setupAmazonBedrockTaskSettingsDeserializer); - - protected static void setupAmazonBedrockTaskSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::maxNewTokens, JsonpDeserializer.integerDeserializer(), "max_new_tokens"); - op.add(Builder::temperature, JsonpDeserializer.floatDeserializer(), "temperature"); - op.add(Builder::topK, JsonpDeserializer.floatDeserializer(), "top_k"); - op.add(Builder::topP, JsonpDeserializer.floatDeserializer(), "top_p"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskType.java deleted file mode 100644 index 67d56cc4f..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/AmazonBedrockTaskType.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_amazonbedrock; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum AmazonBedrockTaskType implements JsonEnum { - Completion("completion"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - AmazonBedrockTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - AmazonBedrockTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/ServiceType.java deleted file mode 100644 index 417d4e7c7..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_amazonbedrock/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_amazonbedrock; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Amazonbedrock("amazonbedrock"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicServiceSettings.java deleted file mode 100644 index fd1133481..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicServiceSettings.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_anthropic; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_anthropic.AnthropicServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AnthropicServiceSettings implements JsonpSerializable { - private final String apiKey; - - private final String modelId; - - @Nullable - private final RateLimitSetting rateLimit; - - // --------------------------------------------------------------------------------------------- - - private AnthropicServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); - this.rateLimit = builder.rateLimit; - - } - - public static AnthropicServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid API key for the Anthropic API. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * Anthropic documentation for the list of supported models. - *

- * API name: {@code model_id} - */ - public final String modelId() { - return this.modelId; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Anthropic. By default, the anthropic service sets the number of - * requests allowed per minute to 50. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - generator.writeKey("model_id"); - generator.write(this.modelId); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AnthropicServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - private String modelId; - - @Nullable - private RateLimitSetting rateLimit; - - /** - * Required - A valid API key for the Anthropic API. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * Anthropic documentation for the list of supported models. - *

- * API name: {@code model_id} - */ - public final Builder modelId(String value) { - this.modelId = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Anthropic. By default, the anthropic service sets the number of - * requests allowed per minute to 50. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Anthropic. By default, the anthropic service sets the number of - * requests allowed per minute to 50. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AnthropicServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AnthropicServiceSettings build() { - _checkSingleUse(); - - return new AnthropicServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AnthropicServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AnthropicServiceSettings::setupAnthropicServiceSettingsDeserializer); - - protected static void setupAnthropicServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskSettings.java deleted file mode 100644 index cababb804..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskSettings.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_anthropic; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Float; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_anthropic.AnthropicTaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AnthropicTaskSettings implements JsonpSerializable { - private final int maxTokens; - - @Nullable - private final Float temperature; - - @Nullable - private final Integer topK; - - @Nullable - private final Float topP; - - // --------------------------------------------------------------------------------------------- - - private AnthropicTaskSettings(Builder builder) { - - this.maxTokens = ApiTypeHelper.requireNonNull(builder.maxTokens, this, "maxTokens"); - this.temperature = builder.temperature; - this.topK = builder.topK; - this.topP = builder.topP; - - } - - public static AnthropicTaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - For a completion task, it is the maximum number of - * tokens to generate before stopping. - *

- * API name: {@code max_tokens} - */ - public final int maxTokens() { - return this.maxTokens; - } - - /** - * For a completion task, it is the amount of randomness injected - * into the response. For more details about the supported range, refer to - * Anthropic documentation. - *

- * API name: {@code temperature} - */ - @Nullable - public final Float temperature() { - return this.temperature; - } - - /** - * For a completion task, it specifies to only sample from the top - * K options for each subsequent token. It is recommended for advanced use cases - * only. You usually only need to use temperature. - *

- * API name: {@code top_k} - */ - @Nullable - public final Integer topK() { - return this.topK; - } - - /** - * For a completion task, it specifies to use Anthropic's nucleus - * sampling. In nucleus sampling, Anthropic computes the cumulative distribution - * over all the options for each subsequent token in decreasing probability - * order and cuts it off once it reaches the specified probability. You should - * either alter temperature or top_p, but not both. It - * is recommended for advanced use cases only. You usually only need to use - * temperature. - *

- * API name: {@code top_p} - */ - @Nullable - public final Float topP() { - return this.topP; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("max_tokens"); - generator.write(this.maxTokens); - - if (this.temperature != null) { - generator.writeKey("temperature"); - generator.write(this.temperature); - - } - if (this.topK != null) { - generator.writeKey("top_k"); - generator.write(this.topK); - - } - if (this.topP != null) { - generator.writeKey("top_p"); - generator.write(this.topP); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AnthropicTaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private Integer maxTokens; - - @Nullable - private Float temperature; - - @Nullable - private Integer topK; - - @Nullable - private Float topP; - - /** - * Required - For a completion task, it is the maximum number of - * tokens to generate before stopping. - *

- * API name: {@code max_tokens} - */ - public final Builder maxTokens(int value) { - this.maxTokens = value; - return this; - } - - /** - * For a completion task, it is the amount of randomness injected - * into the response. For more details about the supported range, refer to - * Anthropic documentation. - *

- * API name: {@code temperature} - */ - public final Builder temperature(@Nullable Float value) { - this.temperature = value; - return this; - } - - /** - * For a completion task, it specifies to only sample from the top - * K options for each subsequent token. It is recommended for advanced use cases - * only. You usually only need to use temperature. - *

- * API name: {@code top_k} - */ - public final Builder topK(@Nullable Integer value) { - this.topK = value; - return this; - } - - /** - * For a completion task, it specifies to use Anthropic's nucleus - * sampling. In nucleus sampling, Anthropic computes the cumulative distribution - * over all the options for each subsequent token in decreasing probability - * order and cuts it off once it reaches the specified probability. You should - * either alter temperature or top_p, but not both. It - * is recommended for advanced use cases only. You usually only need to use - * temperature. - *

- * API name: {@code top_p} - */ - public final Builder topP(@Nullable Float value) { - this.topP = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AnthropicTaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AnthropicTaskSettings build() { - _checkSingleUse(); - - return new AnthropicTaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AnthropicTaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AnthropicTaskSettings::setupAnthropicTaskSettingsDeserializer); - - protected static void setupAnthropicTaskSettingsDeserializer(ObjectDeserializer op) { - - op.add(Builder::maxTokens, JsonpDeserializer.integerDeserializer(), "max_tokens"); - op.add(Builder::temperature, JsonpDeserializer.floatDeserializer(), "temperature"); - op.add(Builder::topK, JsonpDeserializer.integerDeserializer(), "top_k"); - op.add(Builder::topP, JsonpDeserializer.floatDeserializer(), "top_p"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskType.java deleted file mode 100644 index 4599e9d31..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/AnthropicTaskType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_anthropic; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum AnthropicTaskType implements JsonEnum { - Completion("completion"), - - ; - - private final String jsonValue; - - AnthropicTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - AnthropicTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/ServiceType.java deleted file mode 100644 index 2d6288747..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_anthropic/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_anthropic; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Anthropic("anthropic"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioServiceSettings.java deleted file mode 100644 index a407ad66b..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioServiceSettings.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_azureaistudio; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_azureaistudio.AzureAiStudioServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AzureAiStudioServiceSettings implements JsonpSerializable { - private final String apiKey; - - private final String endpointType; - - private final String target; - - private final String provider; - - @Nullable - private final RateLimitSetting rateLimit; - - // --------------------------------------------------------------------------------------------- - - private AzureAiStudioServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.endpointType = ApiTypeHelper.requireNonNull(builder.endpointType, this, "endpointType"); - this.target = ApiTypeHelper.requireNonNull(builder.target, this, "target"); - this.provider = ApiTypeHelper.requireNonNull(builder.provider, this, "provider"); - this.rateLimit = builder.rateLimit; - - } - - public static AzureAiStudioServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid API key of your Azure AI Studio model deployment. This key - * can be found on the overview page for your deployment in the management - * section of your Azure AI Studio account. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * Required - The type of endpoint that is available for deployment through - * Azure AI Studio: token or realtime. The - * token endpoint type is for "pay as you go" endpoints - * that are billed per token. The realtime endpoint type is for - * "real-time" endpoints that are billed per hour of usage. - *

- * API name: {@code endpoint_type} - */ - public final String endpointType() { - return this.endpointType; - } - - /** - * Required - The target URL of your Azure AI Studio model deployment. This can - * be found on the overview page for your deployment in the management section - * of your Azure AI Studio account. - *

- * API name: {@code target} - */ - public final String target() { - return this.target; - } - - /** - * Required - The model provider for your deployment. Note that some providers - * may support only certain task types. Supported providers include: - *

    - *
  • cohere - available for text_embedding and - * completion task types
  • - *
  • databricks - available for completion task type - * only
  • - *
  • meta - available for completion task type - * only
  • - *
  • microsoft_phi - available for completion task - * type only
  • - *
  • mistral - available for completion task type - * only
  • - *
  • openai - available for text_embedding and - * completion task types
  • - *
- *

- * API name: {@code provider} - */ - public final String provider() { - return this.provider; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Azure AI Studio. By default, the azureaistudio service sets the - * number of requests allowed per minute to 240. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - generator.writeKey("endpoint_type"); - generator.write(this.endpointType); - - generator.writeKey("target"); - generator.write(this.target); - - generator.writeKey("provider"); - generator.write(this.provider); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AzureAiStudioServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - private String endpointType; - - private String target; - - private String provider; - - @Nullable - private RateLimitSetting rateLimit; - - /** - * Required - A valid API key of your Azure AI Studio model deployment. This key - * can be found on the overview page for your deployment in the management - * section of your Azure AI Studio account. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * Required - The type of endpoint that is available for deployment through - * Azure AI Studio: token or realtime. The - * token endpoint type is for "pay as you go" endpoints - * that are billed per token. The realtime endpoint type is for - * "real-time" endpoints that are billed per hour of usage. - *

- * API name: {@code endpoint_type} - */ - public final Builder endpointType(String value) { - this.endpointType = value; - return this; - } - - /** - * Required - The target URL of your Azure AI Studio model deployment. This can - * be found on the overview page for your deployment in the management section - * of your Azure AI Studio account. - *

- * API name: {@code target} - */ - public final Builder target(String value) { - this.target = value; - return this; - } - - /** - * Required - The model provider for your deployment. Note that some providers - * may support only certain task types. Supported providers include: - *

    - *
  • cohere - available for text_embedding and - * completion task types
  • - *
  • databricks - available for completion task type - * only
  • - *
  • meta - available for completion task type - * only
  • - *
  • microsoft_phi - available for completion task - * type only
  • - *
  • mistral - available for completion task type - * only
  • - *
  • openai - available for text_embedding and - * completion task types
  • - *
- *

- * API name: {@code provider} - */ - public final Builder provider(String value) { - this.provider = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Azure AI Studio. By default, the azureaistudio service sets the - * number of requests allowed per minute to 240. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Azure AI Studio. By default, the azureaistudio service sets the - * number of requests allowed per minute to 240. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AzureAiStudioServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AzureAiStudioServiceSettings build() { - _checkSingleUse(); - - return new AzureAiStudioServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AzureAiStudioServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AzureAiStudioServiceSettings::setupAzureAiStudioServiceSettingsDeserializer); - - protected static void setupAzureAiStudioServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::endpointType, JsonpDeserializer.stringDeserializer(), "endpoint_type"); - op.add(Builder::target, JsonpDeserializer.stringDeserializer(), "target"); - op.add(Builder::provider, JsonpDeserializer.stringDeserializer(), "provider"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskSettings.java deleted file mode 100644 index df846c062..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskSettings.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_azureaistudio; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Float; -import java.lang.Integer; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_azureaistudio.AzureAiStudioTaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AzureAiStudioTaskSettings implements JsonpSerializable { - @Nullable - private final Float doSample; - - @Nullable - private final Integer maxNewTokens; - - @Nullable - private final Float temperature; - - @Nullable - private final Float topP; - - @Nullable - private final String user; - - // --------------------------------------------------------------------------------------------- - - private AzureAiStudioTaskSettings(Builder builder) { - - this.doSample = builder.doSample; - this.maxNewTokens = builder.maxNewTokens; - this.temperature = builder.temperature; - this.topP = builder.topP; - this.user = builder.user; - - } - - public static AzureAiStudioTaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * For a completion task, instruct the inference process to perform - * sampling. It has no effect unless temperature or - * top_p is specified. - *

- * API name: {@code do_sample} - */ - @Nullable - public final Float doSample() { - return this.doSample; - } - - /** - * For a completion task, provide a hint for the maximum number of - * output tokens to be generated. - *

- * API name: {@code max_new_tokens} - */ - @Nullable - public final Integer maxNewTokens() { - return this.maxNewTokens; - } - - /** - * For a completion task, control the apparent creativity of - * generated completions with a sampling temperature. It must be a number in the - * range of 0.0 to 2.0. It should not be used if top_p is - * specified. - *

- * API name: {@code temperature} - */ - @Nullable - public final Float temperature() { - return this.temperature; - } - - /** - * For a completion task, make the model consider the results of - * the tokens with nucleus sampling probability. It is an alternative value to - * temperature and must be a number in the range of 0.0 to 2.0. It - * should not be used if temperature is specified. - *

- * API name: {@code top_p} - */ - @Nullable - public final Float topP() { - return this.topP; - } - - /** - * For a text_embedding task, specify the user issuing the request. - * This information can be used for abuse detection. - *

- * API name: {@code user} - */ - @Nullable - public final String user() { - return this.user; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.doSample != null) { - generator.writeKey("do_sample"); - generator.write(this.doSample); - - } - if (this.maxNewTokens != null) { - generator.writeKey("max_new_tokens"); - generator.write(this.maxNewTokens); - - } - if (this.temperature != null) { - generator.writeKey("temperature"); - generator.write(this.temperature); - - } - if (this.topP != null) { - generator.writeKey("top_p"); - generator.write(this.topP); - - } - if (this.user != null) { - generator.writeKey("user"); - generator.write(this.user); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AzureAiStudioTaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private Float doSample; - - @Nullable - private Integer maxNewTokens; - - @Nullable - private Float temperature; - - @Nullable - private Float topP; - - @Nullable - private String user; - - /** - * For a completion task, instruct the inference process to perform - * sampling. It has no effect unless temperature or - * top_p is specified. - *

- * API name: {@code do_sample} - */ - public final Builder doSample(@Nullable Float value) { - this.doSample = value; - return this; - } - - /** - * For a completion task, provide a hint for the maximum number of - * output tokens to be generated. - *

- * API name: {@code max_new_tokens} - */ - public final Builder maxNewTokens(@Nullable Integer value) { - this.maxNewTokens = value; - return this; - } - - /** - * For a completion task, control the apparent creativity of - * generated completions with a sampling temperature. It must be a number in the - * range of 0.0 to 2.0. It should not be used if top_p is - * specified. - *

- * API name: {@code temperature} - */ - public final Builder temperature(@Nullable Float value) { - this.temperature = value; - return this; - } - - /** - * For a completion task, make the model consider the results of - * the tokens with nucleus sampling probability. It is an alternative value to - * temperature and must be a number in the range of 0.0 to 2.0. It - * should not be used if temperature is specified. - *

- * API name: {@code top_p} - */ - public final Builder topP(@Nullable Float value) { - this.topP = value; - return this; - } - - /** - * For a text_embedding task, specify the user issuing the request. - * This information can be used for abuse detection. - *

- * API name: {@code user} - */ - public final Builder user(@Nullable String value) { - this.user = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AzureAiStudioTaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AzureAiStudioTaskSettings build() { - _checkSingleUse(); - - return new AzureAiStudioTaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AzureAiStudioTaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AzureAiStudioTaskSettings::setupAzureAiStudioTaskSettingsDeserializer); - - protected static void setupAzureAiStudioTaskSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::doSample, JsonpDeserializer.floatDeserializer(), "do_sample"); - op.add(Builder::maxNewTokens, JsonpDeserializer.integerDeserializer(), "max_new_tokens"); - op.add(Builder::temperature, JsonpDeserializer.floatDeserializer(), "temperature"); - op.add(Builder::topP, JsonpDeserializer.floatDeserializer(), "top_p"); - op.add(Builder::user, JsonpDeserializer.stringDeserializer(), "user"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskType.java deleted file mode 100644 index 7a8b074fe..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/AzureAiStudioTaskType.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_azureaistudio; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum AzureAiStudioTaskType implements JsonEnum { - Completion("completion"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - AzureAiStudioTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - AzureAiStudioTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/ServiceType.java deleted file mode 100644 index 5e3b80f0e..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureaistudio/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_azureaistudio; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Azureaistudio("azureaistudio"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAIServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAIServiceSettings.java deleted file mode 100644 index 849f7bee6..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAIServiceSettings.java +++ /dev/null @@ -1,368 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_azureopenai; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_azureopenai.AzureOpenAIServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AzureOpenAIServiceSettings implements JsonpSerializable { - @Nullable - private final String apiKey; - - private final String apiVersion; - - private final String deploymentId; - - @Nullable - private final String entraId; - - @Nullable - private final RateLimitSetting rateLimit; - - private final String resourceName; - - // --------------------------------------------------------------------------------------------- - - private AzureOpenAIServiceSettings(Builder builder) { - - this.apiKey = builder.apiKey; - this.apiVersion = ApiTypeHelper.requireNonNull(builder.apiVersion, this, "apiVersion"); - this.deploymentId = ApiTypeHelper.requireNonNull(builder.deploymentId, this, "deploymentId"); - this.entraId = builder.entraId; - this.rateLimit = builder.rateLimit; - this.resourceName = ApiTypeHelper.requireNonNull(builder.resourceName, this, "resourceName"); - - } - - public static AzureOpenAIServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * A valid API key for your Azure OpenAI account. You must specify either - * api_key or entra_id. If you do not provide either - * or you provide both, you will receive an error when you try to create your - * model. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - @Nullable - public final String apiKey() { - return this.apiKey; - } - - /** - * Required - The Azure API version ID to use. It is recommended to use the - * latest supported non-preview version. - *

- * API name: {@code api_version} - */ - public final String apiVersion() { - return this.apiVersion; - } - - /** - * Required - The deployment name of your deployed models. Your Azure OpenAI - * deployments can be found though the Azure OpenAI Studio portal that is linked - * to your subscription. - *

- * API name: {@code deployment_id} - */ - public final String deploymentId() { - return this.deploymentId; - } - - /** - * A valid Microsoft Entra token. You must specify either api_key - * or entra_id. If you do not provide either or you provide both, - * you will receive an error when you try to create your model. - *

- * API name: {@code entra_id} - */ - @Nullable - public final String entraId() { - return this.entraId; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Azure. The azureopenai service sets a default number of requests - * allowed per minute depending on the task type. For - * text_embedding, it is set to 1440. For - * completion, it is set to 120. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Required - The name of your Azure OpenAI resource. You can find this from the - * list of resources in the Azure Portal for your subscription. - *

- * API name: {@code resource_name} - */ - public final String resourceName() { - return this.resourceName; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.apiKey != null) { - generator.writeKey("api_key"); - generator.write(this.apiKey); - - } - generator.writeKey("api_version"); - generator.write(this.apiVersion); - - generator.writeKey("deployment_id"); - generator.write(this.deploymentId); - - if (this.entraId != null) { - generator.writeKey("entra_id"); - generator.write(this.entraId); - - } - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - generator.writeKey("resource_name"); - generator.write(this.resourceName); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AzureOpenAIServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private String apiKey; - - private String apiVersion; - - private String deploymentId; - - @Nullable - private String entraId; - - @Nullable - private RateLimitSetting rateLimit; - - private String resourceName; - - /** - * A valid API key for your Azure OpenAI account. You must specify either - * api_key or entra_id. If you do not provide either - * or you provide both, you will receive an error when you try to create your - * model. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(@Nullable String value) { - this.apiKey = value; - return this; - } - - /** - * Required - The Azure API version ID to use. It is recommended to use the - * latest supported non-preview version. - *

- * API name: {@code api_version} - */ - public final Builder apiVersion(String value) { - this.apiVersion = value; - return this; - } - - /** - * Required - The deployment name of your deployed models. Your Azure OpenAI - * deployments can be found though the Azure OpenAI Studio portal that is linked - * to your subscription. - *

- * API name: {@code deployment_id} - */ - public final Builder deploymentId(String value) { - this.deploymentId = value; - return this; - } - - /** - * A valid Microsoft Entra token. You must specify either api_key - * or entra_id. If you do not provide either or you provide both, - * you will receive an error when you try to create your model. - *

- * API name: {@code entra_id} - */ - public final Builder entraId(@Nullable String value) { - this.entraId = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Azure. The azureopenai service sets a default number of requests - * allowed per minute depending on the task type. For - * text_embedding, it is set to 1440. For - * completion, it is set to 120. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Azure. The azureopenai service sets a default number of requests - * allowed per minute depending on the task type. For - * text_embedding, it is set to 1440. For - * completion, it is set to 120. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * Required - The name of your Azure OpenAI resource. You can find this from the - * list of resources in the Azure Portal for your subscription. - *

- * API name: {@code resource_name} - */ - public final Builder resourceName(String value) { - this.resourceName = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AzureOpenAIServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AzureOpenAIServiceSettings build() { - _checkSingleUse(); - - return new AzureOpenAIServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AzureOpenAIServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AzureOpenAIServiceSettings::setupAzureOpenAIServiceSettingsDeserializer); - - protected static void setupAzureOpenAIServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::apiVersion, JsonpDeserializer.stringDeserializer(), "api_version"); - op.add(Builder::deploymentId, JsonpDeserializer.stringDeserializer(), "deployment_id"); - op.add(Builder::entraId, JsonpDeserializer.stringDeserializer(), "entra_id"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::resourceName, JsonpDeserializer.stringDeserializer(), "resource_name"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAITaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAITaskType.java deleted file mode 100644 index 4c6414276..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/AzureOpenAITaskType.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_azureopenai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum AzureOpenAITaskType implements JsonEnum { - Completion("completion"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - AzureOpenAITaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - AzureOpenAITaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/ServiceType.java deleted file mode 100644 index c27837b69..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_azureopenai/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_azureopenai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Azureopenai("azureopenai"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereServiceSettings.java deleted file mode 100644 index 86c1c9e24..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereServiceSettings.java +++ /dev/null @@ -1,363 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_cohere; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_cohere.CohereServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class CohereServiceSettings implements JsonpSerializable { - private final String apiKey; - - @Nullable - private final EmbeddingType embeddingType; - - @Nullable - private final String modelId; - - @Nullable - private final RateLimitSetting rateLimit; - - @Nullable - private final SimilarityType similarity; - - // --------------------------------------------------------------------------------------------- - - private CohereServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.embeddingType = builder.embeddingType; - this.modelId = builder.modelId; - this.rateLimit = builder.rateLimit; - this.similarity = builder.similarity; - - } - - public static CohereServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid API key for your Cohere account. You can find or create - * your Cohere API keys on the Cohere API key settings page. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * For a text_embedding task, the types of embeddings you want to - * get back. Use byte for signed int8 embeddings (this is a synonym - * of int8). Use float for the default float - * embeddings. Use int8 for signed int8 embeddings. - *

- * API name: {@code embedding_type} - */ - @Nullable - public final EmbeddingType embeddingType() { - return this.embeddingType; - } - - /** - * For a completion, rerank, or - * text_embedding task, the name of the model to use for the - * inference task. - *

- *

- * The default value for a text embedding task is - * embed-english-v2.0. - *

- * API name: {@code model_id} - */ - @Nullable - public final String modelId() { - return this.modelId; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Cohere. By default, the cohere service sets the number of - * requests allowed per minute to 10000. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * The similarity measure. If the embedding_type is - * float, the default value is dot_product. If the - * embedding_type is int8 or byte, the - * default value is cosine. - *

- * API name: {@code similarity} - */ - @Nullable - public final SimilarityType similarity() { - return this.similarity; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - if (this.embeddingType != null) { - generator.writeKey("embedding_type"); - this.embeddingType.serialize(generator, mapper); - } - if (this.modelId != null) { - generator.writeKey("model_id"); - generator.write(this.modelId); - - } - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - if (this.similarity != null) { - generator.writeKey("similarity"); - this.similarity.serialize(generator, mapper); - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link CohereServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - @Nullable - private EmbeddingType embeddingType; - - @Nullable - private String modelId; - - @Nullable - private RateLimitSetting rateLimit; - - @Nullable - private SimilarityType similarity; - - /** - * Required - A valid API key for your Cohere account. You can find or create - * your Cohere API keys on the Cohere API key settings page. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * For a text_embedding task, the types of embeddings you want to - * get back. Use byte for signed int8 embeddings (this is a synonym - * of int8). Use float for the default float - * embeddings. Use int8 for signed int8 embeddings. - *

- * API name: {@code embedding_type} - */ - public final Builder embeddingType(@Nullable EmbeddingType value) { - this.embeddingType = value; - return this; - } - - /** - * For a completion, rerank, or - * text_embedding task, the name of the model to use for the - * inference task. - *

- *

- * The default value for a text embedding task is - * embed-english-v2.0. - *

- * API name: {@code model_id} - */ - public final Builder modelId(@Nullable String value) { - this.modelId = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Cohere. By default, the cohere service sets the number of - * requests allowed per minute to 10000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Cohere. By default, the cohere service sets the number of - * requests allowed per minute to 10000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * The similarity measure. If the embedding_type is - * float, the default value is dot_product. If the - * embedding_type is int8 or byte, the - * default value is cosine. - *

- * API name: {@code similarity} - */ - public final Builder similarity(@Nullable SimilarityType value) { - this.similarity = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link CohereServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public CohereServiceSettings build() { - _checkSingleUse(); - - return new CohereServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link CohereServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, CohereServiceSettings::setupCohereServiceSettingsDeserializer); - - protected static void setupCohereServiceSettingsDeserializer(ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::embeddingType, EmbeddingType._DESERIALIZER, "embedding_type"); - op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::similarity, SimilarityType._DESERIALIZER, "similarity"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskSettings.java deleted file mode 100644 index 77947b3ee..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskSettings.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_cohere; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_cohere.CohereTaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class CohereTaskSettings implements JsonpSerializable { - @Nullable - private final InputType inputType; - - @Nullable - private final Boolean returnDocuments; - - @Nullable - private final Integer topN; - - @Nullable - private final TruncateType truncate; - - // --------------------------------------------------------------------------------------------- - - private CohereTaskSettings(Builder builder) { - - this.inputType = builder.inputType; - this.returnDocuments = builder.returnDocuments; - this.topN = builder.topN; - this.truncate = builder.truncate; - - } - - public static CohereTaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * For a text_embedding task, the type of input passed to the - * model. Valid values are: - *

    - *
  • classification: Use it for embeddings passed through a text - * classifier.
  • - *
  • clustering: Use it for the embeddings run through a - * clustering algorithm.
  • - *
  • ingest: Use it for storing document embeddings in a vector - * database.
  • - *
  • search: Use it for storing embeddings of search queries run - * against a vector database to find relevant documents.
  • - *
- *

- * IMPORTANT: The input_type field is required when using embedding - * models v3 and higher. - *

- * API name: {@code input_type} - */ - @Nullable - public final InputType inputType() { - return this.inputType; - } - - /** - * For a rerank task, return doc text within the results. - *

- * API name: {@code return_documents} - */ - @Nullable - public final Boolean returnDocuments() { - return this.returnDocuments; - } - - /** - * For a rerank task, the number of most relevant documents to - * return. It defaults to the number of the documents. If this inference - * endpoint is used in a text_similarity_reranker retriever query - * and top_n is set, it must be greater than or equal to - * rank_window_size in the query. - *

- * API name: {@code top_n} - */ - @Nullable - public final Integer topN() { - return this.topN; - } - - /** - * For a text_embedding task, the method to handle inputs longer - * than the maximum token length. Valid values are: - *

    - *
  • END: When the input exceeds the maximum input token length, - * the end of the input is discarded.
  • - *
  • NONE: When the input exceeds the maximum input token length, - * an error is returned.
  • - *
  • START: When the input exceeds the maximum input token - * length, the start of the input is discarded.
  • - *
- *

- * API name: {@code truncate} - */ - @Nullable - public final TruncateType truncate() { - return this.truncate; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.inputType != null) { - generator.writeKey("input_type"); - this.inputType.serialize(generator, mapper); - } - if (this.returnDocuments != null) { - generator.writeKey("return_documents"); - generator.write(this.returnDocuments); - - } - if (this.topN != null) { - generator.writeKey("top_n"); - generator.write(this.topN); - - } - if (this.truncate != null) { - generator.writeKey("truncate"); - this.truncate.serialize(generator, mapper); - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link CohereTaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private InputType inputType; - - @Nullable - private Boolean returnDocuments; - - @Nullable - private Integer topN; - - @Nullable - private TruncateType truncate; - - /** - * For a text_embedding task, the type of input passed to the - * model. Valid values are: - *

    - *
  • classification: Use it for embeddings passed through a text - * classifier.
  • - *
  • clustering: Use it for the embeddings run through a - * clustering algorithm.
  • - *
  • ingest: Use it for storing document embeddings in a vector - * database.
  • - *
  • search: Use it for storing embeddings of search queries run - * against a vector database to find relevant documents.
  • - *
- *

- * IMPORTANT: The input_type field is required when using embedding - * models v3 and higher. - *

- * API name: {@code input_type} - */ - public final Builder inputType(@Nullable InputType value) { - this.inputType = value; - return this; - } - - /** - * For a rerank task, return doc text within the results. - *

- * API name: {@code return_documents} - */ - public final Builder returnDocuments(@Nullable Boolean value) { - this.returnDocuments = value; - return this; - } - - /** - * For a rerank task, the number of most relevant documents to - * return. It defaults to the number of the documents. If this inference - * endpoint is used in a text_similarity_reranker retriever query - * and top_n is set, it must be greater than or equal to - * rank_window_size in the query. - *

- * API name: {@code top_n} - */ - public final Builder topN(@Nullable Integer value) { - this.topN = value; - return this; - } - - /** - * For a text_embedding task, the method to handle inputs longer - * than the maximum token length. Valid values are: - *

    - *
  • END: When the input exceeds the maximum input token length, - * the end of the input is discarded.
  • - *
  • NONE: When the input exceeds the maximum input token length, - * an error is returned.
  • - *
  • START: When the input exceeds the maximum input token - * length, the start of the input is discarded.
  • - *
- *

- * API name: {@code truncate} - */ - public final Builder truncate(@Nullable TruncateType value) { - this.truncate = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link CohereTaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public CohereTaskSettings build() { - _checkSingleUse(); - - return new CohereTaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link CohereTaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, CohereTaskSettings::setupCohereTaskSettingsDeserializer); - - protected static void setupCohereTaskSettingsDeserializer(ObjectDeserializer op) { - - op.add(Builder::inputType, InputType._DESERIALIZER, "input_type"); - op.add(Builder::returnDocuments, JsonpDeserializer.booleanDeserializer(), "return_documents"); - op.add(Builder::topN, JsonpDeserializer.integerDeserializer(), "top_n"); - op.add(Builder::truncate, TruncateType._DESERIALIZER, "truncate"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskType.java deleted file mode 100644 index 81025c4aa..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/CohereTaskType.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_cohere; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum CohereTaskType implements JsonEnum { - Completion("completion"), - - Rerank("rerank"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - CohereTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - CohereTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/EmbeddingType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/EmbeddingType.java deleted file mode 100644 index 0527144d6..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/EmbeddingType.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_cohere; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum EmbeddingType implements JsonEnum { - Byte("byte"), - - Float("float"), - - Int8("int8"), - - ; - - private final String jsonValue; - - EmbeddingType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - EmbeddingType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/InputType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/InputType.java deleted file mode 100644 index e4ff40c8f..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/InputType.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_cohere; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum InputType implements JsonEnum { - Classification("classification"), - - Clustering("clustering"), - - Ingest("ingest"), - - Search("search"), - - ; - - private final String jsonValue; - - InputType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - InputType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/ServiceType.java deleted file mode 100644 index ff717e85a..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_cohere; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Cohere("cohere"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/SimilarityType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/SimilarityType.java deleted file mode 100644 index 651346c62..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/SimilarityType.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_cohere; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum SimilarityType implements JsonEnum { - Cosine("cosine"), - - DotProduct("dot_product"), - - L2Norm("l2_norm"), - - ; - - private final String jsonValue; - - SimilarityType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - SimilarityType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/TruncateType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/TruncateType.java deleted file mode 100644 index b3f7691cd..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_cohere/TruncateType.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_cohere; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum TruncateType implements JsonEnum { - End("END"), - - None("NONE"), - - Start("START"), - - ; - - private final String jsonValue; - - TruncateType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - TruncateType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/EisServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/EisServiceSettings.java deleted file mode 100644 index 56c3ec63f..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/EisServiceSettings.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_eis; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_eis.EisServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class EisServiceSettings implements JsonpSerializable { - private final String modelId; - - @Nullable - private final RateLimitSetting rateLimit; - - // --------------------------------------------------------------------------------------------- - - private EisServiceSettings(Builder builder) { - - this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); - this.rateLimit = builder.rateLimit; - - } - - public static EisServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The name of the model to use for the inference task. - *

- * API name: {@code model_id} - */ - public final String modelId() { - return this.modelId; - } - - /** - * This setting helps to minimize the number of rate limit errors returned. By - * default, the elastic service sets the number of requests allowed - * per minute to 240 in case of chat_completion. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("model_id"); - generator.write(this.modelId); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link EisServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String modelId; - - @Nullable - private RateLimitSetting rateLimit; - - /** - * Required - The name of the model to use for the inference task. - *

- * API name: {@code model_id} - */ - public final Builder modelId(String value) { - this.modelId = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned. By - * default, the elastic service sets the number of requests allowed - * per minute to 240 in case of chat_completion. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned. By - * default, the elastic service sets the number of requests allowed - * per minute to 240 in case of chat_completion. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link EisServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public EisServiceSettings build() { - _checkSingleUse(); - - return new EisServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link EisServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, EisServiceSettings::setupEisServiceSettingsDeserializer); - - protected static void setupEisServiceSettingsDeserializer(ObjectDeserializer op) { - - op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/EisTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/EisTaskType.java deleted file mode 100644 index 59d10e58b..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/EisTaskType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_eis; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum EisTaskType implements JsonEnum { - ChatCompletion("chat_completion"), - - ; - - private final String jsonValue; - - EisTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - EisTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/ServiceType.java deleted file mode 100644 index ecb074488..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_eis/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_eis; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Elastic("elastic"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/AdaptiveAllocations.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/AdaptiveAllocations.java deleted file mode 100644 index b5c60a2ae..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/AdaptiveAllocations.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_elasticsearch; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_elasticsearch.AdaptiveAllocations - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AdaptiveAllocations implements JsonpSerializable { - @Nullable - private final Boolean enabled; - - @Nullable - private final Integer maxNumberOfAllocations; - - @Nullable - private final Integer minNumberOfAllocations; - - // --------------------------------------------------------------------------------------------- - - private AdaptiveAllocations(Builder builder) { - - this.enabled = builder.enabled; - this.maxNumberOfAllocations = builder.maxNumberOfAllocations; - this.minNumberOfAllocations = builder.minNumberOfAllocations; - - } - - public static AdaptiveAllocations of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Turn on adaptive_allocations. - *

- * API name: {@code enabled} - */ - @Nullable - public final Boolean enabled() { - return this.enabled; - } - - /** - * The maximum number of allocations to scale to. If set, it must be greater - * than or equal to min_number_of_allocations. - *

- * API name: {@code max_number_of_allocations} - */ - @Nullable - public final Integer maxNumberOfAllocations() { - return this.maxNumberOfAllocations; - } - - /** - * The minimum number of allocations to scale to. If set, it must be greater - * than or equal to 0. If not defined, the deployment scales to 0. - *

- * API name: {@code min_number_of_allocations} - */ - @Nullable - public final Integer minNumberOfAllocations() { - return this.minNumberOfAllocations; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.enabled != null) { - generator.writeKey("enabled"); - generator.write(this.enabled); - - } - if (this.maxNumberOfAllocations != null) { - generator.writeKey("max_number_of_allocations"); - generator.write(this.maxNumberOfAllocations); - - } - if (this.minNumberOfAllocations != null) { - generator.writeKey("min_number_of_allocations"); - generator.write(this.minNumberOfAllocations); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AdaptiveAllocations}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private Boolean enabled; - - @Nullable - private Integer maxNumberOfAllocations; - - @Nullable - private Integer minNumberOfAllocations; - - /** - * Turn on adaptive_allocations. - *

- * API name: {@code enabled} - */ - public final Builder enabled(@Nullable Boolean value) { - this.enabled = value; - return this; - } - - /** - * The maximum number of allocations to scale to. If set, it must be greater - * than or equal to min_number_of_allocations. - *

- * API name: {@code max_number_of_allocations} - */ - public final Builder maxNumberOfAllocations(@Nullable Integer value) { - this.maxNumberOfAllocations = value; - return this; - } - - /** - * The minimum number of allocations to scale to. If set, it must be greater - * than or equal to 0. If not defined, the deployment scales to 0. - *

- * API name: {@code min_number_of_allocations} - */ - public final Builder minNumberOfAllocations(@Nullable Integer value) { - this.minNumberOfAllocations = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AdaptiveAllocations}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AdaptiveAllocations build() { - _checkSingleUse(); - - return new AdaptiveAllocations(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AdaptiveAllocations} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AdaptiveAllocations::setupAdaptiveAllocationsDeserializer); - - protected static void setupAdaptiveAllocationsDeserializer(ObjectDeserializer op) { - - op.add(Builder::enabled, JsonpDeserializer.booleanDeserializer(), "enabled"); - op.add(Builder::maxNumberOfAllocations, JsonpDeserializer.integerDeserializer(), "max_number_of_allocations"); - op.add(Builder::minNumberOfAllocations, JsonpDeserializer.integerDeserializer(), "min_number_of_allocations"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchServiceSettings.java deleted file mode 100644 index e9e60d46a..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchServiceSettings.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_elasticsearch; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Integer; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_elasticsearch.ElasticsearchServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class ElasticsearchServiceSettings implements JsonpSerializable { - @Nullable - private final AdaptiveAllocations adaptiveAllocations; - - @Nullable - private final String deploymentId; - - private final String modelId; - - @Nullable - private final Integer numAllocations; - - private final int numThreads; - - // --------------------------------------------------------------------------------------------- - - private ElasticsearchServiceSettings(Builder builder) { - - this.adaptiveAllocations = builder.adaptiveAllocations; - this.deploymentId = builder.deploymentId; - this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); - this.numAllocations = builder.numAllocations; - this.numThreads = ApiTypeHelper.requireNonNull(builder.numThreads, this, "numThreads"); - - } - - public static ElasticsearchServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Adaptive allocations configuration details. If enabled is true, - * the number of allocations of the model is set based on the current load the - * process gets. When the load is high, a new model allocation is automatically - * created, respecting the value of max_number_of_allocations if - * it's set. When the load is low, a model allocation is automatically removed, - * respecting the value of min_number_of_allocations if it's set. - * If enabled is true, do not set the number of allocations - * manually. - *

- * API name: {@code adaptive_allocations} - */ - @Nullable - public final AdaptiveAllocations adaptiveAllocations() { - return this.adaptiveAllocations; - } - - /** - * The deployment identifier for a trained model deployment. When - * deployment_id is used the model_id is optional. - *

- * API name: {@code deployment_id} - */ - @Nullable - public final String deploymentId() { - return this.deploymentId; - } - - /** - * Required - The name of the model to use for the inference task. It can be the - * ID of a built-in model (for example, .multilingual-e5-small for - * E5) or a text embedding model that was uploaded by using the Eland client. - *

- * API name: {@code model_id} - */ - public final String modelId() { - return this.modelId; - } - - /** - * The total number of allocations that are assigned to the model across machine - * learning nodes. Increasing this value generally increases the throughput. If - * adaptive allocations are enabled, do not set this value because it's - * automatically set. - *

- * API name: {@code num_allocations} - */ - @Nullable - public final Integer numAllocations() { - return this.numAllocations; - } - - /** - * Required - The number of threads used by each model allocation during - * inference. This setting generally increases the speed per inference request. - * The inference process is a compute-bound process; - * threads_per_allocations must not exceed the number of available - * allocated processors per node. The value must be a power of 2. The maximum - * value is 32. - *

- * API name: {@code num_threads} - */ - public final int numThreads() { - return this.numThreads; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.adaptiveAllocations != null) { - generator.writeKey("adaptive_allocations"); - this.adaptiveAllocations.serialize(generator, mapper); - - } - if (this.deploymentId != null) { - generator.writeKey("deployment_id"); - generator.write(this.deploymentId); - - } - generator.writeKey("model_id"); - generator.write(this.modelId); - - if (this.numAllocations != null) { - generator.writeKey("num_allocations"); - generator.write(this.numAllocations); - - } - generator.writeKey("num_threads"); - generator.write(this.numThreads); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link ElasticsearchServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private AdaptiveAllocations adaptiveAllocations; - - @Nullable - private String deploymentId; - - private String modelId; - - @Nullable - private Integer numAllocations; - - private Integer numThreads; - - /** - * Adaptive allocations configuration details. If enabled is true, - * the number of allocations of the model is set based on the current load the - * process gets. When the load is high, a new model allocation is automatically - * created, respecting the value of max_number_of_allocations if - * it's set. When the load is low, a model allocation is automatically removed, - * respecting the value of min_number_of_allocations if it's set. - * If enabled is true, do not set the number of allocations - * manually. - *

- * API name: {@code adaptive_allocations} - */ - public final Builder adaptiveAllocations(@Nullable AdaptiveAllocations value) { - this.adaptiveAllocations = value; - return this; - } - - /** - * Adaptive allocations configuration details. If enabled is true, - * the number of allocations of the model is set based on the current load the - * process gets. When the load is high, a new model allocation is automatically - * created, respecting the value of max_number_of_allocations if - * it's set. When the load is low, a model allocation is automatically removed, - * respecting the value of min_number_of_allocations if it's set. - * If enabled is true, do not set the number of allocations - * manually. - *

- * API name: {@code adaptive_allocations} - */ - public final Builder adaptiveAllocations( - Function> fn) { - return this.adaptiveAllocations(fn.apply(new AdaptiveAllocations.Builder()).build()); - } - - /** - * The deployment identifier for a trained model deployment. When - * deployment_id is used the model_id is optional. - *

- * API name: {@code deployment_id} - */ - public final Builder deploymentId(@Nullable String value) { - this.deploymentId = value; - return this; - } - - /** - * Required - The name of the model to use for the inference task. It can be the - * ID of a built-in model (for example, .multilingual-e5-small for - * E5) or a text embedding model that was uploaded by using the Eland client. - *

- * API name: {@code model_id} - */ - public final Builder modelId(String value) { - this.modelId = value; - return this; - } - - /** - * The total number of allocations that are assigned to the model across machine - * learning nodes. Increasing this value generally increases the throughput. If - * adaptive allocations are enabled, do not set this value because it's - * automatically set. - *

- * API name: {@code num_allocations} - */ - public final Builder numAllocations(@Nullable Integer value) { - this.numAllocations = value; - return this; - } - - /** - * Required - The number of threads used by each model allocation during - * inference. This setting generally increases the speed per inference request. - * The inference process is a compute-bound process; - * threads_per_allocations must not exceed the number of available - * allocated processors per node. The value must be a power of 2. The maximum - * value is 32. - *

- * API name: {@code num_threads} - */ - public final Builder numThreads(int value) { - this.numThreads = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link ElasticsearchServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public ElasticsearchServiceSettings build() { - _checkSingleUse(); - - return new ElasticsearchServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link ElasticsearchServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, ElasticsearchServiceSettings::setupElasticsearchServiceSettingsDeserializer); - - protected static void setupElasticsearchServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::adaptiveAllocations, AdaptiveAllocations._DESERIALIZER, "adaptive_allocations"); - op.add(Builder::deploymentId, JsonpDeserializer.stringDeserializer(), "deployment_id"); - op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); - op.add(Builder::numAllocations, JsonpDeserializer.integerDeserializer(), "num_allocations"); - op.add(Builder::numThreads, JsonpDeserializer.integerDeserializer(), "num_threads"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskSettings.java deleted file mode 100644 index 085c5faad..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskSettings.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_elasticsearch; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_elasticsearch.ElasticsearchTaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class ElasticsearchTaskSettings implements JsonpSerializable { - @Nullable - private final Boolean returnDocuments; - - // --------------------------------------------------------------------------------------------- - - private ElasticsearchTaskSettings(Builder builder) { - - this.returnDocuments = builder.returnDocuments; - - } - - public static ElasticsearchTaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * For a rerank task, return the document instead of only the - * index. - *

- * API name: {@code return_documents} - */ - @Nullable - public final Boolean returnDocuments() { - return this.returnDocuments; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.returnDocuments != null) { - generator.writeKey("return_documents"); - generator.write(this.returnDocuments); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link ElasticsearchTaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private Boolean returnDocuments; - - /** - * For a rerank task, return the document instead of only the - * index. - *

- * API name: {@code return_documents} - */ - public final Builder returnDocuments(@Nullable Boolean value) { - this.returnDocuments = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link ElasticsearchTaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public ElasticsearchTaskSettings build() { - _checkSingleUse(); - - return new ElasticsearchTaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link ElasticsearchTaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, ElasticsearchTaskSettings::setupElasticsearchTaskSettingsDeserializer); - - protected static void setupElasticsearchTaskSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::returnDocuments, JsonpDeserializer.booleanDeserializer(), "return_documents"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskType.java deleted file mode 100644 index bdd5a9230..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ElasticsearchTaskType.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_elasticsearch; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ElasticsearchTaskType implements JsonEnum { - Rerank("rerank"), - - SparseEmbedding("sparse_embedding"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - ElasticsearchTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ElasticsearchTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ServiceType.java deleted file mode 100644 index 623a65181..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elasticsearch/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_elasticsearch; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Elasticsearch("elasticsearch"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/AdaptiveAllocations.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/AdaptiveAllocations.java deleted file mode 100644 index 3facca41b..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/AdaptiveAllocations.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_elser; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_elser.AdaptiveAllocations - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class AdaptiveAllocations implements JsonpSerializable { - @Nullable - private final Boolean enabled; - - @Nullable - private final Integer maxNumberOfAllocations; - - @Nullable - private final Integer minNumberOfAllocations; - - // --------------------------------------------------------------------------------------------- - - private AdaptiveAllocations(Builder builder) { - - this.enabled = builder.enabled; - this.maxNumberOfAllocations = builder.maxNumberOfAllocations; - this.minNumberOfAllocations = builder.minNumberOfAllocations; - - } - - public static AdaptiveAllocations of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Turn on adaptive_allocations. - *

- * API name: {@code enabled} - */ - @Nullable - public final Boolean enabled() { - return this.enabled; - } - - /** - * The maximum number of allocations to scale to. If set, it must be greater - * than or equal to min_number_of_allocations. - *

- * API name: {@code max_number_of_allocations} - */ - @Nullable - public final Integer maxNumberOfAllocations() { - return this.maxNumberOfAllocations; - } - - /** - * The minimum number of allocations to scale to. If set, it must be greater - * than or equal to 0. If not defined, the deployment scales to 0. - *

- * API name: {@code min_number_of_allocations} - */ - @Nullable - public final Integer minNumberOfAllocations() { - return this.minNumberOfAllocations; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.enabled != null) { - generator.writeKey("enabled"); - generator.write(this.enabled); - - } - if (this.maxNumberOfAllocations != null) { - generator.writeKey("max_number_of_allocations"); - generator.write(this.maxNumberOfAllocations); - - } - if (this.minNumberOfAllocations != null) { - generator.writeKey("min_number_of_allocations"); - generator.write(this.minNumberOfAllocations); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link AdaptiveAllocations}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private Boolean enabled; - - @Nullable - private Integer maxNumberOfAllocations; - - @Nullable - private Integer minNumberOfAllocations; - - /** - * Turn on adaptive_allocations. - *

- * API name: {@code enabled} - */ - public final Builder enabled(@Nullable Boolean value) { - this.enabled = value; - return this; - } - - /** - * The maximum number of allocations to scale to. If set, it must be greater - * than or equal to min_number_of_allocations. - *

- * API name: {@code max_number_of_allocations} - */ - public final Builder maxNumberOfAllocations(@Nullable Integer value) { - this.maxNumberOfAllocations = value; - return this; - } - - /** - * The minimum number of allocations to scale to. If set, it must be greater - * than or equal to 0. If not defined, the deployment scales to 0. - *

- * API name: {@code min_number_of_allocations} - */ - public final Builder minNumberOfAllocations(@Nullable Integer value) { - this.minNumberOfAllocations = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link AdaptiveAllocations}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public AdaptiveAllocations build() { - _checkSingleUse(); - - return new AdaptiveAllocations(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link AdaptiveAllocations} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, AdaptiveAllocations::setupAdaptiveAllocationsDeserializer); - - protected static void setupAdaptiveAllocationsDeserializer(ObjectDeserializer op) { - - op.add(Builder::enabled, JsonpDeserializer.booleanDeserializer(), "enabled"); - op.add(Builder::maxNumberOfAllocations, JsonpDeserializer.integerDeserializer(), "max_number_of_allocations"); - op.add(Builder::minNumberOfAllocations, JsonpDeserializer.integerDeserializer(), "min_number_of_allocations"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserServiceSettings.java deleted file mode 100644 index 5cee104ba..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserServiceSettings.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_elser; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_elser.ElserServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class ElserServiceSettings implements JsonpSerializable { - @Nullable - private final AdaptiveAllocations adaptiveAllocations; - - private final int numAllocations; - - private final int numThreads; - - // --------------------------------------------------------------------------------------------- - - private ElserServiceSettings(Builder builder) { - - this.adaptiveAllocations = builder.adaptiveAllocations; - this.numAllocations = ApiTypeHelper.requireNonNull(builder.numAllocations, this, "numAllocations"); - this.numThreads = ApiTypeHelper.requireNonNull(builder.numThreads, this, "numThreads"); - - } - - public static ElserServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Adaptive allocations configuration details. If enabled is true, - * the number of allocations of the model is set based on the current load the - * process gets. When the load is high, a new model allocation is automatically - * created, respecting the value of max_number_of_allocations if - * it's set. When the load is low, a model allocation is automatically removed, - * respecting the value of min_number_of_allocations if it's set. - * If enabled is true, do not set the number of allocations - * manually. - *

- * API name: {@code adaptive_allocations} - */ - @Nullable - public final AdaptiveAllocations adaptiveAllocations() { - return this.adaptiveAllocations; - } - - /** - * Required - The total number of allocations this model is assigned across - * machine learning nodes. Increasing this value generally increases the - * throughput. If adaptive allocations is enabled, do not set this value because - * it's automatically set. - *

- * API name: {@code num_allocations} - */ - public final int numAllocations() { - return this.numAllocations; - } - - /** - * Required - The number of threads used by each model allocation during - * inference. Increasing this value generally increases the speed per inference - * request. The inference process is a compute-bound process; - * threads_per_allocations must not exceed the number of available - * allocated processors per node. The value must be a power of 2. The maximum - * value is 32.

- *

- * info If you want to optimize your ELSER endpoint for ingest, set the number - * of threads to 1. If you want to optimize your ELSER endpoint for search, set - * the number of threads to greater than 1. - *

- *
- *

- * API name: {@code num_threads} - */ - public final int numThreads() { - return this.numThreads; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.adaptiveAllocations != null) { - generator.writeKey("adaptive_allocations"); - this.adaptiveAllocations.serialize(generator, mapper); - - } - generator.writeKey("num_allocations"); - generator.write(this.numAllocations); - - generator.writeKey("num_threads"); - generator.write(this.numThreads); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link ElserServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private AdaptiveAllocations adaptiveAllocations; - - private Integer numAllocations; - - private Integer numThreads; - - /** - * Adaptive allocations configuration details. If enabled is true, - * the number of allocations of the model is set based on the current load the - * process gets. When the load is high, a new model allocation is automatically - * created, respecting the value of max_number_of_allocations if - * it's set. When the load is low, a model allocation is automatically removed, - * respecting the value of min_number_of_allocations if it's set. - * If enabled is true, do not set the number of allocations - * manually. - *

- * API name: {@code adaptive_allocations} - */ - public final Builder adaptiveAllocations(@Nullable AdaptiveAllocations value) { - this.adaptiveAllocations = value; - return this; - } - - /** - * Adaptive allocations configuration details. If enabled is true, - * the number of allocations of the model is set based on the current load the - * process gets. When the load is high, a new model allocation is automatically - * created, respecting the value of max_number_of_allocations if - * it's set. When the load is low, a model allocation is automatically removed, - * respecting the value of min_number_of_allocations if it's set. - * If enabled is true, do not set the number of allocations - * manually. - *

- * API name: {@code adaptive_allocations} - */ - public final Builder adaptiveAllocations( - Function> fn) { - return this.adaptiveAllocations(fn.apply(new AdaptiveAllocations.Builder()).build()); - } - - /** - * Required - The total number of allocations this model is assigned across - * machine learning nodes. Increasing this value generally increases the - * throughput. If adaptive allocations is enabled, do not set this value because - * it's automatically set. - *

- * API name: {@code num_allocations} - */ - public final Builder numAllocations(int value) { - this.numAllocations = value; - return this; - } - - /** - * Required - The number of threads used by each model allocation during - * inference. Increasing this value generally increases the speed per inference - * request. The inference process is a compute-bound process; - * threads_per_allocations must not exceed the number of available - * allocated processors per node. The value must be a power of 2. The maximum - * value is 32.

- *

- * info If you want to optimize your ELSER endpoint for ingest, set the number - * of threads to 1. If you want to optimize your ELSER endpoint for search, set - * the number of threads to greater than 1. - *

- *
- *

- * API name: {@code num_threads} - */ - public final Builder numThreads(int value) { - this.numThreads = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link ElserServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public ElserServiceSettings build() { - _checkSingleUse(); - - return new ElserServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link ElserServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, ElserServiceSettings::setupElserServiceSettingsDeserializer); - - protected static void setupElserServiceSettingsDeserializer(ObjectDeserializer op) { - - op.add(Builder::adaptiveAllocations, AdaptiveAllocations._DESERIALIZER, "adaptive_allocations"); - op.add(Builder::numAllocations, JsonpDeserializer.integerDeserializer(), "num_allocations"); - op.add(Builder::numThreads, JsonpDeserializer.integerDeserializer(), "num_threads"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserTaskType.java deleted file mode 100644 index b06065905..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_elser/ElserTaskType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_elser; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ElserTaskType implements JsonEnum { - SparseEmbedding("sparse_embedding"), - - ; - - private final String jsonValue; - - ElserTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ElserTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioServiceSettings.java deleted file mode 100644 index 9fa3878c5..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioServiceSettings.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_googleaistudio; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_googleaistudio.GoogleAiStudioServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class GoogleAiStudioServiceSettings implements JsonpSerializable { - private final String apiKey; - - private final String modelId; - - @Nullable - private final RateLimitSetting rateLimit; - - // --------------------------------------------------------------------------------------------- - - private GoogleAiStudioServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); - this.rateLimit = builder.rateLimit; - - } - - public static GoogleAiStudioServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid API key of your Google Gemini account. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * Google documentation for the list of supported models. - *

- * API name: {@code model_id} - */ - public final String modelId() { - return this.modelId; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Google AI Studio. By default, the googleaistudio service sets - * the number of requests allowed per minute to 360. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - generator.writeKey("model_id"); - generator.write(this.modelId); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link GoogleAiStudioServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - private String modelId; - - @Nullable - private RateLimitSetting rateLimit; - - /** - * Required - A valid API key of your Google Gemini account. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * Google documentation for the list of supported models. - *

- * API name: {@code model_id} - */ - public final Builder modelId(String value) { - this.modelId = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Google AI Studio. By default, the googleaistudio service sets - * the number of requests allowed per minute to 360. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Google AI Studio. By default, the googleaistudio service sets - * the number of requests allowed per minute to 360. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link GoogleAiStudioServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public GoogleAiStudioServiceSettings build() { - _checkSingleUse(); - - return new GoogleAiStudioServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link GoogleAiStudioServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, GoogleAiStudioServiceSettings::setupGoogleAiStudioServiceSettingsDeserializer); - - protected static void setupGoogleAiStudioServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioTaskType.java deleted file mode 100644 index 7c9fa04ea..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/GoogleAiStudioTaskType.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_googleaistudio; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum GoogleAiStudioTaskType implements JsonEnum { - Completion("completion"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - GoogleAiStudioTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - GoogleAiStudioTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/ServiceType.java deleted file mode 100644 index cc2d8aca2..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googleaistudio/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_googleaistudio; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Googleaistudio("googleaistudio"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAIServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAIServiceSettings.java deleted file mode 100644 index 8482cbdfa..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAIServiceSettings.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_googlevertexai; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_googlevertexai.GoogleVertexAIServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class GoogleVertexAIServiceSettings implements JsonpSerializable { - private final String location; - - private final String modelId; - - private final String projectId; - - @Nullable - private final RateLimitSetting rateLimit; - - private final String serviceAccountJson; - - // --------------------------------------------------------------------------------------------- - - private GoogleVertexAIServiceSettings(Builder builder) { - - this.location = ApiTypeHelper.requireNonNull(builder.location, this, "location"); - this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); - this.projectId = ApiTypeHelper.requireNonNull(builder.projectId, this, "projectId"); - this.rateLimit = builder.rateLimit; - this.serviceAccountJson = ApiTypeHelper.requireNonNull(builder.serviceAccountJson, this, "serviceAccountJson"); - - } - - public static GoogleVertexAIServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - The name of the location to use for the inference task. Refer to - * the Google documentation for the list of supported locations. - *

- * API name: {@code location} - */ - public final String location() { - return this.location; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * Google documentation for the list of supported models. - *

- * API name: {@code model_id} - */ - public final String modelId() { - return this.modelId; - } - - /** - * Required - The name of the project to use for the inference task. - *

- * API name: {@code project_id} - */ - public final String projectId() { - return this.projectId; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Google Vertex AI. By default, the googlevertexai service sets - * the number of requests allowed per minute to 30.000. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Required - A valid service account in JSON format for the Google Vertex AI - * API. - *

- * API name: {@code service_account_json} - */ - public final String serviceAccountJson() { - return this.serviceAccountJson; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("location"); - generator.write(this.location); - - generator.writeKey("model_id"); - generator.write(this.modelId); - - generator.writeKey("project_id"); - generator.write(this.projectId); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - generator.writeKey("service_account_json"); - generator.write(this.serviceAccountJson); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link GoogleVertexAIServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String location; - - private String modelId; - - private String projectId; - - @Nullable - private RateLimitSetting rateLimit; - - private String serviceAccountJson; - - /** - * Required - The name of the location to use for the inference task. Refer to - * the Google documentation for the list of supported locations. - *

- * API name: {@code location} - */ - public final Builder location(String value) { - this.location = value; - return this; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * Google documentation for the list of supported models. - *

- * API name: {@code model_id} - */ - public final Builder modelId(String value) { - this.modelId = value; - return this; - } - - /** - * Required - The name of the project to use for the inference task. - *

- * API name: {@code project_id} - */ - public final Builder projectId(String value) { - this.projectId = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Google Vertex AI. By default, the googlevertexai service sets - * the number of requests allowed per minute to 30.000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Google Vertex AI. By default, the googlevertexai service sets - * the number of requests allowed per minute to 30.000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * Required - A valid service account in JSON format for the Google Vertex AI - * API. - *

- * API name: {@code service_account_json} - */ - public final Builder serviceAccountJson(String value) { - this.serviceAccountJson = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link GoogleVertexAIServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public GoogleVertexAIServiceSettings build() { - _checkSingleUse(); - - return new GoogleVertexAIServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link GoogleVertexAIServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, GoogleVertexAIServiceSettings::setupGoogleVertexAIServiceSettingsDeserializer); - - protected static void setupGoogleVertexAIServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::location, JsonpDeserializer.stringDeserializer(), "location"); - op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); - op.add(Builder::projectId, JsonpDeserializer.stringDeserializer(), "project_id"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::serviceAccountJson, JsonpDeserializer.stringDeserializer(), "service_account_json"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskSettings.java deleted file mode 100644 index 99ea25c03..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskSettings.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_googlevertexai; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_googlevertexai.GoogleVertexAITaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class GoogleVertexAITaskSettings implements JsonpSerializable { - @Nullable - private final Boolean autoTruncate; - - @Nullable - private final Integer topN; - - // --------------------------------------------------------------------------------------------- - - private GoogleVertexAITaskSettings(Builder builder) { - - this.autoTruncate = builder.autoTruncate; - this.topN = builder.topN; - - } - - public static GoogleVertexAITaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * For a text_embedding task, truncate inputs longer than the - * maximum token length automatically. - *

- * API name: {@code auto_truncate} - */ - @Nullable - public final Boolean autoTruncate() { - return this.autoTruncate; - } - - /** - * For a rerank task, the number of the top N documents that should - * be returned. - *

- * API name: {@code top_n} - */ - @Nullable - public final Integer topN() { - return this.topN; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.autoTruncate != null) { - generator.writeKey("auto_truncate"); - generator.write(this.autoTruncate); - - } - if (this.topN != null) { - generator.writeKey("top_n"); - generator.write(this.topN); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link GoogleVertexAITaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private Boolean autoTruncate; - - @Nullable - private Integer topN; - - /** - * For a text_embedding task, truncate inputs longer than the - * maximum token length automatically. - *

- * API name: {@code auto_truncate} - */ - public final Builder autoTruncate(@Nullable Boolean value) { - this.autoTruncate = value; - return this; - } - - /** - * For a rerank task, the number of the top N documents that should - * be returned. - *

- * API name: {@code top_n} - */ - public final Builder topN(@Nullable Integer value) { - this.topN = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link GoogleVertexAITaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public GoogleVertexAITaskSettings build() { - _checkSingleUse(); - - return new GoogleVertexAITaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link GoogleVertexAITaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, GoogleVertexAITaskSettings::setupGoogleVertexAITaskSettingsDeserializer); - - protected static void setupGoogleVertexAITaskSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::autoTruncate, JsonpDeserializer.booleanDeserializer(), "auto_truncate"); - op.add(Builder::topN, JsonpDeserializer.integerDeserializer(), "top_n"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskType.java deleted file mode 100644 index 4b1859642..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/GoogleVertexAITaskType.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_googlevertexai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum GoogleVertexAITaskType implements JsonEnum { - Rerank("rerank"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - GoogleVertexAITaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - GoogleVertexAITaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/ServiceType.java deleted file mode 100644 index 65b054f2e..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_googlevertexai/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_googlevertexai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Googlevertexai("googlevertexai"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceServiceSettings.java deleted file mode 100644 index 07464ac58..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceServiceSettings.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_hugging_face; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_hugging_face.HuggingFaceServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class HuggingFaceServiceSettings implements JsonpSerializable { - private final String apiKey; - - @Nullable - private final RateLimitSetting rateLimit; - - private final String url; - - // --------------------------------------------------------------------------------------------- - - private HuggingFaceServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.rateLimit = builder.rateLimit; - this.url = ApiTypeHelper.requireNonNull(builder.url, this, "url"); - - } - - public static HuggingFaceServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid access token for your HuggingFace account. You can create - * or find your access tokens on the HuggingFace settings page. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Hugging Face. By default, the hugging_face service sets the - * number of requests allowed per minute to 3000. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Required - The URL endpoint to use for the requests. - *

- * API name: {@code url} - */ - public final String url() { - return this.url; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - generator.writeKey("url"); - generator.write(this.url); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link HuggingFaceServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - @Nullable - private RateLimitSetting rateLimit; - - private String url; - - /** - * Required - A valid access token for your HuggingFace account. You can create - * or find your access tokens on the HuggingFace settings page. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Hugging Face. By default, the hugging_face service sets the - * number of requests allowed per minute to 3000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Hugging Face. By default, the hugging_face service sets the - * number of requests allowed per minute to 3000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * Required - The URL endpoint to use for the requests. - *

- * API name: {@code url} - */ - public final Builder url(String value) { - this.url = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link HuggingFaceServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public HuggingFaceServiceSettings build() { - _checkSingleUse(); - - return new HuggingFaceServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link HuggingFaceServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, HuggingFaceServiceSettings::setupHuggingFaceServiceSettingsDeserializer); - - protected static void setupHuggingFaceServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::url, JsonpDeserializer.stringDeserializer(), "url"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceTaskType.java deleted file mode 100644 index 3a36ada42..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/HuggingFaceTaskType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_hugging_face; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum HuggingFaceTaskType implements JsonEnum { - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - HuggingFaceTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - HuggingFaceTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/ServiceType.java deleted file mode 100644 index 870661dba..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_hugging_face/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_hugging_face; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - HuggingFace("hugging_face"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAIServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAIServiceSettings.java deleted file mode 100644 index 26f5e7643..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAIServiceSettings.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_jinaai; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_jinaai.JinaAIServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class JinaAIServiceSettings implements JsonpSerializable { - private final String apiKey; - - @Nullable - private final String modelId; - - @Nullable - private final RateLimitSetting rateLimit; - - @Nullable - private final SimilarityType similarity; - - // --------------------------------------------------------------------------------------------- - - private JinaAIServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.modelId = builder.modelId; - this.rateLimit = builder.rateLimit; - this.similarity = builder.similarity; - - } - - public static JinaAIServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid API key of your JinaAI account. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * The name of the model to use for the inference task. For a - * rerank task, it is required. For a text_embedding - * task, it is optional. - *

- * API name: {@code model_id} - */ - @Nullable - public final String modelId() { - return this.modelId; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * JinaAI. By default, the jinaai service sets the number of - * requests allowed per minute to 2000 for all task types. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * For a text_embedding task, the similarity measure. One of - * cosine, dot_product, l2_norm. The default values varies with the embedding - * type. For example, a float embedding type uses a dot_product - * similarity measure by default. - *

- * API name: {@code similarity} - */ - @Nullable - public final SimilarityType similarity() { - return this.similarity; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - if (this.modelId != null) { - generator.writeKey("model_id"); - generator.write(this.modelId); - - } - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - if (this.similarity != null) { - generator.writeKey("similarity"); - this.similarity.serialize(generator, mapper); - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link JinaAIServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - @Nullable - private String modelId; - - @Nullable - private RateLimitSetting rateLimit; - - @Nullable - private SimilarityType similarity; - - /** - * Required - A valid API key of your JinaAI account. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * The name of the model to use for the inference task. For a - * rerank task, it is required. For a text_embedding - * task, it is optional. - *

- * API name: {@code model_id} - */ - public final Builder modelId(@Nullable String value) { - this.modelId = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * JinaAI. By default, the jinaai service sets the number of - * requests allowed per minute to 2000 for all task types. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * JinaAI. By default, the jinaai service sets the number of - * requests allowed per minute to 2000 for all task types. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * For a text_embedding task, the similarity measure. One of - * cosine, dot_product, l2_norm. The default values varies with the embedding - * type. For example, a float embedding type uses a dot_product - * similarity measure by default. - *

- * API name: {@code similarity} - */ - public final Builder similarity(@Nullable SimilarityType value) { - this.similarity = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link JinaAIServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public JinaAIServiceSettings build() { - _checkSingleUse(); - - return new JinaAIServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link JinaAIServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, JinaAIServiceSettings::setupJinaAIServiceSettingsDeserializer); - - protected static void setupJinaAIServiceSettingsDeserializer(ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::similarity, SimilarityType._DESERIALIZER, "similarity"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskSettings.java deleted file mode 100644 index 25888bdce..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskSettings.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_jinaai; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.lang.Integer; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_jinaai.JinaAITaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class JinaAITaskSettings implements JsonpSerializable { - @Nullable - private final Boolean returnDocuments; - - @Nullable - private final TextEmbeddingTask task; - - @Nullable - private final Integer topN; - - // --------------------------------------------------------------------------------------------- - - private JinaAITaskSettings(Builder builder) { - - this.returnDocuments = builder.returnDocuments; - this.task = builder.task; - this.topN = builder.topN; - - } - - public static JinaAITaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * For a rerank task, return the doc text within the results. - *

- * API name: {@code return_documents} - */ - @Nullable - public final Boolean returnDocuments() { - return this.returnDocuments; - } - - /** - * For a text_embedding task, the task passed to the model. Valid - * values are: - *

    - *
  • classification: Use it for embeddings passed through a text - * classifier.
  • - *
  • clustering: Use it for the embeddings run through a - * clustering algorithm.
  • - *
  • ingest: Use it for storing document embeddings in a vector - * database.
  • - *
  • search: Use it for storing embeddings of search queries run - * against a vector database to find relevant documents.
  • - *
- *

- * API name: {@code task} - */ - @Nullable - public final TextEmbeddingTask task() { - return this.task; - } - - /** - * For a rerank task, the number of most relevant documents to - * return. It defaults to the number of the documents. If this inference - * endpoint is used in a text_similarity_reranker retriever query - * and top_n is set, it must be greater than or equal to - * rank_window_size in the query. - *

- * API name: {@code top_n} - */ - @Nullable - public final Integer topN() { - return this.topN; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.returnDocuments != null) { - generator.writeKey("return_documents"); - generator.write(this.returnDocuments); - - } - if (this.task != null) { - generator.writeKey("task"); - this.task.serialize(generator, mapper); - } - if (this.topN != null) { - generator.writeKey("top_n"); - generator.write(this.topN); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link JinaAITaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private Boolean returnDocuments; - - @Nullable - private TextEmbeddingTask task; - - @Nullable - private Integer topN; - - /** - * For a rerank task, return the doc text within the results. - *

- * API name: {@code return_documents} - */ - public final Builder returnDocuments(@Nullable Boolean value) { - this.returnDocuments = value; - return this; - } - - /** - * For a text_embedding task, the task passed to the model. Valid - * values are: - *

    - *
  • classification: Use it for embeddings passed through a text - * classifier.
  • - *
  • clustering: Use it for the embeddings run through a - * clustering algorithm.
  • - *
  • ingest: Use it for storing document embeddings in a vector - * database.
  • - *
  • search: Use it for storing embeddings of search queries run - * against a vector database to find relevant documents.
  • - *
- *

- * API name: {@code task} - */ - public final Builder task(@Nullable TextEmbeddingTask value) { - this.task = value; - return this; - } - - /** - * For a rerank task, the number of most relevant documents to - * return. It defaults to the number of the documents. If this inference - * endpoint is used in a text_similarity_reranker retriever query - * and top_n is set, it must be greater than or equal to - * rank_window_size in the query. - *

- * API name: {@code top_n} - */ - public final Builder topN(@Nullable Integer value) { - this.topN = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link JinaAITaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public JinaAITaskSettings build() { - _checkSingleUse(); - - return new JinaAITaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link JinaAITaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, JinaAITaskSettings::setupJinaAITaskSettingsDeserializer); - - protected static void setupJinaAITaskSettingsDeserializer(ObjectDeserializer op) { - - op.add(Builder::returnDocuments, JsonpDeserializer.booleanDeserializer(), "return_documents"); - op.add(Builder::task, TextEmbeddingTask._DESERIALIZER, "task"); - op.add(Builder::topN, JsonpDeserializer.integerDeserializer(), "top_n"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskType.java deleted file mode 100644 index 0d8771a24..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/JinaAITaskType.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_jinaai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum JinaAITaskType implements JsonEnum { - Rerank("rerank"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - JinaAITaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - JinaAITaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/ServiceType.java deleted file mode 100644 index f9df9ea40..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_jinaai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Jinaai("jinaai"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/SimilarityType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/SimilarityType.java deleted file mode 100644 index 970051384..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/SimilarityType.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_jinaai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum SimilarityType implements JsonEnum { - Cosine("cosine"), - - DotProduct("dot_product"), - - L2Norm("l2_norm"), - - ; - - private final String jsonValue; - - SimilarityType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - SimilarityType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/TextEmbeddingTask.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/TextEmbeddingTask.java deleted file mode 100644 index 1a1667667..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_jinaai/TextEmbeddingTask.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_jinaai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum TextEmbeddingTask implements JsonEnum { - Classification("classification"), - - Clustering("clustering"), - - Ingest("ingest"), - - Search("search"), - - ; - - private final String jsonValue; - - TextEmbeddingTask(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - TextEmbeddingTask.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralServiceSettings.java deleted file mode 100644 index fbcc888ec..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralServiceSettings.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_mistral; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Integer; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_mistral.MistralServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class MistralServiceSettings implements JsonpSerializable { - private final String apiKey; - - @Nullable - private final Integer maxInputTokens; - - private final String model; - - @Nullable - private final RateLimitSetting rateLimit; - - // --------------------------------------------------------------------------------------------- - - private MistralServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.maxInputTokens = builder.maxInputTokens; - this.model = ApiTypeHelper.requireNonNull(builder.model, this, "model"); - this.rateLimit = builder.rateLimit; - - } - - public static MistralServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid API key of your Mistral account. You can find your Mistral - * API keys or you can create a new one on the API Keys page. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * The maximum number of tokens per input before chunking occurs. - *

- * API name: {@code max_input_tokens} - */ - @Nullable - public final Integer maxInputTokens() { - return this.maxInputTokens; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * Mistral models documentation for the list of available text embedding models. - *

- * API name: {@code model} - */ - public final String model() { - return this.model; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * the Mistral API. By default, the mistral service sets the number - * of requests allowed per minute to 240. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - if (this.maxInputTokens != null) { - generator.writeKey("max_input_tokens"); - generator.write(this.maxInputTokens); - - } - generator.writeKey("model"); - generator.write(this.model); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link MistralServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - @Nullable - private Integer maxInputTokens; - - private String model; - - @Nullable - private RateLimitSetting rateLimit; - - /** - * Required - A valid API key of your Mistral account. You can find your Mistral - * API keys or you can create a new one on the API Keys page. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * The maximum number of tokens per input before chunking occurs. - *

- * API name: {@code max_input_tokens} - */ - public final Builder maxInputTokens(@Nullable Integer value) { - this.maxInputTokens = value; - return this; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * Mistral models documentation for the list of available text embedding models. - *

- * API name: {@code model} - */ - public final Builder model(String value) { - this.model = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * the Mistral API. By default, the mistral service sets the number - * of requests allowed per minute to 240. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * the Mistral API. By default, the mistral service sets the number - * of requests allowed per minute to 240. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link MistralServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public MistralServiceSettings build() { - _checkSingleUse(); - - return new MistralServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link MistralServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, MistralServiceSettings::setupMistralServiceSettingsDeserializer); - - protected static void setupMistralServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::maxInputTokens, JsonpDeserializer.integerDeserializer(), "max_input_tokens"); - op.add(Builder::model, JsonpDeserializer.stringDeserializer(), "model"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralTaskType.java deleted file mode 100644 index 94c34e12c..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/MistralTaskType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_mistral; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum MistralTaskType implements JsonEnum { - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - MistralTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - MistralTaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/ServiceType.java deleted file mode 100644 index 36f555841..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_mistral/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_mistral; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Mistral("mistral"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAIServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAIServiceSettings.java deleted file mode 100644 index 8d4fa4222..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAIServiceSettings.java +++ /dev/null @@ -1,368 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_openai; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Integer; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_openai.OpenAIServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class OpenAIServiceSettings implements JsonpSerializable { - private final String apiKey; - - @Nullable - private final Integer dimensions; - - private final String modelId; - - @Nullable - private final String organizationId; - - @Nullable - private final RateLimitSetting rateLimit; - - @Nullable - private final String url; - - // --------------------------------------------------------------------------------------------- - - private OpenAIServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.dimensions = builder.dimensions; - this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); - this.organizationId = builder.organizationId; - this.rateLimit = builder.rateLimit; - this.url = builder.url; - - } - - public static OpenAIServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid API key of your OpenAI account. You can find your OpenAI - * API keys in your OpenAI account under the API keys section. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * The number of dimensions the resulting output embeddings should have. It is - * supported only in text-embedding-3 and later models. If it is - * not set, the OpenAI defined default for the model is used. - *

- * API name: {@code dimensions} - */ - @Nullable - public final Integer dimensions() { - return this.dimensions; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * OpenAI documentation for the list of available text embedding models. - *

- * API name: {@code model_id} - */ - public final String modelId() { - return this.modelId; - } - - /** - * The unique identifier for your organization. You can find the Organization ID - * in your OpenAI account under Settings > Organizations. - *

- * API name: {@code organization_id} - */ - @Nullable - public final String organizationId() { - return this.organizationId; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * OpenAI. The openai service sets a default number of requests - * allowed per minute depending on the task type. For - * text_embedding, it is set to 3000. For - * completion, it is set to 500. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * The URL endpoint to use for the requests. It can be changed for testing - * purposes. - *

- * API name: {@code url} - */ - @Nullable - public final String url() { - return this.url; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - if (this.dimensions != null) { - generator.writeKey("dimensions"); - generator.write(this.dimensions); - - } - generator.writeKey("model_id"); - generator.write(this.modelId); - - if (this.organizationId != null) { - generator.writeKey("organization_id"); - generator.write(this.organizationId); - - } - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - if (this.url != null) { - generator.writeKey("url"); - generator.write(this.url); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link OpenAIServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - @Nullable - private Integer dimensions; - - private String modelId; - - @Nullable - private String organizationId; - - @Nullable - private RateLimitSetting rateLimit; - - @Nullable - private String url; - - /** - * Required - A valid API key of your OpenAI account. You can find your OpenAI - * API keys in your OpenAI account under the API keys section. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * The number of dimensions the resulting output embeddings should have. It is - * supported only in text-embedding-3 and later models. If it is - * not set, the OpenAI defined default for the model is used. - *

- * API name: {@code dimensions} - */ - public final Builder dimensions(@Nullable Integer value) { - this.dimensions = value; - return this; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * OpenAI documentation for the list of available text embedding models. - *

- * API name: {@code model_id} - */ - public final Builder modelId(String value) { - this.modelId = value; - return this; - } - - /** - * The unique identifier for your organization. You can find the Organization ID - * in your OpenAI account under Settings > Organizations. - *

- * API name: {@code organization_id} - */ - public final Builder organizationId(@Nullable String value) { - this.organizationId = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * OpenAI. The openai service sets a default number of requests - * allowed per minute depending on the task type. For - * text_embedding, it is set to 3000. For - * completion, it is set to 500. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * OpenAI. The openai service sets a default number of requests - * allowed per minute depending on the task type. For - * text_embedding, it is set to 3000. For - * completion, it is set to 500. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * The URL endpoint to use for the requests. It can be changed for testing - * purposes. - *

- * API name: {@code url} - */ - public final Builder url(@Nullable String value) { - this.url = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link OpenAIServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public OpenAIServiceSettings build() { - _checkSingleUse(); - - return new OpenAIServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link OpenAIServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, OpenAIServiceSettings::setupOpenAIServiceSettingsDeserializer); - - protected static void setupOpenAIServiceSettingsDeserializer(ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::dimensions, JsonpDeserializer.integerDeserializer(), "dimensions"); - op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); - op.add(Builder::organizationId, JsonpDeserializer.stringDeserializer(), "organization_id"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::url, JsonpDeserializer.stringDeserializer(), "url"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAITaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAITaskSettings.java deleted file mode 100644 index e80616c0b..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAITaskSettings.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_openai; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_openai.OpenAITaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class OpenAITaskSettings implements JsonpSerializable { - @Nullable - private final String user; - - // --------------------------------------------------------------------------------------------- - - private OpenAITaskSettings(Builder builder) { - - this.user = builder.user; - - } - - public static OpenAITaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * For a completion or text_embedding task, specify - * the user issuing the request. This information can be used for abuse - * detection. - *

- * API name: {@code user} - */ - @Nullable - public final String user() { - return this.user; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.user != null) { - generator.writeKey("user"); - generator.write(this.user); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link OpenAITaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private String user; - - /** - * For a completion or text_embedding task, specify - * the user issuing the request. This information can be used for abuse - * detection. - *

- * API name: {@code user} - */ - public final Builder user(@Nullable String value) { - this.user = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link OpenAITaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public OpenAITaskSettings build() { - _checkSingleUse(); - - return new OpenAITaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link OpenAITaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, OpenAITaskSettings::setupOpenAITaskSettingsDeserializer); - - protected static void setupOpenAITaskSettingsDeserializer(ObjectDeserializer op) { - - op.add(Builder::user, JsonpDeserializer.stringDeserializer(), "user"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAITaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAITaskType.java deleted file mode 100644 index 12c8b6c5b..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/OpenAITaskType.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_openai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum OpenAITaskType implements JsonEnum { - ChatCompletion("chat_completion"), - - Completion("completion"), - - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - OpenAITaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - OpenAITaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java deleted file mode 100644 index 451b2e64a..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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. - */ - -<<<<<<<< HEAD:java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/ServiceType.java -package co.elastic.clients.elasticsearch.inference.put_voyageai; -======== -package co.elastic.clients.elasticsearch.inference.put_openai; ->>>>>>>> c86960dc6 (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API -======== - * "../../doc-files/api-spec.html#inference.put_openai.ServiceType">API ->>>>>>>> c86960dc6 (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { -<<<<<<<< HEAD:java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/ServiceType.java - Voyageai("voyageai"), -======== - Openai("openai"), ->>>>>>>> c86960dc6 (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/ServiceType.java deleted file mode 100644 index ad66756ad..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_voyageai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Voyageai("voyageai"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAIServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAIServiceSettings.java deleted file mode 100644 index 5b3c7c0ce..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAIServiceSettings.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_voyageai; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Float; -import java.lang.Integer; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_voyageai.VoyageAIServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class VoyageAIServiceSettings implements JsonpSerializable { - @Nullable - private final Integer dimensions; - - private final String modelId; - - @Nullable - private final RateLimitSetting rateLimit; - - @Nullable - private final Float embeddingType; - - // --------------------------------------------------------------------------------------------- - - private VoyageAIServiceSettings(Builder builder) { - - this.dimensions = builder.dimensions; - this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); - this.rateLimit = builder.rateLimit; - this.embeddingType = builder.embeddingType; - - } - - public static VoyageAIServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * The number of dimensions for resulting output embeddings. This setting maps - * to output_dimension in the VoyageAI documentation. Only for the - * text_embedding task type. - *

- * API name: {@code dimensions} - */ - @Nullable - public final Integer dimensions() { - return this.dimensions; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * VoyageAI documentation for the list of available text embedding and rerank - * models. - *

- * API name: {@code model_id} - */ - public final String modelId() { - return this.modelId; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * VoyageAI. The voyageai service sets a default number of requests - * allowed per minute depending on the task type. For both - * text_embedding and rerank, it is set to - * 2000. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * The data type for the embeddings to be returned. This setting maps to - * output_dtype in the VoyageAI documentation. Permitted values: - * float, int8, bit. int8 is a synonym of byte in the - * VoyageAI documentation. bit is a synonym of binary - * in the VoyageAI documentation. Only for the text_embedding task - * type. - *

- * API name: {@code embedding_type} - */ - @Nullable - public final Float embeddingType() { - return this.embeddingType; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.dimensions != null) { - generator.writeKey("dimensions"); - generator.write(this.dimensions); - - } - generator.writeKey("model_id"); - generator.write(this.modelId); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - if (this.embeddingType != null) { - generator.writeKey("embedding_type"); - generator.write(this.embeddingType); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link VoyageAIServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private Integer dimensions; - - private String modelId; - - @Nullable - private RateLimitSetting rateLimit; - - @Nullable - private Float embeddingType; - - /** - * The number of dimensions for resulting output embeddings. This setting maps - * to output_dimension in the VoyageAI documentation. Only for the - * text_embedding task type. - *

- * API name: {@code dimensions} - */ - public final Builder dimensions(@Nullable Integer value) { - this.dimensions = value; - return this; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * VoyageAI documentation for the list of available text embedding and rerank - * models. - *

- * API name: {@code model_id} - */ - public final Builder modelId(String value) { - this.modelId = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * VoyageAI. The voyageai service sets a default number of requests - * allowed per minute depending on the task type. For both - * text_embedding and rerank, it is set to - * 2000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * VoyageAI. The voyageai service sets a default number of requests - * allowed per minute depending on the task type. For both - * text_embedding and rerank, it is set to - * 2000. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * The data type for the embeddings to be returned. This setting maps to - * output_dtype in the VoyageAI documentation. Permitted values: - * float, int8, bit. int8 is a synonym of byte in the - * VoyageAI documentation. bit is a synonym of binary - * in the VoyageAI documentation. Only for the text_embedding task - * type. - *

- * API name: {@code embedding_type} - */ - public final Builder embeddingType(@Nullable Float value) { - this.embeddingType = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link VoyageAIServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public VoyageAIServiceSettings build() { - _checkSingleUse(); - - return new VoyageAIServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link VoyageAIServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, VoyageAIServiceSettings::setupVoyageAIServiceSettingsDeserializer); - - protected static void setupVoyageAIServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::dimensions, JsonpDeserializer.integerDeserializer(), "dimensions"); - op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::embeddingType, JsonpDeserializer.floatDeserializer(), "embedding_type"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAITaskSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAITaskSettings.java deleted file mode 100644 index de5db0b54..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAITaskSettings.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_voyageai; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.Boolean; -import java.lang.Integer; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_voyageai.VoyageAITaskSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class VoyageAITaskSettings implements JsonpSerializable { - @Nullable - private final String inputType; - - @Nullable - private final Boolean returnDocuments; - - @Nullable - private final Integer topK; - - @Nullable - private final Boolean truncation; - - // --------------------------------------------------------------------------------------------- - - private VoyageAITaskSettings(Builder builder) { - - this.inputType = builder.inputType; - this.returnDocuments = builder.returnDocuments; - this.topK = builder.topK; - this.truncation = builder.truncation; - - } - - public static VoyageAITaskSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Type of the input text. Permitted values: ingest (maps to - * document in the VoyageAI documentation), search - * (maps to query in the VoyageAI documentation). Only for the - * text_embedding task type. - *

- * API name: {@code input_type} - */ - @Nullable - public final String inputType() { - return this.inputType; - } - - /** - * Whether to return the source documents in the response. Only for the - * rerank task type. - *

- * API name: {@code return_documents} - */ - @Nullable - public final Boolean returnDocuments() { - return this.returnDocuments; - } - - /** - * The number of most relevant documents to return. If not specified, the - * reranking results of all documents will be returned. Only for the - * rerank task type. - *

- * API name: {@code top_k} - */ - @Nullable - public final Integer topK() { - return this.topK; - } - - /** - * Whether to truncate the input texts to fit within the context length. - *

- * API name: {@code truncation} - */ - @Nullable - public final Boolean truncation() { - return this.truncation; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - if (this.inputType != null) { - generator.writeKey("input_type"); - generator.write(this.inputType); - - } - if (this.returnDocuments != null) { - generator.writeKey("return_documents"); - generator.write(this.returnDocuments); - - } - if (this.topK != null) { - generator.writeKey("top_k"); - generator.write(this.topK); - - } - if (this.truncation != null) { - generator.writeKey("truncation"); - generator.write(this.truncation); - - } - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link VoyageAITaskSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - @Nullable - private String inputType; - - @Nullable - private Boolean returnDocuments; - - @Nullable - private Integer topK; - - @Nullable - private Boolean truncation; - - /** - * Type of the input text. Permitted values: ingest (maps to - * document in the VoyageAI documentation), search - * (maps to query in the VoyageAI documentation). Only for the - * text_embedding task type. - *

- * API name: {@code input_type} - */ - public final Builder inputType(@Nullable String value) { - this.inputType = value; - return this; - } - - /** - * Whether to return the source documents in the response. Only for the - * rerank task type. - *

- * API name: {@code return_documents} - */ - public final Builder returnDocuments(@Nullable Boolean value) { - this.returnDocuments = value; - return this; - } - - /** - * The number of most relevant documents to return. If not specified, the - * reranking results of all documents will be returned. Only for the - * rerank task type. - *

- * API name: {@code top_k} - */ - public final Builder topK(@Nullable Integer value) { - this.topK = value; - return this; - } - - /** - * Whether to truncate the input texts to fit within the context length. - *

- * API name: {@code truncation} - */ - public final Builder truncation(@Nullable Boolean value) { - this.truncation = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link VoyageAITaskSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public VoyageAITaskSettings build() { - _checkSingleUse(); - - return new VoyageAITaskSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link VoyageAITaskSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, VoyageAITaskSettings::setupVoyageAITaskSettingsDeserializer); - - protected static void setupVoyageAITaskSettingsDeserializer(ObjectDeserializer op) { - - op.add(Builder::inputType, JsonpDeserializer.stringDeserializer(), "input_type"); - op.add(Builder::returnDocuments, JsonpDeserializer.booleanDeserializer(), "return_documents"); - op.add(Builder::topK, JsonpDeserializer.integerDeserializer(), "top_k"); - op.add(Builder::truncation, JsonpDeserializer.booleanDeserializer(), "truncation"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAITaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAITaskType.java deleted file mode 100644 index efe36056a..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/VoyageAITaskType.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_voyageai; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum VoyageAITaskType implements JsonEnum { - TextEmbedding("text_embedding"), - - Rerank("rerank"), - - ; - - private final String jsonValue; - - VoyageAITaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - VoyageAITaskType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/ServiceType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/ServiceType.java deleted file mode 100644 index a5f8ddbb4..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/ServiceType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_watsonx; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { - Watsonxai("watsonxai"), - - ; - - private final String jsonValue; - - ServiceType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - ServiceType.values()); -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/WatsonxServiceSettings.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/WatsonxServiceSettings.java deleted file mode 100644 index f43664eea..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/WatsonxServiceSettings.java +++ /dev/null @@ -1,346 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_watsonx; - -import co.elastic.clients.elasticsearch.inference.RateLimitSetting; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.WithJsonObjectBuilderBase; -import jakarta.json.stream.JsonGenerator; -import java.lang.String; -import java.util.Objects; -import java.util.function.Function; -import javax.annotation.Nullable; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -// typedef: inference.put_watsonx.WatsonxServiceSettings - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public class WatsonxServiceSettings implements JsonpSerializable { - private final String apiKey; - - private final String apiVersion; - - private final String modelId; - - private final String projectId; - - @Nullable - private final RateLimitSetting rateLimit; - - private final String url; - - // --------------------------------------------------------------------------------------------- - - private WatsonxServiceSettings(Builder builder) { - - this.apiKey = ApiTypeHelper.requireNonNull(builder.apiKey, this, "apiKey"); - this.apiVersion = ApiTypeHelper.requireNonNull(builder.apiVersion, this, "apiVersion"); - this.modelId = ApiTypeHelper.requireNonNull(builder.modelId, this, "modelId"); - this.projectId = ApiTypeHelper.requireNonNull(builder.projectId, this, "projectId"); - this.rateLimit = builder.rateLimit; - this.url = ApiTypeHelper.requireNonNull(builder.url, this, "url"); - - } - - public static WatsonxServiceSettings of(Function> fn) { - return fn.apply(new Builder()).build(); - } - - /** - * Required - A valid API key of your Watsonx account. You can find your Watsonx - * API keys or you can create a new one on the API keys page. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final String apiKey() { - return this.apiKey; - } - - /** - * Required - A version parameter that takes a version date in the format of - * YYYY-MM-DD. For the active version data parameters, refer to the - * Wastonx documentation. - *

- * API name: {@code api_version} - */ - public final String apiVersion() { - return this.apiVersion; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * IBM Embedding Models section in the Watsonx documentation for the list of - * available text embedding models. - *

- * API name: {@code model_id} - */ - public final String modelId() { - return this.modelId; - } - - /** - * Required - The identifier of the IBM Cloud project to use for the inference - * task. - *

- * API name: {@code project_id} - */ - public final String projectId() { - return this.projectId; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Watsonx. By default, the watsonxai service sets the number of - * requests allowed per minute to 120. - *

- * API name: {@code rate_limit} - */ - @Nullable - public final RateLimitSetting rateLimit() { - return this.rateLimit; - } - - /** - * Required - The URL of the inference endpoint that you created on Watsonx. - *

- * API name: {@code url} - */ - public final String url() { - return this.url; - } - - /** - * Serialize this object to JSON. - */ - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - serializeInternal(generator, mapper); - generator.writeEnd(); - } - - protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { - - generator.writeKey("api_key"); - generator.write(this.apiKey); - - generator.writeKey("api_version"); - generator.write(this.apiVersion); - - generator.writeKey("model_id"); - generator.write(this.modelId); - - generator.writeKey("project_id"); - generator.write(this.projectId); - - if (this.rateLimit != null) { - generator.writeKey("rate_limit"); - this.rateLimit.serialize(generator, mapper); - - } - generator.writeKey("url"); - generator.write(this.url); - - } - - @Override - public String toString() { - return JsonpUtils.toString(this); - } - - // --------------------------------------------------------------------------------------------- - - /** - * Builder for {@link WatsonxServiceSettings}. - */ - - public static class Builder extends WithJsonObjectBuilderBase - implements - ObjectBuilder { - private String apiKey; - - private String apiVersion; - - private String modelId; - - private String projectId; - - @Nullable - private RateLimitSetting rateLimit; - - private String url; - - /** - * Required - A valid API key of your Watsonx account. You can find your Watsonx - * API keys or you can create a new one on the API keys page. - *

- * IMPORTANT: You need to provide the API key only once, during the inference - * model creation. The get inference endpoint API does not retrieve your API - * key. After creating the inference model, you cannot change the associated API - * key. If you want to use a different API key, delete the inference model and - * recreate it with the same name and the updated API key. - *

- * API name: {@code api_key} - */ - public final Builder apiKey(String value) { - this.apiKey = value; - return this; - } - - /** - * Required - A version parameter that takes a version date in the format of - * YYYY-MM-DD. For the active version data parameters, refer to the - * Wastonx documentation. - *

- * API name: {@code api_version} - */ - public final Builder apiVersion(String value) { - this.apiVersion = value; - return this; - } - - /** - * Required - The name of the model to use for the inference task. Refer to the - * IBM Embedding Models section in the Watsonx documentation for the list of - * available text embedding models. - *

- * API name: {@code model_id} - */ - public final Builder modelId(String value) { - this.modelId = value; - return this; - } - - /** - * Required - The identifier of the IBM Cloud project to use for the inference - * task. - *

- * API name: {@code project_id} - */ - public final Builder projectId(String value) { - this.projectId = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Watsonx. By default, the watsonxai service sets the number of - * requests allowed per minute to 120. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(@Nullable RateLimitSetting value) { - this.rateLimit = value; - return this; - } - - /** - * This setting helps to minimize the number of rate limit errors returned from - * Watsonx. By default, the watsonxai service sets the number of - * requests allowed per minute to 120. - *

- * API name: {@code rate_limit} - */ - public final Builder rateLimit(Function> fn) { - return this.rateLimit(fn.apply(new RateLimitSetting.Builder()).build()); - } - - /** - * Required - The URL of the inference endpoint that you created on Watsonx. - *

- * API name: {@code url} - */ - public final Builder url(String value) { - this.url = value; - return this; - } - - @Override - protected Builder self() { - return this; - } - - /** - * Builds a {@link WatsonxServiceSettings}. - * - * @throws NullPointerException - * if some of the required fields are null. - */ - public WatsonxServiceSettings build() { - _checkSingleUse(); - - return new WatsonxServiceSettings(this); - } - } - - // --------------------------------------------------------------------------------------------- - - /** - * Json deserializer for {@link WatsonxServiceSettings} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, WatsonxServiceSettings::setupWatsonxServiceSettingsDeserializer); - - protected static void setupWatsonxServiceSettingsDeserializer( - ObjectDeserializer op) { - - op.add(Builder::apiKey, JsonpDeserializer.stringDeserializer(), "api_key"); - op.add(Builder::apiVersion, JsonpDeserializer.stringDeserializer(), "api_version"); - op.add(Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id"); - op.add(Builder::projectId, JsonpDeserializer.stringDeserializer(), "project_id"); - op.add(Builder::rateLimit, RateLimitSetting._DESERIALIZER, "rate_limit"); - op.add(Builder::url, JsonpDeserializer.stringDeserializer(), "url"); - - } - -} diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/WatsonxTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/WatsonxTaskType.java deleted file mode 100644 index 2a702f6e5..000000000 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_watsonx/WatsonxTaskType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.inference.put_watsonx; - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; - -//---------------------------------------------------------------- -// THIS CODE IS GENERATED. MANUAL EDITS WILL BE LOST. -//---------------------------------------------------------------- -// -// This code is generated from the Elasticsearch API specification -// at https://github.com/elastic/elasticsearch-specification -// -// Manual updates to this file will be lost when the code is -// re-generated. -// -// If you find a property that is missing or wrongly typed, please -// open an issue or a PR on the API specification repository. -// -//---------------------------------------------------------------- - -/** - * - * @see API - * specification - */ -@JsonpDeserializable -public enum WatsonxTaskType implements JsonEnum { - TextEmbedding("text_embedding"), - - ; - - private final String jsonValue; - - WatsonxTaskType(String jsonValue) { - this.jsonValue = jsonValue; - } - - public String jsonValue() { - return this.jsonValue; - } - - public static final JsonEnum.Deserializer _DESERIALIZER = new JsonEnum.Deserializer<>( - WatsonxTaskType.values()); -} From 11ae0f5ee90ef9abbfb84d4dbf9796edc21a3931 Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Mon, 31 Mar 2025 16:47:16 +0200 Subject: [PATCH 37/38] fixing tests --- .../clients/documentation/usage/SearchingTest.java | 2 +- .../elastic/clients/elasticsearch/model/UnionTests.java | 8 ++++---- .../clients/elasticsearch/spec_issues/SpecIssuesTest.java | 2 +- .../test/java/co/elastic/clients/json/WithJsonTest.java | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-client/src/test/java/co/elastic/clients/documentation/usage/SearchingTest.java b/java-client/src/test/java/co/elastic/clients/documentation/usage/SearchingTest.java index b0179e037..1e3f7a988 100644 --- a/java-client/src/test/java/co/elastic/clients/documentation/usage/SearchingTest.java +++ b/java-client/src/test/java/co/elastic/clients/documentation/usage/SearchingTest.java @@ -167,7 +167,7 @@ public void searchTemplate() throws Exception { .id("query-script") // <1> .script(s -> s .lang("mustache") - .source("{\"query\":{\"match\":{\"{{field}}\":\"{{value}}\"}}}") + .source(so -> so.scriptString("{\"query\":{\"match\":{\"{{field}}\":\"{{value}}\"}}}")) )); //end::search-template-script diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/UnionTests.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/UnionTests.java index 386f9f9ee..d87f0f2ea 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/UnionTests.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/UnionTests.java @@ -43,13 +43,13 @@ public class UnionTests extends ModelTestCase { @Test public void testScriptDeserializer() { - // A union discriminated by its field names (source -> inline, id -> stored) + // the source field in script is both a shortcut and an externally tagged union { Script s = Script.of(_1 -> _1 - .source("a script") + .source(_2 -> _2.scriptString("a script")) ); s = checkJsonRoundtrip(s, "{\"source\":\"a script\"}"); - assertEquals("a script", s.source()); + assertEquals("a script", s.source().scriptString()); } { @@ -63,7 +63,7 @@ public void testScriptDeserializer() { { // Test shortcut property Script s = fromJson("\"a script\"", Script.class); - assertEquals("a script", s.source()); + assertEquals("a script", s.source().scriptString()); } } diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/spec_issues/SpecIssuesTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/spec_issues/SpecIssuesTest.java index f36672b8f..7e7d5cba9 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/spec_issues/SpecIssuesTest.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/spec_issues/SpecIssuesTest.java @@ -98,7 +98,7 @@ public void i0298_runtimeMappings() throws Exception { RuntimeField runtimeField = RuntimeField.of(rf -> rf .type(RuntimeFieldType.Double) .script(Script.of(s -> s - .source("emit(doc['price'].value * 1.19)") + .source(so -> so.scriptString("emit(doc['price'].value * 1.19)")) )) ); diff --git a/java-client/src/test/java/co/elastic/clients/json/WithJsonTest.java b/java-client/src/test/java/co/elastic/clients/json/WithJsonTest.java index 02a9e15a0..5f05bb381 100644 --- a/java-client/src/test/java/co/elastic/clients/json/WithJsonTest.java +++ b/java-client/src/test/java/co/elastic/clients/json/WithJsonTest.java @@ -128,7 +128,7 @@ public void testTypeWithParent() { .withJson(new StringReader(json)) ); - assertEquals("return doc;", is.source()); + assertEquals("return doc;", is.source().scriptString()); } @Test From b1287e669b735749ce268403074102a4f54263b7 Mon Sep 17 00:00:00 2001 From: Laura Trotta Date: Mon, 31 Mar 2025 17:13:27 +0200 Subject: [PATCH 38/38] regen --- .../elasticsearch/doc-files/api-spec.html | 39 ------ .../ChatCompletionUnifiedRequest.java | 98 -------------- .../elasticsearch/inference/EisTaskType.java | 36 ----- .../ElasticsearchInferenceAsyncClient.java | 66 ---------- .../ElasticsearchInferenceClient.java | 66 ---------- .../PostEisChatCompletionRequest.java | 124 ------------------ .../inference/PutAlibabacloudRequest.java | 76 ----------- .../inference/PutAmazonbedrockRequest.java | 76 ----------- .../inference/PutAnthropicRequest.java | 76 ----------- .../inference/PutAzureaistudioRequest.java | 76 ----------- .../inference/PutAzureopenaiRequest.java | 76 ----------- .../inference/PutCohereRequest.java | 76 ----------- .../inference/PutEisRequest.java | 49 ------- .../inference/PutElasticsearchRequest.java | 76 ----------- .../inference/PutElserRequest.java | 75 ----------- .../inference/PutGoogleaistudioRequest.java | 75 ----------- .../inference/PutGooglevertexaiRequest.java | 76 ----------- .../inference/PutHuggingFaceRequest.java | 75 ----------- .../inference/PutJinaaiRequest.java | 76 ----------- .../inference/PutMistralRequest.java | 75 ----------- .../inference/PutOpenaiRequest.java | 50 ------- .../inference/PutVoyageaiRequest.java | 50 ------- .../inference/PutWatsonxRequest.java | 49 ------- .../inference/TextEmbeddingResponse.java | 90 ------------- 24 files changed, 1701 deletions(-) diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/doc-files/api-spec.html b/java-client/src/main/java/co/elastic/clients/elasticsearch/doc-files/api-spec.html index 4cd9caa47..654a4dd87 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/doc-files/api-spec.html +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/doc-files/api-spec.html @@ -26,15 +26,7 @@ '_global.create.Request': '_global/create/CreateRequest.ts#L35-L221', '_global.create.Response': '_global/create/CreateResponse.ts#L22-L25', '_global.delete.Request': '_global/delete/DeleteRequest.ts#L34-L146', -<<<<<<< HEAD -<<<<<<< HEAD '_global.delete.Response': '_global/delete/DeleteResponse.ts#L22-L35', -======= -'_global.delete.Response': '_global/delete/DeleteResponse.ts#L22-L34', ->>>>>>> 03828daff (regen from latest spec) -======= -'_global.delete.Response': '_global/delete/DeleteResponse.ts#L22-L35', ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) '_global.delete_by_query.Request': '_global/delete_by_query/DeleteByQueryRequest.ts#L36-L314', '_global.delete_by_query.Response': '_global/delete_by_query/DeleteByQueryResponse.ts#L26-L88', '_global.delete_by_query_rethrottle.Request': '_global/delete_by_query_rethrottle/DeleteByQueryRethrottleRequest.ts#L24-L55', @@ -1816,10 +1808,6 @@ 'inference._types.TextEmbeddingByteResult': 'inference/_types/Results.ts#L53-L58', 'inference._types.TextEmbeddingInferenceResult': 'inference/_types/Results.ts#L67-L75', 'inference._types.TextEmbeddingResult': 'inference/_types/Results.ts#L60-L65', -<<<<<<< HEAD -<<<<<<< HEAD -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) 'inference._types.ToolCall': 'inference/_types/CommonTypes.ts#L112-L128', 'inference._types.ToolCallFunction': 'inference/_types/CommonTypes.ts#L98-L110', 'inference._types.VoyageAIServiceSettings': 'inference/_types/CommonTypes.ts#L1075-L1106', @@ -1831,41 +1819,14 @@ 'inference._types.WatsonxTaskType': 'inference/_types/CommonTypes.ts#L1182-L1184', 'inference.chat_completion_unified.Request': 'inference/chat_completion_unified/UnifiedRequest.ts#L24-L53', 'inference.chat_completion_unified.Response': 'inference/chat_completion_unified/UnifiedResponse.ts#L22-L25', -<<<<<<< HEAD -======= -'inference.chat_completion_unified.CompletionTool': 'inference/chat_completion_unified/UnifiedRequest.ts#L180-L192', -'inference.chat_completion_unified.CompletionToolChoice': 'inference/chat_completion_unified/UnifiedRequest.ts#L143-L155', -'inference.chat_completion_unified.CompletionToolChoiceFunction': 'inference/chat_completion_unified/UnifiedRequest.ts#L132-L141', -'inference.chat_completion_unified.CompletionToolFunction': 'inference/chat_completion_unified/UnifiedRequest.ts#L157-L178', -'inference.chat_completion_unified.CompletionToolType': 'inference/chat_completion_unified/UnifiedRequest.ts#L54-L57', -'inference.chat_completion_unified.ContentObject': 'inference/chat_completion_unified/UnifiedRequest.ts#L59-L71', -'inference.chat_completion_unified.Message': 'inference/chat_completion_unified/UnifiedRequest.ts#L110-L130', -'inference.chat_completion_unified.MessageContent': 'inference/chat_completion_unified/UnifiedRequest.ts#L105-L108', -'inference.chat_completion_unified.Request': 'inference/chat_completion_unified/UnifiedRequest.ts#L25-L52', -'inference.chat_completion_unified.Response': 'inference/chat_completion_unified/UnifiedResponse.ts#L22-L24', -'inference.chat_completion_unified.ToolCall': 'inference/chat_completion_unified/UnifiedRequest.ts#L87-L103', -'inference.chat_completion_unified.ToolCallFunction': 'inference/chat_completion_unified/UnifiedRequest.ts#L73-L85', ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) 'inference.completion.Request': 'inference/completion/CompletionRequest.ts#L25-L63', 'inference.completion.Response': 'inference/completion/CompletionResponse.ts#L22-L25', 'inference.delete.Request': 'inference/delete/DeleteRequest.ts#L24-L66', 'inference.delete.Response': 'inference/delete/DeleteResponse.ts#L22-L25', 'inference.get.Request': 'inference/get/GetRequest.ts#L24-L56', 'inference.get.Response': 'inference/get/GetResponse.ts#L22-L26', -<<<<<<< HEAD -<<<<<<< HEAD -'inference.post_eis_chat_completion.Request': 'inference/post_eis_chat_completion/PostEisChatCompletionRequest.ts#L23-L48', -'inference.post_eis_chat_completion.Response': 'inference/post_eis_chat_completion/PostEisChatCompletionResponse.ts#L22-L25', -======= -'inference.post_eis_chat_completion.Request': 'inference/post_eis_chat_completion/PostEisChatCompletionRequest.ts#L23-L46', -'inference.post_eis_chat_completion.Response': 'inference/post_eis_chat_completion/PostEisChatCompletionResponse.ts#L22-L24', ->>>>>>> 03828daff (regen from latest spec) -======= 'inference.post_eis_chat_completion.Request': 'inference/post_eis_chat_completion/PostEisChatCompletionRequest.ts#L23-L48', 'inference.post_eis_chat_completion.Response': 'inference/post_eis_chat_completion/PostEisChatCompletionResponse.ts#L22-L25', ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) 'inference.put.Request': 'inference/put/PutRequest.ts#L25-L65', 'inference.put.Response': 'inference/put/PutResponse.ts#L22-L25', 'inference.put_alibabacloud.Request': 'inference/put_alibabacloud/PutAlibabaCloudRequest.ts#L30-L83', diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ChatCompletionUnifiedRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ChatCompletionUnifiedRequest.java index 8b44188a6..4b2bb22e2 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ChatCompletionUnifiedRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ChatCompletionUnifiedRequest.java @@ -35,17 +35,7 @@ import co.elastic.clients.util.ApiTypeHelper; import co.elastic.clients.util.ObjectBuilder; import jakarta.json.stream.JsonGenerator; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD import jakarta.json.stream.JsonParser; -======= ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= -import jakarta.json.stream.JsonParser; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import java.lang.String; import java.util.HashMap; import java.util.Map; @@ -84,38 +74,16 @@ public class ChatCompletionUnifiedRequest extends RequestBase implements JsonpSe @Nullable private final Time timeout; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - private final RequestChatCompletion chatCompletionRequest; - -======= ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private final RequestChatCompletion chatCompletionRequest; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // --------------------------------------------------------------------------------------------- private ChatCompletionUnifiedRequest(Builder builder) { this.inferenceId = ApiTypeHelper.requireNonNull(builder.inferenceId, this, "inferenceId"); this.timeout = builder.timeout; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - this.chatCompletionRequest = ApiTypeHelper.requireNonNull(builder.chatCompletionRequest, this, - "chatCompletionRequest"); -======= ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= this.chatCompletionRequest = ApiTypeHelper.requireNonNull(builder.chatCompletionRequest, this, "chatCompletionRequest"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } @@ -142,11 +110,6 @@ public final Time timeout() { return this.timeout; } -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) /** * Required - Request body. */ @@ -162,13 +125,6 @@ public void serialize(JsonGenerator generator, JsonpMapper mapper) { } -<<<<<<< HEAD -======= ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // --------------------------------------------------------------------------------------------- /** @@ -183,19 +139,8 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private Time timeout; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD private RequestChatCompletion chatCompletionRequest; -======= ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private RequestChatCompletion chatCompletionRequest; - ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) /** * Required - The inference Id *

@@ -225,11 +170,6 @@ public final Builder timeout(Function> fn) { return this.timeout(fn.apply(new Time.Builder()).build()); } -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) /** * Required - Request body. */ @@ -255,13 +195,6 @@ public Builder withJson(JsonParser parser, JsonpMapper mapper) { return this.chatCompletionRequest(value); } -<<<<<<< HEAD -======= ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) @Override protected Builder self() { return this; @@ -280,36 +213,6 @@ public ChatCompletionUnifiedRequest build() { } } -<<<<<<< HEAD -<<<<<<< HEAD - public static final JsonpDeserializer _DESERIALIZER = createChatCompletionUnifiedRequestDeserializer(); - protected static JsonpDeserializer createChatCompletionUnifiedRequestDeserializer() { - -<<<<<<< HEAD - JsonpDeserializer valueDeserializer = RequestChatCompletion._DESERIALIZER; -======= -======= - // --------------------------------------------------------------------------------------------- - ->>>>>>> c49af58dc (Revert "temp rebase fix") - /** - * Json deserializer for {@link ChatCompletionUnifiedRequest} - */ - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer - .lazy(Builder::new, ChatCompletionUnifiedRequest::setupChatCompletionUnifiedRequestDeserializer); - - protected static void setupChatCompletionUnifiedRequestDeserializer( - ObjectDeserializer op) { - RequestChatCompletionBase.setupRequestChatCompletionBaseDeserializer(op); -<<<<<<< HEAD ->>>>>>> 03828daff (regen from latest spec) - - return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() - .chatCompletionRequest(valueDeserializer.deserialize(parser, mapper, event)).build()); -======= - ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public static final JsonpDeserializer _DESERIALIZER = createChatCompletionUnifiedRequestDeserializer(); protected static JsonpDeserializer createChatCompletionUnifiedRequestDeserializer() { @@ -317,7 +220,6 @@ protected static JsonpDeserializer createChatCompl return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() .chatCompletionRequest(valueDeserializer.deserialize(parser, mapper, event)).build()); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } // --------------------------------------------------------------------------------------------- diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java index 8c6278aa1..e9f2597a9 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java @@ -17,19 +17,7 @@ * under the License. */ -<<<<<<< HEAD -<<<<<<< HEAD:java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java package co.elastic.clients.elasticsearch.inference; -======= -<<<<<<<< HEAD:java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/ServiceType.java -package co.elastic.clients.elasticsearch.inference.put_voyageai; -======== -package co.elastic.clients.elasticsearch.inference.put_openai; ->>>>>>>> c86960dc6 (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java ->>>>>>> 03828daff (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java -======= -package co.elastic.clients.elasticsearch.inference; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonEnum; import co.elastic.clients.json.JsonpDeserializable; @@ -52,36 +40,12 @@ >>>>>>> b5f478d93 ([codegen] update to latest spec and generator) /** * -<<<<<<< HEAD -<<<<<<< HEAD:java-client/src/main/java/co/elastic/clients/elasticsearch/inference/EisTaskType.java -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * @see API * specification */ @JsonpDeserializable public enum EisTaskType implements JsonEnum { ChatCompletion("chat_completion"), -<<<<<<< HEAD -======= - * @see API -======== - * "../../doc-files/api-spec.html#inference.put_openai.ServiceType">API ->>>>>>>> c86960dc6 (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java - * specification - */ -@JsonpDeserializable -public enum ServiceType implements JsonEnum { -<<<<<<<< HEAD:java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_voyageai/ServiceType.java - Voyageai("voyageai"), -======== - Openai("openai"), ->>>>>>>> c86960dc6 (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java ->>>>>>> 03828daff (regen from latest spec):java-client/src/main/java/co/elastic/clients/elasticsearch/inference/put_openai/ServiceType.java -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) ; diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceAsyncClient.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceAsyncClient.java index ea4611142..940c51544 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceAsyncClient.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceAsyncClient.java @@ -320,10 +320,6 @@ public final CompletableFuture put(Function>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // ----- Endpoint: inference.put_alibabacloud /** @@ -726,11 +722,6 @@ public final CompletableFuture putCohere( return putCohere(fn.apply(new PutCohereRequest.Builder()).build()); } -<<<<<<< HEAD -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // ----- Endpoint: inference.put_eis /** @@ -740,15 +731,7 @@ >>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * Inference Service (EIS). * * @see Documentation -======= - * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-eis.html">Documentation ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - * "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-eis">Documentation ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * on elastic.co */ @@ -769,15 +752,7 @@ public CompletableFuture putEis(PutEisRequest request) { * a function that initializes a builder to create the * {@link PutEisRequest} * @see Documentation -======= - * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-eis.html">Documentation ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= * "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-eis">Documentation ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * on elastic.co */ @@ -786,10 +761,6 @@ public final CompletableFuture putEis( return putEis(fn.apply(new PutEisRequest.Builder()).build()); } -<<<<<<< HEAD -<<<<<<< HEAD -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // ----- Endpoint: inference.put_elasticsearch /** @@ -1317,26 +1288,13 @@ public final CompletableFuture putMistral( return putMistral(fn.apply(new PutMistralRequest.Builder()).build()); } -<<<<<<< HEAD -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // ----- Endpoint: inference.put_openai /** * Create an OpenAI inference endpoint. *

* Create an inference endpoint to perform an inference task with the -<<<<<<< HEAD -<<<<<<< HEAD - * openai service or openai compatible APIs. -======= - * openai service. ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= * openai service or openai compatible APIs. ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) *

* When you create an inference endpoint, the associated machine learning model * is automatically deployed if it is not already running. After creating the @@ -1349,15 +1307,7 @@ >>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * consumes significant resources. * * @see Documentation -======= - * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-openai.html">Documentation ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - * "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-openai">Documentation ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * on elastic.co */ @@ -1372,15 +1322,7 @@ public CompletableFuture putOpenai(PutOpenaiRequest request) * Create an OpenAI inference endpoint. *

* Create an inference endpoint to perform an inference task with the -<<<<<<< HEAD -<<<<<<< HEAD - * openai service or openai compatible APIs. -======= - * openai service. ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= * openai service or openai compatible APIs. ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) *

* When you create an inference endpoint, the associated machine learning model * is automatically deployed if it is not already running. After creating the @@ -1396,15 +1338,7 @@ >>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * a function that initializes a builder to create the * {@link PutOpenaiRequest} * @see Documentation -======= - * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-openai.html">Documentation ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= * "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-openai">Documentation ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * on elastic.co */ diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceClient.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceClient.java index e0d5adb10..b9ac0f07f 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceClient.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/ElasticsearchInferenceClient.java @@ -324,10 +324,6 @@ public final PutResponse put(Function>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // ----- Endpoint: inference.put_alibabacloud /** @@ -739,11 +735,6 @@ public final PutCohereResponse putCohere(Function>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // ----- Endpoint: inference.put_eis /** @@ -753,15 +744,7 @@ >>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * Inference Service (EIS). * * @see Documentation -======= - * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-eis.html">Documentation ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - * "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-eis">Documentation ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * on elastic.co */ @@ -782,15 +765,7 @@ public PutEisResponse putEis(PutEisRequest request) throws IOException, Elastics * a function that initializes a builder to create the * {@link PutEisRequest} * @see Documentation -======= - * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-eis.html">Documentation ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= * "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-eis">Documentation ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * on elastic.co */ @@ -799,10 +774,6 @@ public final PutEisResponse putEis(Function>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // ----- Endpoint: inference.put_elasticsearch /** @@ -1338,26 +1309,13 @@ public final PutMistralResponse putMistral(Function>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // ----- Endpoint: inference.put_openai /** * Create an OpenAI inference endpoint. *

* Create an inference endpoint to perform an inference task with the -<<<<<<< HEAD -<<<<<<< HEAD - * openai service or openai compatible APIs. -======= - * openai service. ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= * openai service or openai compatible APIs. ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) *

* When you create an inference endpoint, the associated machine learning model * is automatically deployed if it is not already running. After creating the @@ -1370,15 +1328,7 @@ >>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * consumes significant resources. * * @see Documentation -======= - * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-openai.html">Documentation ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - * "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-openai">Documentation ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * on elastic.co */ @@ -1393,15 +1343,7 @@ public PutOpenaiResponse putOpenai(PutOpenaiRequest request) throws IOException, * Create an OpenAI inference endpoint. *

* Create an inference endpoint to perform an inference task with the -<<<<<<< HEAD -<<<<<<< HEAD - * openai service or openai compatible APIs. -======= - * openai service. ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= * openai service or openai compatible APIs. ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) *

* When you create an inference endpoint, the associated machine learning model * is automatically deployed if it is not already running. After creating the @@ -1417,15 +1359,7 @@ >>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * a function that initializes a builder to create the * {@link PutOpenaiRequest} * @see Documentation -======= - * "https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-openai.html">Documentation ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= * "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-openai">Documentation ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * on elastic.co */ diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PostEisChatCompletionRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PostEisChatCompletionRequest.java index 56c847756..ae994a764 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PostEisChatCompletionRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PostEisChatCompletionRequest.java @@ -20,27 +20,11 @@ package co.elastic.clients.elasticsearch.inference; import co.elastic.clients.elasticsearch._types.ErrorResponse; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.elasticsearch._types.RequestBase; import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; import co.elastic.clients.json.JsonpSerializable; -<<<<<<< HEAD -======= -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; ->>>>>>> 03828daff (regen from latest spec) -======= -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.ObjectBuilderDeserializer; import co.elastic.clients.json.ObjectDeserializer; import co.elastic.clients.transport.Endpoint; @@ -50,17 +34,7 @@ >>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.util.ApiTypeHelper; import co.elastic.clients.util.ObjectBuilder; import jakarta.json.stream.JsonGenerator; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD import jakarta.json.stream.JsonParser; -======= ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= -import jakarta.json.stream.JsonParser; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import java.lang.String; import java.util.Collections; import java.util.HashMap; @@ -97,28 +71,7 @@ >>>>>>> b5f478d93 ([codegen] update to latest spec and generator) * specification */ @JsonpDeserializable -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -public class PostEisChatCompletionRequest extends RequestBase implements JsonpSerializable { - private final String eisInferenceId; - - private final RequestChatCompletion chatCompletionRequest; - - // --------------------------------------------------------------------------------------------- - - private PostEisChatCompletionRequest(Builder builder) { - - this.eisInferenceId = ApiTypeHelper.requireNonNull(builder.eisInferenceId, this, "eisInferenceId"); - this.chatCompletionRequest = ApiTypeHelper.requireNonNull(builder.chatCompletionRequest, this, - "chatCompletionRequest"); -======= -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -public class PostEisChatCompletionRequest extends RequestChatCompletionBase { -======= public class PostEisChatCompletionRequest extends RequestBase implements JsonpSerializable { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final String eisInferenceId; private final RequestChatCompletion chatCompletionRequest; @@ -128,15 +81,8 @@ >>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private PostEisChatCompletionRequest(Builder builder) { this.eisInferenceId = ApiTypeHelper.requireNonNull(builder.eisInferenceId, this, "eisInferenceId"); -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= this.chatCompletionRequest = ApiTypeHelper.requireNonNull(builder.chatCompletionRequest, this, "chatCompletionRequest"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } @@ -153,11 +99,6 @@ public final String eisInferenceId() { return this.eisInferenceId; } -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) /** * Required - Request body. */ @@ -173,49 +114,19 @@ public void serialize(JsonGenerator generator, JsonpMapper mapper) { } -<<<<<<< HEAD -======= ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // --------------------------------------------------------------------------------------------- /** * Builder for {@link PostEisChatCompletionRequest}. */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - public static class Builder extends RequestBase.AbstractBuilder -======= - public static class Builder extends RequestChatCompletionBase.AbstractBuilder ->>>>>>> 03828daff (regen from latest spec) -======= - public static class Builder extends RequestChatCompletionBase.AbstractBuilder ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public static class Builder extends RequestBase.AbstractBuilder ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) implements ObjectBuilder { private String eisInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD private RequestChatCompletion chatCompletionRequest; -======= ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private RequestChatCompletion chatCompletionRequest; - ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) /** * Required - The unique identifier of the inference endpoint. *

@@ -226,11 +137,6 @@ public final Builder eisInferenceId(String value) { return this; } -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) /** * Required - Request body. */ @@ -256,13 +162,6 @@ public Builder withJson(JsonParser parser, JsonpMapper mapper) { return this.chatCompletionRequest(value); } -<<<<<<< HEAD -======= ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) @Override protected Builder self() { return this; @@ -281,36 +180,13 @@ public PostEisChatCompletionRequest build() { } } -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - public static final JsonpDeserializer _DESERIALIZER = createPostEisChatCompletionRequestDeserializer(); - protected static JsonpDeserializer createPostEisChatCompletionRequestDeserializer() { - - JsonpDeserializer valueDeserializer = RequestChatCompletion._DESERIALIZER; - - return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() - .chatCompletionRequest(valueDeserializer.deserialize(parser, mapper, event)).build()); -======= -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") - // --------------------------------------------------------------------------------------------- -======= public static final JsonpDeserializer _DESERIALIZER = createPostEisChatCompletionRequestDeserializer(); protected static JsonpDeserializer createPostEisChatCompletionRequestDeserializer() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) JsonpDeserializer valueDeserializer = RequestChatCompletion._DESERIALIZER; -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() .chatCompletionRequest(valueDeserializer.deserialize(parser, mapper, event)).build()); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } // --------------------------------------------------------------------------------------------- diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudRequest.java index bc4d55475..c0954788d 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAlibabacloudRequest.java @@ -21,22 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -import co.elastic.clients.elasticsearch.inference.put_alibabacloud.AlibabaCloudServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_alibabacloud.AlibabaCloudTaskSettings; -import co.elastic.clients.elasticsearch.inference.put_alibabacloud.AlibabaCloudTaskType; -import co.elastic.clients.elasticsearch.inference.put_alibabacloud.ServiceType; -<<<<<<< HEAD ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -100,19 +84,7 @@ public class PutAlibabacloudRequest extends RequestBase implements JsonpSerializ @Nullable private final InferenceChunkingSettings chunkingSettings; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD private final AlibabaCloudServiceType service; -======= - private final ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final AlibabaCloudServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final AlibabaCloudServiceSettings serviceSettings; @@ -164,19 +136,7 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - public final AlibabaCloudServiceType service() { -======= - public final ServiceType service() { ->>>>>>> 03828daff (regen from latest spec) -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final AlibabaCloudServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -253,19 +213,7 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - private AlibabaCloudServiceType service; -======= - private ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private AlibabaCloudServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private AlibabaCloudServiceSettings serviceSettings; @@ -310,19 +258,7 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(AlibabaCloudServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> 03828daff (regen from latest spec) -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(AlibabaCloudServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -411,19 +347,7 @@ protected static void setupPutAlibabacloudRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, AlibabaCloudServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> 03828daff (regen from latest spec) -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, AlibabaCloudServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, AlibabaCloudServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AlibabaCloudTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockRequest.java index fe53c4bc7..55b01e4bf 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAmazonbedrockRequest.java @@ -21,22 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -import co.elastic.clients.elasticsearch.inference.put_amazonbedrock.AmazonBedrockServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_amazonbedrock.AmazonBedrockTaskSettings; -import co.elastic.clients.elasticsearch.inference.put_amazonbedrock.AmazonBedrockTaskType; -import co.elastic.clients.elasticsearch.inference.put_amazonbedrock.ServiceType; -<<<<<<< HEAD ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -109,19 +93,7 @@ public class PutAmazonbedrockRequest extends RequestBase implements JsonpSeriali @Nullable private final InferenceChunkingSettings chunkingSettings; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD private final AmazonBedrockServiceType service; -======= - private final ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final AmazonBedrockServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final AmazonBedrockServiceSettings serviceSettings; @@ -173,19 +145,7 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - public final AmazonBedrockServiceType service() { -======= - public final ServiceType service() { ->>>>>>> 03828daff (regen from latest spec) -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final AmazonBedrockServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -262,19 +222,7 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - private AmazonBedrockServiceType service; -======= - private ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private AmazonBedrockServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private AmazonBedrockServiceSettings serviceSettings; @@ -319,19 +267,7 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(AmazonBedrockServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> 03828daff (regen from latest spec) -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(AmazonBedrockServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -420,19 +356,7 @@ protected static void setupPutAmazonbedrockRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, AmazonBedrockServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> 03828daff (regen from latest spec) -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, AmazonBedrockServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, AmazonBedrockServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AmazonBedrockTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicRequest.java index 564d81bb7..2d1507c5e 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAnthropicRequest.java @@ -21,22 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -import co.elastic.clients.elasticsearch.inference.put_anthropic.AnthropicServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_anthropic.AnthropicTaskSettings; -import co.elastic.clients.elasticsearch.inference.put_anthropic.AnthropicTaskType; -import co.elastic.clients.elasticsearch.inference.put_anthropic.ServiceType; -<<<<<<< HEAD ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -99,19 +83,7 @@ public class PutAnthropicRequest extends RequestBase implements JsonpSerializabl @Nullable private final InferenceChunkingSettings chunkingSettings; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD private final AnthropicServiceType service; -======= - private final ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final AnthropicServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final AnthropicServiceSettings serviceSettings; @@ -163,19 +135,7 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - public final AnthropicServiceType service() { -======= - public final ServiceType service() { ->>>>>>> 03828daff (regen from latest spec) -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final AnthropicServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -253,19 +213,7 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - private AnthropicServiceType service; -======= - private ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private AnthropicServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private AnthropicServiceSettings serviceSettings; @@ -310,19 +258,7 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(AnthropicServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> 03828daff (regen from latest spec) -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(AnthropicServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -411,19 +347,7 @@ public PutAnthropicRequest build() { protected static void setupPutAnthropicRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, AnthropicServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> 03828daff (regen from latest spec) -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, AnthropicServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, AnthropicServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AnthropicTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioRequest.java index 6c84a9940..3a0d1ef54 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureaistudioRequest.java @@ -21,22 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -import co.elastic.clients.elasticsearch.inference.put_azureaistudio.AzureAiStudioServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_azureaistudio.AzureAiStudioTaskSettings; -import co.elastic.clients.elasticsearch.inference.put_azureaistudio.AzureAiStudioTaskType; -import co.elastic.clients.elasticsearch.inference.put_azureaistudio.ServiceType; -<<<<<<< HEAD ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -100,19 +84,7 @@ public class PutAzureaistudioRequest extends RequestBase implements JsonpSeriali @Nullable private final InferenceChunkingSettings chunkingSettings; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD private final AzureAiStudioServiceType service; -======= - private final ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final AzureAiStudioServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final AzureAiStudioServiceSettings serviceSettings; @@ -164,19 +136,7 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - public final AzureAiStudioServiceType service() { -======= - public final ServiceType service() { ->>>>>>> 03828daff (regen from latest spec) -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final AzureAiStudioServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -253,19 +213,7 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - private AzureAiStudioServiceType service; -======= - private ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private AzureAiStudioServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private AzureAiStudioServiceSettings serviceSettings; @@ -310,19 +258,7 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(AzureAiStudioServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> 03828daff (regen from latest spec) -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(AzureAiStudioServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -411,19 +347,7 @@ protected static void setupPutAzureaistudioRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, AzureAiStudioServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> 03828daff (regen from latest spec) -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, AzureAiStudioServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, AzureAiStudioServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AzureAiStudioTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiRequest.java index 0eb1d17e7..9b14d99ec 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutAzureopenaiRequest.java @@ -21,22 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -import co.elastic.clients.elasticsearch.inference.put_azureopenai.AzureOpenAIServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_azureopenai.AzureOpenAITaskSettings; -import co.elastic.clients.elasticsearch.inference.put_azureopenai.AzureOpenAITaskType; -import co.elastic.clients.elasticsearch.inference.put_azureopenai.ServiceType; -<<<<<<< HEAD ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -115,19 +99,7 @@ public class PutAzureopenaiRequest extends RequestBase implements JsonpSerializa @Nullable private final InferenceChunkingSettings chunkingSettings; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD private final AzureOpenAIServiceType service; -======= - private final ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final AzureOpenAIServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final AzureOpenAIServiceSettings serviceSettings; @@ -179,19 +151,7 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - public final AzureOpenAIServiceType service() { -======= - public final ServiceType service() { ->>>>>>> 03828daff (regen from latest spec) -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final AzureOpenAIServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -270,19 +230,7 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - private AzureOpenAIServiceType service; -======= - private ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private AzureOpenAIServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private AzureOpenAIServiceSettings serviceSettings; @@ -327,19 +275,7 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(AzureOpenAIServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> 03828daff (regen from latest spec) -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(AzureOpenAIServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -429,19 +365,7 @@ public PutAzureopenaiRequest build() { protected static void setupPutAzureopenaiRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, AzureOpenAIServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> 03828daff (regen from latest spec) -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, AzureOpenAIServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, AzureOpenAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, AzureOpenAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereRequest.java index 9c75cf425..26de9cff1 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutCohereRequest.java @@ -21,22 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -import co.elastic.clients.elasticsearch.inference.put_cohere.CohereServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_cohere.CohereTaskSettings; -import co.elastic.clients.elasticsearch.inference.put_cohere.CohereTaskType; -import co.elastic.clients.elasticsearch.inference.put_cohere.ServiceType; -<<<<<<< HEAD ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -99,19 +83,7 @@ public class PutCohereRequest extends RequestBase implements JsonpSerializable { private final String cohereInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD private final CohereServiceType service; -======= - private final ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final CohereServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final CohereServiceSettings serviceSettings; @@ -162,19 +134,7 @@ public final String cohereInferenceId() { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - public final CohereServiceType service() { -======= - public final ServiceType service() { ->>>>>>> 03828daff (regen from latest spec) -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final CohereServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -251,19 +211,7 @@ public static class Builder extends RequestBase.AbstractBuilder private String cohereInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - private CohereServiceType service; -======= - private ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private CohereServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private CohereServiceSettings serviceSettings; @@ -308,19 +256,7 @@ public final Builder cohereInferenceId(String value) { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(CohereServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> 03828daff (regen from latest spec) -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(CohereServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -407,19 +343,7 @@ public PutCohereRequest build() { protected static void setupPutCohereRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, CohereServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> 03828daff (regen from latest spec) -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, CohereServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, CohereServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, CohereTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisRequest.java index 29e105d3e..cf752f4e6 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutEisRequest.java @@ -21,15 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -======= -import co.elastic.clients.elasticsearch.inference.put_eis.EisServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_eis.EisTaskType; -import co.elastic.clients.elasticsearch.inference.put_eis.ServiceType; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -79,15 +70,7 @@ >>>>>>> b5f478d93 ([codegen] update to latest spec and generator) public class PutEisRequest extends RequestBase implements JsonpSerializable { private final String eisInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD private final EisServiceType service; -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final EisServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final EisServiceSettings serviceSettings; @@ -123,15 +106,7 @@ public final String eisInferenceId() { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD - public final EisServiceType service() { -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final EisServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -183,15 +158,7 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { public static class Builder extends RequestBase.AbstractBuilder implements ObjectBuilder { private String eisInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD - private EisServiceType service; -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private EisServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private EisServiceSettings serviceSettings; @@ -213,15 +180,7 @@ public final Builder eisInferenceId(String value) { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(EisServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(EisServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -288,15 +247,7 @@ public PutEisRequest build() { protected static void setupPutEisRequestDeserializer(ObjectDeserializer op) { -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, EisServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, EisServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, EisServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchRequest.java index 512fcb38d..26747fe1a 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElasticsearchRequest.java @@ -21,22 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -import co.elastic.clients.elasticsearch.inference.put_elasticsearch.ElasticsearchServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_elasticsearch.ElasticsearchTaskSettings; -import co.elastic.clients.elasticsearch.inference.put_elasticsearch.ElasticsearchTaskType; -import co.elastic.clients.elasticsearch.inference.put_elasticsearch.ServiceType; -<<<<<<< HEAD ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -117,19 +101,7 @@ public class PutElasticsearchRequest extends RequestBase implements JsonpSeriali private final String elasticsearchInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD private final ElasticsearchServiceType service; -======= - private final ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final ElasticsearchServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final ElasticsearchServiceSettings serviceSettings; @@ -182,19 +154,7 @@ public final String elasticsearchInferenceId() { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - public final ElasticsearchServiceType service() { -======= - public final ServiceType service() { ->>>>>>> 03828daff (regen from latest spec) -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final ElasticsearchServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -271,19 +231,7 @@ public static class Builder extends RequestBase.AbstractBuilder private String elasticsearchInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - private ElasticsearchServiceType service; -======= - private ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private ElasticsearchServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private ElasticsearchServiceSettings serviceSettings; @@ -329,19 +277,7 @@ public final Builder elasticsearchInferenceId(String value) { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(ElasticsearchServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> 03828daff (regen from latest spec) -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(ElasticsearchServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -430,19 +366,7 @@ protected static void setupPutElasticsearchRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, ElasticsearchServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> 03828daff (regen from latest spec) -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, ElasticsearchServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, ElasticsearchServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, ElasticsearchTaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserRequest.java index d28b829d7..8ead10e62 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutElserRequest.java @@ -21,21 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= -import co.elastic.clients.elasticsearch.inference.put_elser.ElserServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_elser.ElserTaskType; -import co.elastic.clients.elasticsearch.inference.put_elser.ServiceType; ->>>>>>> 03828daff (regen from latest spec) -======= -import co.elastic.clients.elasticsearch.inference.put_elser.ElserServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_elser.ElserTaskType; -import co.elastic.clients.elasticsearch.inference.put_elser.ServiceType; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -119,19 +104,7 @@ public class PutElserRequest extends RequestBase implements JsonpSerializable { private final String elserInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD private final ElserServiceType service; -======= - private final ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final ElserServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final ElserServiceSettings serviceSettings; @@ -178,19 +151,7 @@ public final String elserInferenceId() { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - public final ElserServiceType service() { -======= - public final ServiceType service() { ->>>>>>> 03828daff (regen from latest spec) -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final ElserServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -248,19 +209,7 @@ public static class Builder extends RequestBase.AbstractBuilder impleme private String elserInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - private ElserServiceType service; -======= - private ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private ElserServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private ElserServiceSettings serviceSettings; @@ -302,19 +251,7 @@ public final Builder elserInferenceId(String value) { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(ElserServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> 03828daff (regen from latest spec) -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(ElserServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -380,19 +317,7 @@ public PutElserRequest build() { protected static void setupPutElserRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, ElserServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> 03828daff (regen from latest spec) -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, ElserServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, ElserServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioRequest.java index 185eec74e..fb2949825 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGoogleaistudioRequest.java @@ -21,21 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= -import co.elastic.clients.elasticsearch.inference.put_googleaistudio.GoogleAiStudioServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_googleaistudio.GoogleAiStudioTaskType; -import co.elastic.clients.elasticsearch.inference.put_googleaistudio.ServiceType; ->>>>>>> 03828daff (regen from latest spec) -======= -import co.elastic.clients.elasticsearch.inference.put_googleaistudio.GoogleAiStudioServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_googleaistudio.GoogleAiStudioTaskType; -import co.elastic.clients.elasticsearch.inference.put_googleaistudio.ServiceType; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -99,19 +84,7 @@ public class PutGoogleaistudioRequest extends RequestBase implements JsonpSerial private final String googleaistudioInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD private final GoogleAiServiceType service; -======= - private final ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final GoogleAiServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final GoogleAiStudioServiceSettings serviceSettings; @@ -159,19 +132,7 @@ public final String googleaistudioInferenceId() { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - public final GoogleAiServiceType service() { -======= - public final ServiceType service() { ->>>>>>> 03828daff (regen from latest spec) -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final GoogleAiServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -231,19 +192,7 @@ public static class Builder extends RequestBase.AbstractBuilder private String googleaistudioInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - private GoogleAiServiceType service; -======= - private ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private GoogleAiServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private GoogleAiStudioServiceSettings serviceSettings; @@ -285,19 +234,7 @@ public final Builder googleaistudioInferenceId(String value) { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(GoogleAiServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> 03828daff (regen from latest spec) -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(GoogleAiServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -364,19 +301,7 @@ protected static void setupPutGoogleaistudioRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, GoogleAiServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> 03828daff (regen from latest spec) -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, GoogleAiServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, GoogleAiStudioServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiRequest.java index 808122ab7..c491288d4 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutGooglevertexaiRequest.java @@ -21,22 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -import co.elastic.clients.elasticsearch.inference.put_googlevertexai.GoogleVertexAIServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_googlevertexai.GoogleVertexAITaskSettings; -import co.elastic.clients.elasticsearch.inference.put_googlevertexai.GoogleVertexAITaskType; -import co.elastic.clients.elasticsearch.inference.put_googlevertexai.ServiceType; -<<<<<<< HEAD ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -100,19 +84,7 @@ public class PutGooglevertexaiRequest extends RequestBase implements JsonpSerial private final String googlevertexaiInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD private final GoogleVertexAIServiceType service; -======= - private final ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final GoogleVertexAIServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final GoogleVertexAIServiceSettings serviceSettings; @@ -164,19 +136,7 @@ public final String googlevertexaiInferenceId() { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - public final GoogleVertexAIServiceType service() { -======= - public final ServiceType service() { ->>>>>>> 03828daff (regen from latest spec) -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final GoogleVertexAIServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -253,19 +213,7 @@ public static class Builder extends RequestBase.AbstractBuilder private String googlevertexaiInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - private GoogleVertexAIServiceType service; -======= - private ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private GoogleVertexAIServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private GoogleVertexAIServiceSettings serviceSettings; @@ -310,19 +258,7 @@ public final Builder googlevertexaiInferenceId(String value) { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(GoogleVertexAIServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> 03828daff (regen from latest spec) -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(GoogleVertexAIServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -411,19 +347,7 @@ protected static void setupPutGooglevertexaiRequestDeserializer( ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, GoogleVertexAIServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> 03828daff (regen from latest spec) -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, GoogleVertexAIServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, GoogleVertexAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, GoogleVertexAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceRequest.java index 072cc78e7..3b081c97f 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutHuggingFaceRequest.java @@ -21,21 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= -import co.elastic.clients.elasticsearch.inference.put_hugging_face.HuggingFaceServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_hugging_face.HuggingFaceTaskType; -import co.elastic.clients.elasticsearch.inference.put_hugging_face.ServiceType; ->>>>>>> 03828daff (regen from latest spec) -======= -import co.elastic.clients.elasticsearch.inference.put_hugging_face.HuggingFaceServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_hugging_face.HuggingFaceTaskType; -import co.elastic.clients.elasticsearch.inference.put_hugging_face.ServiceType; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -117,19 +102,7 @@ public class PutHuggingFaceRequest extends RequestBase implements JsonpSerializa private final String huggingfaceInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD private final HuggingFaceServiceType service; -======= - private final ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final HuggingFaceServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final HuggingFaceServiceSettings serviceSettings; @@ -177,19 +150,7 @@ public final String huggingfaceInferenceId() { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - public final HuggingFaceServiceType service() { -======= - public final ServiceType service() { ->>>>>>> 03828daff (regen from latest spec) -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final HuggingFaceServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -249,19 +210,7 @@ public static class Builder extends RequestBase.AbstractBuilder private String huggingfaceInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - private HuggingFaceServiceType service; -======= - private ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private HuggingFaceServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private HuggingFaceServiceSettings serviceSettings; @@ -303,19 +252,7 @@ public final Builder huggingfaceInferenceId(String value) { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(HuggingFaceServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> 03828daff (regen from latest spec) -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(HuggingFaceServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -381,19 +318,7 @@ public PutHuggingFaceRequest build() { protected static void setupPutHuggingFaceRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, HuggingFaceServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> 03828daff (regen from latest spec) -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, HuggingFaceServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, HuggingFaceServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiRequest.java index b7aff29fa..ab9b47ccb 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutJinaaiRequest.java @@ -21,22 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -import co.elastic.clients.elasticsearch.inference.put_jinaai.JinaAIServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_jinaai.JinaAITaskSettings; -import co.elastic.clients.elasticsearch.inference.put_jinaai.JinaAITaskType; -import co.elastic.clients.elasticsearch.inference.put_jinaai.ServiceType; -<<<<<<< HEAD ->>>>>>> 03828daff (regen from latest spec) -======= ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -104,19 +88,7 @@ public class PutJinaaiRequest extends RequestBase implements JsonpSerializable { private final String jinaaiInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD private final JinaAIServiceType service; -======= - private final ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final JinaAIServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final JinaAIServiceSettings serviceSettings; @@ -167,19 +139,7 @@ public final String jinaaiInferenceId() { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - public final JinaAIServiceType service() { -======= - public final ServiceType service() { ->>>>>>> 03828daff (regen from latest spec) -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final JinaAIServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -256,19 +216,7 @@ public static class Builder extends RequestBase.AbstractBuilder private String jinaaiInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - private JinaAIServiceType service; -======= - private ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private JinaAIServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private JinaAIServiceSettings serviceSettings; @@ -313,19 +261,7 @@ public final Builder jinaaiInferenceId(String value) { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(JinaAIServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> 03828daff (regen from latest spec) -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(JinaAIServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -412,19 +348,7 @@ public PutJinaaiRequest build() { protected static void setupPutJinaaiRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, JinaAIServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> 03828daff (regen from latest spec) -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, JinaAIServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, JinaAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, JinaAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralRequest.java index 81b494927..cde473677 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutMistralRequest.java @@ -21,21 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= -import co.elastic.clients.elasticsearch.inference.put_mistral.MistralServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_mistral.MistralTaskType; -import co.elastic.clients.elasticsearch.inference.put_mistral.ServiceType; ->>>>>>> 03828daff (regen from latest spec) -======= -import co.elastic.clients.elasticsearch.inference.put_mistral.MistralServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_mistral.MistralTaskType; -import co.elastic.clients.elasticsearch.inference.put_mistral.ServiceType; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -98,19 +83,7 @@ public class PutMistralRequest extends RequestBase implements JsonpSerializable private final String mistralInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD private final MistralServiceType service; -======= - private final ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final MistralServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final MistralServiceSettings serviceSettings; @@ -157,19 +130,7 @@ public final String mistralInferenceId() { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - public final MistralServiceType service() { -======= - public final ServiceType service() { ->>>>>>> 03828daff (regen from latest spec) -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final MistralServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -230,19 +191,7 @@ public static class Builder extends RequestBase.AbstractBuilder private String mistralInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - private MistralServiceType service; -======= - private ServiceType service; ->>>>>>> 03828daff (regen from latest spec) -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private MistralServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private MistralServiceSettings serviceSettings; @@ -284,19 +233,7 @@ public final Builder mistralInferenceId(String value) { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(MistralServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> 03828daff (regen from latest spec) -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(MistralServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -363,19 +300,7 @@ public PutMistralRequest build() { protected static void setupPutMistralRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, MistralServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> 03828daff (regen from latest spec) -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, MistralServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, MistralServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiRequest.java index 73e6c00e9..2b10fe33f 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutOpenaiRequest.java @@ -21,16 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -======= -import co.elastic.clients.elasticsearch.inference.put_openai.OpenAIServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_openai.OpenAITaskSettings; -import co.elastic.clients.elasticsearch.inference.put_openai.OpenAITaskType; -import co.elastic.clients.elasticsearch.inference.put_openai.ServiceType; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -93,15 +83,7 @@ public class PutOpenaiRequest extends RequestBase implements JsonpSerializable { private final String openaiInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD private final OpenAIServiceType service; -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final OpenAIServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final OpenAIServiceSettings serviceSettings; @@ -152,15 +134,7 @@ public final String openaiInferenceId() { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD - public final OpenAIServiceType service() { -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final OpenAIServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -239,15 +213,7 @@ public static class Builder extends RequestBase.AbstractBuilder private String openaiInferenceId; -<<<<<<< HEAD -<<<<<<< HEAD - private OpenAIServiceType service; -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private OpenAIServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private OpenAIServiceSettings serviceSettings; @@ -292,15 +258,7 @@ public final Builder openaiInferenceId(String value) { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(OpenAIServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(OpenAIServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -389,15 +347,7 @@ public PutOpenaiRequest build() { protected static void setupPutOpenaiRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, OpenAIServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, OpenAIServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, OpenAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, OpenAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiRequest.java index 97bfbea2e..d16468247 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutVoyageaiRequest.java @@ -21,16 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -======= -import co.elastic.clients.elasticsearch.inference.put_voyageai.ServiceType; -import co.elastic.clients.elasticsearch.inference.put_voyageai.VoyageAIServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_voyageai.VoyageAITaskSettings; -import co.elastic.clients.elasticsearch.inference.put_voyageai.VoyageAITaskType; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -84,15 +74,7 @@ public class PutVoyageaiRequest extends RequestBase implements JsonpSerializable @Nullable private final InferenceChunkingSettings chunkingSettings; -<<<<<<< HEAD -<<<<<<< HEAD private final VoyageAIServiceType service; -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final VoyageAIServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final VoyageAIServiceSettings serviceSettings; @@ -137,15 +119,7 @@ public final InferenceChunkingSettings chunkingSettings() { *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD - public final VoyageAIServiceType service() { -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final VoyageAIServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -229,15 +203,7 @@ public static class Builder extends RequestBase.AbstractBuilder @Nullable private InferenceChunkingSettings chunkingSettings; -<<<<<<< HEAD -<<<<<<< HEAD - private VoyageAIServiceType service; -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private VoyageAIServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private VoyageAIServiceSettings serviceSettings; @@ -274,15 +240,7 @@ public final Builder chunkingSettings( *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(VoyageAIServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(VoyageAIServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -380,15 +338,7 @@ public PutVoyageaiRequest build() { protected static void setupPutVoyageaiRequestDeserializer(ObjectDeserializer op) { op.add(Builder::chunkingSettings, InferenceChunkingSettings._DESERIALIZER, "chunking_settings"); -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, VoyageAIServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, VoyageAIServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, VoyageAIServiceSettings._DESERIALIZER, "service_settings"); op.add(Builder::taskSettings, VoyageAITaskSettings._DESERIALIZER, "task_settings"); diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxRequest.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxRequest.java index 05e3d282a..2529929f7 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxRequest.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/PutWatsonxRequest.java @@ -21,15 +21,6 @@ import co.elastic.clients.elasticsearch._types.ErrorResponse; import co.elastic.clients.elasticsearch._types.RequestBase; -<<<<<<< HEAD -<<<<<<< HEAD -======= -import co.elastic.clients.elasticsearch.inference.put_watsonx.ServiceType; -import co.elastic.clients.elasticsearch.inference.put_watsonx.WatsonxServiceSettings; -import co.elastic.clients.elasticsearch.inference.put_watsonx.WatsonxTaskType; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) import co.elastic.clients.json.JsonpDeserializable; import co.elastic.clients.json.JsonpDeserializer; import co.elastic.clients.json.JsonpMapper; @@ -90,15 +81,7 @@ >>>>>>> b5f478d93 ([codegen] update to latest spec and generator) */ @JsonpDeserializable public class PutWatsonxRequest extends RequestBase implements JsonpSerializable { -<<<<<<< HEAD -<<<<<<< HEAD private final WatsonxServiceType service; -======= - private final ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final WatsonxServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private final WatsonxServiceSettings serviceSettings; @@ -127,15 +110,7 @@ public static PutWatsonxRequest of(Function * API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD - public final WatsonxServiceType service() { -======= - public final ServiceType service() { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final WatsonxServiceType service() { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this.service; } @@ -195,15 +170,7 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { public static class Builder extends RequestBase.AbstractBuilder implements ObjectBuilder { -<<<<<<< HEAD -<<<<<<< HEAD - private WatsonxServiceType service; -======= - private ServiceType service; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private WatsonxServiceType service; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) private WatsonxServiceSettings serviceSettings; @@ -217,15 +184,7 @@ >>>>>>> b5f478d93 ([codegen] update to latest spec and generator) *

* API name: {@code service} */ -<<<<<<< HEAD -<<<<<<< HEAD public final Builder service(WatsonxServiceType value) { -======= - public final Builder service(ServiceType value) { ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder service(WatsonxServiceType value) { ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) this.service = value; return this; } @@ -301,15 +260,7 @@ public PutWatsonxRequest build() { protected static void setupPutWatsonxRequestDeserializer(ObjectDeserializer op) { -<<<<<<< HEAD -<<<<<<< HEAD - op.add(Builder::service, WatsonxServiceType._DESERIALIZER, "service"); -======= - op.add(Builder::service, ServiceType._DESERIALIZER, "service"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= op.add(Builder::service, WatsonxServiceType._DESERIALIZER, "service"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) op.add(Builder::serviceSettings, WatsonxServiceSettings._DESERIALIZER, "service_settings"); } diff --git a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResponse.java b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResponse.java index d0811ab69..6672e9c9a 100644 --- a/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResponse.java +++ b/java-client/src/main/java/co/elastic/clients/elasticsearch/inference/TextEmbeddingResponse.java @@ -60,29 +60,13 @@ */ @JsonpDeserializable public class TextEmbeddingResponse implements JsonpSerializable { -<<<<<<< HEAD -<<<<<<< HEAD private final TextEmbeddingInferenceResult inferenceResult; -======= - private final TextEmbeddingInferenceResult valueBody; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - private final TextEmbeddingInferenceResult inferenceResult; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) // --------------------------------------------------------------------------------------------- private TextEmbeddingResponse(Builder builder) { -<<<<<<< HEAD -<<<<<<< HEAD - this.inferenceResult = ApiTypeHelper.requireNonNull(builder.inferenceResult, this, "inferenceResult"); -======= - this.valueBody = ApiTypeHelper.requireNonNull(builder.valueBody, this, "valueBody"); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= this.inferenceResult = ApiTypeHelper.requireNonNull(builder.inferenceResult, this, "inferenceResult"); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } @@ -93,33 +77,15 @@ public static TextEmbeddingResponse of(Function>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final TextEmbeddingInferenceResult inferenceResult() { return this.inferenceResult; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } /** * Serialize this value to JSON. */ public void serialize(JsonGenerator generator, JsonpMapper mapper) { -<<<<<<< HEAD -<<<<<<< HEAD this.inferenceResult.serialize(generator, mapper); -======= - this.valueBody.serialize(generator, mapper); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - this.inferenceResult.serialize(generator, mapper); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } @@ -137,69 +103,29 @@ public String toString() { public static class Builder extends WithJsonObjectBuilderBase implements ObjectBuilder { -<<<<<<< HEAD -<<<<<<< HEAD - private TextEmbeddingInferenceResult inferenceResult; -======= - private TextEmbeddingInferenceResult valueBody; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= private TextEmbeddingInferenceResult inferenceResult; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) /** * Required - Response value. */ -<<<<<<< HEAD -<<<<<<< HEAD - public final Builder inferenceResult(TextEmbeddingInferenceResult value) { - this.inferenceResult = value; -======= - public final Builder valueBody(TextEmbeddingInferenceResult value) { - this.valueBody = value; ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= public final Builder inferenceResult(TextEmbeddingInferenceResult value) { this.inferenceResult = value; ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this; } /** * Required - Response value. */ -<<<<<<< HEAD -<<<<<<< HEAD public final Builder inferenceResult( Function> fn) { return this.inferenceResult(fn.apply(new TextEmbeddingInferenceResult.Builder()).build()); -======= - public final Builder valueBody( - Function> fn) { - return this.valueBody(fn.apply(new TextEmbeddingInferenceResult.Builder()).build()); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder inferenceResult( - Function> fn) { - return this.inferenceResult(fn.apply(new TextEmbeddingInferenceResult.Builder()).build()); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } /** * Required - Response value. */ -<<<<<<< HEAD -<<<<<<< HEAD public final Builder inferenceResult(TextEmbeddingInferenceResultVariant value) { this.inferenceResult = value._toTextEmbeddingInferenceResult(); -======= - public final Builder valueBody(TextEmbeddingInferenceResultVariant value) { - this.valueBody = value._toTextEmbeddingInferenceResult(); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - public final Builder inferenceResult(TextEmbeddingInferenceResultVariant value) { - this.inferenceResult = value._toTextEmbeddingInferenceResult(); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) return this; } @@ -209,15 +135,7 @@ public Builder withJson(JsonParser parser, JsonpMapper mapper) { @SuppressWarnings("unchecked") TextEmbeddingInferenceResult value = (TextEmbeddingInferenceResult) TextEmbeddingInferenceResult._DESERIALIZER .deserialize(parser, mapper); -<<<<<<< HEAD -<<<<<<< HEAD return this.inferenceResult(value); -======= - return this.valueBody(value); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= - return this.inferenceResult(value); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } @Override @@ -244,15 +162,7 @@ protected static JsonpDeserializer createTextEmbeddingRes JsonpDeserializer valueDeserializer = TextEmbeddingInferenceResult._DESERIALIZER; return JsonpDeserializer.of(valueDeserializer.acceptedEvents(), (parser, mapper, event) -> new Builder() -<<<<<<< HEAD -<<<<<<< HEAD - .inferenceResult(valueDeserializer.deserialize(parser, mapper, event)).build()); -======= - .valueBody(valueDeserializer.deserialize(parser, mapper, event)).build()); ->>>>>>> c49af58dc (Revert "temp rebase fix") -======= .inferenceResult(valueDeserializer.deserialize(parser, mapper, event)).build()); ->>>>>>> b5f478d93 ([codegen] update to latest spec and generator) } }

- * See Enumerations in Serde.rs that clearly explains the - * various strategies to represent polymorphic values in JSON. - */ - public static class ExternallyTagged { - - /** - * Creates a parser for externally tagged variants - */ - public static JsonpDeserializer pparser(Variants variants) { - return JsonpDeserializer.of(EnumSet.of(JsonParser.Event.START_OBJECT), (parser, params) -> { - JsonpUtils.expectNextEvent(parser, JsonParser.Event.START_OBJECT); - JsonpUtils.expectNextEvent(parser, JsonParser.Event.KEY_NAME); - - String variant = parser.getString(); - JsonpDeserializer variantParser = variants.variantParser(variant); - - if (variantParser == null) { - throw new JsonParsingException("Unknown variant '" + variant + "'", parser.getLocation()); - } - - T result = variantParser.deserialize(parser, params); - - JsonpUtils.expectNextEvent(parser, JsonParser.Event.END_OBJECT); - - return result; - }); - } - - /** - * Serializes an externally tagged variant object - */ - - public static void serialize( - Variants variants, T v, JsonGenerator builder, JsonpMapper mapper - ) { - @SuppressWarnings("unchecked") - String variant = variants.variantName((Class)v.getClass()); - - if (variant == null) { - throw new IllegalArgumentException("No variant name found for " + v.getClass().getName()); - } - - builder.writeStartObject(); - builder.writeKey(variant); - v.serialize(builder, mapper); - builder.writeEnd(); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnion.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnion.java deleted file mode 100644 index 905c319e3..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnion.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.containers; -/* - // @variants internal tag='type' - interface SomeUnion = UnionItemA | UnionItemB; - - interface VariantA { - type: 'variant_a' - variant_a_prop: String - } - - interface VariantB { - type: 'variant_b' - variant_b_prop: String - } -*/ - -import co.elastic.clients.json.JsonEnum; -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import co.elastic.clients.util.TaggedUnion; -import co.elastic.clients.util.TaggedUnionUtils; -import jakarta.json.stream.JsonGenerator; - -import java.util.function.Function; - -@JsonpDeserializable -public class SomeUnion implements TaggedUnion, JsonpSerializable { - - public enum Kind implements JsonEnum { - VariantA("variant_a"), - VariantB("variant_b"); - - private final String jsonValue; - - Kind(String jsonValue) { - this.jsonValue = jsonValue; - } - - @Override - public String jsonValue() { - return null; - } - } - - private final SomeUnionVariant _value; - private final Kind _type; - - public SomeUnion(Builder builder) { - this._value = builder._value; - this._type = builder._type; - } - - @Override - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - // Delegate to the variant object - if (_value instanceof JsonpSerializable) { - ((JsonpSerializable)_value).serialize(generator, mapper); - } - } - - @Override - public Kind _kind() { - return _type; - } - - @Override - public SomeUnionVariant _get() { - return _value; - } - - public UVariantA variantA() { - return TaggedUnionUtils.get(this, Kind.VariantA); - } - - public UVariantB variantB() { - return TaggedUnionUtils.get(this, Kind.VariantB); - } - - static class Builder { - - private SomeUnionVariant _value; - private Kind _type; - - // This "builder" doesn't allow building objects. It only contains methods to set a variant. - // These methods return a builder class with no other methods. This enforces the choice of one and only one - // variant at the type level (i.e. at compile time). - - // variant_a - - public ObjectBuilder variantA(UVariantA value) { - this._value = value; - this._type = Kind.VariantA; - final SomeUnion result = build(); - return () -> result; - } - - public ObjectBuilder variantA(Function fn) { - return this.variantA(fn.apply(new UVariantA.Builder()).build()); - } - - // variant_b - - public ObjectBuilder variantB(UVariantB value) { - this._value = value; - this._type = Kind.VariantB; - final SomeUnion result = build(); - return () -> result; - } - - public ObjectBuilder variantB(Function fn) { - return this.variantB(fn.apply(new UVariantB.Builder()).build()); - } - - protected SomeUnion build() { - return new SomeUnion(this); - } - } - - public static final JsonpDeserializer _DESERIALIZER = ObjectBuilderDeserializer.lazy(SomeUnion.Builder::new, - SomeUnion::setupSomeUnionDeserializer, SomeUnion.Builder::build); - - protected static void setupSomeUnionDeserializer(ObjectDeserializer op) { - op.add(SomeUnion.Builder::variantA, UVariantA._DESERIALIZER, "variant_a"); - op.add(SomeUnion.Builder::variantB, UVariantB._DESERIALIZER, "variant_b"); - - op.setTypeProperty("type", null); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnionTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnionTest.java deleted file mode 100644 index c257b9cc0..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnionTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.containers; - -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import jakarta.json.spi.JsonProvider; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import jakarta.json.stream.JsonParsingException; -import org.junit.jupiter.api.Test; - -import java.io.ByteArrayOutputStream; -import java.io.StringReader; - -public class SomeUnionTest extends ModelTestCase { - - SomeUnion su = new SomeUnion.Builder() - .variantA(a_ -> a_ - .name("a-name") - ).build(); - - String json = "{\"type\":\"variant_a\",\"name\":\"a-name\"}"; - - @Test - public void testContainerBuilder() { - assertEquals("a-name", su.variantA().name()); - } - - @Test - public void testDeserialization() { - SomeUnion u = fromJson(json, SomeUnion.class); - UVariantA uVariantA = u.variantA(); - assertEquals("a-name", uVariantA.name()); - } - - @Test - public void testSerialization() { - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - JsonProvider provider = JsonpUtils.provider(); - JsonGenerator generator = provider.createGenerator(baos); - - su.serialize(generator, new JsonbJsonpMapper()); - generator.close(); - - System.out.println(baos.toString()); - - assertEquals(json, baos.toString()); - - } - - @Test - public void testMissingVariantDeserialization() { - String json = "{}"; - - JsonProvider provider = JsonpUtils.provider(); - JsonParser parser = provider.createParser(new StringReader(json)); - - JsonParsingException e = assertThrows(JsonParsingException.class, () -> { - SomeUnion c = SomeUnion._DESERIALIZER.deserialize(parser, new JsonbJsonpMapper()); - }); - - assertTrue(e.getMessage().contains("Property 'type' not found")); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnionVariant.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnionVariant.java deleted file mode 100644 index 2bb9ee595..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/SomeUnionVariant.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.containers; - -import co.elastic.clients.elasticsearch.experiments.UnionVariant; - -public interface SomeUnionVariant extends UnionVariant { -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/UVariantA.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/UVariantA.java deleted file mode 100644 index 61aad4942..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/UVariantA.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.containers; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import javax.annotation.Nullable; - -@JsonpDeserializable -public class UVariantA implements SomeUnionVariant, JsonpSerializable { - - private final String name; - - @Override - public String _variantType() { - return "variant_a"; - } - - @Nullable - public String name() { - return this.name; - } - - public UVariantA(UVariantA.Builder builder) { - this.name = builder.name; - } - - @Override - public void serialize(JsonGenerator builder, JsonpMapper mapper) { - builder.writeStartObject(); - // Write variant value - builder.write("type", _variantType()); - if (this.name != null) builder.write("name", this.name); - builder.writeEnd(); - } - - public static class Builder implements ObjectBuilder { - private String name; - - public Builder name(@Nullable String name) { - this.name = name; - return this; - } - - public UVariantA build() { - return new UVariantA(this); - } - } - - public static final JsonpDeserializer _DESERIALIZER; - - static { - ObjectDeserializer op = new ObjectDeserializer<>(UVariantA.Builder::new); - op.add(UVariantA.Builder::name, JsonpDeserializer.stringDeserializer(), "name"); - op.ignore("type"); - _DESERIALIZER = new ObjectBuilderDeserializer<>(op); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/UVariantB.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/UVariantB.java deleted file mode 100644 index 2ddae5dfd..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/containers/UVariantB.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.containers; - -import co.elastic.clients.json.JsonpDeserializable; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import javax.annotation.Nullable; - -@JsonpDeserializable -public class UVariantB implements SomeUnionVariant, JsonpSerializable { - - private final Integer number; - - @Override - public String _variantType() { - return "variant_a"; - } - - @Nullable - public Integer number () { - return this.number; - } - - public UVariantB(UVariantB.Builder builder) { - this.number = builder.number; - } - - @Override - public void serialize(JsonGenerator builder, JsonpMapper mapper) { - builder.writeStartObject(); - // Write variant value - builder.write("type", _variantType()); - if (this.number != null) builder.write("number", this.number); - builder.writeEnd(); - } - - public static class Builder implements ObjectBuilder { - private Integer number; - - public Builder number(@Nullable Integer number) { - this.number = number; - return this; - } - - public UVariantB build() { - return new UVariantB(this); - } - } - - public static final JsonpDeserializer _DESERIALIZER; - - static { - ObjectDeserializer op = new ObjectDeserializer<>(UVariantB.Builder::new); - op.add(UVariantB.Builder::number, JsonpDeserializer.integerDeserializer(), "number"); - op.ignore("type"); - _DESERIALIZER = new ObjectBuilderDeserializer<>(op); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/generics/GenericClass.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/generics/GenericClass.java deleted file mode 100644 index 85d4de0c6..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/generics/GenericClass.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.generics; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.JsonpSerializer; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.transport.Endpoint; -import co.elastic.clients.transport.endpoints.SimpleEndpoint; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import java.util.function.Supplier; - -public class GenericClass implements JsonpSerializable { - - // Serializers for generic parameters - private final JsonpSerializer genParamSerializer; - - // Properties - private final GenParam genParam; - - protected GenericClass(Builder builder) { - this.genParamSerializer = builder.genParamSerializer; - this.genParam = builder.genParam; - } - - public GenParam genParam() { - return this.genParam; - } - - @Override - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - generator.writeKey("genParam"); - JsonpUtils.serialize(genParam, generator, genParamSerializer, mapper); - generator.writeEnd(); - } - - public static class Builder implements ObjectBuilder> { - private GenParam genParam; - private JsonpSerializer genParamSerializer; - - /** - * Sets the JSON serializer for {@link GenParam} values. If not set, the client will try to find a suitable - * serializer in the {@link JsonpMapper} and will fail if none is found. - */ - // Internal generic parameters always call this method to avoid runtime lookup - public Builder genParamSerializer(JsonpSerializer value) { - this.genParamSerializer = value; - return this; - } - - public Builder genParam(GenParam value) { - this.genParam = value; - return this; - } - - @Override - public GenericClass build() { - return null; - } - } - - public static JsonpDeserializer> parser( - // A deserializer for each generic parameter - JsonpDeserializer getParamDeserializer - ) { - - return ObjectBuilderDeserializer.createForObject( - (Supplier>) Builder::new, - (op) -> GenericClass.setupParser(op, getParamDeserializer) - ); - } - - private static void setupParser(ObjectDeserializer> op, JsonpDeserializer deserializer) { - op.add(Builder::genParam, deserializer, "genParam"); - } - - - public static Endpoint, ErrorResponse> endpoint( - JsonpDeserializer genParamDeserializer - ) { - return new SimpleEndpoint<>( - "genclass", - // Request method - request -> "GET", - // Request path - request -> "/genclass", - // Path parameters - SimpleEndpoint.emptyMap(), - // Request parameters - SimpleEndpoint.emptyMap(), - // Headers - SimpleEndpoint.emptyMap(), - true, - GenericClass.parser(genParamDeserializer) - ); - } - -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/InheritanceTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/InheritanceTest.java deleted file mode 100644 index ddd636af9..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/InheritanceTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.inheritance; - -import co.elastic.clients.elasticsearch.experiments.inheritance.child.ChildClass; -import co.elastic.clients.elasticsearch.experiments.inheritance.final_.FinalClass; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import jakarta.json.spi.JsonProvider; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.ByteArrayOutputStream; -import java.io.StringReader; - -public class InheritanceTest extends Assertions { - - @Test - public void testSerialization() { - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - JsonProvider provider = JsonpUtils.provider(); - - FinalClass fc = new FinalClass.Builder() - // Start fields from the top of the hierarchy to test setter return values - .baseField("baseValue") - .childField("childValue") - .finalField("finalValue") - .build(); - - JsonGenerator generator = provider.createGenerator(baos); - fc.serialize(generator, new JsonbJsonpMapper()); - - generator.close(); - String str = baos.toString(); - - assertEquals("{\"baseField\":\"baseValue\",\"childField\":\"childValue\",\"finalField\":\"finalValue\"}", str); - - baos.reset(); - - ChildClass cc = new ChildClass.Builder() - // Start fields from the top of the hierarchy to test setter return values - .baseField("baseValue") - .childField("childValue") - .build(); - - generator = provider.createGenerator(baos); - cc.serialize(generator, new JsonbJsonpMapper()); - - generator.close(); - str = baos.toString(); - - assertEquals("{\"baseField\":\"baseValue\",\"childField\":\"childValue\"}", str); - } - - @Test - public void testDeserialization() { - JsonProvider provider = JsonpUtils.provider(); - - JsonParser parser = provider.createParser(new StringReader( - "{\"baseField\":\"baseValue\",\"childField\":\"childValue\",\"finalField\":\"finalValue\"}")); - - FinalClass fc = FinalClass.JSONP_PARSER.deserialize(parser, new JsonbJsonpMapper()); - - assertEquals("baseValue", fc.baseField()); - assertEquals("childValue", fc.childField()); - assertEquals("finalValue", fc.finalField()); - - - parser = provider.createParser(new StringReader( - "{\"baseField\":\"baseValue\",\"childField\":\"childValue\"}")); - - ChildClass cc = ChildClass.JSONP_PARSER.deserialize(parser, new JsonbJsonpMapper()); - - assertEquals("baseValue", cc.baseField()); - assertEquals("childValue", cc.childField()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/base/BaseClass.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/base/BaseClass.java deleted file mode 100644 index 7cb760dbd..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/base/BaseClass.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.inheritance.base; - -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectDeserializer; -import jakarta.json.stream.JsonGenerator; - -import java.util.Objects; - -/** - * An abstract transport class - */ -public abstract class BaseClass implements JsonpSerializable { - - private final String baseField; - - public BaseClass(AbstractBuilder builder) { - this.baseField = Objects.requireNonNull(builder.baseField, "baseField"); - } - - public String baseField() { - return this.baseField; - } - - @Override - public void serialize(JsonGenerator generator, JsonpMapper mapper) { - generator.writeStartObject(); - toJsonpInternal(generator, mapper); - generator.writeEnd(); - } - - protected void toJsonpInternal(JsonGenerator generator, JsonpMapper mapper) { - generator.write("baseField", this.baseField); - } - - //--------------------------------------------------------------------------------------------- - - // This is class protected as it's only of interest to subclasses. Yet public members are visible - // from the outside on public subclasses. - protected abstract static class AbstractBuilder> { - - private String baseField; - - public T baseField(String value) { - this.baseField = value; - return self(); - } - - protected abstract T self(); - } - - //--------------------------------------------------------------------------------------------- - - protected static > void setupBaseClassParser(ObjectDeserializer op) { - op.add(AbstractBuilder::baseField, JsonpDeserializer.stringDeserializer(), "baseField"); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/child/ChildClass.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/child/ChildClass.java deleted file mode 100644 index a8d967896..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/child/ChildClass.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.inheritance.child; - -import co.elastic.clients.elasticsearch.experiments.inheritance.base.BaseClass; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpSerializable; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import java.util.Objects; - -/** - * A concrete class that both inherits a parent class and has child classes - */ -public class ChildClass extends BaseClass implements JsonpSerializable { - - private final String childField; - - public ChildClass(AbstractBuilder builder) { - super(builder); - this.childField = Objects.requireNonNull(builder.childField, "childField"); - } - - public String childField() { - return this.childField; - } - - @Override - protected void toJsonpInternal(JsonGenerator generator, JsonpMapper params) { - super.toJsonpInternal(generator, params); - generator.write("childField", this.childField); - } - - //--------------------------------------------------------------------------------------------- - - protected abstract static class AbstractBuilder> extends BaseClass.AbstractBuilder { - - private String childField; - - public T childField(String value) { - this.childField = value; - return self(); - } - } - - // We cannot use AbstractBuilder directly, as it would cause a signature clash with subclasses on build(). - // And even without it, the generic parameter on AbstractBuilder is an implementation detail of builder - // inheritance that isn't needed nor nice in user applications. - public static class Builder extends AbstractBuilder implements ObjectBuilder { - @Override - protected Builder self() { - return this; - } - - @Override - public ChildClass build() { - return new ChildClass(this); - } - } - - //--------------------------------------------------------------------------------------------- - - protected static > void setupChildClassParser(ObjectDeserializer op) { - BaseClass.setupBaseClassParser(op); - op.add(AbstractBuilder::childField, JsonpDeserializer.stringDeserializer(), "childField"); - } - - public static final JsonpDeserializer JSONP_PARSER = ObjectBuilderDeserializer.createForObject( - Builder::new, ChildClass::setupChildClassParser - ); - -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/final_/FinalClass.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/final_/FinalClass.java deleted file mode 100644 index 12dfd16ce..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/inheritance/final_/FinalClass.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.experiments.inheritance.final_; - -import co.elastic.clients.elasticsearch.experiments.inheritance.child.ChildClass; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.ObjectBuilderDeserializer; -import co.elastic.clients.json.ObjectDeserializer; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.stream.JsonGenerator; - -import java.util.Objects; - -/** - * A concrete class that inherits a parent class but has no child classes - */ -public final class FinalClass extends ChildClass { - - private final String finalField; - - public FinalClass(Builder builder) { - super(builder); - this.finalField = Objects.requireNonNull(builder.finalField, "finalField"); - } - - public String finalField() { - return this.finalField; - } - - @Override - protected void toJsonpInternal(JsonGenerator generator, JsonpMapper mapper) { - super.toJsonpInternal(generator, mapper); - generator.write("finalField", this.finalField); - } - - //--------------------------------------------------------------------------------------------- - - public static class Builder - extends ChildClass.AbstractBuilder - implements ObjectBuilder { - - private String finalField; - - public Builder finalField(String value) { - this.finalField = value; - return self(); - } - - @Override - protected Builder self() { - return this; - } - - @Override - public FinalClass build() { - return new FinalClass(this); - } - } - - //--------------------------------------------------------------------------------------------- - - private static void setupFinalClassParser(ObjectDeserializer op) { - ChildClass.setupChildClassParser(op); - op.add(Builder::finalField, JsonpDeserializer.stringDeserializer(), "finalField"); - } - - // Static methods cannot hide other static methods with a different return type or the same erased signature. - // Two possible solutions: - // - use different names, but having SomeClass.someClassParser() has some redundancy in the name - // - use a static field, as a static field can hide a static field of a different type in the parent class - // - // Our choice is to use different names for protected/private parser setup methods are they are hidden from - // the user and use a static field for the final parser, so that we can uniformly write SomeClass.PARSER - // (even if users should rarely have to interact directly with the parser). - - public static final JsonpDeserializer JSONP_PARSER = ObjectBuilderDeserializer.createForObject( - Builder::new, FinalClass::setupFinalClassParser - ); - -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/package-info.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/package-info.java deleted file mode 100644 index 05c034865..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/experiments/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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. - */ - -/** - * Experiments for the design of high-level client classes and usage illustration of the XContent-related classes. - */ -package co.elastic.clients.elasticsearch.experiments; diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/BuiltinTypesTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/BuiltinTypesTest.java deleted file mode 100644 index ed9d57382..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/BuiltinTypesTest.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.model; - -import co.elastic.clients.elasticsearch._types.FieldValue; -import co.elastic.clients.elasticsearch._types.SortOptions; -import co.elastic.clients.elasticsearch._types.SortOrder; -import co.elastic.clients.elasticsearch._types.aggregations.StatsAggregate; -import co.elastic.clients.elasticsearch._types.aggregations.StringStatsAggregate; -import co.elastic.clients.elasticsearch._types.query_dsl.SpanGapQuery; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.indices.IndexRoutingAllocationDisk; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.testkit.ModelTestCase; -import jakarta.json.stream.JsonParser; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; -import java.util.List; - -public class BuiltinTypesTest extends ModelTestCase { - - @Test - public void testPrimitiveTypes() { - - assertGetterType(Integer.class, SearchRequest.class, "size"); - - // Lenient boolean: 'threshold_enabled'?: boolean | string - assertGetterType(Boolean.class, IndexRoutingAllocationDisk.class, "thresholdEnabled"); - - } - - @Test - public void testLenientArray() { - // index: Indices --> type Indices = IndexName | IndexName[] - assertGetterType(List.class, SearchRequest.class, "index"); - } - - @Test - public void testNullArrayItem() { - // See https://github.com/elastic/elasticsearch-java/issues/66 - - String json = "[\"a\", null, \"c\"]"; - - // Types that don't accept null events should end up as null values in the list - { - JsonpDeserializer stringDeser = JsonpDeserializer.stringDeserializer(); - assertFalse(stringDeser.accepts(JsonParser.Event.VALUE_NULL)); - - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - - List stringList = JsonpDeserializer.arrayDeserializer(stringDeser).deserialize(parser, mapper); - assertEquals("a", stringList.get(0)); - assertNull(stringList.get(1)); - assertEquals("c", stringList.get(2)); - } - - // Types that do accept null events should end up as their null representation - { - assertTrue(FieldValue._DESERIALIZER.accepts(JsonParser.Event.VALUE_NULL)); - - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - List valueList = JsonpDeserializer.arrayDeserializer(FieldValue._DESERIALIZER).deserialize(parser, mapper); - - assertEquals("a", valueList.get(0)._get()); - assertTrue(valueList.get(1).isNull()); - assertEquals("c", valueList.get(2)._get()); - } - } - - @Test - public void testSpanGapQuery() { - // Hand-written class - SpanGapQuery q = SpanGapQuery.of(b -> b - .field("a-field") - .spanWidth(12) - ); - - q = checkJsonRoundtrip(q, "{\"a-field\":12}"); - - assertEquals("a-field", q.field()); - assertEquals(12, q.spanWidth()); - } - - @Test - public void testSortOptions() { - // Has a custom deserializer - // Examples: see https://www.elastic.co/guide/en/elasticsearch/reference/current/sort-search-results.html - - String json; - SortOptions sort; - - // Arbitrary field - sort = fromJson( - "{ \"post_date\" : {\"order\" : \"asc\", \"format\": \"strict_date_optional_time_nanos\"}}", - SortOptions.class); - - assertEquals("post_date", sort.field().field()); - assertEquals(SortOrder.Asc, sort.field().order()); - - sort = fromJson("{\n" + - " \"offer.price\" : {\n" + - " \"mode\" : \"avg\",\n" + - " \"order\" : \"asc\",\n" + - " \"nested\": {\n" + - " \"path\": \"offer\",\n" + - " \"filter\": {\n" + - " \"term\" : { \"offer.color\" : \"blue\" }\n" + - " }\n" + - " }\n" + - " }\n" + - " }", SortOptions.class); - - assertEquals("blue", sort.field().nested().filter().term().value().stringValue()); - - // Geo distance - sort = fromJson("{\n" + - " \"_geo_distance\" : {\n" + - " \"pin.location\" : {\n" + - " \"lat\" : 40,\n" + - " \"lon\" : -70\n" + - " },\n" + - " \"order\" : \"asc\",\n" + - " \"unit\" : \"km\"\n" + - " }\n" + - " }", SortOptions.class); - - assertEquals(40, sort.geoDistance().location().get(0).latlon().lat(), 0.1); - - // Simple string shortcuts - sort = fromJson("\"user\"", SortOptions.class); - assertEquals("user", sort.field().field()); - - sort = fromJson("\"_doc\"", SortOptions.class); - assertTrue(sort.isDoc()); - - sort = fromJson("\"_score\"", SortOptions.class); - assertTrue(sort.isScore()); - } - - @Test - public void testFieldValue() { - - FieldValue f; - - f = FieldValue.of(b -> b.nullValue()); - f = checkJsonRoundtrip(f, "null"); - assertTrue(f.isNull()); - assertEquals("null", f._toJsonString()); - - f = FieldValue.of(b -> b.doubleValue(1.23)); - f = checkJsonRoundtrip(f, "1.23"); - assertTrue(f.isDouble()); - assertEquals(1.23, f.doubleValue(), 0.01); - assertEquals("1.23", f._toJsonString()); - - f = FieldValue.of(b -> b.longValue(123)); - f = checkJsonRoundtrip(f, "123"); - assertTrue(f.isLong()); - assertEquals(123, f.longValue()); - assertEquals("123", f._toJsonString()); - - f = FieldValue.of(b -> b.booleanValue(true)); - f = checkJsonRoundtrip(f, "true"); - assertTrue(f.isBoolean()); - assertTrue(f.booleanValue()); - assertEquals("true", f._toJsonString()); - - f = FieldValue.of(b -> b.booleanValue(false)); - f = checkJsonRoundtrip(f, "false"); - assertTrue(f.isBoolean()); - assertFalse(f.booleanValue()); - assertEquals("false", f._toJsonString()); - - f = FieldValue.of(b -> b.stringValue("foo")); - f = checkJsonRoundtrip(f, "\"foo\""); - assertTrue(f.isString()); - assertEquals("foo", f.stringValue()); - assertEquals("foo", f._toJsonString()); - - } - - @Test - public void testNullableDouble() { - StatsAggregate stats; - - // Regular values - stats = StatsAggregate.statsAggregateOf(b -> b // Parent classes can't have an overloaded "of" method - .count(10) - .min(1.0) - .avg(1.5) - .max(2.0) - .sum(5.0) - ); - - stats = checkJsonRoundtrip(stats, "{\"count\":10,\"min\":1.0,\"max\":2.0,\"avg\":1.5,\"sum\":5.0}"); - assertEquals(10, stats.count()); - assertEquals(1.0, stats.min(), 0.01); - assertEquals(1.5, stats.avg(), 0.01); - assertEquals(2.0, stats.max(), 0.01); - assertEquals(5.0, stats.sum(), 0.01); - - // Missing values (Java mapping same as json) - String json = "{\"count\":0,\"min\":null,\"max\":null,\"avg\":0.0,\"sum\":0.0}"; - stats = fromJson(json, StatsAggregate.class); - - assertEquals(0, stats.count()); - assertEquals(null, stats.min()); - assertEquals(0.0, stats.avg(), 0.01); - assertEquals(null, stats.max()); - assertEquals(0.0, stats.sum(), 0.01); - - // We don't serialize null - assertEquals("{\"count\":0,\"avg\":0.0,\"sum\":0.0}", toJson(stats)); - } - - @Test - public void testNullableInt() { - StringStatsAggregate stats = StringStatsAggregate.of(b -> b - .count(1) - .minLength(2) - .avgLength(3D) - .maxLength(4) - .entropy(0D) - ); - - stats = checkJsonRoundtrip(stats, "{\"count\":1,\"min_length\":2,\"max_length\":4,\"avg_length\":3.0,\"entropy\":0.0}"); - assertEquals(2, stats.minLength()); - assertEquals(4, stats.maxLength()); - assertEquals(0, stats.entropy()); - - // Missing values - String json = "{\"count\":1,\"min_length\":null,\"max_length\":null,\"avg_length\":null,\"entropy\":null}"; - stats = fromJson(json, StringStatsAggregate.class); - assertEquals(1, stats.count()); - assertEquals(null, stats.minLength()); - assertEquals(null, stats.maxLength()); - assertEquals(null, stats.entropy()); - } - - @Test - public void testVoidDeserialization() { - String json = "{\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + - "\"hits\":{\"hits\":[{\"_index\":\"foo\",\"_id\":\"w\",\"_source\":{\"foo\": \"bar\"}}]}," + - "\"took\":42,\"timed_out\":false" + - "}"; - - SearchResponse response = fromJson(json, SearchResponse.createSearchResponseDeserializer(JsonpDeserializer.of(Void.class))); - - // Void type skips all the JSON and is serialized to null. - assertEquals(1, response.hits().hits().size()); - assertNull(response.hits().hits().get(0).source()); - assertEquals(42, response.took()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/ClassStructureTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/ClassStructureTest.java deleted file mode 100644 index d18faa465..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/ClassStructureTest.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.model; - -import co.elastic.clients.elasticsearch._types.ErrorCause; -import co.elastic.clients.elasticsearch._types.SortOrder; -import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; -import co.elastic.clients.elasticsearch._types.aggregations.Aggregation; -import co.elastic.clients.elasticsearch._types.aggregations.Buckets; -import co.elastic.clients.elasticsearch._types.aggregations.CardinalityAggregate; -import co.elastic.clients.elasticsearch._types.aggregations.DateRangeAggregate; -import co.elastic.clients.elasticsearch._types.aggregations.RangeBucket; -import co.elastic.clients.elasticsearch._types.aggregations.TermsAggregation; -import co.elastic.clients.elasticsearch._types.aggregations.ValueCountAggregation; -import co.elastic.clients.elasticsearch._types.query_dsl.FieldAndFormat; -import co.elastic.clients.elasticsearch._types.query_dsl.IntervalsQuery; -import co.elastic.clients.elasticsearch.core.GetRequest; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.elasticsearch.core.search.HitsMetadata; -import co.elastic.clients.elasticsearch.core.search.TotalHits; -import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.util.ApiTypeHelper; -import co.elastic.clients.util.MissingRequiredPropertyException; -import co.elastic.clients.util.NamedValue; -import co.elastic.clients.util.ObjectBuilder; -import org.junit.jupiter.api.Test; - -import javax.annotation.Nullable; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * Tests that verify common features of generated classes. - */ -public class ClassStructureTest extends ModelTestCase { - - /** - * Tests optional and required primitive types - */ - @Test - public void testPrimitiveTypes() throws Exception { - // Optional primitive should use the boxed type and be @Nullable - { - Method searchSize = SearchRequest.class.getMethod("size"); - assertNotNull(searchSize.getAnnotation(Nullable.class)); - assertEquals(Integer.class, searchSize.getReturnType()); - } - - // Builder setter for optional primitive should use the boxed type and be @Nullable - { - Method searchBuilderSize = SearchRequest.Builder.class.getMethod("size", Integer.class); - assertTrue(Arrays.stream(searchBuilderSize.getParameterAnnotations()[0]) - .anyMatch(a -> a.annotationType() == Nullable.class)); - } - - // Required primitive should use the primitive type and not be @Nullable - { - Method totalHitsValue = TotalHits.class.getMethod("value"); - assertNull(totalHitsValue.getAnnotation(Nullable.class)); - assertEquals(long.class, totalHitsValue.getReturnType()); - } - - // Builder setter for required primitive should use the primitive type and not be @Nullable - { - Method totalHitsBuilderValue = TotalHits.Builder.class.getMethod("value", long.class); - assertFalse(Arrays.stream(totalHitsBuilderValue.getParameterAnnotations()[0]) - .anyMatch(a -> a.annotationType() == Nullable.class)); - } - - // Not setting a required primitive should throw an exception - { - assertThrows(MissingRequiredPropertyException.class, () -> TotalHits.of(b -> b)); - } - } - - /** - * Tests correct initialization of inherited fields through builders and data class inheritance. - */ - @Test - public void testDataClassInheritedFieldAssignment() { - // 1 ancestor - { - CardinalityAggregate card = CardinalityAggregate.of(b -> b - .meta(Collections.singletonMap("foo", JsonData.of("bar"))) - .value(1) - ); - - assertAncestorCount(1, card); - assertEquals("bar", card.meta().get("foo").to(String.class)); - assertEquals("{\"meta\":{\"foo\":\"bar\"},\"value\":1}", toJson(card)); - } - - // 3 ancestors - { - DateRangeAggregate date = DateRangeAggregate.of(_1 -> _1 - .meta(Collections.singletonMap("foo", JsonData.of("bar"))) - .buckets(Buckets.of(b -> b.array(Collections.singletonList(RangeBucket.of(_2 -> _2.docCount(1)))))) - ); - - assertAncestorCount(3, date); - assertEquals("bar", date.meta().get("foo").to(String.class)); - assertEquals("{\"meta\":{\"foo\":\"bar\"},\"buckets\":[{\"doc_count\":1}]}", toJson(date)); - } - } - - /** - * Tests correct initialization of inherited fields for union typed. - */ - @Test - public void testUnionInheritedFieldAssignment() { - IntervalsQuery iq = IntervalsQuery.of(_1 -> _1 - .boost(2.0f) - .field("foo") - .allOf(b -> b.intervals(Collections.emptyList())) - ); - assertAncestorCount(1, iq); - assertEquals(2.0f, iq.boost(), 0.01); - assertEquals("{\"foo\":{\"boost\":2.0,\"all_of\":{\"intervals\":[]}}}", toJson(iq)); - } - - @Test - public void testUndefinedCollections() { - // Not setting a required list should throw an exception - { - MissingRequiredPropertyException ex = assertThrows(MissingRequiredPropertyException.class, - () -> HitsMetadata.of(_1 -> _1.total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)))); - assertTrue(ex.getMessage().contains(".hits")); - } - - // Unset list should be non-null, empty but not serialized - { - SearchRequest search = SearchRequest.of(b -> b); - assertNotNull(search.storedFields()); - assertEquals(0, search.storedFields().size()); - assertFalse(ApiTypeHelper.isDefined(search.storedFields())); - assertEquals("{}", toJson(search)); - } - - // Setting an empty list defines it - { - SearchRequest search = SearchRequest.of(b -> b.storedFields(Collections.emptyList())); - assertNotNull(search.storedFields()); - assertEquals(0, search.storedFields().size()); - assertTrue(ApiTypeHelper.isDefined(search.storedFields())); - assertEquals("{\"stored_fields\":[]}", toJson(search)); - } - - // Unset map should be non-null, empty but not serialized - { - CardinalityAggregate card = CardinalityAggregate.of(b -> b.value(1)); - assertNotNull(card.meta()); - assertEquals(0, card.meta().size()); - assertFalse(ApiTypeHelper.isDefined(card.meta())); - assertEquals("{\"value\":1}", toJson(card)); - } - - // Setting an empty map defines it - { - CardinalityAggregate card = CardinalityAggregate.of(b -> b - .value(1) - .meta(Collections.emptyMap()) - ); - assertNotNull(card.meta()); - assertEquals(0, card.meta().size()); - assertTrue(ApiTypeHelper.isDefined(card.meta())); - assertEquals("{\"meta\":{},\"value\":1}", toJson(card)); - } - } - - @Test - public void testListSetters() { - List fields = Arrays.asList("a", "b"); - - { - // Appending doesn't modify the original collection - SearchRequest search = SearchRequest.of(b -> b - .storedFields(fields) - .storedFields("c") - .storedFields("d", "e", "f") - ); - assertEquals(Arrays.asList("a", "b"), fields); - assertEquals(Arrays.asList("a", "b", "c", "d", "e", "f"), search.storedFields()); - } - - { - // Appending doesn't modify the original collection (appending the same list twice) - SearchRequest search = SearchRequest.of(b -> b - .storedFields(fields) - .storedFields(fields) - ); - assertEquals(Arrays.asList("a", "b"), fields); - assertEquals(Arrays.asList("a", "b", "a", "b"), search.storedFields()); - } - - - { - // List cannot be null - List nullFields = null; - assertThrows(NullPointerException.class, () -> { - SearchRequest.of(b -> b - .storedFields(nullFields) - ); - }); - } - - { - // Combine value and builder - FieldAndFormat fieldA = FieldAndFormat.of(f -> f.field("a")); - SearchRequest search = SearchRequest.of(b -> b - .docvalueFields(fieldA) - .docvalueFields(f -> f.field("b")) - .docvalueFields(f -> f.field("c")) - ); - - assertEquals(Arrays.asList("a", "b", "c"), search.docvalueFields().stream() - .map(FieldAndFormat::field).collect(Collectors.toList())); - } - } - - @Test - public void testMapSetters() { - ValueCountAggregation countA = ValueCountAggregation.of(v -> v.field("a")); - ValueCountAggregation countB = ValueCountAggregation.of(v -> v.field("b")); - ValueCountAggregation countC = ValueCountAggregation.of(v -> v.field("c")); - - Map aggs = new HashMap<>(); - aggs.put("aggA", countA._toAggregation()); - aggs.put("aggB", countB._toAggregation()); - - { - // Appending doesn't modify the original collection - SearchRequest search = SearchRequest.of(b -> b - .aggregations(aggs) - .aggregations("aggC", countC._toAggregation()) - .aggregations("aggD", a -> a.valueCount(c -> c.field("d"))) - ); - - // Original map wasn't modified - assertEquals(2, aggs.size()); - - assertEquals(4, search.aggregations().size()); - assertEquals("a", search.aggregations().get("aggA").valueCount().field()); - assertEquals("b", search.aggregations().get("aggB").valueCount().field()); - assertEquals("c", search.aggregations().get("aggC").valueCount().field()); - assertEquals("d", search.aggregations().get("aggD").valueCount().field()); - } - - { - // Map cannot be null - assertThrows(NullPointerException.class, () -> { - Map nullMap = null; - SearchRequest.of(b -> b.aggregations(nullMap)); - }); - } - } - - @Test - public void testDataClassesSingleBuilderUse() { - // no ancestor + WithJsonBase + ObjectBuilderBase - checkSingleBuilderUse(2, new ErrorCause.Builder().type("foo").reason("bar")); - - // 1 ancestor + WithJsonBase + ObjectBuilderBase - checkSingleBuilderUse(3, new CardinalityAggregate.Builder().value(0)); - - // 3 ancestors + WithJsonBase + ObjectBuilderBase - checkSingleBuilderUse(5, new DateRangeAggregate.Builder().buckets(Buckets.of(b -> b.array(Collections.emptyList())))); - } - - @Test - public void testUnionSingleBuilderUse() { - // no ancestor + ObjectBuilderBase - checkSingleBuilderUse(1, new Aggregate.Builder().cardinality(b -> b.value(0))); - - // 1 ancestor + WithJsonBase + ObjectBuilderBase - checkSingleBuilderUse(3, new IntervalsQuery.Builder().field("foo").allOf(b -> b.intervals(Collections.emptyList()))); - } - - @Test - public void testRequiredProperty() { - // All required properties present - GetRequest r = GetRequest.of(b -> b.index("foo").id("bar")); - - // Missing id property throws an exception - MissingRequiredPropertyException ex = assertThrows(MissingRequiredPropertyException.class, () -> { - GetRequest r1 = GetRequest.of(b -> b.index("foo")); - }); - assertEquals("id", ex.getPropertyName()); - - // Disable checks, missing id property is accepted. - try (ApiTypeHelper.DisabledChecksHandle h = ApiTypeHelper.DANGEROUS_disableRequiredPropertiesCheck(true)) { - GetRequest r1 = GetRequest.of(b -> b.index("foo")); - assertNull(r1.id()); - } - - // Checks are enabled again after the try block - ex = assertThrows(MissingRequiredPropertyException.class, () -> { - GetRequest r1 = GetRequest.of(b -> b.index("foo")); - }); - assertEquals("id", ex.getPropertyName()); - } - - /** - * Tests SingleKeyDictionary fields that are not transformed into a behavior. - */ - @Test - public void testNamedValue() { - TermsAggregation termsAgg = TermsAggregation.of(ta -> ta - .order(NamedValue.of("a", SortOrder.Asc)) - .order(NamedValue.of("b", SortOrder.Desc)) - ); - - checkJsonRoundtrip(termsAgg, "{\"order\":[{\"a\":\"asc\"},{\"b\":\"desc\"}]}"); - } - - private void assertAncestorCount(int count, Object obj) { - Class clazz = obj.getClass(); - while(count-- >= 0) { - clazz = clazz.getSuperclass(); - } - assertEquals(Object.class, clazz); - } - - private void checkSingleBuilderUse(int count, ObjectBuilder builder) { - assertAncestorCount(count, builder); - - // Building once should succeed - builder.build(); - - // Building twice should fail - IllegalStateException ex = assertThrows(IllegalStateException.class, builder::build); - assertEquals("Object builders can only be used once", ex.getMessage()); - - // One more for good measure - ex = assertThrows(IllegalStateException.class, builder::build); - assertEquals("Object builders can only be used once", ex.getMessage()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/CodeAdditionsTests.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/CodeAdditionsTests.java deleted file mode 100644 index e19ea16a0..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/CodeAdditionsTests.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.model; - -import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery; -import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class CodeAdditionsTests extends Assertions { - - @Test - public void testHasClauses() { - - { - BoolQuery.Builder builder = new BoolQuery.Builder(); - assertFalse(builder.hasClauses()); - - BoolQuery query = builder.build(); - assertFalse(query.hasClauses()); - } - - { - BoolQuery.Builder builder = new BoolQuery.Builder(); - builder.must(QueryBuilders.matchAll(b -> b)); - assertTrue(builder.hasClauses()); - - BoolQuery query = builder.build(); - assertTrue(query.hasClauses()); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/EndpointTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/EndpointTest.java deleted file mode 100644 index 1065c2c5f..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/EndpointTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.model; - -import co.elastic.clients.elasticsearch._types.ExpandWildcard; -import co.elastic.clients.elasticsearch.core.ExistsRequest; -import co.elastic.clients.elasticsearch.core.InfoRequest; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.elasticsearch.indices.RefreshRequest; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class EndpointTest extends Assertions { - - @Test - public void testArrayPathParameter() { - RefreshRequest req; - - req = RefreshRequest.of(b -> b); - assertNotNull(req.index()); - assertEquals("/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); - - req = RefreshRequest.of(b -> b.index("a")); - assertEquals("/a/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); - - req = RefreshRequest.of(b -> b.index("a", "b")); - assertEquals("/a,b/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); - - req = RefreshRequest.of(b -> b.index("a", "b", "c")); - assertEquals("/a,b,c/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); - } - - @Test - public void testPathEncoding() { - RefreshRequest req; - - req = RefreshRequest.of(b -> b.index("a/b")); - assertEquals("/a%2Fb/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); - - req = RefreshRequest.of(b -> b.index("a/b", "c/d")); - assertEquals("/a%2Fb,c%2Fd/_refresh", RefreshRequest._ENDPOINT.requestUrl(req)); - - } - - @Test - public void testArrayQueryParameter() { - RefreshRequest req; - - req = RefreshRequest.of(b -> b); - assertNotNull(req.expandWildcards()); // undefined list - assertNull(RefreshRequest._ENDPOINT.queryParameters(req).get("expand_wildcards")); - - req = RefreshRequest.of(b -> b.expandWildcards(ExpandWildcard.All)); - // Also tests query encoding of enums - assertEquals("all", RefreshRequest._ENDPOINT.queryParameters(req).get("expand_wildcards")); - - req = RefreshRequest.of(b -> b.expandWildcards(ExpandWildcard.All, ExpandWildcard.Closed)); - assertEquals("all,closed", RefreshRequest._ENDPOINT.queryParameters(req).get("expand_wildcards")); - } - - @Test - public void testRequestToString() { - // Simple path, no parameters, no body - assertEquals("InfoRequest: GET /", InfoRequest._INSTANCE.toString()); - - // Complex path, parameters, no body - assertEquals( - "ExistsRequest: HEAD /idx/_doc/id1?preference=foo&refresh=true", - ExistsRequest.of(b -> b.index("idx").id("id1").preference("foo").refresh(true)).toString() - ); - - assertEquals( - "SearchRequest: POST /idx/_search?typed_keys=true {\"size\":10}", - SearchRequest.of(s -> s.index("idx").size(10)).toString() - ); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/EnumTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/EnumTest.java deleted file mode 100644 index b36ab6d6e..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/EnumTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.model; - -import co.elastic.clients.elasticsearch._types.Bytes; -import co.elastic.clients.elasticsearch._types.Refresh; -import co.elastic.clients.elasticsearch._types.mapping.GeoOrientation; -import co.elastic.clients.testkit.ModelTestCase; -import org.junit.jupiter.api.Test; - -import java.util.Arrays; - -public class EnumTest extends ModelTestCase { - - @Test - public void testSimpleEnum() { - assertNull(Bytes.GigaBytes.aliases()); - assertEquals(Bytes.GigaBytes, Bytes._DESERIALIZER.parse("gb")); - } - - @Test - public void testEnumWithAliases() { - assertEquals("left", GeoOrientation.Left.jsonValue()); - assertNotNull(GeoOrientation.Left.aliases()); - - Arrays.asList("right", "RIGHT", "counterclockwise", "ccw").forEach(alias -> { - assertEquals(GeoOrientation.Right, GeoOrientation._DESERIALIZER.parse(alias)); - }); - } - - @Test - public void testBooleanEnum() { - // Quoted value - assertEquals(Refresh.WaitFor, checkJsonRoundtrip(Refresh.WaitFor, "\"wait_for\"")); - - // Unquoted boolean values - assertEquals(Refresh.True, checkJsonRoundtrip(Refresh.True, "true")); - assertEquals(Refresh.False, checkJsonRoundtrip(Refresh.False, "false")); - - // true/false as strings - assertEquals(Refresh.True, fromJson("\"true\"", Refresh.class)); - assertEquals(Refresh.False, fromJson("\"false\"", Refresh.class)); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/RequestEncodingTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/RequestEncodingTest.java deleted file mode 100644 index 83b9f5e84..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/RequestEncodingTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.model; - -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import co.elastic.clients.testkit.ModelTestCase; -import org.junit.jupiter.api.Test; - -public class RequestEncodingTest extends ModelTestCase { - - @Test - public void testParametersNotInJson() { - - // This checks that path parameters ("q") are not serialized as json - // and variant containers ser/deser - - SearchRequest request = new SearchRequest.Builder() - .q("blah") - .query(b1 -> b1 - .type(b2 -> b2 - .value("foo")) - ) - .aggregations( - "myagg", b2 -> b2 - .avg(b3 -> b3.field("foo")) - ) - .build(); - - JsonbJsonpMapper mapper = new JsonbJsonpMapper(); - String str = toJson(request, mapper); - - assertEquals("{\"aggregations\":{\"myagg\":{\"avg\":{\"field\":\"foo\"}}},\"query\":{\"type\":{\"value\":\"foo\"}}}", str); - - request = fromJson(str, SearchRequest.class, mapper); - - assertTrue(request.query().isType()); - assertEquals("foo", request.query().type().value()); - assertNull(request.q()); - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/TypedKeysTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/TypedKeysTest.java deleted file mode 100644 index 609b08822..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/TypedKeysTest.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.model; - -import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; -import co.elastic.clients.elasticsearch._types.aggregations.AvgAggregate; -import co.elastic.clients.elasticsearch._types.aggregations.StringTermsAggregate; -import co.elastic.clients.elasticsearch._types.aggregations.StringTermsBucket; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpMapperFeatures; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.util.ListBuilder; -import co.elastic.clients.util.MapBuilder; -import jakarta.json.spi.JsonProvider; -import jakarta.json.stream.JsonGenerator; -import org.junit.jupiter.api.Test; - -import java.io.StringWriter; -import java.util.Collections; - -public class TypedKeysTest extends ModelTestCase { - - @Test - public void testMapProperty() { - - SearchResponse resp = new SearchResponse.Builder() - .aggregations( - "foo", _2 -> _2 - .avg(_3 -> _3.value(3.14)) - ) - // Required properties on a SearchResponse - .took(1) - .shards(_1 -> _1.successful(1).failed(0).total(1)) - .hits(_1 -> _1 - .total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)) - .hits(Collections.emptyList()) - ) - .timedOut(false) - .build(); - - String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + - "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]},\"aggregations\":{\"avg#foo\":{\"value\":3.14}}}"; - - assertEquals(json, toJson(resp)); - - resp = fromJson(json, SearchResponse.createSearchResponseDeserializer(JsonpDeserializer.voidDeserializer())); - - assertEquals(1, resp.took()); - assertEquals(3.14, resp.aggregations().get("foo").avg().value(), 0.001); - - } - - @Test - public void testMapPropertyWithoutTypedKeys() { - - SearchResponse resp = new SearchResponse.Builder() - .aggregations( - "foo", _2 -> _2 - .avg(_3 -> _3.value(3.14)) - ) - // Required properties on a SearchResponse - .took(1) - .shards(_1 -> _1.successful(1).failed(0).total(1)) - .hits(_1 -> _1 - .total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)) - .hits(Collections.emptyList()) - ) - .timedOut(false) - .build(); - - // Note "foo" and not "avg#foo" below - String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + - "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]},\"aggregations\":{\"foo\":{\"value\":3.14}}}"; - - JsonpMapper newMapper = mapper.withAttribute(JsonpMapperFeatures.SERIALIZE_TYPED_KEYS, false); - - assertEquals(json, toJson(resp, newMapper)); - } - - - @Test - public void testAdditionalProperties() { - - Aggregate avg1 = AvgAggregate.of(_1 -> _1.value(1.0))._toAggregate(); - Aggregate avg2 = AvgAggregate.of(_1 -> _1.value(2.0))._toAggregate(); - - Aggregate aggregate = StringTermsAggregate.of(_0 -> _0 - .sumOtherDocCount(1L) - .buckets(b -> b.array( - ListBuilder.of(StringTermsBucket.Builder::new) - .add(_1 -> _1 - .key("key_1") - .docCount(1) - .aggregations(MapBuilder.of("bar", avg1)) - ) - .add(_1 -> _1 - .key("key_2") - .docCount(2) - .aggregations(MapBuilder.of("bar", avg2)) - ) - .build() - )) - ) - ._toAggregate(); - - SearchResponse resp = new SearchResponse.Builder() - .aggregations("foo", aggregate) - // Required properties on a SearchResponse - .took(1) - .shards(_1 -> _1.successful(1).failed(0).total(1)) - .hits(_1 -> _1 - .total(_2 -> _2.value(0).relation(TotalHitsRelation.Eq)) - .hits(Collections.emptyList()) - ) - .timedOut(false) - .build(); - - - String json = "{\"took\":1,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0}," + - "\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]}," + - "\"aggregations\":{\"sterms#foo\":{\"buckets\":[" + - "{\"avg#bar\":{\"value\":1.0},\"doc_count\":1,\"key\":\"key_1\"}," + - "{\"avg#bar\":{\"value\":2.0},\"doc_count\":2,\"key\":\"key_2\"}" + - "],\"sum_other_doc_count\":1}}}"; - - assertEquals(json, toJson(resp)); - resp = fromJson(json, SearchResponse.createSearchResponseDeserializer(JsonpDeserializer.voidDeserializer())); - - StringTermsAggregate foo = resp.aggregations().get("foo").sterms(); - assertEquals(1, foo.sumOtherDocCount()); - assertEquals(1, foo.buckets().array().get(0).docCount()); - assertEquals("key_1", foo.buckets().array().get(0).key().stringValue()); - assertEquals(1.0, foo.buckets().array().get(0).aggregations().get("bar").avg().value(), 0.01); - assertEquals("key_2", foo.buckets().array().get(1).key().stringValue()); - assertEquals(2.0, foo.buckets().array().get(1).aggregations().get("bar").avg().value(), 0.01); - } - - // Example taken from - // https://www.elastic.co/guide/en/elasticsearch/reference/8.2/search-aggregations-bucket-reverse-nested-aggregation.html - private static final String nestedJsonWithTypedKeys = "{\n" + - " \"took\": 0," + - " \"timed_out\": false," + - " \"_shards\": {\n" + - " \"successful\": 1,\n" + - " \"failed\": 0,\n" + - " \"skipped\": 0,\n" + - " \"total\": 1\n" + - " },\n" + - " \"hits\": {\n" + - " \"hits\": [],\n" + - " \"total\": {\n" + - " \"relation\": \"eq\",\n" + - " \"value\": 5\n" + - " },\n" + - " \"max_score\": null\n" + - " }," + - " \"aggregations\" : {\n" + - " \"nested#comments\" : {\n" + - " \"doc_count\" : 3,\n" + - " \"sterms#top_usernames\" : {\n" + - " \"doc_count_error_upper_bound\" : 0,\n" + - " \"sum_other_doc_count\" : 0,\n" + - " \"buckets\" : [\n" + - " {\n" + - " \"key\" : \"dan\",\n" + - " \"doc_count\" : 3,\n" + - " \"reverse_nested#comment_to_issue\" : {\n" + - " \"doc_count\" : 1,\n" + - " \"sterms#top_tags_per_comment\" : {\n" + - " \"doc_count_error_upper_bound\" : 0,\n" + - " \"sum_other_doc_count\" : 0,\n" + - " \"buckets\" : [\n" + - " {\n" + - " \"key\" : \"tag1\",\n" + - " \"doc_count\" : 1\n" + - " },\n" + - " {\n" + - " \"key\" : \"tag2\",\n" + - " \"doc_count\" : 1\n" + - " }\n" + - " ]\n" + - " }\n" + - " }\n" + - " }\n" + - " ]\n" + - " }\n" + - " }\n" + - " }\n" + - "}"; - - @Test - public void testSerializeNested() { - - SearchResponse response = fromJson(nestedJsonWithTypedKeys, SearchResponse.class); - - // Check some deeply nested properties - StringTermsBucket bucket = response - .aggregations().get("comments").nested() - .aggregations().get("top_usernames").sterms() - .buckets().array().get(0) - .aggregations().get("comment_to_issue").reverseNested() - .aggregations().get("top_tags_per_comment").sterms() - .buckets().array().get(0); - - assertEquals("tag1", bucket.key().stringValue()); - assertEquals(1, bucket.docCount()); - - // Check that it's typed_keys encoded - String serialized = toJson(response); - assertTrue(serialized.contains("nested#comments")); - assertTrue(serialized.contains("sterms#top_usernames")); - assertTrue(serialized.contains("reverse_nested#comment_to_issue")); - assertTrue(serialized.contains("sterms#top_tags_per_comment")); - - { - // Test direct serialization - JsonProvider jsonProvider = mapper.jsonProvider(); - StringWriter stringWriter = new StringWriter(); - JsonGenerator generator = jsonProvider.createGenerator(stringWriter); - response.serialize(generator, mapper); - generator.close(); - - String directSerialized = stringWriter.toString(); - assertTrue(directSerialized.contains("nested#comments")); - assertTrue(directSerialized.contains("sterms#top_usernames")); - assertTrue(directSerialized.contains("reverse_nested#comment_to_issue")); - assertTrue(directSerialized.contains("sterms#top_tags_per_comment")); - - } - - // Re-parse and re-check - response = fromJson(serialized, SearchResponse.class); - - bucket = response - .aggregations().get("comments").nested() - .aggregations().get("top_usernames").sterms() - .buckets().array().get(0) - .aggregations().get("comment_to_issue").reverseNested() - .aggregations().get("top_tags_per_comment").sterms() - .buckets().array().get(0); - - assertEquals("tag1", bucket.key().stringValue()); - assertEquals(1, bucket.docCount()); - - - JsonProvider jsonProvider = mapper.jsonProvider(); - StringWriter stringWriter = new StringWriter(); - JsonGenerator generator = jsonProvider.createGenerator(stringWriter); - response.serialize(generator, mapper); - generator.close(); - - System.out.println(stringWriter.toString()); - } - - @Test - public void testSerializeNestedWithoutTypedKeys() { - - SearchResponse response = fromJson(nestedJsonWithTypedKeys, SearchResponse.class); - - // Check that it's typed_keys encoded - String serialized = toJson(response); - assertTrue(serialized.contains("nested#comments")); - assertTrue(serialized.contains("sterms#top_usernames")); - assertTrue(serialized.contains("reverse_nested#comment_to_issue")); - assertTrue(serialized.contains("sterms#top_tags_per_comment")); - - // Build the non-typed_keys version (replace 'type#' with 'type#name') - serialized = serialized.replaceAll("\"[^\"]*#", "\""); - assertFalse(serialized.contains("nested#comments")); - assertFalse(serialized.contains("sterms#top_usernames")); - assertFalse(serialized.contains("reverse_nested#comment_to_issue")); - assertFalse(serialized.contains("sterms#top_tags_per_comment")); - - // Serialize without typed keys - JsonpMapper newMapper = mapper.withAttribute(JsonpMapperFeatures.SERIALIZE_TYPED_KEYS, false); - assertEquals(serialized, toJson(response, newMapper)); - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/UnionTests.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/UnionTests.java index d87f0f2ea..386f9f9ee 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/UnionTests.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/UnionTests.java @@ -43,13 +43,13 @@ public class UnionTests extends ModelTestCase { @Test public void testScriptDeserializer() { - // the source field in script is both a shortcut and an externally tagged union + // A union discriminated by its field names (source -> inline, id -> stored) { Script s = Script.of(_1 -> _1 - .source(_2 -> _2.scriptString("a script")) + .source("a script") ); s = checkJsonRoundtrip(s, "{\"source\":\"a script\"}"); - assertEquals("a script", s.source().scriptString()); + assertEquals("a script", s.source()); } { @@ -63,7 +63,7 @@ public void testScriptDeserializer() { { // Test shortcut property Script s = fromJson("\"a script\"", Script.class); - assertEquals("a script", s.source().scriptString()); + assertEquals("a script", s.source()); } } diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/VariantsTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/VariantsTest.java deleted file mode 100644 index 1ffbe6ade..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/VariantsTest.java +++ /dev/null @@ -1,351 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.elasticsearch.model; - -import co.elastic.clients.elasticsearch._types.analysis.Analyzer; -import co.elastic.clients.elasticsearch._types.mapping.Property; -import co.elastic.clients.elasticsearch._types.mapping.TypeMapping; -import co.elastic.clients.elasticsearch._types.query_dsl.FunctionScore; -import co.elastic.clients.elasticsearch._types.query_dsl.Query; -import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.elasticsearch.ilm.ExplainLifecycleResponse; -import co.elastic.clients.elasticsearch.ilm.explain_lifecycle.LifecycleExplainManaged; -import co.elastic.clients.elasticsearch.ilm.explain_lifecycle.LifecycleExplainUnmanaged; -import co.elastic.clients.elasticsearch.indices.GetMappingResponse; -import co.elastic.clients.json.JsonData; -import co.elastic.clients.testkit.ModelTestCase; -import org.junit.jupiter.api.Test; - -import java.util.function.Consumer; - -public class VariantsTest extends ModelTestCase { - - @Test - public void testNested() { - // nested containers: query > intervals > interval - // intervals is a single key dictionary - // query has container properties - - Query q = Query.of(_0 -> _0 - .intervals(_1 -> _1 - .queryName("my-query") - .field("a_field") - .anyOf(_2 -> _2 - .intervals(_3 -> _3 - .match( - _5 -> _5 - .query("match-query") - .analyzer("lowercase") - ) - ) - ) - ) - ); - - assertEquals(Query.Kind.Intervals, q._kind()); - assertNotNull(q.intervals()); - assertEquals("a_field", q.intervals().field()); - assertEquals(1, q.intervals().anyOf().intervals().size()); - assertEquals("lowercase", q.intervals().anyOf().intervals().get(0).match().analyzer()); - - String json = toJson(q); - - assertEquals("{\"intervals\":{\"a_field\":{\"_name\":\"my-query\"," + - "\"any_of\":{\"intervals\":[{\"match\":{\"analyzer\":\"lowercase\",\"query\":\"match-query\"}}]}}}}", json); - - Query q2 = fromJson(json, Query.class); - assertEquals(json, toJson(q2)); - - assertEquals(Query.Kind.Intervals, q2._kind()); - assertNotNull(q2.intervals()); - assertEquals("a_field", q2.intervals().field()); - assertEquals(1, q2.intervals().anyOf().intervals().size()); - assertEquals("lowercase", q2.intervals().anyOf().intervals().get(0).match().analyzer()); - - } - - @Test - public void testInternalTag() { - String expected = "{\"type\":\"ip\",\"fields\":{\"a-field\":{\"type\":\"float\",\"coerce\":true}},\"boost\":1" + - ".0,\"index\":true}"; - - Property p = Property.of(_0 -> _0 - .ip(_1 -> _1 - .index(true) - .boost(1.0) - .fields( - "a-field", _3 -> _3 - .float_(_4 -> _4 - .coerce(true) - ) - ) - ) - ); - - assertEquals(expected, toJson(p)); - - Property property = fromJson(expected, Property.class); - assertTrue(property.ip().index()); - assertEquals(1.0, property.ip().boost().doubleValue(), 0.09); - - assertTrue(property.ip().fields().get("a-field").float_().coerce()); - } - - @Test - public void testDefaultInternalTag() { - - Consumer test = s -> { - Analyzer a = fromJson(s, Analyzer.class); - assertEquals(Analyzer.Kind.Custom, a._kind()); - assertEquals("some-filter", a.custom().filter().get(0)); - assertTrue(a.custom().charFilter().isEmpty()); - assertEquals("some-tokenizer", a.custom().tokenizer()); - }; - - // Explicit type - test.accept("{\"type\":\"custom\",\"filter\":[\"some-filter\"],\"tokenizer\":\"some-tokenizer\"}"); - - // Default type - test.accept("{\"filter\":[\"some-filter\"],\"tokenizer\":\"some-tokenizer\"}"); - } - - @Test - public void testBuilders() { - String json = "{\"exists\":{\"field\":\"foo\"}}"; - Query q; - - q = new Query(QueryBuilders.exists().field("foo").build()); - assertEquals(json, toJson(q)); - - q = QueryBuilders.exists(e -> e.field("foo")); - assertEquals(json, toJson(q)); - } - - - @Test - public void testNestedTaggedUnionWithDefaultTag() { - // https://github.com/elastic/elasticsearch-java/issues/45 - - // Object fields don't really exist in ES and are based on a naming convention where field names - // are dot-separated paths. The hierarchy is rebuilt from these names and ES doesn't send back - // "type": "object" for object properties. - // See https://www.elastic.co/guide/en/elasticsearch/reference/current/object.html - // - // Mappings are therefore a hierarchy of internally-tagged unions based on the "type" property - // with a default "object" tag value if the "type" property is missing. - - String json = - "{\n" + - " \"testindex\" : {\n" + - " \"mappings\" : {\n" + - " \"properties\" : {\n" + - " \"id\" : {\n" + - " \"type\" : \"text\",\n" + - " \"fields\" : {\n" + - " \"keyword\" : {\n" + - " \"type\" : \"keyword\",\n" + - " \"ignore_above\" : 256\n" + - " }\n" + - " }\n" + - " },\n" + - " \"name\" : {\n" + - " \"properties\" : {\n" + - " \"first\" : {\n" + - " \"type\" : \"text\",\n" + - " \"fields\" : {\n" + - " \"keyword\" : {\n" + - " \"type\" : \"keyword\",\n" + - " \"ignore_above\" : 256\n" + - " }\n" + - " }\n" + - " },\n" + - " \"last\" : {\n" + - " \"type\" : \"text\",\n" + - " \"fields\" : {\n" + - " \"keyword\" : {\n" + - " \"type\" : \"keyword\",\n" + - " \"ignore_above\" : 256\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - "}"; - - GetMappingResponse response = fromJson(json, GetMappingResponse.class); - - TypeMapping mappings = response.get("testindex").mappings(); - assertTrue(mappings.properties().get("name").isObject()); - - assertEquals(256, mappings - .properties().get("name").object() - .properties().get("first").text() - .fields().get("keyword").keyword(). - ignoreAbove().longValue() - ); - - assertTrue(mappings.properties().get("id").isText()); - - assertEquals(256, mappings.properties().get("id").text().fields().get("keyword").keyword().ignoreAbove().longValue()); - } - - @Test - public void testEmptyProperty() { - // Edge case where we have a property with no fields and no type - String json = "{}"; - Property property = fromJson(json, Property.class); - assertEquals(Property.Kind.Object, property._kind()); - } - - @Test - public void testNestedVariantsWithContainerProperties() { - - SearchRequest search = SearchRequest.of(s -> s - .aggregations( - "agg1", a -> a - .meta("m1", JsonData.of("m1 value")) - // Here we can choose any aggregation type, but build() isn't accessible - .valueCount(v -> v.field("f")) - // Here we can only set container properties (meta and (sub)aggregations) or build() - .meta("m2", JsonData.of("m2 value")) - ) - ); - - assertEquals("m1 value", search.aggregations().get("agg1").meta().get("m1").to(String.class)); - assertEquals("m2 value", search.aggregations().get("agg1").meta().get("m2").to(String.class)); - } - - @Test - public void testContainerWithOptionalVariants() { - // FunctionScore is the only occurrence of this - - Query q = QueryBuilders.term(t -> t.field("foo").value("bar")); - - // No variant - { - Query fsq = QueryBuilders.functionScore(fs -> fs - .query(q) - .functions(f -> f.weight(1.0)) - ); - - String json = "{\"function_score\":{\"functions\":[{\"weight\":1.0}]," + - "\"query\":{\"term\":{\"foo\":{\"value\":\"bar\"}}}}}"; - assertEquals(json, toJson(fsq)); - - Query fsq2 = checkJsonRoundtrip(fsq, json); - - assertNull(fsq2.functionScore().functions().get(0)._kind()); - assertEquals(1.0, fsq2.functionScore().functions().get(0).weight(), 0.001); - } - - // With a variant - { - Query fsq = QueryBuilders.functionScore(fs -> fs - .query(q) - .functions(f -> f - .weight(1.0) - .linear(l -> l - .numeric(n -> n - .field("foo") - .placement(p -> p.decay(2.0)) - ) - ) - )); - - String json = "{\"function_score\":{\"functions\":[{\"weight\":1.0,\"linear\":{\"foo\":{\"decay\":2.0}}}]," + - "\"query\":{\"term\":{\"foo\":{\"value\":\"bar\"}}}}}"; - assertEquals(json, toJson(fsq)); - - Query fsq2 = checkJsonRoundtrip(fsq, json); - - assertEquals(FunctionScore.Kind.Linear, fsq2.functionScore().functions().get(0)._kind()); - assertEquals(1.0, fsq2.functionScore().functions().get(0).weight(), 0.001); - assertEquals(2.0, fsq2.functionScore().functions().get(0).linear().untyped().placement().decay(), 0.001); - } - } - - @Test - public void testBooleanVariantTag() { - - String jsonT = "{\n" + - " \"indices\": {\n" + - " \"test\": {\n" + - " \"index\": \"test\",\n" + - " \"managed\": true,\n" + - " \"policy\": \"my_policy\",\n" + - " \"index_creation_date_millis\": 1736785235558,\n" + - " \"time_since_index_creation\": \"27.75d\",\n" + - " \"lifecycle_date_millis\": 1736785235558,\n" + - " \"age\": \"27.75d\",\n" + - " \"phase\": \"warm\",\n" + - " \"phase_time_millis\": 1739183166898,\n" + - " \"action\": \"migrate\",\n" + - " \"action_time_millis\": 1739183166898,\n" + - " \"step\": \"check-migration\",\n" + - " \"step_time_millis\": 1739183166898,\n" + - " \"step_info\": {\n" + - " \"message\": \"Waiting for all shard copies to be active\",\n" + - " \"shards_left_to_allocate\": -1,\n" + - " \"all_shards_active\": false,\n" + - " \"number_of_replicas\": 1\n" + - " },\n" + - " \"phase_execution\": {\n" + - " \"policy\": \"my_policy\",\n" + - " \"phase_definition\": {\n" + - " \"min_age\": \"10d\",\n" + - " \"actions\": {\n" + - " \"forcemerge\": {\n" + - " \"max_num_segments\": 1\n" + - " }\n" + - " }\n" + - " },\n" + - " \"version\": 1,\n" + - " \"modified_date_in_millis\": 1739183005443\n" + - " }\n" + - " }\n" + - " }\n" + - "}"; - - ExplainLifecycleResponse respT = fromJson(jsonT,ExplainLifecycleResponse.class); - - // if managed is "true" then the variant class must be Managed - assertTrue(respT.indices().get("test").isTrue()); - assertTrue(respT.indices().get("test")._get().getClass().equals(LifecycleExplainManaged.class)); - - String jsonF = "{\n" + - " \"indices\": {\n" + - " \"test\": {\n" + - " \"index\": \"test\",\n" + - " \"managed\": false\n" + - " }\n" + - " }\n" + - "}"; - - ExplainLifecycleResponse respF = fromJson(jsonF,ExplainLifecycleResponse.class); - - // if managed is "false" then the variant class must be Unmanaged - assertTrue(respF.indices().get("test").isFalse()); - assertTrue(respF.indices().get("test")._get().getClass().equals(LifecycleExplainUnmanaged.class)); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/package-info.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/model/package-info.java deleted file mode 100644 index e58c3560b..000000000 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/model/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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. - */ - -/** - * Tests that verify correct types and serialization/deserialization of the API specification model using API - * structures that cover the various model features - */ -package co.elastic.clients.elasticsearch.model; diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/spec_issues/SpecIssuesTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/spec_issues/SpecIssuesTest.java index 7fae2ea82..22fafd85f 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/spec_issues/SpecIssuesTest.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/spec_issues/SpecIssuesTest.java @@ -98,7 +98,7 @@ public void i0298_runtimeMappings() throws Exception { RuntimeField runtimeField = RuntimeField.of(rf -> rf .type(RuntimeFieldType.Double) .script(Script.of(s -> s - .source(so -> so.scriptString("emit(doc['price'].value * 1.19)")) + .source("emit(doc['price'].value * 1.19)") )) ); diff --git a/java-client/src/test/java/co/elastic/clients/json/JsonDataTest.java b/java-client/src/test/java/co/elastic/clients/json/JsonDataTest.java deleted file mode 100644 index d752a8558..000000000 --- a/java-client/src/test/java/co/elastic/clients/json/JsonDataTest.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.json; - -import co.elastic.clients.elasticsearch.core.search.Hit; -import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.util.ObjectBuilder; -import jakarta.json.JsonString; -import jakarta.json.JsonValue; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import org.junit.jupiter.api.Test; - -import java.io.Reader; -import java.io.StringReader; -import java.io.StringWriter; - -public class JsonDataTest extends ModelTestCase { - -// public JsonDataTest() { -// super(JsonImpl.Jackson); -// } - - public static > B withJson(B builder, Reader json, JsonpMapper mapper) { - JsonpDeserializer classDeser = JsonpMapperBase.findDeserializer(builder.getClass().getEnclosingClass()); - - @SuppressWarnings("unchecked") - ObjectDeserializer builderDeser = (ObjectDeserializer)DelegatingDeserializer.unwrap(classDeser); - - JsonParser parser = mapper.jsonProvider().createParser(json); - builderDeser.deserialize(builder, parser, mapper, parser.next()); - return builder; - } - - @Test - public void testBuilderDeserializerHack() { - - CreateIndexRequest.Builder b = new CreateIndexRequest.Builder(); - - // Required request parameter - b.index("foo"); - - // Read body from JSON - withJson(b, new StringReader("{\"aliases\": {\"foo\": {\"is_hidden\": true}}}"), new JacksonJsonpMapper()); - - CreateIndexRequest createIndexRequest = b.build(); - } - - @Test - public void testParsing() { - if (jsonImpl == JsonImpl.Simple) { - return; // Doesn't support user-defined object mapping - } - - String json = "{\"children\":[{\"doubleValue\":3.2,\"intValue\":2}],\"doubleValue\":2.1,\"intValue\":1," + - "\"stringValue\":\"foo\"}"; - - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - - JsonData data = JsonData.from(parser, mapper); - checkClass(data); - assertEquals("foo", data.toJson().asJsonObject().getString("stringValue")); - - JsonpMapperTest.SomeClass to = data.to(JsonpMapperTest.SomeClass.class); - assertEquals("foo", to.getStringValue()); - } - - @Test - public void testSerializeObject() { - if (jsonImpl == JsonImpl.Simple) { - return; // Doesn't support user-defined object mapping - } - - String json = "{\"children\":[{\"doubleValue\":3.2,\"intValue\":2}],\"doubleValue\":2.1,\"intValue\":1," + - "\"stringValue\":\"foo\"}"; - - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - JsonpMapperTest.SomeClass sc = - mapper.deserialize(parser, JsonpMapperTest.SomeClass.class); - - assertEquals("foo", sc.getStringValue()); - assertEquals(1, sc.getChildren().size()); - assertEquals(2, sc.getChildren().get(0).getIntValue()); - // All good - - JsonData data = JsonData.of(sc); - - StringWriter sw = new StringWriter(); - JsonGenerator generator = mapper.jsonProvider().createGenerator(sw); - - data.serialize(generator, mapper); - generator.close(); - - assertEquals(json, sw.toString()); - } - - @Test - public void testSerializeValueOrBuffer() { - String json = "{\"children\":[{\"doubleValue\":3.2,\"intValue\":2}],\"doubleValue\":2.1,\"intValue\":1," + - "\"stringValue\":\"foo\"}"; - - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - - JsonData data = JsonData.from(parser, mapper); - checkClass(data); - - assertEquals(json, toJson(data, mapper)); - } - - @Test - public void testConvert() { - - JsonData json = JsonData.of("foo"); - - final JsonValue value = json.toJson(mapper); - - assertEquals(JsonValue.ValueType.STRING, value.getValueType()); - assertEquals("foo", ((JsonString)value).getString()); - } - - @Test - public void testFieldValues() { - // Specific test for https://github.com/elastic/elasticsearch-java/issues/548 which led to buffered JsonData - - String json = "{\"_index\":\"idx\",\"_id\":\"doc_id\",\"fields\":{\"bar\":\"Bar value\",\"foo\":1}}"; - - Hit hit = fromJson(json, Hit.createHitDeserializer(JsonpDeserializer.voidDeserializer())); - - assertEquals(1, hit.fields().get("foo").to(Integer.class)); - assertEquals("Bar value", hit.fields().get("bar").to(String.class)); - - checkClass(hit.fields().get("foo")); - checkClass(hit.fields().get("bar")); - - assertEquals(json, toJson(hit)); - } - - private void checkClass(JsonData data) { - String name = data.getClass().getName(); - switch (jsonImpl) { - case Jackson: - assertEquals(name, "co.elastic.clients.json.jackson.JacksonJsonBuffer"); - break; - - case Jsonb: - case Simple: - assertEquals(name, "co.elastic.clients.json.JsonDataImpl"); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/json/JsonpDeserializerBaseTest.java b/java-client/src/test/java/co/elastic/clients/json/JsonpDeserializerBaseTest.java deleted file mode 100644 index a25e3830b..000000000 --- a/java-client/src/test/java/co/elastic/clients/json/JsonpDeserializerBaseTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.json; - -import co.elastic.clients.testkit.ModelTestCase; -import jakarta.json.stream.JsonParser; -import org.junit.jupiter.api.Test; - -import java.util.List; - -public class JsonpDeserializerBaseTest extends ModelTestCase { - - @Test - public void testArrayDeserializer() { - - JsonpDeserializer> deser = - JsonpDeserializer.arrayDeserializer(JsonpDeserializer.integerDeserializer()); - - assertFalse(deser.nativeEvents().contains(JsonParser.Event.VALUE_NUMBER)); - assertTrue(deser.acceptedEvents().contains(JsonParser.Event.VALUE_NUMBER)); - - List values = fromJson("[ 42, 43 ]", deser); - assertEquals(2, values.size()); - assertEquals(42, values.get(0)); - assertEquals(43, values.get(1)); - - // Single value representation - values = fromJson("42", deser); - assertEquals(1, values.size()); - assertEquals(42, values.get(0)); - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/json/JsonpDeserializerTest.java b/java-client/src/test/java/co/elastic/clients/json/JsonpDeserializerTest.java deleted file mode 100644 index 34c99500f..000000000 --- a/java-client/src/test/java/co/elastic/clients/json/JsonpDeserializerTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.json; - -import co.elastic.clients.testkit.ModelTestCase; -import jakarta.json.stream.JsonParser; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; -import java.util.List; - -public class JsonpDeserializerTest extends ModelTestCase { - - @Test - public void testNullStringInArray() { - JsonpDeserializer> deser = JsonpDeserializer.arrayDeserializer(JsonpDeserializer.stringDeserializer()); - - JsonParser parser = mapper.jsonProvider().createParser(new StringReader("[\"a\", null, \"b\"]")); - List list = deser.deserialize(parser, mapper); - - assertEquals("a", list.get(0)); - assertNull(list.get(1)); - assertEquals("b", list.get(2)); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/json/JsonpMapperTest.java b/java-client/src/test/java/co/elastic/clients/json/JsonpMapperTest.java deleted file mode 100644 index 37f31249f..000000000 --- a/java-client/src/test/java/co/elastic/clients/json/JsonpMapperTest.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.json; - -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import jakarta.json.JsonArray; -import jakarta.json.JsonNumber; -import jakarta.json.bind.spi.JsonbProvider; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import org.eclipse.parsson.JsonProviderImpl; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; -import java.io.StringWriter; -import java.lang.reflect.Type; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class JsonpMapperTest extends Assertions { - - String json = "{\"children\":[{\"doubleValue\":3.2,\"intValue\":2}],\"doubleValue\":2.1,\"intValue\":1," + - "\"stringValue\":\"foo\"}"; - - @Test - public void testJsonb() { - JsonpMapper mapper = new JsonbJsonpMapper(new JsonProviderImpl(), JsonbProvider.provider()); - testSerialize(mapper, json); - testDeserialize(mapper, json); - testLargeNumber(mapper); - } - - @Test - public void testJackson() { - JacksonJsonpMapper mapper = new JacksonJsonpMapper(); - testSerialize(mapper, json); - testDeserialize(mapper, json); - testLargeNumber(mapper); - } - - @Test - public void testJacksonCustomMapper() { - ObjectMapper jkMapper = new ObjectMapper(); - jkMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); - jkMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - - JacksonJsonpMapper mapper = new JacksonJsonpMapper(jkMapper); - - String json = "{\"children\":[{\"double_value\":3.2,\"int_value\":2}],\"double_value\":2.1,\"int_value\":1," + - "\"string_value\":\"foo\"}"; - - testSerialize(mapper, json); - testDeserialize(mapper, json); - } - - @Test - public void testDeserializeWithType() { - - String json = "{\"foo\":{\"int_value\":1,\"double_value\":1.0},\"bar\":{\"int_value\":2,\"double_value\":2.0}}"; - - ObjectMapper jkMapper = new ObjectMapper(); - jkMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); - JacksonJsonpMapper mapper = new JacksonJsonpMapper(jkMapper); - - // With type erasure, map values are raw json nodes - { - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - Map map = new HashMap<>(); - map = mapper.deserialize(parser, (Type) map.getClass()); - - Map finalMap = map; - assertThrows(ClassCastException.class, () -> { - assertEquals(1, finalMap.get("foo").intValue); - }); - } - - // Use a j.l.reflect.Type to deserialize map values correctly - { - TypeReference> typeRef = new TypeReference>() {}; - - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - Map map = mapper.deserialize(parser, typeRef.getType()); - - System.out.println(map); - assertEquals(1, map.get("foo").intValue); - assertEquals(2, map.get("bar").intValue); - } - } - - private void testSerialize(JsonpMapper mapper, String expected) { - - SomeClass something = new SomeClass(); - something.setIntValue(1); - something.setDoubleValue(2.1); - something.setStringValue("foo"); - - SomeClass other = new SomeClass(); - other.setIntValue(2); - other.setDoubleValue(3.2); - something.setChildren(Collections.singletonList(other)); - - StringWriter strw = new StringWriter(); - JsonGenerator generator = mapper.jsonProvider().createGenerator(strw); - - mapper.serialize(something, generator); - - generator.close(); - - assertEquals(expected, strw.getBuffer().toString()); - } - - private void testDeserialize(JsonpMapper mapper, String json) { - - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - SomeClass parsed = mapper.deserialize(parser, SomeClass.class); - - assertEquals(1, parsed.getIntValue()); - assertEquals(2.1, parsed.getDoubleValue(), 0.0); - assertEquals("foo", parsed.getStringValue()); - - List children = parsed.getChildren(); - assertEquals(1, children.size()); - - SomeClass child = children.get(0); - - assertEquals(2, child.getIntValue()); - assertEquals(3.2, child.getDoubleValue(), 0.0); - assertNull(child.getStringValue()); - assertNull(child.getChildren()); - } - - private void testLargeNumber(JsonpMapper mapper) { - String json = "[1e999999]"; - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - parser.next(); - - JsonArray array = parser.getValue().asJsonArray(); - - JsonNumber number = array.getJsonNumber(0); - - assertTrue(Double.isInfinite(number.doubleValue())); - - Assertions.assertThrows(Exception.class, number::bigIntegerValue); - } - - public static class SomeClass { - private List children; - private double doubleValue; - private int intValue; - private String stringValue; - - public int getIntValue() { - return intValue; - } - - public void setIntValue(int intValue) { - this.intValue = intValue; - } - - public String getStringValue() { - return stringValue; - } - - public void setStringValue(String stringValue) { - this.stringValue = stringValue; - } - - public double getDoubleValue() { - return doubleValue; - } - - public void setDoubleValue(double doubleValue) { - this.doubleValue = doubleValue; - } - - public List getChildren() { - return children; - } - - public void setChildren(List children) { - this.children = children; - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/json/JsonpMappingExceptionTest.java b/java-client/src/test/java/co/elastic/clients/json/JsonpMappingExceptionTest.java deleted file mode 100644 index 0354e22a1..000000000 --- a/java-client/src/test/java/co/elastic/clients/json/JsonpMappingExceptionTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.json; - -import co.elastic.clients.elasticsearch._types.mapping.TypeMapping; -import co.elastic.clients.elasticsearch.core.SearchResponse; -import co.elastic.clients.testkit.ModelTestCase; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; - -public class JsonpMappingExceptionTest extends ModelTestCase { - - @Test - public void testObjectAndArrayPath() { - - String json = "{" + - " \"took\" : 9," + - " \"timed_out\" : false," + - " \"_shards\" : {" + - " \"total\" : 1," + - " \"successful\" : 1," + - " \"skipped\" : 0," + - " \"failed\" : 0" + - " }," + - " \"hits\" : {" + - " \"total\" : {" + - " \"value\" : 1," + - " \"relation\" : \"eq\"" + - " }," + - " \"max_score\" : 1.0," + - " \"hits\" : [" + - " {" + - " \"_index\" : \"test\"," + - " \"_id\" : \"8aSerXUBs1w7Wkuj31zd\"," + - " \"_score\" : \"1.0\"," + - " \"_source\" : {" + - " \"foo\" : \"bar\"" + - " }" + - " }," + - " {" + - " \"_index\" : \"test\"," + - " \"_id\" : \"8aSerXUBs1w7Wkuj31zd\"," + - " \"_score\" : \"abc\"," + // <====== error here - " \"_source\" : {" + - " \"foo\" : \"bar\"" + - " }" + - " }" + - " ]" + - " }" + - "}"; - - JsonpMappingException e = assertThrows(JsonpMappingException.class, () -> { - // withJson() will read values of the generic parameter type as JsonData - SearchResponse r = SearchResponse.of(b -> b - .withJson(new StringReader(json)) - ); - }); - - assertTrue(e.getMessage().contains("Error deserializing co.elastic.clients.elasticsearch.core.search.Hit")); - assertTrue(e.getMessage().contains("java.lang.NumberFormatException")); - - // Also checks array index in path - assertEquals("hits.hits[1]._score", e.path()); - } - - @Test - public void testLookAhead() { - - String json = - "{" + - " \"properties\": { " + - " \"foo-bar\": {" + - " \"type\": \"text\"," + - " \"baz\": false" + - " }" + - " }" + - "}"; - - // Error deserializing co.elastic.clients.elasticsearch._types.mapping.TextProperty: - // Unknown field 'baz' (JSON path: properties['foo-bar'].baz) (...line no=1, column no=36, offset=35) - - JsonpMappingException e = assertThrows(JsonpMappingException.class, () -> { - fromJson(json, TypeMapping.class, SimpleJsonpMapper.INSTANCE_REJECT_UNKNOWN_FIELDS); - }); - - // Check escaping of non identifier path elements and path from map elements - assertEquals("properties['foo-bar'].baz", e.path()); - - String msg = e.getMessage(); - assertTrue(msg.contains("Unknown field 'baz'")); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/json/JsonpUtilsTest.java b/java-client/src/test/java/co/elastic/clients/json/JsonpUtilsTest.java deleted file mode 100644 index a7f9b7a75..000000000 --- a/java-client/src/test/java/co/elastic/clients/json/JsonpUtilsTest.java +++ /dev/null @@ -1,331 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.json; - -import co.elastic.clients.elasticsearch.core.search.Hit; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.elasticsearch.security.IndexPrivilege; -import co.elastic.clients.elasticsearch.security.IndicesPrivileges; -import co.elastic.clients.elasticsearch.security.RoleTemplateScript; -import co.elastic.clients.elasticsearch.security.UserIndicesPrivileges; -import co.elastic.clients.util.AllowForbiddenApis; -import jakarta.json.JsonException; -import jakarta.json.spi.JsonProvider; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; -import java.io.StringWriter; -import java.net.URL; -import java.util.Collections; -import java.util.Enumeration; -import java.util.function.Consumer; - -public class JsonpUtilsTest extends ModelTestCase { - - @Test - @AllowForbiddenApis("Testing JsonpUtil.provider()") - public void testProviderLoading() { - // See https://github.com/elastic/elasticsearch-java/issues/163 - - // Create an empty non-delegating classloader and set it as the context classloader. It simulates a - // plugin system that doesn't set the context classloader to the plugins classloader. - ClassLoader emptyLoader = new ClassLoader() { - @Override - public Enumeration getResources(String name) { - return Collections.emptyEnumeration(); - } - }; - - ClassLoader savedLoader = Thread.currentThread().getContextClassLoader(); - try { - Thread.currentThread().setContextClassLoader(emptyLoader); - - assertThrows(JsonException.class, () -> { - assertNotNull(JsonProvider.provider()); - }); - - assertNotNull(JsonpUtils.provider()); - - } finally { - Thread.currentThread().setContextClassLoader(savedLoader); - } - } - - @Test - @AllowForbiddenApis("Testing JsonpUtil.provider()") - public void testProviderCache() { - // A new provider at each call - assertNotSame(JsonpUtils.findProvider(), JsonpUtils.findProvider()); - - // Result is cached - assertSame(JsonpUtils.provider(), JsonpUtils.provider()); - } - - @Test - public void testObjectToString() { - // Test that we call toString() on application classes. - Hit hit = Hit.of(h -> h - .source(new SomeUserData()) - .index("idx") - .id("id1") - ); - assertEquals("Hit: {\"_index\":\"idx\",\"_id\":\"id1\",\"_source\":\"Some user data\"}", hit.toString()); - } - - private static class SomeUserData { - @Override - public String toString() { - return "Some user data"; - } - } - - @Test - public void testLargeObjectToString() { - // Build a large string - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 1001; i++) { - sb.append("0123456789"); - } - - String text = sb.toString(); - assertEquals(10010, text.length()); - - Hit hit = Hit.of(h -> h - .source(text) - .index("idx") - .id("id1") - ); - - String toString = hit.toString(); - - assertEquals(10000 + "Hit: ".length() + "...".length(), toString.length()); - assertTrue(toString.startsWith("Hit: ")); - assertTrue(toString.endsWith("...")); - } - - @Test - public void testSerializeDoubleOrNull() { - // ---- Double values - assertEquals("{\"a\":null}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, Double.NaN, Double.NaN))); - assertEquals("{\"a\":1.0}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, 1.0, Double.NaN))); - - assertEquals("{\"a\":null}", - orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY))); - assertEquals("{\"a\":1.0}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, 1.0, Double.POSITIVE_INFINITY))); - - assertEquals("{\"a\":null}", - orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY))); - assertEquals("{\"a\":1.0}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, 1.0, Double.NEGATIVE_INFINITY))); - - assertEquals("{\"a\":null}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, Double.NaN, 0.0))); - - // Serialize defined default values - assertEquals("{\"a\":0.0}", orNullHelper(g -> JsonpUtils.serializeDoubleOrNull(g, 0.0, 0.0))); - - } - - @Test - public void testSerializeIntOrNull() { - assertEquals("{\"a\":null}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, Integer.MAX_VALUE, Integer.MAX_VALUE))); - assertEquals("{\"a\":1}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, 1, Integer.MAX_VALUE))); - assertEquals("{\"a\":1}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, 1, 0))); - - // Integer.MAX_VALUE is valid if not the default value - assertEquals("{\"a\":2147483647}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, Integer.MAX_VALUE, 0))); - assertEquals("{\"a\":2147483647}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, Integer.MAX_VALUE, Integer.MIN_VALUE))); - - // Serialize non infinite default values - assertEquals("{\"a\":0}", orNullHelper(g -> JsonpUtils.serializeIntOrNull(g, 0, 0))); - } - - @Test - public void testJsonString() { - // Single value - { - IndicesPrivileges priv = IndicesPrivileges.of(i -> i - .names("bar") - .query(q -> q.term(t -> t.field("baz").value(1))) - .privileges(IndexPrivilege.All.jsonValue()) - ); - - String json = "{\"names\":[\"bar\"],\"privileges\":[\"all\"],\"query\":\"{\\\"term\\\":{\\\"baz\\\":{\\\"value\\\":1}}}\"}"; - - assertEquals(json, toJson(priv)); - - priv = fromJson(json, IndicesPrivileges.class); - assertEquals("baz", priv.query().term().field()); - } - - // Single value template - { - IndicesPrivileges priv = IndicesPrivileges.of(i -> i - .names("bar") - .query(q -> q._custom("template", RoleTemplateScript.of(s -> s.id("foo")))) - .privileges(IndexPrivilege.All.jsonValue()) - ); - - String json = "{\"names\":[\"bar\"],\"privileges\":[\"all\"],\"query\":\"{\\\"template\\\":{\\\"id\\\":\\\"foo\\\"}}\"}"; - - assertEquals(json, toJson(priv)); - - priv = fromJson(json, IndicesPrivileges.class); - assertEquals("foo", priv.query()._custom().to(RoleTemplateScript.class).id()); - } - - // Array value - { - UserIndicesPrivileges priv = UserIndicesPrivileges.of(i -> i - .names("bar") - .query(q -> q.term(t -> t.field("baz").value(1))) - .privileges(IndexPrivilege.All.jsonValue()) - .allowRestrictedIndices(false) - ); - - String json = "{\"names\":[\"bar\"],\"privileges\":[\"all\"],\"query\":[\"{\\\"term\\\":{\\\"baz\\\":{\\\"value\\\":1}}}\"]," + - "\"allow_restricted_indices\":false}"; - - assertEquals(json, toJson(priv)); - - priv = fromJson(json, UserIndicesPrivileges.class); - assertEquals("baz", priv.query().get(0).term().field()); - } - } - - @Test - public void testCopy() { - // Tests round-tripping a json document that contains all event types and various kinds of nesting - - String json = "{\n" + - " \"p1\": \"str1\",\n" + - " \"p2\": 42,\n" + - " \"p3\": [\"str31\", \"str32\"],\n" + - " \"p4\": {\n" + - " \"p41\": \"str41\",\n" + - " \"p42\": [\"str421\", \"str422\"],\n" + - " \"p43\": {\n" + - " \"p431\": \"str431\"\n" + - " },\n" + - " \"p44\": true,\n" + - " \"p45\": false,\n" + - " \"p46\": 3.14\n" + - " },\n" + - " \"p5\": [{\n" + - " \"p51\": {\n" + - " \"p511\": \"str511\"\n" + - " }\n" + - " }],\n" + - " \"p6\": null\n" + - "}\n"; - - json = normalizeIndent(json); - - JsonProvider provider = JsonpUtils.provider(); - - JsonParser parser = provider.createParser(new StringReader(json)); - StringWriter sw = new StringWriter(); - JsonGenerator generator = provider.createGenerator(sw); - - JsonpUtils.copy(parser, generator); - parser.close(); - generator.close(); - - assertEquals(json, sw.toString()); - } - - private static String orNullHelper(Consumer c) { - StringWriter sw = new StringWriter(); - JsonGenerator generator = JsonpUtils.provider().createGenerator(sw); - - generator.writeStartObject(); - generator.writeKey("a"); - c.accept(generator); - generator.writeEnd(); - generator.close(); - - return sw.toString(); - } - - /** - * Normalizes the whitespace and indentation of a JSON string by parsing it and copying it to a string generator. - */ - private static String normalizeIndent(String json) { - JsonParser parser = JsonpUtils.provider().createParser(new StringReader(json)); - StringWriter sw = new StringWriter(); - JsonGenerator generator = JsonpUtils.provider().createGenerator(sw); - - copyAll(parser, generator); - - parser.close(); - generator.close(); - return sw.toString(); - } - - private static void copyAll(JsonParser parser, JsonGenerator generator) { - while(parser.hasNext()) { - switch (parser.next()) { - case START_OBJECT: - generator.writeStartObject(); - break; - - case END_OBJECT: - generator.writeEnd(); - break; - - case START_ARRAY: - generator.writeStartArray(); - break; - - case END_ARRAY: - generator.writeEnd(); - break; - - case KEY_NAME: - generator.writeKey(parser.getString()); - break; - - case VALUE_STRING: - generator.write(parser.getString()); - break; - - case VALUE_NULL: - generator.writeNull(); - break; - - case VALUE_TRUE: - generator.write(true); - break; - - case VALUE_FALSE: - generator.write(false); - break; - - case VALUE_NUMBER: - if (parser.isIntegralNumber()) { - generator.write(parser.getLong()); - } else { - generator.write(parser.getBigDecimal()); - } - break; - } - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/json/LazyDeserializerTest.java b/java-client/src/test/java/co/elastic/clients/json/LazyDeserializerTest.java deleted file mode 100644 index fef389daf..000000000 --- a/java-client/src/test/java/co/elastic/clients/json/LazyDeserializerTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.json; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.util.concurrent.CompletableFuture; - -public class LazyDeserializerTest extends Assertions { - - @Test - public void testConcurrentInit() throws Exception { - // See https://github.com/elastic/elasticsearch-java/issues/58 - - final LazyDeserializer ld = new LazyDeserializer<>(JsonpDeserializer::stringDeserializer); - - CompletableFuture> fut1; - CompletableFuture> fut2; - - // Lock the mutex and start 2 threads that will compete for it. - synchronized (ld) { - fut1 = futureUnwrap(ld); - fut2 = futureUnwrap(ld); - } - - // We should see the same non-null results everywhere - assertNotNull(fut1.get()); - assertNotNull(fut2.get()); - - final JsonpDeserializer unwrapped = ld.unwrap(); - assertEquals(unwrapped, fut1.get()); - assertEquals(unwrapped, fut2.get()); - - } - - private CompletableFuture> futureUnwrap(LazyDeserializer d) { - - final CompletableFuture> result = new CompletableFuture<>(); - - new Thread(() -> { - try { - result.complete(d.unwrap()); - } catch (Throwable e) { - result.completeExceptionally(e); - } - }).start(); - - return result; - } -} diff --git a/java-client/src/test/java/co/elastic/clients/json/ObjectBuilderDeserializerTest.java b/java-client/src/test/java/co/elastic/clients/json/ObjectBuilderDeserializerTest.java deleted file mode 100644 index 98954eea8..000000000 --- a/java-client/src/test/java/co/elastic/clients/json/ObjectBuilderDeserializerTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.json; - -import co.elastic.clients.elasticsearch._types.mapping.TextProperty; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.elasticsearch.transform.UpdateTransformRequest; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; - -public class ObjectBuilderDeserializerTest extends ModelTestCase { - - @Test - public void testNullObjectValue() { - // Should also accept null for optional values - String json = "{ \"index_prefixes\": null }"; - fromJson(json, TextProperty.class); - } - - @Test - public void testNullObjectValueInFunctionBuilder() { - String json = "{\n" + - " \"retention_policy\": null\n" + - " }"; - - UpdateTransformRequest.Builder builder = new UpdateTransformRequest.Builder(); - builder.transformId("foo"); - builder.withJson(new StringReader(json)); - builder.build(); - } - -} diff --git a/java-client/src/test/java/co/elastic/clients/json/WithJsonTest.java b/java-client/src/test/java/co/elastic/clients/json/WithJsonTest.java index 5f05bb381..02a9e15a0 100644 --- a/java-client/src/test/java/co/elastic/clients/json/WithJsonTest.java +++ b/java-client/src/test/java/co/elastic/clients/json/WithJsonTest.java @@ -128,7 +128,7 @@ public void testTypeWithParent() { .withJson(new StringReader(json)) ); - assertEquals("return doc;", is.source().scriptString()); + assertEquals("return doc;", is.source()); } @Test diff --git a/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonJsonpGeneratorTest.java b/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonJsonpGeneratorTest.java deleted file mode 100644 index 1266f6495..000000000 --- a/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonJsonpGeneratorTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.json.jackson; - -import jakarta.json.Json; -import jakarta.json.JsonValue; -import jakarta.json.stream.JsonGenerator; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.StringWriter; - -public class JacksonJsonpGeneratorTest extends Assertions { - - @Test - public void testWrite(){ - StringWriter sw = new StringWriter(); - JsonGenerator generator = new JacksonJsonpMapper().jsonProvider().createGenerator(sw); - - generator.writeStartObject(); - - // Boolean - generator.write("bool1", true); - generator.writeKey("bool2"); - generator.write(false); - - // String - generator.write("str1", "foo"); - generator.writeKey("str2"); - generator.write("bar"); - - // Integer - generator.write("int1", 42); - generator.writeKey("int2"); - generator.write(1337); - - // Long - generator.write("long1", 123456789012345L); - generator.writeKey("long2"); - generator.write(123456789012345L); - - generator.write("double1", 0.001); - generator.writeKey("double2"); - generator.write(12345.6789); - - // JsonValue - JsonValue jsonValue = Json.createObjectBuilder() - .add("bool", true) - .add("str", "foo") - .add("int", 42) - .add("long", 123456789012345L) - .add("double", 12345.6789) - .build(); - - generator.write("value", jsonValue); - - generator.close(); - - assertEquals("{" + - "\"bool1\":true," + - "\"bool2\":false," + - "\"str1\":\"foo\"," + - "\"str2\":\"bar\"," + - "\"int1\":42," + - "\"int2\":1337," + - "\"long1\":123456789012345," + - "\"long2\":123456789012345," + - "\"double1\":0.001," + - "\"double2\":12345.6789," + - "\"value\":{\"bool\":true,\"str\":\"foo\",\"int\":42,\"long\":123456789012345,\"double\":12345.6789}" + - "}", sw.toString()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonJsonpParserTest.java b/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonJsonpParserTest.java deleted file mode 100644 index 3ac15c3f6..000000000 --- a/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonJsonpParserTest.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.json.jackson; - -import co.elastic.clients.elasticsearch.core.MsearchResponse; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.testkit.ModelTestCase; -import jakarta.json.stream.JsonParser; -import jakarta.json.stream.JsonParser.Event; -import org.junit.jupiter.api.Test; - -import java.io.StringReader; - -public class JacksonJsonpParserTest extends ModelTestCase { - - private static final String json = - "{ 'foo': 'fooValue', 'bar': { 'baz': 1}, 'quux': [true] }".replace('\'', '"'); - - @Test - public void testEventStream() { - - JacksonJsonProvider provider = new JacksonJsonProvider(); - JsonParser parser = provider.createParser(new StringReader(json)); - - assertEquals(Event.START_OBJECT, parser.next()); - - assertEquals(Event.KEY_NAME, parser.next()); - assertEquals("foo", parser.getString()); - - assertEquals(Event.VALUE_STRING, parser.next()); - assertEquals("fooValue", parser.getString()); - - // test it sometimes, but not always to detect invalid state management - assertTrue(parser.hasNext()); - - assertEquals(Event.KEY_NAME, parser.next()); - assertEquals("bar", parser.getString()); - - assertEquals(Event.START_OBJECT, parser.next()); - - assertEquals(Event.KEY_NAME, parser.next()); - assertEquals("baz", parser.getString()); - - assertTrue(parser.hasNext()); - assertEquals(Event.VALUE_NUMBER, parser.next()); - assertEquals(1, parser.getInt()); - - assertEquals(Event.END_OBJECT, parser.next()); - - assertEquals(Event.KEY_NAME, parser.next()); - assertEquals("quux", parser.getString()); - - assertEquals(Event.START_ARRAY, parser.next()); - - assertEquals(Event.VALUE_TRUE, parser.next()); - - assertEquals(Event.END_ARRAY, parser.next()); - assertEquals(Event.END_OBJECT, parser.next()); - - assertFalse(parser.hasNext()); - } - - @Test - public void testForbidValueGettersAfterHasNext() { - - JacksonJsonProvider provider = new JacksonJsonProvider(); - JsonParser parser = provider.createParser(new StringReader(json)); - - assertEquals(Event.START_OBJECT, parser.next()); - assertEquals(Event.KEY_NAME, parser.next()); - assertEquals(Event.VALUE_STRING, parser.next()); - assertEquals("fooValue", parser.getString()); - - assertTrue(parser.hasNext()); - - try { - assertEquals("fooValue", parser.getString()); - fail(); - } catch (IllegalStateException e) { - // expected - } - } - - @Test - void testMultiSearchResponse() { - String json = - "{\n" + - " \"took\" : 1,\n" + - " \"responses\" : [\n" + - " {\n" + - " \"error\" : {\n" + - " \"root_cause\" : [\n" + - " {\n" + - " \"type\" : \"index_not_found_exception\",\n" + - " \"reason\" : \"no such index [foo_bar]\",\n" + - " \"resource.type\" : \"index_or_alias\",\n" + - " \"resource.id\" : \"foo_bar\",\n" + - " \"index_uuid\" : \"_na_\",\n" + - " \"index\" : \"foo_bar\"\n" + - " }\n" + - " ],\n" + - " \"type\" : \"index_not_found_exception\",\n" + - " \"reason\" : \"no such index [foo_bar]\",\n" + - " \"resource.type\" : \"index_or_alias\",\n" + - " \"resource.id\" : \"foo_bar\",\n" + - " \"index_uuid\" : \"_na_\",\n" + - " \"index\" : \"foo_bar\"\n" + - " },\n" + - " \"status\" : 404\n" + - " },\n" + - " {\n" + - " \"took\" : 1,\n" + - " \"timed_out\" : false,\n" + - " \"_shards\" : {\n" + - " \"total\" : 1,\n" + - " \"successful\" : 1,\n" + - " \"skipped\" : 0,\n" + - " \"failed\" : 0\n" + - " },\n" + - " \"hits\" : {\n" + - " \"total\" : {\n" + - " \"value\" : 5,\n" + - " \"relation\" : \"eq\"\n" + - " },\n" + - " \"max_score\" : 1.0,\n" + - " \"hits\" : [\n" + - " {\n" + - " \"_index\" : \"foo\",\n" + - " \"_id\" : \"Wr0ApoEBa_iiaABtVM57\",\n" + - " \"_score\" : 1.0,\n" + - " \"_source\" : {\n" + - " \"x\" : 1,\n" + - " \"y\" : true\n" + - " }\n" + - " }\n" + - " ]\n" + - " },\n" + - " \"status\" : 200\n" + - " }\n" + - " ]\n" + - "}\n"; - - JsonpMapper mapper = new JacksonJsonpMapper(); - mapper = mapper.withAttribute("co.elastic.clients:Deserializer:_global.msearch.Response.TDocument", - JsonpDeserializer.of(Foo.class)); - @SuppressWarnings("unchecked") - MsearchResponse response = fromJson(json, MsearchResponse.class, mapper); - - assertEquals(2, response.responses().size()); - assertEquals(404, response.responses().get(0).failure().status()); - assertEquals(200, response.responses().get(1).result().status()); - } - - public static class Foo { - private int x; - private boolean y; - - public int getX() { - return x; - } - - public void setX(int x) { - this.x = x; - } - - public boolean isY() { - return y; - } - - public void setY(boolean y) { - this.y = y; - } - } - -} diff --git a/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonMapperTest.java b/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonMapperTest.java deleted file mode 100644 index 56d42d7ac..000000000 --- a/java-client/src/test/java/co/elastic/clients/json/jackson/JacksonMapperTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.json.jackson; - -import co.elastic.clients.elasticsearch.core.search.Hit; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonNaming; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.Collections; -import java.util.List; - -public class JacksonMapperTest extends ModelTestCase { - - @Test - public void testCustomDeserializer() { - // See https://github.com/elastic/elasticsearch-java/issues/120 - JsonpMapper jsonpMapper = new JacksonJsonpMapper(); - - String json = "{\"_index\":\"foo\",\"_id\":\"1\",\"_source\":{\"model\":\"Foo\",\"age\":42}}"; - - Hit testDataHit = fromJson(json, - Hit.createHitDeserializer(JsonpDeserializer.of(TestData.class)), - jsonpMapper - ); - TestData data = testDataHit.source(); - assertEquals("Foo", data.theModel); - assertEquals(42, data.theAge); - } - - @JsonDeserialize(using = TestData.TestDeserializer.class) - public static class TestData { - public String theModel; - public int theAge; - - public static class TestDeserializer extends JsonDeserializer { - - @Override - public TestData deserialize(JsonParser jp, DeserializationContext ctx) throws IOException { - JsonNode node = jp.getCodec().readTree(jp); - - TestData res = new TestData(); - if (node.has("age")) { - res.theAge = node.get("age").asInt(); - } - if (node.has("model")) { - res.theModel = node.get("model").asText(); - } - return res; - } - } - } - - @Test - public void testSingleValueAsList() { - JsonpMapper jsonpMapper = new JacksonJsonpMapper(); - - String json = "{\"_index\":\"foo\",\"_id\":\"1\",\"_source\":{\"emp_no\":42,\"job_positions\":\"SWE\"}}"; - - Hit testDataHit = fromJson(json, - Hit.createHitDeserializer(JsonpDeserializer.of(EmpData.class)), - jsonpMapper - ); - EmpData data = testDataHit.source(); - assertEquals(42, data.empNo); - assertEquals(Collections.singletonList("SWE"), data.jobPositions); - } - - @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) - @JsonIgnoreProperties(ignoreUnknown = true) - public static class EmpData { - public int empNo; - public List jobPositions; - } -} diff --git a/java-client/src/test/java/co/elastic/clients/json/jackson/JsonEnumTest.java b/java-client/src/test/java/co/elastic/clients/json/jackson/JsonEnumTest.java deleted file mode 100644 index 3ae53e2fc..000000000 --- a/java-client/src/test/java/co/elastic/clients/json/jackson/JsonEnumTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.json.jackson; - -import co.elastic.clients.elasticsearch._types.query_dsl.SimpleQueryStringFlag; -import co.elastic.clients.elasticsearch._types.query_dsl.SimpleQueryStringQuery; -import co.elastic.clients.testkit.ModelTestCase; -import org.junit.jupiter.api.Test; - -public class JsonEnumTest extends ModelTestCase { - - @Test - public void testPipeSeparatedEnum() { - { - // Empty flags - String jsonNoFlags = "{\"query\":\"foo\"}"; - SimpleQueryStringQuery q = SimpleQueryStringQuery.of(b -> b - .query("foo") - ); - q = checkJsonRoundtrip(q, jsonNoFlags); - assertEquals("foo", q.query()); - assertTrue(q.flags().isEmpty()); - } - - { - // With flags - String jsonWithFlags = "{\"flags\":\"AND|NEAR\",\"query\":\"foo\"}"; - SimpleQueryStringQuery q = SimpleQueryStringQuery.of(b -> b - .query("foo") - .flags(SimpleQueryStringFlag.And, SimpleQueryStringFlag.Near) - ); - q = checkJsonRoundtrip(q, jsonWithFlags); - assertEquals("foo", q.query()); - assertEquals(2, q.flags().size()); - assertEquals(SimpleQueryStringFlag.And, q.flags().get(0)); - assertEquals(SimpleQueryStringFlag.Near, q.flags().get(1)); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/json/jackson/JsonValueParserTest.java b/java-client/src/test/java/co/elastic/clients/json/jackson/JsonValueParserTest.java deleted file mode 100644 index 0f49a6191..000000000 --- a/java-client/src/test/java/co/elastic/clients/json/jackson/JsonValueParserTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.json.jackson; - -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import jakarta.json.JsonObject; -import jakarta.json.JsonValue; -import jakarta.json.stream.JsonParser; - -import java.io.StringReader; -import java.util.Map; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class JsonValueParserTest extends Assertions { - - public static class Data { - public Map data; - } - - @Test - public void testFloatsShouldDeserializeAsFloats() throws Exception { - // When using Jackson to target a map of objects, values with a decimal separator - // should deserialize as a double even if they fit in an int or long. - // See https://github.com/elastic/elasticsearch-java/issues/156 - - String json = "{\"data\": {\"value\": 1.4778125E7, \"value2\": 1.4778125E7 }}"; - JsonpMapper mapper = new JacksonJsonpMapper(); - - { - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - Data data = mapper.deserialize(parser, Data.class); - - Double d = (Double)data.data.get("value"); - assertEquals(1.4778125E7, d, 0.001); - } - - { - // Test with buffering used in union resolution - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - parser.next(); - JsonObject object = parser.getObject(); - - // Test equals/hashcode - JsonValue v = object.getJsonObject("data").get("value"); - JsonValue v2 = object.getJsonObject("data").get("value2"); - - assertEquals(v.hashCode(), v2.hashCode()); - assertEquals(v, v2); - - parser = JsonpUtils.jsonValueParser(object, mapper); - Data data = mapper.deserialize(parser, Data.class); - - Double d = (Double)data.data.get("value"); - assertEquals(1.4778125E7, d, 0.001); - } - - } -} diff --git a/java-client/src/test/java/co/elastic/clients/testkit/MockHttpClient.java b/java-client/src/test/java/co/elastic/clients/testkit/MockHttpClient.java deleted file mode 100644 index cc2c0e878..000000000 --- a/java-client/src/test/java/co/elastic/clients/testkit/MockHttpClient.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.testkit; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.transport.ElasticsearchTransportBase; -import co.elastic.clients.transport.TransportException; -import co.elastic.clients.transport.TransportOptions; -import co.elastic.clients.transport.http.TransportHttpClient; -import co.elastic.clients.util.BinaryData; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; - -public class MockHttpClient implements TransportHttpClient { - - private static final Response NotFound = new MockResponse(404, null); - - Map responses = new ConcurrentHashMap<>(); - - public MockHttpClient add(String path, String contentType, byte[] data) { - responses.put(path, new MockResponse(200, BinaryData.of(data, contentType))); - return this; - } - - public MockHttpClient add(String path, String contentType, String text) { - responses.put(path, new MockResponse(200, BinaryData.of(text.getBytes(StandardCharsets.UTF_8), contentType))); - return this; - } - - public ElasticsearchClient client() { - return client(new ModelTestCase() {}.mapper); - } - - public ElasticsearchClient client(JsonpMapper mapper) { - return new ElasticsearchClient(new ElasticsearchTransportBase(this, null, mapper) { - @Override - public void close() throws IOException { - super.close(); - } - }); - } - - - @Override - public Response performRequest( - String endpointId, @Nullable TransportHttpClient.Node node, Request request, TransportOptions option - ) throws IOException { - Response response = responses.get(request.path()); - - if (response == null) { - throw new TransportException(NotFound, "Not found", endpointId); - } - - return response; - } - - @Override - public CompletableFuture performRequestAsync( - String endpointId, @Nullable TransportHttpClient.Node node, Request request, TransportOptions options - ) { - CompletableFuture result = new CompletableFuture<>(); - try { - Response response = performRequest(endpointId, node, request, options); - result.complete(response); - } catch (Exception e) { - result.completeExceptionally(e); - } - return result; - } - - @Override - public void close() throws IOException { - } - - private static class MockResponse implements TransportHttpClient.Response { - - private final int statusCode; - private final BinaryData body; - private final Map headers; - - MockResponse(int statusCode, BinaryData body) { - this.statusCode = statusCode; - this.headers = new HashMap<>(); - this.body = body; - - if (body != null) { - headers.put("content-type", body.contentType()); - } - headers.put("x-elastic-product", "Elasticsearch"); - } - - @Override - public Node node() { - return null; - } - - @Override - public int statusCode() { - return statusCode; - } - - @Nullable - @Override - public String header(String name) { - return headers.get(name.toLowerCase()); - } - - @Override - public List headers(String name) { - String header = header(name); - return header == null ? null : Collections.singletonList(header); - } - - @Nullable - @Override - public BinaryData body() throws IOException { - return body; - } - - @Nullable - @Override - public Object originalResponse() { - return null; - } - - @Override - public void close() throws IOException { - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/testkit/ModelTestCase.java b/java-client/src/test/java/co/elastic/clients/testkit/ModelTestCase.java deleted file mode 100644 index 7d6cdbbb2..000000000 --- a/java-client/src/test/java/co/elastic/clients/testkit/ModelTestCase.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.testkit; - -import co.elastic.clients.json.JsonpDeserializer; -import co.elastic.clients.json.JsonpMapper; -import co.elastic.clients.json.SimpleJsonpMapper; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import jakarta.json.spi.JsonProvider; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; -import org.junit.jupiter.api.Assertions; - -import java.io.StringReader; -import java.io.StringWriter; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.util.EnumSet; -import java.util.Random; - -/** - * Base class for tests that encode/decode json - */ -public abstract class ModelTestCase extends Assertions { - - protected enum JsonImpl { Jsonb, Jackson, Simple }; - - // Same value for all tests in a test run - private static final int RAND = new Random().nextInt(100); - - protected final JsonImpl jsonImpl; - protected final JsonpMapper mapper; - - private static JsonImpl chooseJsonImpl(EnumSet jsonImplCandidates, int rand) { - // Converting an EnumSet to an array always uses the same order. - return jsonImplCandidates.toArray(new JsonImpl[jsonImplCandidates.size()])[rand % jsonImplCandidates.size()]; - } - - private static JsonpMapper createMapper(JsonImpl jsonImpl, int rand) { - switch(jsonImpl) { - case Jsonb: - System.out.println("Using a JsonB mapper (rand = " + rand + ")."); - return new JsonbJsonpMapper(); - - case Jackson: - System.out.println("Using a Jackson mapper (rand = " + rand + ")."); - return new JacksonJsonpMapper(); - - default: - System.out.println("Using a simple mapper (rand = " + rand + ")."); - return SimpleJsonpMapper.INSTANCE; - } - } - - protected ModelTestCase(EnumSet jsonImplCandidates, int rand) { - jsonImpl = chooseJsonImpl(jsonImplCandidates, rand); - mapper = createMapper(jsonImpl, rand); - } - - protected ModelTestCase(EnumSet jsonImplCandidates) { - this(jsonImplCandidates, RAND); - } - - protected ModelTestCase(JsonImpl jsonImpl) { - this(EnumSet.of(jsonImpl), RAND); - } - - protected ModelTestCase(int rand) { - this(EnumSet.allOf(JsonImpl.class), rand); - } - - protected ModelTestCase() { - this(EnumSet.allOf(JsonImpl.class), RAND); - } - - protected String toJson(T value) { - return toJson(value, mapper); - } - - public static String toJson(T value, JsonpMapper mapper) { - StringWriter sw = new StringWriter(); - JsonProvider provider = mapper.jsonProvider(); - JsonGenerator generator = provider.createGenerator(sw); - mapper.serialize(value, generator); - generator.close(); - return sw.toString(); - } - - public static T fromJson(String json, Class clazz, JsonpMapper mapper) { - return fromJson(json, (Type)clazz, mapper); - } - - public static T fromJson(String json, Type type, JsonpMapper mapper) { - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - return mapper.deserialize(parser, type); - } - - protected T fromJson(String json, Class clazz) { - return fromJson(json, clazz, mapper); - } - - protected T fromJson(String json, Type type) { - return fromJson(json, type, mapper); - } - - @SuppressWarnings("unchecked") - protected T checkJsonRoundtrip(T value, String expectedJson) { - assertEquals(expectedJson, toJson(value)); - return fromJson(expectedJson, (Class)value.getClass()); - } - - protected T fromJson(String json, JsonpDeserializer deserializer) { - return fromJson(json, deserializer, mapper); - } - - protected T fromJson(String json, JsonpDeserializer deserializer, JsonpMapper mapper) { - JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); - return deserializer.deserialize(parser, mapper); - } - - - public static void assertGetterType(Class expected, Class clazz, String name) { - Method method; - try { - method = clazz.getMethod(name); - } catch (NoSuchMethodException e) { - fail("Getter '" + clazz.getName() + "." + name + "' doesn't exist"); - return; - } - - assertSame(expected, method.getReturnType()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/RequestOptionsTest.java b/java-client/src/test/java/co/elastic/clients/transport5/RequestOptionsTest.java deleted file mode 100644 index 3a3e50286..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/RequestOptionsTest.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.json.jsonb.JsonbJsonpMapper; -import co.elastic.clients.transport.rest5_client.RestClientTransport; -import com.sun.net.httpserver.HttpServer; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.NameValuePair; -import org.apache.hc.core5.net.URLEncodedUtils; -import org.elasticsearch.client.ResponseException; -import org.elasticsearch.client.RestClient; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; - -public class RequestOptionsTest extends Assertions { - - private static HttpServer httpServer; - private static RestClient restClient; - - @BeforeEach - public void classSetup() throws IOException { - - httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); - httpServer.createContext("/", ex -> { - if (ex.getRequestMethod().equals("HEAD")) { - // Call to ping() - ex.sendResponseHeaders(200, -1); - } - - // Call to info() - // Send back all request headers with a 501 that will cause an exception where we can access the LLRC response - ex.getResponseHeaders().putAll(ex.getRequestHeaders()); - ex.sendResponseHeaders(501, 0); - OutputStreamWriter out = new OutputStreamWriter(ex.getResponseBody(), StandardCharsets.UTF_8); - for (Map.Entry> header: ex.getRequestHeaders().entrySet()) { - out.write("header-"); - out.write(header.getKey().toLowerCase(Locale.ROOT)); - out.write("="); - out.write(header.getValue().get(0)); - out.write("\n"); - } - final List params = URLEncodedUtils.parse(ex.getRequestURI(), StandardCharsets.UTF_8); - for (NameValuePair param: params) { - out.write("param-"); - out.write(param.getName()); - out.write("="); - out.write(param.getValue()); - } - out.close(); - }); - - httpServer.start(); - restClient = RestClient.builder(new HttpHost("http",httpServer.getAddress().getHostString(), - httpServer.getAddress().getPort())).build(); - } - - @AfterEach - public void classTearDown() throws IOException { - httpServer.stop(0); - restClient.close(); - } - - private Properties getProps(ElasticsearchClient client) throws IOException { - ResponseException ex = assertThrows(ResponseException.class, client::info); - assertEquals(501, ex.getResponse().getStatusCode()); - Properties result = new Properties(); - result.load(ex.getResponse().getEntity().getContent()); - return result; - } - - @Test - public void testNonNullClientOptions() { - final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); - final ElasticsearchClient client = new ElasticsearchClient(trsp); - - assertNotNull(client._transportOptions()); - assertSame(trsp.options(), client._transportOptions()); - } - - @Test - public void testDefaultHeaders() throws IOException { - final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); - final ElasticsearchClient client = new ElasticsearchClient(trsp); - - Properties props = getProps(client); - - assertTrue(props.getProperty("header-user-agent").startsWith("elastic-java/" + Version.VERSION.toString())); - assertTrue(props.getProperty("header-x-elastic-client-meta").contains("es=")); - assertTrue(props.getProperty("header-x-elastic-client-meta").contains("hl=2")); - assertEquals( - "application/vnd.elasticsearch+json; compatible-with=" + Version.VERSION.major(), - props.getProperty("header-accept") - ); - } - - @Test - public void testClientHeader() throws IOException { - final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); - final ElasticsearchClient client = new ElasticsearchClient(trsp) - .withTransportOptions(b -> b - .addHeader("X-Foo", "Bar") - .addHeader("uSer-agEnt", "MegaClient/1.2.3") - ); - - Properties props = getProps(client); - assertEquals("Bar", props.getProperty("header-x-foo")); - assertEquals("MegaClient/1.2.3", props.getProperty("header-user-agent")); - } - - @Test - public void testQueryParameter() throws IOException { - final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); - final ElasticsearchClient client = new ElasticsearchClient(trsp) - .withTransportOptions(trsp.options().with( - b -> b.setParameter("format", "pretty") - ) - ); - - Properties props = getProps(client); - assertEquals("pretty", props.getProperty("param-format")); - } - - @Test - public void testMissingProductHeader() { - final RestClientTransport trsp = new RestClientTransport(restClient, new JsonbJsonpMapper()); - final ElasticsearchClient client = new ElasticsearchClient(trsp); - - final TransportException ex = assertThrows(TransportException.class, client::ping); - assertTrue(ex.getMessage().contains("Missing [X-Elastic-Product] header")); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/TransportTest.java b/java-client/src/test/java/co/elastic/clients/transport5/TransportTest.java deleted file mode 100644 index dec29b338..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/TransportTest.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.http.RepeatableBodyResponse; -import co.elastic.clients.transport.http.TransportHttpClient; -import co.elastic.clients.transport.rest5_client.RestClientOptions; -import co.elastic.clients.transport.rest5_client.RestClientTransport; -import co.elastic.clients.util.BinaryData; -import com.sun.net.httpserver.HttpServer; -import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.RestClient; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; -import java.util.Collections; - -import static co.elastic.clients.util.ContentType.APPLICATION_JSON; - -public class TransportTest extends Assertions { - - @Test - public void testXMLResponse() throws Exception { - HttpServer httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), - 0), 0); - - httpServer.createContext("/_cat/indices", exchange -> { - exchange.sendResponseHeaders(401, 0); - OutputStream out = exchange.getResponseBody(); - out.write( - "Error".getBytes(StandardCharsets.UTF_8) - ); - out.close(); - }); - - httpServer.start(); - InetSocketAddress address = httpServer.getAddress(); - - RestClient restClient = RestClient - .builder(new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort())) - .build(); - - ElasticsearchClient esClient = new ElasticsearchClient(new RestClientTransport(restClient, - new JacksonJsonpMapper())); - - TransportException ex = Assertions.assertThrows( - TransportException.class, - () -> esClient.cat().indices() - ); - - httpServer.stop(0); - - assertEquals(401, ex.statusCode()); - assertEquals("es/cat.indices", ex.endpointId()); - - // Original response is transport-dependent - Response restClientResponse = (Response) ex.response().originalResponse(); - assertEquals(401, restClientResponse.getStatusCode()); - } - - - @Test - public void testOriginalJsonBodyRetrievalException() throws Exception { - HttpServer httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), - 0), 0); - - httpServer.createContext("/_cat/indices", exchange -> { - exchange.getResponseHeaders().put("Content-Type", Collections.singletonList(APPLICATION_JSON)); - exchange.getResponseHeaders().put("X-Elastic-Product", Collections.singletonList("Elasticsearch" - )); - exchange.sendResponseHeaders(200, 0); - OutputStream out = exchange.getResponseBody(); - out.write( - "definitely not json".getBytes(StandardCharsets.UTF_8) - ); - out.close(); - }); - - httpServer.start(); - - RestClient restClient = RestClient - .builder(new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort())) - .build(); - - // no transport options, response is not RepeatableBodyResponse, original body cannot be retrieved - ElasticsearchClient esClient = new ElasticsearchClient(new RestClientTransport(restClient, - new JacksonJsonpMapper())); - - TransportException ex = Assertions.assertThrows( - TransportException.class, - () -> esClient.cat().indices() - ); - - assertEquals(200, ex.statusCode()); - assertNotEquals(RepeatableBodyResponse.class, ex.response().getClass()); - - // setting transport option - RestClientOptions options = new RestClientOptions(RequestOptions.DEFAULT, true); - - ElasticsearchTransport transport = new RestClientTransport( - restClient, new JacksonJsonpMapper(), options); - - ElasticsearchClient esClientOptions = new ElasticsearchClient(transport); - - ex = Assertions.assertThrows( - TransportException.class, - () -> esClientOptions.cat().indices() - ); - - httpServer.stop(0); - - assertEquals(200, ex.statusCode()); - //TODO apparently the new byteentity is always repeatable - // no need for the whole RepeatableBodyResponse if true? - //assertEquals(RepeatableBodyResponse.class, ex.response().getClass()); - - try (TransportHttpClient.Response repeatableResponse = ex.response()){ - BinaryData body = repeatableResponse.body(); - StringBuilder sb = new StringBuilder(); - BufferedReader br = new BufferedReader(new InputStreamReader(body.asInputStream())); - String read; - - while ((read = br.readLine()) != null) { - sb.append(read); - } - br.close(); - assertEquals("definitely not json",sb.toString()); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/TransportUtilsTest.java b/java-client/src/test/java/co/elastic/clients/transport5/TransportUtilsTest.java deleted file mode 100644 index bfe836793..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/TransportUtilsTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.ElasticsearchTestServer; -import co.elastic.clients.json.SimpleJsonpMapper; -import co.elastic.clients.transport.rest5_client.RestClientTransport; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.message.BasicHeader; -import org.elasticsearch.client.RestClient; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.testcontainers.elasticsearch.ElasticsearchContainer; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLHandshakeException; -import java.io.ByteArrayInputStream; -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.cert.Certificate; -import java.security.cert.CertificateFactory; -import java.util.Base64; -import java.util.Optional; - -public class TransportUtilsTest extends Assertions { - - @Test - public void testNoSslContext() { - assertThrows( - SSLHandshakeException.class, - () -> checkConnection(null) - ); - } - - @Test - public void testCaCertificate() throws Exception { - byte[] cert = ElasticsearchTestServer.global().container().caCertAsBytes().get(); - - checkConnection( - TransportUtils.sslContextFromHttpCaCrt(new ByteArrayInputStream(cert)) - ); - } - - @Test void testCaFingerprint() throws Exception { - byte[] pemCert = ElasticsearchTestServer.global().container().caCertAsBytes().get(); - - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - Certificate x509cert = cf.generateCertificate(new ByteArrayInputStream(pemCert)); - - // Compute SHA-256 fingerprint, which is what ES outputs at start time - String fingerprint = fingerprint(x509cert.getEncoded(), "SHA-256"); - - checkConnection( - TransportUtils.sslContextFromCaFingerprint(fingerprint) - ); - } - - @Test void testInvalidFingerprint() throws Exception { - // Build a dummy SHA-256 signature - String fingerprint = fingerprint("foobar".getBytes(StandardCharsets.UTF_8), "SHA-256"); - - assertThrows( - SSLHandshakeException.class, - () -> checkConnection( - TransportUtils.sslContextFromCaFingerprint(fingerprint) - ) - ); - } - - private void checkConnection(SSLContext sslContext) throws Exception { - ElasticsearchContainer container = ElasticsearchTestServer.global().container(); - - var creds = Base64.getEncoder().encodeToString("elastic:changeme".getBytes()); - - RestClient restClient = RestClient.builder(new HttpHost("https", "localhost", - container.getMappedPort(9200))) - .setSslContext(Optional.ofNullable(sslContext).orElse(SSLContext.getDefault())) - .setDefaultHeaders(new Header[]{ - new BasicHeader("Authorization", "Basic " + creds) - }).build(); - - RestClientTransport transport = new RestClientTransport(restClient, SimpleJsonpMapper.INSTANCE); - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - assertNotNull(esClient.info()); - } - - private String fingerprint(byte[] bytes, String algorithm) throws Exception { - byte[] fingerprint; - MessageDigest md = MessageDigest.getInstance(algorithm); - md.update(bytes); - fingerprint = md.digest(); - - StringBuilder sb = new StringBuilder(fingerprint.length * 2); - for(byte b: fingerprint) { - sb.append(String.format("%02x", b)); - } - - return sb.toString(); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/VersionInfoTest.java b/java-client/src/test/java/co/elastic/clients/transport5/VersionInfoTest.java deleted file mode 100644 index c324c21ed..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/VersionInfoTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class VersionInfoTest { - - @Test - public void testClientMeta() { - String version = VersionInfo.VERSION; - Assertions.assertTrue(ElasticsearchTransportBase.getClientMeta().startsWith("es=" + version + ",jv=")); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/endpoints/BinaryEndpointTest.java b/java-client/src/test/java/co/elastic/clients/transport5/endpoints/BinaryEndpointTest.java deleted file mode 100644 index aaf3ea549..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/endpoints/BinaryEndpointTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.endpoints; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.ElasticsearchTestServer; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.json.SimpleJsonpMapper; -import co.elastic.clients.transport.TransportOptions; -import co.elastic.clients.transport.rest5_client.RestClientTransport; -import com.sun.net.httpserver.HttpServer; -import org.apache.commons.io.IOUtils; -import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.RestClient; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; - -public class BinaryEndpointTest extends Assertions { - - /** Collected headers by test name */ - private static HttpServer httpServer; - - @BeforeAll - public static void setup() throws IOException { - httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); - - // Register a handler on the core.exists("capture-handler/{name}") endpoint that will capture request headers. - httpServer.createContext("/foo/_mvt/bar/1/0/0", exchange -> { - // Reply with an empty 200 response - exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); - exchange.getResponseHeaders().set("Content-Type", "application/vnd.hello-world"); - exchange.sendResponseHeaders(200, 0); - exchange.getResponseBody().write("Hello world".getBytes(StandardCharsets.UTF_8)); - exchange.close(); - }); - - httpServer.start(); - } - - @AfterAll - public static void cleanup() { - httpServer.stop(0); - httpServer = null; - } - - @Test - public void testMvtSearch() throws IOException { - RestClient llrc = RestClient.builder( - new HttpHost("http",httpServer.getAddress().getHostString(), httpServer.getAddress().getPort()) - ).build(); - - RestClientTransport transport = new RestClientTransport(llrc, new SimpleJsonpMapper()); - ElasticsearchClient esClient = new ElasticsearchClient(transport); - - BinaryResponse resp = esClient.searchMvt(s -> s - .index("foo") - .field("bar") - .x(0) - .y(0) - .zoom(1) - ); - - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buffer = new byte[256]; - - try(InputStream input = resp.content()) { - int len; - while ((len = input.read(buffer)) > 0) { - baos.write(buffer, 0, len); - } - } - - assertEquals("application/vnd.hello-world", resp.contentType()); - assertEquals("Hello world", baos.toString(StandardCharsets.UTF_8.name())); - } - - @Test - public void convertJsonToBinaryEndpoint() throws IOException { - - ElasticsearchClient esClient = ElasticsearchTestServer.global().client(); - - // Create the search request - SearchRequest request = SearchRequest.of(b -> b); - - // Create a binary endpoint from the regular search endpoint. It will not deserialize - // the response and instead will just return the raw response input stream. - BinaryEndpoint binarySearchEndpoint = SearchRequest._ENDPOINT.withBinaryResponse(); - - // Force typed_keys to false, so that aggregations names do not hold type information - TransportOptions options = esClient._transportOptions().toBuilder() - .setParameter("typed_keys", "false") - .build(); - - // Call Elasticsearch by providing the transport the request and endpoint - BinaryResponse binaryResponse = esClient._transport().performRequest(request, binarySearchEndpoint, options); - - // Do something with the response - String response = IOUtils.toString(binaryResponse.content(), StandardCharsets.UTF_8); - assertTrue(response.matches("\\{\"took\":\\d+,\"timed_out\":false.*")); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/endpoints/BooleanEndpointTest.java b/java-client/src/test/java/co/elastic/clients/transport5/endpoints/BooleanEndpointTest.java deleted file mode 100644 index c3fbc3465..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/endpoints/BooleanEndpointTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.endpoints; - -import co.elastic.clients.elasticsearch.core.ExistsRequest; -import co.elastic.clients.elasticsearch.security.SamlCompleteLogoutRequest; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class BooleanEndpointTest extends Assertions { - - @Test - public void testHasRequestBody() { - ExistsRequest er = ExistsRequest.of(r -> r.index("foo").id("1")); - assertNull(ExistsRequest._ENDPOINT.body(er)); - - SamlCompleteLogoutRequest sclr = SamlCompleteLogoutRequest.of(r -> r.ids("1").realm("r")); - assertNotNull(SamlCompleteLogoutRequest._ENDPOINT.body(sclr)); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/endpoints/EndpointBaseTest.java b/java-client/src/test/java/co/elastic/clients/transport5/endpoints/EndpointBaseTest.java deleted file mode 100644 index 3c5f2b46c..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/endpoints/EndpointBaseTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.endpoints; - -import co.elastic.clients.elasticsearch._types.ErrorResponse; -import co.elastic.clients.elasticsearch.core.PingRequest; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.transport.Endpoint; -import org.junit.jupiter.api.Test; - -public class EndpointBaseTest extends ModelTestCase { - - @Test - public void testPathEncoding() { - assertEquals("abCD12;-_*", pathEncode("abCD12;-_*")); - assertEquals("XYZ%5B", pathEncode("XYZ[")); - assertEquals("xyz%7B", pathEncode("xyz{")); - assertEquals("foo%2Fbar", pathEncode("foo/bar")); - assertEquals("foo%20bar", pathEncode("foo bar")); - assertEquals("f%C3%AAl%C3%A9", pathEncode("fêlé")); - } - - private String pathEncode(String s) { - StringBuilder sb = new StringBuilder(); - EndpointBase.pathEncode(s, sb); - return sb.toString(); - } - - @Test - public void testErrorDecoding() { - Endpoint endpoint = PingRequest._ENDPOINT; - - { - String json = "{\"error\":\"some error\"}"; - - ErrorResponse response = fromJson(json, endpoint.errorDeserializer(404)); - assertEquals(404, response.status()); - assertEquals("some error", response.error().reason()); - assertEquals("http_status_404", response.error().type()); - } - - { - String json = "{\"status\":401,\"error\":{\"type\":\"the_error_type\",\"reason\":\"some error\"}}"; - - ErrorResponse response = fromJson(json, endpoint.errorDeserializer(404)); - assertEquals(401, response.status()); // value in response body has precedence - assertEquals("some error", response.error().reason()); - assertEquals("the_error_type", response.error().type()); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/endpoints/SimpleEndpointTest.java b/java-client/src/test/java/co/elastic/clients/transport5/endpoints/SimpleEndpointTest.java deleted file mode 100644 index 45a0e3df2..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/endpoints/SimpleEndpointTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.endpoints; - -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch.core.CountResponse; -import co.elastic.clients.testkit.MockHttpClient; -import co.elastic.clients.testkit.ModelTestCase; -import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.ElasticsearchTransportBase; -import co.elastic.clients.transport.TransportOptions; -import co.elastic.clients.transport.http.TransportHttpClient; -import org.jetbrains.annotations.Nullable; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -public class SimpleEndpointTest extends ModelTestCase { - - @Test - public void testNoBodyForEmptyObject() throws Exception { - - List requests = new ArrayList<>(); - - MockHttpClient httpClient = new MockHttpClient() { - @Override - public Response performRequest( - String endpointId, @Nullable Node node, Request request, TransportOptions option - ) throws IOException { - requests.add(request); - return super.performRequest(endpointId, node, request, option); - } - }; - - httpClient.add("/_count", "application/json", toJson( - CountResponse.of(c -> c - .count(1) - .shards(s -> s.successful(1).failed(0).total(1)) - ))); - - ElasticsearchTransport transport = new ElasticsearchTransportBase(httpClient, null, mapper) {}; - ElasticsearchClient client = new ElasticsearchClient(transport, null); - - client.count(); - client.count(c -> c.q("foo:bar")); - client.count(c -> c.query(q -> q.term(t -> t.field("foo").value("bar")))); - - assertNull(requests.get(0).body()); - assertNull(requests.get(1).body()); - assertNotNull(requests.get(2).body()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/http/HeaderMapTest.java b/java-client/src/test/java/co/elastic/clients/transport5/http/HeaderMapTest.java deleted file mode 100644 index 9c583a5df..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/http/HeaderMapTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.http; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.util.Iterator; -import java.util.Map; - -class HeaderMapTest extends Assertions { - - @Test - public void testCaseSensitivity() { - HeaderMap headers = new HeaderMap(); - - headers.put("Foo", "bar"); - assertEquals("bar", headers.get("Foo")); - assertEquals("bar", headers.get("foo")); - assertEquals("bar", headers.get("fOO")); - - headers.put("foo", "baz"); - assertEquals("baz", headers.get("Foo")); - assertEquals("baz", headers.get("foo")); - assertEquals("baz", headers.get("fOO")); - } - - @Test - public void testLock() { - HeaderMap headers = new HeaderMap(); - - headers.put("foo", "bar"); - - HeaderMap locked = headers.locked(); - assertEquals("bar", headers.get("Foo")); - - assertThrows(UnsupportedOperationException.class, () -> { - locked.put("foo", "baz"); - }); - - assertThrows(UnsupportedOperationException.class, () -> { - Iterator> iterator = locked.entrySet().iterator(); - assertEquals("bar", iterator.next().getValue()); - iterator.remove(); - }); - - headers.put("foo", "baz"); - assertEquals("baz", headers.get("Foo")); - assertEquals("bar", locked.get("Foo")); - } - - @Test - public void testAdd() { - HeaderMap headers = new HeaderMap(); - - headers.add("Foo", "bar"); - headers.add("foo", "baz"); - - assertEquals("bar; baz", headers.get("Foo")); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/instrumentation/OpenTelemetryForElasticsearchTest.java b/java-client/src/test/java/co/elastic/clients/transport5/instrumentation/OpenTelemetryForElasticsearchTest.java deleted file mode 100644 index 62236265e..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/instrumentation/OpenTelemetryForElasticsearchTest.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.instrumentation; - -import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; -import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._types.query_dsl.Query; -import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.json.JsonpUtils; -import co.elastic.clients.json.jackson.JacksonJsonpMapper; -import co.elastic.clients.transport.instrumentation.Instrumentation; -import co.elastic.clients.transport.instrumentation.OpenTelemetryForElasticsearch; -import co.elastic.clients.transport.rest5_client.RestClientTransport; -import com.sun.net.httpserver.HttpServer; -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.common.AttributeKey; -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.sdk.OpenTelemetrySdk; -import io.opentelemetry.sdk.common.CompletableResultCode; -import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.opentelemetry.sdk.trace.data.SpanData; -import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; -import io.opentelemetry.sdk.trace.export.SpanExporter; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; -import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; -import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.RestClient; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -public class OpenTelemetryForElasticsearchTest { - private static final String INDEX = "test-index"; - private static final String DOC_ID = "1234567"; - private static final String DOC_RESPONSE = "{\n" + - " \"_index\": \"" + INDEX + "\",\n" + - " \"_id\": \"" + DOC_ID + "\",\n" + - " \"_version\": 1,\n" + - " \"_seq_no\": 0,\n" + - " \"_primary_term\": 1,\n" + - " \"found\": true,\n" + - " \"_source\": {\n" + - " \"@timestamp\": \"2099-11-15T14:12:12\",\n" + - " \"message\": \"GET /search HTTP/1.1 200 1070000\"\n" + - " }\n" + - "}"; - private static final String SEARCH_RESPONSE = "{\n" + - " \"took\": 5,\n" + - " \"timed_out\": false,\n" + - " \"_shards\": {\n" + - " \"total\": 1,\n" + - " \"successful\": 1,\n" + - " \"skipped\": 0,\n" + - " \"failed\": 0\n" + - " },\n" + - " \"hits\": {\n" + - " \"total\": {\n" + - " \"value\": 1,\n" + - " \"relation\": \"eq\"\n" + - " },\n" + - " \"max_score\": 1.3862942,\n" + - " \"hits\": [\n" + - " {\n" + - " \"_index\": \"" + INDEX + "\",\n" + - " \"_id\": \"" + DOC_ID + "\",\n" + - " \"_score\": 1.3862942,\n" + - " \"_source\": {\n" + - " \"@timestamp\": \"2099-11-15T14:12:12\",\n" + - " \"message\": \"GET /search HTTP/1.1 200 1070000\"\n" + - " }\n" + - " }\n" + - " ]\n" + - " }\n" + - "}"; - public static final String DB_OPERATION = "db.operation"; - public static final String URL_FULL = "url.full"; - public static final String SERVER_ADDRESS = "server.address"; - public static final String SERVER_PORT = "server.port"; - // has been renamed in 1.21 from http.method - see https://github.com/open-telemetry/semantic-conventions/blob/main/schemas/1.21.0 - public static final String HTTP_REQUEST_METHOD = "http.request.method"; - private static HttpServer httpServer; - private static MockSpanExporter spanExporter; - private static OpenTelemetry openTelemetry; - private static RestClient restClient; - private static RestClientTransport transport; - private static ElasticsearchClient client; - private static ElasticsearchAsyncClient asyncClient; - - @BeforeAll - public static void setup() throws IOException { - setupOTel(); - setupHttpServer(); - setupClient(); - } - - @AfterAll - public static void cleanUp() throws IOException { - httpServer.stop(0); - transport.close(); - } - - private static void setupClient() { - restClient = - RestClient.builder(new HttpHost(httpServer.getAddress().getAddress(), httpServer.getAddress().getPort())).build(); - - Instrumentation instrumentation = new OpenTelemetryForElasticsearch(openTelemetry, false); - - transport = new RestClientTransport(restClient, new JacksonJsonpMapper(), null, instrumentation); - - client = new ElasticsearchClient(transport); - asyncClient = new ElasticsearchAsyncClient(transport); - } - - private static void setupHttpServer() throws IOException { - httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); - - // handler for GetRequest - httpServer.createContext("/" + INDEX + "/_doc/" + DOC_ID, exchange -> { - exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); - exchange.getResponseHeaders().set("Content-Type", "application/json"); - exchange.sendResponseHeaders(200, 0); - exchange.getResponseBody().write(DOC_RESPONSE.getBytes()); - exchange.close(); - }); - - // handler for SearchRequest - httpServer.createContext("/" + INDEX + "/_search", exchange -> { - exchange.getResponseHeaders().set("X-Elastic-Product", "Elasticsearch"); - exchange.getResponseHeaders().set("Content-Type", "application/json"); - exchange.sendResponseHeaders(200, 0); - exchange.getResponseBody().write(SEARCH_RESPONSE.getBytes()); - exchange.close(); - }); - - httpServer.start(); - } - - private static void setupOTel() { - Resource resource = Resource.getDefault() - .merge(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, "es-api-test"))); - - spanExporter = new MockSpanExporter(); - - SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() - .addSpanProcessor(SimpleSpanProcessor.create(spanExporter)) - .setResource(resource) - .build(); - - openTelemetry = OpenTelemetrySdk.builder() - .setTracerProvider(sdkTracerProvider) - .build(); - } - - @BeforeEach - public void reset() { - spanExporter.reset(); - } - - @Test - public void testGetRequest() throws IOException, InterruptedException { - client.get(r -> r.index(INDEX).id(DOC_ID).refresh(true), Object.class); - Assertions.assertEquals(spanExporter.getSpans().size(), 1); - SpanData span = spanExporter.getSpans().get(0); - Assertions.assertEquals("get", span.getName()); - Assertions.assertEquals("get", span.getAttributes().get(AttributeKey.stringKey(DB_OPERATION))); - Assertions.assertEquals("GET", span.getAttributes().get(AttributeKey.stringKey(HTTP_REQUEST_METHOD))); - Assertions.assertEquals("elasticsearch", span.getAttributes().get(SemanticAttributes.DB_SYSTEM)); - - String url = "http://" + httpServer.getAddress().getHostName() + ":" + httpServer.getAddress().getPort() + - "/" + INDEX + "/_doc/" + DOC_ID + "?refresh=true"; - Assertions.assertEquals(url, span.getAttributes().get(AttributeKey.stringKey(URL_FULL))); - Assertions.assertEquals(httpServer.getAddress().getHostName(), span.getAttributes().get(AttributeKey.stringKey(SERVER_ADDRESS))); - Assertions.assertEquals(httpServer.getAddress().getPort(), span.getAttributes().get(AttributeKey.longKey(SERVER_PORT))); - - // Path parts - Assertions.assertEquals(DOC_ID, span.getAttributes().get(AttributeKey.stringKey("db.elasticsearch.path_parts.id"))); - } - - @Test - public void testSearchRequest() throws IOException, InterruptedException { - // A client that will capture requests - ElasticsearchClient client = new ElasticsearchClient(new RestClientTransport( - restClient, this.client._jsonpMapper(), null, new OpenTelemetryForElasticsearch(openTelemetry, true)) - ); - SearchRequest req = SearchRequest.of(r -> r.index(INDEX).query(q -> q.term(t -> t.field("x").value("y")))); - String queryAsString = JsonpUtils.toJsonString(req, client._jsonpMapper()); - client.search(req, Object.class); - Assertions.assertEquals(spanExporter.getSpans().size(), 1); - SpanData span = spanExporter.getSpans().get(0); - Assertions.assertEquals("search", span.getName()); - Assertions.assertEquals(queryAsString, span.getAttributes().get(SemanticAttributes.DB_STATEMENT)); - } - - @Test - public void testAsyncSearchRequest() throws IOException, InterruptedException, TimeoutException, ExecutionException { - Query query = Query.of(q -> q.term(t -> t.field("x").value("y"))); - Future future = asyncClient.search(r -> r.index(INDEX).query(query), Object.class); - future.get(2, TimeUnit.SECONDS); - spanExporter.awaitNumSpans(1, 2000); - Assertions.assertEquals(spanExporter.getSpans().size(), 1); - SpanData span = spanExporter.getSpans().get(0); - Assertions.assertEquals("search", span.getName()); - - // We're not capturing bodies by default - Assertions.assertNull(span.getAttributes().get(SemanticAttributes.DB_STATEMENT)); - } - - private static class MockSpanExporter implements SpanExporter { - - private final List spans = new ArrayList(); - - @Override - public CompletableResultCode export(Collection spans) { - this.spans.addAll(spans); - synchronized (this) { - notifyAll(); - } - return CompletableResultCode.ofSuccess(); - } - - @Override - public CompletableResultCode flush() { - return CompletableResultCode.ofSuccess(); - } - - @Override - public CompletableResultCode shutdown() { - spans.clear(); - return CompletableResultCode.ofSuccess(); - } - - public List getSpans() { - return spans; - } - - public void reset() { - spans.clear(); - } - - public synchronized void awaitNumSpans(int num, long timeoutMillis) throws InterruptedException { - while(spans.size() < num){ - wait(timeoutMillis); - } - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/BasicAsyncResponseConsumerTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/BasicAsyncResponseConsumerTests.java deleted file mode 100644 index f12ec7855..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/BasicAsyncResponseConsumerTests.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import org.apache.hc.core5.http.ClassicHttpResponse; -import org.apache.hc.core5.http.ContentTooLongException; -import org.apache.hc.core5.http.ContentType; -import org.apache.hc.core5.http.io.entity.ByteArrayEntity; -import org.apache.hc.core5.http.message.BasicClassicHttpResponse; -import org.apache.hc.core5.http.nio.AsyncResponseConsumer; -import org.apache.hc.core5.http.nio.ContentDecoder; -import org.apache.hc.core5.http.protocol.HttpContext; -import org.elasticsearch.client.RestClientTestCase; -import org.elasticsearch.client.consumer.HttpAsyncResponseConsumerFactory; -import org.junit.Assert; - -import java.nio.ByteBuffer; - -import static org.mockito.Mockito.mock; - -public class BasicAsyncResponseConsumerTests extends RestClientTestCase { - - // maximum buffer that this test ends up allocating is 50MB - private static final int MAX_TEST_BUFFER_SIZE = 50 * 1024 * 1024; - - public void testResponseProcessing() throws Exception { - ContentDecoder contentDecoder = mock(ContentDecoder.class); - HttpContext httpContext = mock(HttpContext.class); - - AsyncResponseConsumer consumer = - new HttpAsyncResponseConsumerFactory.BasicAsyncResponseConsumerFactory(MAX_TEST_BUFFER_SIZE) - .createHttpAsyncResponseConsumer(); - - BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(200, "OK"); - ByteArrayEntity entity = new ByteArrayEntity("test".getBytes(), ContentType.APPLICATION_JSON); - httpResponse.setEntity(entity); - - // everything goes well, no exception thrown - consumer.consumeResponse(httpResponse, entity, httpContext, null); - consumer.consume(ByteBuffer.wrap("test".getBytes())); - } - - public void testBufferLimit() throws Exception { - HttpContext httpContext = mock(HttpContext.class); - - AsyncResponseConsumer consumer = - new HttpAsyncResponseConsumerFactory.BasicAsyncResponseConsumerFactory(MAX_TEST_BUFFER_SIZE) - .createHttpAsyncResponseConsumer(); - - ByteArrayEntity entity = new ByteArrayEntity("test".getBytes(), ContentType.APPLICATION_JSON); - BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(200, "OK"); - httpResponse.setEntity(entity); - - // should throw exception - consumer.consumeResponse(httpResponse, entity, httpContext, null); - Assert.assertThrows(ContentTooLongException.class, - () -> consumer.consume(ByteBuffer.allocate(MAX_TEST_BUFFER_SIZE + 1))); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/ClientsGraalVMThreadsFilter.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/ClientsGraalVMThreadsFilter.java deleted file mode 100644 index 03a7e68bf..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/ClientsGraalVMThreadsFilter.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import com.carrotsearch.randomizedtesting.ThreadFilter; - -/** - * The GraalVM spawns extra threads, which causes our thread leak - * detection to fail. Filter these threads out since we can't clean them up. - */ -public class ClientsGraalVMThreadsFilter implements ThreadFilter { - @Override - public boolean reject(Thread t) { - return t.getName().startsWith("Libgraal"); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/DeadHostStateTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/DeadHostStateTests.java deleted file mode 100644 index bd9071f47..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/DeadHostStateTests.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import org.elasticsearch.client.DeadHostState; -import org.elasticsearch.client.RestClientTestCase; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.greaterThanOrEqualTo; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.lessThan; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -public class DeadHostStateTests extends RestClientTestCase { - - private static long[] EXPECTED_TIMEOUTS_SECONDS = new long[]{60, 84, 120, 169, 240, 339, 480, 678, 960, - 1357, 1800}; - - public void testInitialDeadHostStateDefaultTimeSupplier() { - DeadHostState deadHostState = new DeadHostState(DeadHostState.DEFAULT_TIME_SUPPLIER); - long currentTime = System.nanoTime(); - assertThat(deadHostState.getDeadUntilNanos(), greaterThanOrEqualTo(currentTime)); - assertThat(deadHostState.getFailedAttempts(), equalTo(1)); - } - - public void testDeadHostStateFromPreviousDefaultTimeSupplier() { - DeadHostState previous = new DeadHostState(DeadHostState.DEFAULT_TIME_SUPPLIER); - int iters = randomIntBetween(5, 30); - for (int i = 0; i < iters; i++) { - DeadHostState deadHostState = new DeadHostState(previous); - assertThat(deadHostState.getDeadUntilNanos(), greaterThan(previous.getDeadUntilNanos())); - assertThat(deadHostState.getFailedAttempts(), equalTo(previous.getFailedAttempts() + 1)); - previous = deadHostState; - } - } - - public void testCompareToTimeSupplier() { - int numObjects = randomIntBetween(EXPECTED_TIMEOUTS_SECONDS.length, 30); - DeadHostState[] deadHostStates = new DeadHostState[numObjects]; - final AtomicLong time = new AtomicLong(0); - for (int i = 0; i < numObjects; i++) { - if (i == 0) { - // this test requires a strictly increasing timer. This ensures that even if we call this - // time supplier in a very tight - // loop we always notice time moving forward. This does not happen for real timer - // implementations - // (e.g. on Linux clock_gettime provides microsecond resolution). - deadHostStates[i] = new DeadHostState(time::incrementAndGet); - } else { - deadHostStates[i] = new DeadHostState(deadHostStates[i - 1]); - } - } - for (int k = 1; k < deadHostStates.length; k++) { - assertThat(deadHostStates[k - 1].getDeadUntilNanos(), - lessThan(deadHostStates[k].getDeadUntilNanos())); - assertThat(deadHostStates[k - 1], lessThan(deadHostStates[k])); - } - } - - public void testCompareToDifferingTimeSupplier() { - try { - new DeadHostState(DeadHostState.DEFAULT_TIME_SUPPLIER).compareTo(new DeadHostState(() -> 0L)); - fail("expected failure"); - } catch (IllegalArgumentException e) { - assertEquals( - "can't compare DeadHostStates holding different time suppliers as they may be based on " + - "different clocks", - e.getMessage() - ); - } - } - - public void testShallBeRetried() { - final AtomicLong time = new AtomicLong(0); - DeadHostState deadHostState = null; - for (int i = 0; i < EXPECTED_TIMEOUTS_SECONDS.length; i++) { - long expectedTimeoutSecond = EXPECTED_TIMEOUTS_SECONDS[i]; - if (i == 0) { - deadHostState = new DeadHostState(time::get); - } else { - deadHostState = new DeadHostState(deadHostState); - } - for (int j = 0; j < expectedTimeoutSecond; j++) { - time.addAndGet(TimeUnit.SECONDS.toNanos(1)); - assertThat(deadHostState.shallBeRetried(), is(false)); - } - int iters = randomIntBetween(5, 30); - for (int j = 0; j < iters; j++) { - time.addAndGet(TimeUnit.SECONDS.toNanos(1)); - assertThat(deadHostState.shallBeRetried(), is(true)); - } - } - } - - public void testDeadHostStateTimeouts() { - DeadHostState previous = new DeadHostState(() -> 0L); - for (long expectedTimeoutsSecond : EXPECTED_TIMEOUTS_SECONDS) { - assertThat(TimeUnit.NANOSECONDS.toSeconds(previous.getDeadUntilNanos()), - equalTo(expectedTimeoutsSecond)); - previous = new DeadHostState(previous); - } - // check that from here on the timeout does not increase - int iters = randomIntBetween(5, 30); - for (int i = 0; i < iters; i++) { - DeadHostState deadHostState = new DeadHostState(previous); - assertThat( - TimeUnit.NANOSECONDS.toSeconds(deadHostState.getDeadUntilNanos()), - equalTo(EXPECTED_TIMEOUTS_SECONDS[EXPECTED_TIMEOUTS_SECONDS.length - 1]) - ); - previous = deadHostState; - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/FailureTrackingResponseListenerTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/FailureTrackingResponseListenerTests.java deleted file mode 100644 index 83bf9a48f..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/FailureTrackingResponseListenerTests.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.ProtocolVersion; -import org.apache.hc.core5.http.message.BasicClassicHttpResponse; -import org.apache.hc.core5.http.message.RequestLine; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.ResponseListener; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientTestCase; - -import java.util.concurrent.atomic.AtomicReference; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; - -public class FailureTrackingResponseListenerTests extends RestClientTestCase { - - public void testOnSuccess() { - MockResponseListener responseListener = new MockResponseListener(); - RestClient.FailureTrackingResponseListener listener = - new RestClient.FailureTrackingResponseListener(responseListener); - - final Response response = mockResponse(); - listener.onSuccess(response); - assertSame(response, responseListener.lastResponse.get()); - assertNull(responseListener.lastException.get()); - } - - public void testOnFailure() { - MockResponseListener responseListener = new MockResponseListener(); - RestClient.FailureTrackingResponseListener listener = - new RestClient.FailureTrackingResponseListener(responseListener); - int numIters = randomIntBetween(1, 10); - Exception[] expectedExceptions = new Exception[numIters]; - for (int i = 0; i < numIters; i++) { - RuntimeException runtimeException = new RuntimeException("test" + i); - expectedExceptions[i] = runtimeException; - listener.trackFailure(runtimeException); - assertNull(responseListener.lastResponse.get()); - assertNull(responseListener.lastException.get()); - } - - if (randomBoolean()) { - Response response = mockResponse(); - listener.onSuccess(response); - assertSame(response, responseListener.lastResponse.get()); - assertNull(responseListener.lastException.get()); - } else { - RuntimeException runtimeException = new RuntimeException("definitive"); - listener.onDefinitiveFailure(runtimeException); - assertNull(responseListener.lastResponse.get()); - Throwable exception = responseListener.lastException.get(); - assertSame(runtimeException, exception); - - int i = numIters - 1; - do { - assertNotNull(exception.getSuppressed()); - assertEquals(1, exception.getSuppressed().length); - assertSame(expectedExceptions[i--], exception.getSuppressed()[0]); - exception = exception.getSuppressed()[0]; - } while (i >= 0); - } - } - - private static class MockResponseListener implements ResponseListener { - private final AtomicReference lastResponse = new AtomicReference<>(); - private final AtomicReference lastException = new AtomicReference<>(); - - @Override - public void onSuccess(Response response) { - if (!this.lastResponse.compareAndSet(null, response)) { - throw new IllegalStateException("onSuccess was called multiple times"); - } - } - - @Override - public void onFailure(Exception exception) { - if (!this.lastException.compareAndSet(null, exception)) { - throw new IllegalStateException("onFailure was called multiple times"); - } - } - } - - private static Response mockResponse() { - ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1); - RequestLine requestLine = new RequestLine("GET", "/", protocolVersion); - BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(200, "OK"); - return new Response(requestLine, new HttpHost("localhost", 9200), httpResponse); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/HasAttributeNodeSelectorTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/HasAttributeNodeSelectorTests.java deleted file mode 100644 index 24ecc8fe5..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/HasAttributeNodeSelectorTests.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - - -import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.RestClientTestCase; -import org.elasticsearch.client.node.Node; -import org.elasticsearch.client.node.selector.HasAttributeNodeSelector; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static org.junit.Assert.assertEquals; - -public class HasAttributeNodeSelectorTests extends RestClientTestCase { - public void testHasAttribute() { - Node hasAttributeValue = dummyNode(singletonMap("attr", singletonList("val"))); - Node hasAttributeButNotValue = dummyNode(singletonMap("attr", singletonList("notval"))); - Node hasAttributeValueInList = dummyNode(singletonMap("attr", Arrays.asList("val", "notval"))); - Node notHasAttribute = dummyNode(singletonMap("notattr", singletonList("val"))); - List nodes = new ArrayList<>(); - nodes.add(hasAttributeValue); - nodes.add(hasAttributeButNotValue); - nodes.add(hasAttributeValueInList); - nodes.add(notHasAttribute); - List expected = new ArrayList<>(); - expected.add(hasAttributeValue); - expected.add(hasAttributeValueInList); - new HasAttributeNodeSelector("attr", "val").select(nodes); - assertEquals(expected, nodes); - } - - private static Node dummyNode(Map> attributes) { - final Set roles = new TreeSet<>(); - if (randomBoolean()) { - roles.add("master"); - } - if (randomBoolean()) { - roles.add("data"); - } - if (randomBoolean()) { - roles.add("ingest"); - } - return new Node( - new HttpHost("dummy"), - Collections.emptySet(), - randomAsciiAlphanumOfLength(5), - randomAsciiAlphanumOfLength(5), - new Node.Roles(roles), - attributes - ); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/HostsTrackingFailureListener.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/HostsTrackingFailureListener.java deleted file mode 100644 index 04b858b74..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/HostsTrackingFailureListener.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.node.Node; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; - -/** - * {@link RestClient.FailureListener} impl that allows to track when it gets called for which host. - */ -class HostsTrackingFailureListener extends RestClient.FailureListener { - private volatile Set httpHosts = new HashSet<>(); - - @Override - public void onFailure(Node node) { - httpHosts.add(node.getHost()); - } - - void assertCalled(List nodes) { - HttpHost[] hosts = new HttpHost[nodes.size()]; - for (int i = 0; i < nodes.size(); i++) { - hosts[i] = nodes.get(i).getHost(); - } - assertCalled(hosts); - } - - void assertCalled(HttpHost... hosts) { - assertEquals(hosts.length, this.httpHosts.size()); - assertThat(this.httpHosts, containsInAnyOrder(hosts)); - this.httpHosts.clear(); - } - - void assertNotCalled() { - assertEquals(0, httpHosts.size()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/NodeSelectorTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/NodeSelectorTests.java deleted file mode 100644 index c525cc262..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/NodeSelectorTests.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - - -import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.RestClientTestCase; -import org.elasticsearch.client.node.Node; -import org.elasticsearch.client.node.Node.Roles; -import org.elasticsearch.client.node.selector.NodeSelector; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; - -import static org.junit.Assert.assertEquals; - -public class NodeSelectorTests extends RestClientTestCase { - public void testAny() { - List nodes = new ArrayList<>(); - int size = between(2, 5); - for (int i = 0; i < size; i++) { - nodes.add(dummyNode(randomBoolean(), randomBoolean(), randomBoolean())); - } - List expected = new ArrayList<>(nodes); - NodeSelector.ANY.select(nodes); - assertEquals(expected, nodes); - } - - public void testNotMasterOnly() { - Node masterOnly = dummyNode(true, false, false); - Node all = dummyNode(true, true, true); - Node masterAndData = dummyNode(true, true, false); - Node masterAndIngest = dummyNode(true, false, true); - Node coordinatingOnly = dummyNode(false, false, false); - Node ingestOnly = dummyNode(false, false, true); - Node data = dummyNode(false, true, randomBoolean()); - Node dataContent = dummyNode(false, false, false, true, false, false, false, false); - Node dataHot = dummyNode(false, false, false, false, true, false, false, false); - Node dataWarm = dummyNode(false, false, false, false, false, true, false, false); - Node dataCold = dummyNode(false, false, false, false, false, false, true, false); - Node dataFrozen = dummyNode(false, false, false, false, false, false, false, true); - List nodes = new ArrayList<>(); - nodes.add(masterOnly); - nodes.add(all); - nodes.add(masterAndData); - nodes.add(masterAndIngest); - nodes.add(coordinatingOnly); - nodes.add(ingestOnly); - nodes.add(data); - nodes.add(dataContent); - nodes.add(dataHot); - nodes.add(dataWarm); - nodes.add(dataCold); - nodes.add(dataFrozen); - Collections.shuffle(nodes, getRandom()); - List expected = new ArrayList<>(nodes); - expected.remove(masterOnly); - NodeSelector.SKIP_DEDICATED_MASTERS.select(nodes); - assertEquals(expected, nodes); - } - - private static Node dummyNode(boolean master, boolean data, boolean ingest) { - return dummyNode(master, data, ingest, false, false, false, false, false); - } - - private static Node dummyNode( - boolean master, - boolean data, - boolean ingest, - boolean dataContent, - boolean dataHot, - boolean dataWarm, - boolean dataCold, - boolean dataFrozen - ) { - final Set roles = new TreeSet<>(); - if (master) { - roles.add("master"); - } - if (data) { - roles.add("data"); - } - if (dataContent) { - roles.add("data_content"); - } - if (dataHot) { - roles.add("data_hot"); - } - if (dataWarm) { - roles.add("data_warm"); - } - if (dataCold) { - roles.add("data_cold"); - } - if (dataFrozen) { - roles.add("data_frozen"); - } - if (ingest) { - roles.add("ingest"); - } - return new Node( - new HttpHost("dummy"), - Collections.emptySet(), - randomAsciiAlphanumOfLength(5), - randomAsciiAlphanumOfLength(5), - new Roles(roles), - Collections.>emptyMap() - ); - } - -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/NodeTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/NodeTests.java deleted file mode 100644 index 08f1a791e..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/NodeTests.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.RestClientTestCase; -import org.elasticsearch.client.node.Node; -import org.elasticsearch.client.node.Node.Roles; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.TreeSet; - -import static java.util.Collections.singleton; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public class NodeTests extends RestClientTestCase { - public void testToString() { - Map> attributes = new HashMap<>(); - attributes.put("foo", singletonList("bar")); - attributes.put("baz", Arrays.asList("bort", "zoom")); - assertEquals("[host=http://1]", new Node(new HttpHost("1")).toString()); - assertEquals( - "[host=http://1, attributes={foo=[bar], baz=[bort, zoom]}]", - new Node(new HttpHost("1"), null, null, null, null, attributes).toString() - ); - assertEquals( - "[host=http://1, roles=data,ingest,master]", - new Node(new HttpHost("1"), null, null, null, new Node.Roles(new TreeSet<>(Arrays.asList("master", "data", "ingest"))), null) - .toString() - ); - assertEquals("[host=http://1, version=ver]", new Node(new HttpHost("1"), null, null, "ver", null, null).toString()); - assertEquals("[host=http://1, name=nam]", new Node(new HttpHost("1"), null, "nam", null, null, null).toString()); - assertEquals( - "[host=http://1, bound=[http://1, http://2]]", - new Node(new HttpHost("1"), new HashSet<>(Arrays.asList(new HttpHost("1"), new HttpHost("2"))), null, null, null, null) - .toString() - ); - assertEquals( - "[host=http://1, bound=[http://1, http://2], " - + "name=nam, version=ver, roles=master, attributes={foo=[bar], baz=[bort, zoom]}]", - new Node( - new HttpHost("1"), - new HashSet<>(Arrays.asList(new HttpHost("1"), new HttpHost("2"))), - "nam", - "ver", - new Roles(Collections.singleton("master")), - attributes - ).toString() - ); - } - - public void testEqualsAndHashCode() { - HttpHost host = new HttpHost(randomAsciiAlphanumOfLength(5)); - Node node = new Node( - host, - randomBoolean() ? null : singleton(host), - randomBoolean() ? null : randomAsciiAlphanumOfLength(5), - randomBoolean() ? null : randomAsciiAlphanumOfLength(5), - randomBoolean() ? null : new Roles(new TreeSet<>(Arrays.asList("master", "data", "ingest"))), - randomBoolean() ? null : singletonMap("foo", singletonList("bar")) - ); - assertFalse(node.equals(null)); - assertTrue(node.equals(node)); - assertEquals(node.hashCode(), node.hashCode()); - Node copy = new Node(host, node.getBoundHosts(), node.getName(), node.getVersion(), node.getRoles(), node.getAttributes()); - assertTrue(node.equals(copy)); - assertEquals(node.hashCode(), copy.hashCode()); - assertFalse( - node.equals( - new Node( - new HttpHost(host.toHostString() + "changed"), - node.getBoundHosts(), - node.getName(), - node.getVersion(), - node.getRoles(), - node.getAttributes() - ) - ) - ); - assertFalse( - node.equals( - new Node( - host, - new HashSet<>(Arrays.asList(host, new HttpHost(host.toHostString() + "changed"))), - node.getName(), - node.getVersion(), - node.getRoles(), - node.getAttributes() - ) - ) - ); - assertFalse( - node.equals( - new Node(host, node.getBoundHosts(), node.getName() + "changed", node.getVersion(), node.getRoles(), node.getAttributes()) - ) - ); - assertFalse( - node.equals( - new Node(host, node.getBoundHosts(), node.getName(), node.getVersion() + "changed", node.getRoles(), node.getAttributes()) - ) - ); - assertFalse( - node.equals( - new Node( - host, - node.getBoundHosts(), - node.getName(), - node.getVersion(), - new Roles(Collections.emptySet()), - node.getAttributes() - ) - ) - ); - assertFalse( - node.equals( - new Node( - host, - node.getBoundHosts(), - node.getName(), - node.getVersion(), - node.getRoles(), - singletonMap("bort", singletonList("bing")) - ) - ) - ); - } - - public void testDataRole() { - Roles roles = new Roles(new TreeSet<>(Arrays.asList("data_hot"))); - assertTrue(roles.hasDataHotRole()); - assertTrue(roles.canContainData()); - roles = new Roles(new TreeSet<>(Arrays.asList("data_warm"))); - assertTrue(roles.hasDataWarmRole()); - assertTrue(roles.canContainData()); - roles = new Roles(new TreeSet<>(Arrays.asList("data_cold"))); - assertTrue(roles.hasDataColdRole()); - assertTrue(roles.canContainData()); - roles = new Roles(new TreeSet<>(Arrays.asList("data_frozen"))); - assertTrue(roles.hasDataFrozenRole()); - assertTrue(roles.canContainData()); - roles = new Roles(new TreeSet<>(Arrays.asList("data_content"))); - assertTrue(roles.hasDataContentRole()); - assertTrue(roles.canContainData()); - roles = new Roles(new TreeSet<>(Arrays.asList("data"))); - assertTrue(roles.hasDataRole()); - assertTrue(roles.canContainData()); - roles = new Roles(new TreeSet<>(Arrays.asList("data_foo"))); - assertTrue(roles.canContainData()); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/PreferHasAttributeNodeSelectorTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/PreferHasAttributeNodeSelectorTests.java deleted file mode 100644 index 1cb8f1acb..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/PreferHasAttributeNodeSelectorTests.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - - -import org.apache.hc.core5.http.HttpHost; -import org.elasticsearch.client.RestClientTestCase; -import org.elasticsearch.client.node.Node; -import org.elasticsearch.client.node.Node.Roles; -import org.elasticsearch.client.node.selector.PreferHasAttributeNodeSelector; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static org.junit.Assert.assertEquals; - -public class PreferHasAttributeNodeSelectorTests extends RestClientTestCase { - public void testFoundPreferHasAttribute() { - Node hasAttributeValue = dummyNode(singletonMap("attr", singletonList("val"))); - Node hasAttributeButNotValue = dummyNode(singletonMap("attr", singletonList("notval"))); - Node hasAttributeValueInList = dummyNode(singletonMap("attr", Arrays.asList("val", "notval"))); - Node notHasAttribute = dummyNode(singletonMap("notattr", singletonList("val"))); - List nodes = new ArrayList<>(); - nodes.add(hasAttributeValue); - nodes.add(hasAttributeButNotValue); - nodes.add(hasAttributeValueInList); - nodes.add(notHasAttribute); - List expected = new ArrayList<>(); - expected.add(hasAttributeValue); - expected.add(hasAttributeValueInList); - new PreferHasAttributeNodeSelector("attr", "val").select(nodes); - assertEquals(expected, nodes); - } - - public void testNotFoundPreferHasAttribute() { - Node notHasAttribute = dummyNode(singletonMap("notattr", singletonList("val"))); - List nodes = new ArrayList<>(); - nodes.add(notHasAttribute); - List expected = new ArrayList<>(); - expected.add(notHasAttribute); - new PreferHasAttributeNodeSelector("attr", "val").select(nodes); - assertEquals(expected, nodes); - } - - private static Node dummyNode(Map> attributes) { - final Set roles = new TreeSet<>(); - if (randomBoolean()) { - roles.add("master"); - } - if (randomBoolean()) { - roles.add("data"); - } - if (randomBoolean()) { - roles.add("ingest"); - } - return new Node( - new HttpHost("dummy"), - Collections.emptySet(), - randomAsciiAlphanumOfLength(5), - randomAsciiAlphanumOfLength(5), - new Roles(roles), - attributes - ); - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestLoggerTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestLoggerTests.java deleted file mode 100644 index 2df2a9a0f..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestLoggerTests.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - - -import org.apache.hc.client5.http.classic.methods.HttpHead; -import org.apache.hc.client5.http.classic.methods.HttpOptions; -import org.apache.hc.client5.http.classic.methods.HttpPatch; -import org.apache.hc.client5.http.classic.methods.HttpPost; -import org.apache.hc.client5.http.classic.methods.HttpPut; -import org.apache.hc.client5.http.classic.methods.HttpTrace; -import org.apache.hc.client5.http.classic.methods.HttpUriRequest; -import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; -import org.apache.hc.core5.http.ContentType; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.HttpEntity; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.ParseException; -import org.apache.hc.core5.http.io.entity.ByteArrayEntity; -import org.apache.hc.core5.http.io.entity.EntityUtils; -import org.apache.hc.core5.http.io.entity.InputStreamEntity; -import org.apache.hc.core5.http.io.entity.StringEntity; -import org.apache.hc.core5.http.message.BasicClassicHttpResponse; -import org.apache.hc.core5.http.message.BasicHeader; -import org.elasticsearch.client.HttpDeleteWithEntity; -import org.elasticsearch.client.HttpGetWithEntity; -import org.elasticsearch.client.RequestLogger; -import org.elasticsearch.client.RestClientTestCase; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; - -import static org.elasticsearch.client.RestClientTestUtil.canHaveBody; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; - -public class RequestLoggerTests extends RestClientTestCase { - public void testTraceRequest() throws IOException, URISyntaxException, ParseException { - HttpHost host = new HttpHost(randomBoolean() ? "http" : "https", "localhost", 9200); - String expectedEndpoint = "/index/type/_api"; - URI uri; - if (randomBoolean()) { - uri = new URI(expectedEndpoint); - } else { - uri = new URI("index/type/_api"); - } - HttpUriRequest request = randomHttpRequest(uri); - String expected = "curl -iX " + request.getMethod() + " '" + host + expectedEndpoint + "'"; - boolean hasBody = canHaveBody((HttpUriRequestBase) request) && randomBoolean(); - String requestBody = "{ \"field\": \"value\" }"; - if (hasBody) { - expected += " -d '" + requestBody + "'"; - HttpEntity entity; - switch (randomIntBetween(0, 4)) { - case 0: - case 2: - entity = new StringEntity(requestBody, ContentType.APPLICATION_JSON); - break; - case 1: - entity = new InputStreamEntity( - new ByteArrayInputStream(requestBody.getBytes(StandardCharsets.UTF_8)), - ContentType.APPLICATION_JSON - ); - break; - case 3: - entity = new ByteArrayEntity(requestBody.getBytes(StandardCharsets.UTF_8), - ContentType.APPLICATION_JSON); - break; - case 4: - // Evil entity without a charset - entity = new StringEntity(requestBody, ContentType.create("application/json", - (Charset) null)); - break; - default: - throw new UnsupportedOperationException(); - } - request.setEntity(entity); - } - String traceRequest = RequestLogger.buildTraceRequest(request, host); - assertThat(traceRequest, equalTo(expected)); - if (hasBody) { - // check that the body is still readable as most entities are not repeatable - String body = EntityUtils.toString(request.getEntity(), - StandardCharsets.UTF_8); - assertThat(body, equalTo(requestBody)); - } - } - - public void testTraceResponse() throws IOException, ParseException { - int statusCode = randomIntBetween(200, 599); - String reasonPhrase = "REASON"; - BasicClassicHttpResponse httpResponse = new BasicClassicHttpResponse(statusCode, reasonPhrase); - String expected = "# " + statusCode; - int numHeaders = randomIntBetween(0, 3); - for (int i = 0; i < numHeaders; i++) { - httpResponse.setHeader("header" + i, "value"); - expected += "\n# header" + i + ": value"; - } - expected += "\n#"; - boolean hasBody = getRandom().nextBoolean(); - String responseBody = "{\n \"field\": \"value\"\n}"; - if (hasBody) { - expected += "\n# {"; - expected += "\n# \"field\": \"value\""; - expected += "\n# }"; - HttpEntity entity; - switch (randomIntBetween(0, 2)) { - case 0: - entity = new StringEntity(responseBody, ContentType.APPLICATION_JSON); - break; - case 1: - // test a non repeatable entity - entity = new InputStreamEntity( - new ByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8)), - ContentType.APPLICATION_JSON - ); - break; - case 2: - // Evil entity without a charset - entity = new StringEntity(responseBody, ContentType.create("application/json", - (Charset) null)); - break; - default: - throw new UnsupportedOperationException(); - } - httpResponse.setEntity(entity); - } - String traceResponse = RequestLogger.buildTraceResponse(httpResponse); - assertThat(traceResponse, equalTo(expected)); - if (hasBody) { - // check that the body is still readable as most entities are not repeatable - String body = EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8); - assertThat(body, equalTo(responseBody)); - } - } - - public void testResponseWarnings() throws Exception { - HttpHost host = new HttpHost("localhost", 9200); - HttpUriRequest request = randomHttpRequest(new URI("/index/type/_api")); - int numWarnings = randomIntBetween(1, 5); - StringBuilder expected = new StringBuilder("request [").append(request.getMethod()) - .append(" ") - .append(host) - .append("/index/type/_api] returned ") - .append(numWarnings) - .append(" warnings: "); - Header[] warnings = new Header[numWarnings]; - for (int i = 0; i < numWarnings; i++) { - String warning = "this is warning number " + i; - warnings[i] = new BasicHeader("Warning", warning); - if (i > 0) { - expected.append(","); - } - expected.append("[").append(warning).append("]"); - } - assertEquals(expected.toString(), RequestLogger.buildWarningMessage(request, host, warnings)); - } - - private static HttpUriRequest randomHttpRequest(URI uri) { - int requestType = randomIntBetween(0, 7); - switch (requestType) { - case 0: - return new HttpGetWithEntity(uri); - case 1: - return new HttpPost(uri); - case 2: - return new HttpPut(uri); - case 3: - return new HttpDeleteWithEntity(uri); - case 4: - return new HttpHead(uri); - case 5: - return new HttpTrace(uri); - case 6: - return new HttpOptions(uri); - case 7: - return new HttpPatch(uri); - default: - throw new UnsupportedOperationException(); - } - } -} diff --git a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestOptionsTests.java b/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestOptionsTests.java deleted file mode 100644 index f8b7b540b..000000000 --- a/java-client/src/test/java/co/elastic/clients/transport5/low_level_client/RequestOptionsTests.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * 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. - */ - -package co.elastic.clients.transport5.low_level_client; - -import org.apache.hc.client5.http.config.RequestConfig; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.util.Timeout; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.WarningsHandler; -import org.elasticsearch.client.consumer.HttpAsyncResponseConsumerFactory; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; - -public class RequestOptionsTests extends RestClientTestCase { - public void testDefault() { - assertEquals(Collections.