response) {
+ String contentType = response.headers().firstValue("Content-Type").orElse(null);
+ if (contentType == null) {
+ return StandardCharsets.UTF_8;
+ }
+
+ return parseCharset(contentType, StandardCharsets.UTF_8);
+ }
+
+ // TODO: super simple
+ private static Charset parseCharset(String contentTypeHeader, Charset defaultCharset) {
+ Pattern pattern = Pattern.compile("charset=([\\w-]+)", Pattern.CASE_INSENSITIVE);
+ Matcher matcher = pattern.matcher(contentTypeHeader);
+
+ if (matcher.find()) {
+ return Charset.forName(matcher.group(1));
+ }
+
+ return defaultCharset;
+ }
+
+ private ResponseBodyHandler() {
+ }
+}
diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/ApiKey.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/ApiKey.java
new file mode 100644
index 0000000000..295d6b8562
--- /dev/null
+++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/ApiKey.java
@@ -0,0 +1,37 @@
+package com.walmartlabs.concord.client2.impl.auth;
+
+/*-
+ * *****
+ * Concord
+ * -----
+ * Copyright (C) 2017 - 2023 Walmart Inc.
+ * -----
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =====
+ */
+
+import java.net.http.HttpRequest;
+
+public class ApiKey implements Authentication {
+
+ private final String key;
+
+ public ApiKey(String key) {
+ this.key = key;
+ }
+
+ @Override
+ public HttpRequest.Builder applyTo(HttpRequest.Builder requesBuilder) {
+ return requesBuilder.setHeader("Authorization", key);
+ }
+}
diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/Authentication.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/Authentication.java
new file mode 100644
index 0000000000..4b6245c74d
--- /dev/null
+++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/Authentication.java
@@ -0,0 +1,28 @@
+package com.walmartlabs.concord.client2.impl.auth;
+
+/*-
+ * *****
+ * Concord
+ * -----
+ * Copyright (C) 2017 - 2023 Walmart Inc.
+ * -----
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =====
+ */
+
+import java.net.http.HttpRequest;
+
+public interface Authentication {
+
+ HttpRequest.Builder applyTo(HttpRequest.Builder requesBuilder);
+}
diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/SessionToken.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/SessionToken.java
new file mode 100644
index 0000000000..d7d31331f0
--- /dev/null
+++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/SessionToken.java
@@ -0,0 +1,37 @@
+package com.walmartlabs.concord.client2.impl.auth;
+
+/*-
+ * *****
+ * Concord
+ * -----
+ * Copyright (C) 2017 - 2023 Walmart Inc.
+ * -----
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =====
+ */
+
+import java.net.http.HttpRequest;
+
+public class SessionToken implements Authentication {
+
+ private final String token;
+
+ public SessionToken(String token) {
+ this.token = token;
+ }
+
+ @Override
+ public HttpRequest.Builder applyTo(HttpRequest.Builder requesBuilder) {
+ return requesBuilder.setHeader("X-Concord-SessionToken", token);
+ }
+}
diff --git a/client2/src/main/template/README.md b/client2/src/main/template/README.md
new file mode 100644
index 0000000000..8ebe85a07b
--- /dev/null
+++ b/client2/src/main/template/README.md
@@ -0,0 +1 @@
+Check the diff between `*.mustache` and `*.orig` to see the introduced customizations.
\ No newline at end of file
diff --git a/client2/src/main/template/libraries/native/ApiClient.mustache b/client2/src/main/template/libraries/native/ApiClient.mustache
new file mode 100644
index 0000000000..5a58a59fcc
--- /dev/null
+++ b/client2/src/main/template/libraries/native/ApiClient.mustache
@@ -0,0 +1,462 @@
+{{>licenseInfo}}
+package {{invokerPackage}};
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+{{#openApiNullable}}
+import org.openapitools.jackson.nullable.JsonNullableModule;
+{{/openApiNullable}}
+
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.net.http.HttpClient;
+import java.net.http.HttpConnectTimeoutException;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.time.Duration;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.StringJoiner;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+import com.walmartlabs.concord.client2.impl.auth.Authentication;
+import com.walmartlabs.concord.client2.impl.auth.ApiKey;
+import com.walmartlabs.concord.client2.impl.auth.SessionToken;
+import com.walmartlabs.concord.client2.impl.OffsetDateTimeDeserializer;
+import com.walmartlabs.concord.client2.impl.OffsetDateTimeSerializer;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+/**
+ * Configuration and utility class for API clients.
+ *
+ * This class can be constructed and modified, then used to instantiate the
+ * various API classes. The API classes use the settings in this class to
+ * configure themselves, but otherwise do not store a link to this class.
+ *
+ * This class is mutable and not synchronized, so it is not thread-safe.
+ * The API classes generated from this are immutable and thread-safe.
+ *
+ * The setter methods of this class return the current object to facilitate
+ * a fluent style of configuration.
+ */
+{{>generatedAnnotation}}
+public class ApiClient {
+
+ private final HttpClient httpClient;
+ private ObjectMapper mapper;
+ private String baseUri;
+ private String scheme;
+ private String host;
+ private int port;
+ private String basePath;
+ private Consumer interceptor;
+ private Consumer> responseInterceptor;
+ private Consumer> asyncResponseInterceptor;
+ private Duration readTimeout;
+ private Duration connectTimeout;
+ private Authentication auth;
+ private final Map defaultHeaderMap = new HashMap();
+
+ public Authentication getAuth() {
+ return auth;
+ }
+
+ public void setAuth(Authentication auth) {
+ this.auth = auth;
+ }
+
+ public Map defaultHeaderMap() {
+ return defaultHeaderMap;
+ }
+
+ private static String valueToString(Object value) {
+ if (value == null) {
+ return "";
+ }
+ if (value instanceof OffsetDateTime) {
+ return ((OffsetDateTime) value).format(OffsetDateTimeSerializer.FORMATTER);
+ }
+ return value.toString();
+ }
+
+ /**
+ * URL encode a string in the UTF-8 encoding.
+ *
+ * @param s String to encode.
+ * @return URL-encoded representation of the input string.
+ */
+ public static String urlEncode(String s) {
+ return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20");
+ }
+
+ /**
+ * Convert a URL query name/value parameter to a list of encoded {@link Pair}
+ * objects.
+ *
+ * The value can be null, in which case an empty list is returned.
+ *
+ * @param name The query name parameter.
+ * @param value The query value, which may not be a collection but may be
+ * null.
+ * @return A singleton list of the {@link Pair} objects representing the input
+ * parameters, which is encoded for use in a URL. If the value is null, an
+ * empty list is returned.
+ */
+ public static List parameterToPairs(String name, Object value) {
+ if (name == null || name.isEmpty() || value == null) {
+ return Collections.emptyList();
+ }
+ return Collections.singletonList(new Pair(urlEncode(name), urlEncode(valueToString(value))));
+ }
+
+ /**
+ * Convert a URL query name/collection parameter to a list of encoded
+ * {@link Pair} objects.
+ *
+ * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc).
+ * @param name The query name parameter.
+ * @param values A collection of values for the given query name, which may be
+ * null.
+ * @return A list of {@link Pair} objects representing the input parameters,
+ * which is encoded for use in a URL. If the values collection is null, an
+ * empty list is returned.
+ */
+ public static List parameterToPairs(
+ String collectionFormat, String name, Collection> values) {
+ if (name == null || name.isEmpty() || values == null || values.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ // get the collection format (default: csv)
+ String format = collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat;
+
+ // create the params based on the collection format
+ if ("multi".equals(format)) {
+ return values.stream()
+ .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value))))
+ .collect(Collectors.toList());
+ }
+
+ String delimiter;
+ switch(format) {
+ case "csv":
+ delimiter = urlEncode(",");
+ break;
+ case "ssv":
+ delimiter = urlEncode(" ");
+ break;
+ case "tsv":
+ delimiter = urlEncode("\t");
+ break;
+ case "pipes":
+ delimiter = urlEncode("|");
+ break;
+ default:
+ throw new IllegalArgumentException("Illegal collection format: " + collectionFormat);
+ }
+
+ StringJoiner joiner = new StringJoiner(delimiter);
+ for (Object value : values) {
+ joiner.add(urlEncode(valueToString(value)));
+ }
+
+ return Collections.singletonList(new Pair(urlEncode(name), joiner.toString()));
+ }
+
+ /**
+ * Create an instance of ApiClient.
+ */
+ public ApiClient(HttpClient httpClient) {
+ this.httpClient = httpClient;
+ this.mapper = createDefaultObjectMapper();
+ updateBaseUri(getDefaultBaseUri());
+ interceptor = null;
+ readTimeout = null;
+ connectTimeout = null;
+ responseInterceptor = null;
+ asyncResponseInterceptor = null;
+ }
+
+ public static ObjectMapper createDefaultObjectMapper() {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
+ mapper.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, false);
+ mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+ mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
+ mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
+ mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
+ mapper.registerModule(new JavaTimeModule()
+ .addDeserializer(OffsetDateTime.class, new OffsetDateTimeDeserializer())
+ .addSerializer(OffsetDateTime.class, new OffsetDateTimeSerializer()));
+ {{#openApiNullable}}
+ mapper.registerModule(new JsonNullableModule());
+ {{/openApiNullable}}
+ return mapper;
+ }
+
+ public ApiClient setUserAgent(String userAgent) {
+ addDefaultHeader("User-Agent", userAgent);
+ return this;
+ }
+
+ public ApiClient addDefaultHeader(String key, String value) {
+ defaultHeaderMap.put(key, value);
+ return this;
+ }
+
+ protected String getDefaultBaseUri() {
+ return "{{{basePath}}}";
+ }
+
+ public HttpRequest.Builder requestBuilder() {
+ HttpRequest.Builder result = HttpRequest.newBuilder();
+ for (Map.Entry e : defaultHeaderMap.entrySet()) {
+ result.header(e.getKey(), e.getValue());
+ }
+ if (getAuth() != null) {
+ result = getAuth().applyTo(result);
+ }
+ return result;
+ }
+
+ public void updateBaseUri(String baseUri) {
+ this.baseUri = baseUri;
+
+ URI uri = URI.create(baseUri);
+ scheme = uri.getScheme();
+ host = uri.getHost();
+ port = uri.getPort();
+ basePath = uri.getRawPath();
+ }
+
+ public ApiClient setBaseUrl(String baseUrl) {
+ updateBaseUri(baseUrl);
+ return this;
+ }
+
+ public String getBaseUrl() {
+ return this.baseUri;
+ }
+
+ public ApiClient setSessionToken(String token) {
+ if (token == null) {
+ return this;
+ }
+
+ setAuth(new SessionToken(token));
+
+ return this;
+ }
+
+ public ApiClient setApiKey(String key) {
+ if (key == null) {
+ return this;
+ }
+
+ setAuth(new ApiKey(key));
+
+ return this;
+ }
+
+ /**
+ * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}.
+ *
+ * The returned object is immutable and thread-safe.
+ *
+ * @return The HTTP client.
+ */
+ public HttpClient getHttpClient() {
+ return httpClient;
+ }
+
+ /**
+ * Set a custom {@link ObjectMapper} to serialize and deserialize the request
+ * and response bodies.
+ *
+ * @param mapper Custom object mapper.
+ * @return This object.
+ */
+ public ApiClient setObjectMapper(ObjectMapper mapper) {
+ this.mapper = mapper;
+ return this;
+ }
+
+ /**
+ * Get a copy of the current {@link ObjectMapper}.
+ *
+ * @return A copy of the current object mapper.
+ */
+ public ObjectMapper getObjectMapper() {
+ return mapper.copy();
+ }
+
+ /**
+ * Set a custom host name for the target service.
+ *
+ * @param host The host name of the target service.
+ * @return This object.
+ */
+ public ApiClient setHost(String host) {
+ this.host = host;
+ return this;
+ }
+
+ /**
+ * Set a custom port number for the target service.
+ *
+ * @param port The port of the target service. Set this to -1 to reset the
+ * value to the default for the scheme.
+ * @return This object.
+ */
+ public ApiClient setPort(int port) {
+ this.port = port;
+ return this;
+ }
+
+ /**
+ * Set a custom base path for the target service, for example '/v2'.
+ *
+ * @param basePath The base path against which the rest of the path is
+ * resolved.
+ * @return This object.
+ */
+ public ApiClient setBasePath(String basePath) {
+ this.basePath = basePath;
+ return this;
+ }
+
+ /**
+ * Get the base URI to resolve the endpoint paths against.
+ *
+ * @return The complete base URI that the rest of the API parameters are
+ * resolved against.
+ */
+ public String getBaseUri() {
+ return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath;
+ }
+
+ /**
+ * Set a custom scheme for the target service, for example 'https'.
+ *
+ * @param scheme The scheme of the target service
+ * @return This object.
+ */
+ public ApiClient setScheme(String scheme){
+ this.scheme = scheme;
+ return this;
+ }
+
+ /**
+ * Set a custom request interceptor.
+ *
+ * A request interceptor is a mechanism for altering each request before it
+ * is sent. After the request has been fully configured but not yet built, the
+ * request builder is passed into this function for further modification,
+ * after which it is sent out.
+ *
+ * This is useful for altering the requests in a custom manner, such as
+ * adding headers. It could also be used for logging and monitoring.
+ *
+ * @param interceptor A function invoked before creating each request. A value
+ * of null resets the interceptor to a no-op.
+ * @return This object.
+ */
+ public ApiClient setRequestInterceptor(Consumer interceptor) {
+ this.interceptor = interceptor;
+ return this;
+ }
+
+ /**
+ * Get the custom interceptor.
+ *
+ * @return The custom interceptor that was set, or null if there isn't any.
+ */
+ public Consumer getRequestInterceptor() {
+ return interceptor;
+ }
+
+ /**
+ * Set a custom response interceptor.
+ *
+ * This is useful for logging, monitoring or extraction of header variables
+ *
+ * @param interceptor A function invoked before creating each request. A value
+ * of null resets the interceptor to a no-op.
+ * @return This object.
+ */
+ public ApiClient setResponseInterceptor(Consumer> interceptor) {
+ this.responseInterceptor = interceptor;
+ return this;
+ }
+
+ /**
+ * Get the custom response interceptor.
+ *
+ * @return The custom interceptor that was set, or null if there isn't any.
+ */
+ public Consumer> getResponseInterceptor() {
+ return responseInterceptor;
+ }
+
+ /**
+ * Set a custom async response interceptor. Use this interceptor when asyncNative is set to 'true'.
+ *
+ * This is useful for logging, monitoring or extraction of header variables
+ *
+ * @param interceptor A function invoked before creating each request. A value
+ * of null resets the interceptor to a no-op.
+ * @return This object.
+ */
+ public ApiClient setAsyncResponseInterceptor(Consumer> interceptor) {
+ this.asyncResponseInterceptor = interceptor;
+ return this;
+ }
+
+ /**
+ * Get the custom async response interceptor. Use this interceptor when asyncNative is set to 'true'.
+ *
+ * @return The custom interceptor that was set, or null if there isn't any.
+ */
+ public Consumer> getAsyncResponseInterceptor() {
+ return asyncResponseInterceptor;
+ }
+
+ /**
+ * Set the read timeout for the http client.
+ *
+ * This is the value used by default for each request, though it can be
+ * overridden on a per-request basis with a request interceptor.
+ *
+ * @param readTimeout The read timeout used by default by the http client.
+ * Setting this value to null resets the timeout to an
+ * effectively infinite value.
+ * @return This object.
+ */
+ public ApiClient setReadTimeout(Duration readTimeout) {
+ this.readTimeout = readTimeout;
+ return this;
+ }
+
+ /**
+ * Get the read timeout that was set.
+ *
+ * @return The read timeout, or null if no timeout was set. Null represents
+ * an infinite wait time.
+ */
+ public Duration getReadTimeout() {
+ return readTimeout;
+ }
+}
\ No newline at end of file
diff --git a/client2/src/main/template/libraries/native/api.mustache b/client2/src/main/template/libraries/native/api.mustache
new file mode 100644
index 0000000000..93691d39d8
--- /dev/null
+++ b/client2/src/main/template/libraries/native/api.mustache
@@ -0,0 +1,567 @@
+{{>licenseInfo}}
+package {{package}};
+
+import {{invokerPackage}}.ApiClient;
+import {{invokerPackage}}.ApiException;
+import {{invokerPackage}}.ApiResponse;
+import {{invokerPackage}}.Pair;
+
+{{#imports}}
+import {{import}};
+{{/imports}}
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import com.walmartlabs.concord.client2.impl.*;
+
+{{#hasFormParamsInSpec}}
+{{/hasFormParamsInSpec}}
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.http.HttpRequest;
+import java.nio.channels.Channels;
+import java.nio.channels.Pipe;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.time.Duration;
+
+{{^fullJavaUtil}}
+import java.util.ArrayList;
+import java.util.StringJoiner;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.HashMap;
+import java.util.function.Consumer;
+{{/fullJavaUtil}}
+{{#asyncNative}}
+
+import java.util.concurrent.CompletableFuture;
+{{/asyncNative}}
+
+{{>generatedAnnotation}}
+{{#operations}}
+public class {{classname}} {
+ private final HttpClient memberVarHttpClient;
+ private final ObjectMapper memberVarObjectMapper;
+ private final String memberVarBaseUri;
+ private final {{#fullJavaUtil}}java.util.function.{{/fullJavaUtil}}Consumer memberVarInterceptor;
+ private final Duration memberVarReadTimeout;
+ private final {{#fullJavaUtil}}java.util.function.{{/fullJavaUtil}}Consumer> memberVarResponseInterceptor;
+ private final {{#fullJavaUtil}}java.util.function.{{/fullJavaUtil}}Consumer> memberVarAsyncResponseInterceptor;
+
+ private final ApiClient apiClient;
+
+ public {{classname}}(ApiClient apiClient) {
+ memberVarHttpClient = apiClient.getHttpClient();
+ memberVarObjectMapper = apiClient.getObjectMapper();
+ memberVarBaseUri = apiClient.getBaseUri();
+ memberVarInterceptor = apiClient.getRequestInterceptor();
+ memberVarReadTimeout = apiClient.getReadTimeout();
+ memberVarResponseInterceptor = apiClient.getResponseInterceptor();
+ memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor();
+
+ this.apiClient = apiClient;
+ }
+
+ public ApiClient getApiClient() {
+ return this.apiClient;
+ }
+
+ {{#asyncNative}}
+
+ private ApiException getApiException(String operationId, HttpResponse response) {
+ String message = formatExceptionMessage(operationId, response.statusCode(), response.body());
+ return new ApiException(response.statusCode(), message, response.headers(), response.body());
+ }
+ {{/asyncNative}}
+ {{^asyncNative}}
+
+ protected ApiException getApiException(String operationId, HttpResponse response) throws IOException {
+ String body = response.body() == null ? null : new String(response.body().readAllBytes());
+ String message = formatExceptionMessage(operationId, response.statusCode(), body);
+ return new ApiException(response.statusCode(), message, response.headers(), body);
+ }
+ {{/asyncNative}}
+
+ private String formatExceptionMessage(String operationId, int statusCode, String body) {
+ if (body == null || body.isEmpty()) {
+ body = "[no body]";
+ }
+ return operationId + " call failed with: " + statusCode + " - " + body;
+ }
+
+ {{#operation}}
+ {{#vendorExtensions.x-group-parameters}}
+ {{#hasParams}}
+ /**
+ * {{summary}}
+ * {{notes}}
+ * @param apiRequest {@link API{{operationId}}Request}
+ {{#returnType}}
+ * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}{{returnType}}{{#asyncNative}}>{{/asyncNative}}
+ {{/returnType}}
+ {{^returnType}}
+ {{#asyncNative}}
+ * @return CompletableFuture<Void>
+ {{/asyncNative}}
+ {{/returnType}}
+ * @throws ApiException if fails to make API call
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ {{#externalDocs}}
+ * {{description}}
+ * @see {{summary}} Documentation
+ {{/externalDocs}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}(API{{operationId}}Request apiRequest) throws ApiException {
+ {{#allParams}}
+ {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}();
+ {{/allParams}}
+ {{#returnType}}return {{/returnType}}{{^returnType}}{{#asyncNative}}return {{/asyncNative}}{{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+ }
+
+ /**
+ * {{summary}}
+ * {{notes}}
+ * @param apiRequest {@link API{{operationId}}Request}
+ * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}}
+ * @throws ApiException if fails to make API call
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ {{#externalDocs}}
+ * {{description}}
+ * @see {{summary}} Documentation
+ {{/externalDocs}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo(API{{operationId}}Request apiRequest) throws ApiException {
+ {{#allParams}}
+ {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}();
+ {{/allParams}}
+ return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+ }
+
+ {{/hasParams}}
+ {{/vendorExtensions.x-group-parameters}}
+ /**
+ * {{summary}}
+ * {{notes}}
+ {{#isMultipart}}
+ {{#allParams}}
+ {{^isFormParam}}
+ * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}}
+ {{/isFormParam}}
+ {{/allParams}}
+ {{/isMultipart}}
+ {{^isMultipart}}
+ {{#allParams}}
+ * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}}
+ {{/allParams}}
+ {{/isMultipart}}
+ {{#returnType}}
+ * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}{{returnType}}{{#asyncNative}}>{{/asyncNative}}
+ {{/returnType}}
+ {{^returnType}}
+ {{#asyncNative}}
+ * @return CompletableFuture<Void>
+ {{/asyncNative}}
+ {{/returnType}}
+ * @throws ApiException if fails to make API call
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ {{#externalDocs}}
+ * {{description}}
+ * @see {{summary}} Documentation
+ {{/externalDocs}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+
+ {{#vendorExtensions.x-concord.groupParams}}
+ public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{vendorExtensions.x-concord.groupName}} in) throws ApiException {
+ return {{operationId}}({{#isMultipart}}{{#allParams}}{{^isFormParam}}in.{{paramName}}(),{{/isFormParam}}{{/allParams}} multipartInput{{/isMultipart}}{{^isMultipart}}{{#allParams}}in.{{paramName}}(){{^-last}}, {{/-last}} {{/allParams}}{{/isMultipart}});
+ }
+ {{/vendorExtensions.x-concord.groupParams}}
+
+ public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#isMultipart}}{{#allParams}}{{^isFormParam}}{{#vendorExtensions.x-concord.customQueryParams}}Map{{/vendorExtensions.x-concord.customQueryParams}}{{^vendorExtensions.x-concord.customQueryParams}}{{{dataType}}}{{/vendorExtensions.x-concord.customQueryParams}} {{paramName}},{{/isFormParam}}{{/allParams}} Map multipartInput{{/isMultipart}}{{^isMultipart}}{{#allParams}} {{#vendorExtensions.x-concord.customQueryParams}}Map{{/vendorExtensions.x-concord.customQueryParams}}{{^vendorExtensions.x-concord.customQueryParams}}{{{dataType}}}{{/vendorExtensions.x-concord.customQueryParams}} {{paramName}}{{^-last}}, {{/-last}} {{/allParams}}{{/isMultipart}}) throws ApiException {
+ {{^asyncNative}}
+ {{#returnType}}ApiResponse<{{{.}}}> localVarResponse = {{/returnType}}{{operationId}}WithHttpInfo({{#isMultipart}}{{#allParams}}{{^isFormParam}}{{paramName}},{{/isFormParam}}{{/allParams}} multipartInput{{/isMultipart}}{{^isMultipart}}{{#allParams}}{{paramName}}{{^-last}}, {{/-last}} {{/allParams}}{{/isMultipart}});
+ {{#returnType}}
+ return localVarResponse.getData();
+ {{/returnType}}
+ {{/asyncNative}}
+ {{#asyncNative}}
+ try {
+ HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+ return memberVarHttpClient.sendAsync(
+ localVarRequestBuilder.build(),
+ HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> {
+ if (localVarResponse.statusCode()/ 100 != 2) {
+ return CompletableFuture.failedFuture(getApiException("{{operationId}}", localVarResponse));
+ }
+ {{#returnType}}
+ try {
+ String responseBody = localVarResponse.body();
+ return CompletableFuture.completedFuture(
+ responseBody == null || responseBody.isBlank() ? null : memberVarObjectMapper.readValue(responseBody, new TypeReference<{{{returnType}}}>() {})
+ );
+ } catch (IOException e) {
+ return CompletableFuture.failedFuture(new ApiException(e));
+ }
+ {{/returnType}}
+ {{^returnType}}
+ return CompletableFuture.completedFuture(null);
+ {{/returnType}}
+ });
+ }
+ catch (ApiException e) {
+ return CompletableFuture.failedFuture(e);
+ }
+ {{/asyncNative}}
+ }
+
+ /**
+ * {{summary}}
+ * {{notes}}
+ {{#isMultipart}}
+ {{#allParams}}
+ {{^isFormParam}}
+ * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}}
+ {{/isFormParam}}
+ {{/allParams}}
+ {{/isMultipart}}
+ {{^isMultipart}}
+ {{#allParams}}
+ * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}}
+ {{/allParams}}
+ {{/isMultipart}}
+ * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}}
+ * @throws ApiException if fails to make API call
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ {{#externalDocs}}
+ * {{description}}
+ * @see {{summary}} Documentation
+ {{/externalDocs}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo({{#isMultipart}}{{#allParams}}{{^isFormParam}}{{#vendorExtensions.x-concord.customQueryParams}}Map{{/vendorExtensions.x-concord.customQueryParams}}{{^vendorExtensions.x-concord.customQueryParams}}{{{dataType}}}{{/vendorExtensions.x-concord.customQueryParams}} {{paramName}},{{/isFormParam}}{{/allParams}} Map multipartInput{{/isMultipart}}{{^isMultipart}}{{#allParams}} {{#vendorExtensions.x-concord.customQueryParams}}Map{{/vendorExtensions.x-concord.customQueryParams}}{{^vendorExtensions.x-concord.customQueryParams}}{{{dataType}}}{{/vendorExtensions.x-concord.customQueryParams}} {{paramName}}{{^-last}}, {{/-last}} {{/allParams}}{{/isMultipart}}) throws ApiException {
+ {{^asyncNative}}
+ HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#isMultipart}}{{#allParams}}{{^isFormParam}}{{paramName}},{{/isFormParam}}{{/allParams}} multipartInput{{/isMultipart}}{{^isMultipart}}{{#allParams}}{{paramName}}{{^-last}}, {{/-last}} {{/allParams}}{{/isMultipart}});
+ try {
+ HttpResponse localVarResponse = memberVarHttpClient.send(
+ localVarRequestBuilder.build(),
+ HttpResponse.BodyHandlers.ofInputStream());
+ if (memberVarResponseInterceptor != null) {
+ memberVarResponseInterceptor.accept(localVarResponse);
+ }
+ try {
+ if (localVarResponse.statusCode()/ 100 != 2) {
+ throw getApiException("{{operationId}}", localVarResponse);
+ }
+ if (localVarResponse.statusCode() == 204) {
+ return new ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>(
+ localVarResponse.statusCode(),
+ localVarResponse.headers().map(),
+ null
+ );
+ }
+
+ return new ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>(
+ localVarResponse.statusCode(),
+ localVarResponse.headers().map(),
+ {{#returnType}}
+ ResponseBodyHandler.handle(memberVarObjectMapper, localVarResponse, new TypeReference<{{{returnType}}}>() {})
+ {{/returnType}}
+ {{^returnType}}
+ null
+ {{/returnType}}
+ );
+ } finally {
+ {{^returnType}}
+ // Drain the InputStream
+ while (localVarResponse.body().read() != -1) {
+ // Ignore
+ }
+ localVarResponse.body().close();
+ {{/returnType}}
+ }
+ } catch (IOException e) {
+ throw new ApiException(e);
+ }
+ catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new ApiException(e);
+ }
+ {{/asyncNative}}
+ {{#asyncNative}}
+ try {
+ HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+ return memberVarHttpClient.sendAsync(
+ localVarRequestBuilder.build(),
+ HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> {
+ if (memberVarAsyncResponseInterceptor != null) {
+ memberVarAsyncResponseInterceptor.accept(localVarResponse);
+ }
+ if (localVarResponse.statusCode()/ 100 != 2) {
+ return CompletableFuture.failedFuture(getApiException("{{operationId}}", localVarResponse));
+ }
+ {{#returnType}}
+ try {
+ String responseBody = localVarResponse.body();
+ return CompletableFuture.completedFuture(
+ new ApiResponse<{{{returnType}}}>(
+ localVarResponse.statusCode(),
+ localVarResponse.headers().map(),
+ TODO:)
+ );
+ } catch (IOException e) {
+ return CompletableFuture.failedFuture(new ApiException(e));
+ }
+ {{/returnType}}
+ {{^returnType}}
+ return CompletableFuture.completedFuture(
+ new ApiResponse(localVarResponse.statusCode(), localVarResponse.headers().map(), null)
+ );
+ {{/returnType}}
+ }
+ );
+ }
+ catch (ApiException e) {
+ return CompletableFuture.failedFuture(e);
+ }
+ {{/asyncNative}}
+ }
+
+
+ private HttpRequest.Builder {{operationId}}RequestBuilder({{#isMultipart}}{{#allParams}}{{^isFormParam}}{{#vendorExtensions.x-concord.customQueryParams}}Map{{/vendorExtensions.x-concord.customQueryParams}}{{^vendorExtensions.x-concord.customQueryParams}}{{{dataType}}}{{/vendorExtensions.x-concord.customQueryParams}} {{paramName}},{{/isFormParam}}{{/allParams}} Map multipartInput{{/isMultipart}}{{^isMultipart}}{{#allParams}} {{#vendorExtensions.x-concord.customQueryParams}}Map{{/vendorExtensions.x-concord.customQueryParams}}{{^vendorExtensions.x-concord.customQueryParams}}{{{dataType}}}{{/vendorExtensions.x-concord.customQueryParams}} {{paramName}}{{^-last}}, {{/-last}} {{/allParams}}{{/isMultipart}}) throws ApiException {
+ {{#allParams}}
+ {{#required}}
+ // verify the required parameter '{{paramName}}' is set
+ if ({{paramName}} == null) {
+ throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}");
+ }
+ {{/required}}
+ {{/allParams}}
+
+ HttpRequest.Builder localVarRequestBuilder = apiClient.requestBuilder();
+
+ {{! Switch delimiters for baseName so we can write constants like "{query}" }}
+ String localVarPath = "{{{path}}}"{{#pathParams}}
+ .replace({{=<% %>=}}"{<%baseName%>}"<%={{ }}=%>, ApiClient.urlEncode({{{paramName}}}.toString())){{/pathParams}};
+
+ {{#hasQueryParams}}
+ {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList<>();
+ {{javaUtilPrefix}}StringJoiner localVarQueryStringJoiner = new {{javaUtilPrefix}}StringJoiner("&");
+ {{#queryParams}}
+ {{#vendorExtensions.x-concord.customQueryParams}}
+ if ({{paramName}} != null) {
+ for (Map.Entry e : {{paramName}}.entrySet()) {
+ localVarQueryParams.addAll(ApiClient.parameterToPairs(e.getKey(), e.getValue()));
+ }
+ }
+ {{/vendorExtensions.x-concord.customQueryParams}}
+ {{#collectionFormat}}
+ localVarQueryParams.addAll(ApiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{paramName}}));
+ {{/collectionFormat}}
+ {{^collectionFormat}}
+ {{#isDeepObject}}
+ if ({{paramName}} != null) {
+ {{#isArray}}
+ for (int i=0; i < {{paramName}}.size(); i++) {
+ localVarQueryStringJoiner.add({{paramName}}.get(i).toUrlQueryString(String.format("{{baseName}}[%d]", i)));
+ }
+ {{/isArray}}
+ {{^isArray}}
+ localVarQueryStringJoiner.add({{paramName}}.toUrlQueryString("{{baseName}}"));
+ {{/isArray}}
+ }
+ {{/isDeepObject}}
+ {{^isDeepObject}}
+ {{#isExplode}}
+ {{#hasVars}}
+ {{#vars}}
+ {{#isArray}}
+ localVarQueryParams.addAll(ApiClient.parameterToPairs("multi", "{{baseName}}", {{paramName}}.{{getter}}()));
+ {{/isArray}}
+ {{^isArray}}
+ if ({{paramName}} != null) {
+ localVarQueryParams.addAll(ApiClient.parameterToPairs("{{paramName}}", {{paramName}}.{{getter}}()));
+ }
+ {{/isArray}}
+ {{/vars}}
+ {{/hasVars}}
+ {{^hasVars}}
+ {{#isModel}}
+ localVarQueryStringJoiner.add({{paramName}}.toUrlQueryString());
+ {{/isModel}}
+ {{^isModel}}
+ {{^vendorExtensions.x-concord.customQueryParams}}
+ localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}}));
+ {{/vendorExtensions.x-concord.customQueryParams}}
+ {{/isModel}}
+ {{/hasVars}}
+ {{/isExplode}}
+ {{^isExplode}}
+ localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}}));
+ {{/isExplode}}
+ {{/isDeepObject}}
+ {{/collectionFormat}}
+ {{/queryParams}}
+
+ if (!localVarQueryParams.isEmpty() || localVarQueryStringJoiner.length() != 0) {
+ {{javaUtilPrefix}}StringJoiner queryJoiner = new {{javaUtilPrefix}}StringJoiner("&");
+ localVarQueryParams.forEach(p -> queryJoiner.add(p.getName() + '=' + p.getValue()));
+ if (localVarQueryStringJoiner.length() != 0) {
+ queryJoiner.add(localVarQueryStringJoiner.toString());
+ }
+ localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath + '?' + queryJoiner.toString()));
+ } else {
+ localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath));
+ }
+ {{/hasQueryParams}}
+ {{^hasQueryParams}}
+ localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath));
+ {{/hasQueryParams}}
+
+ {{#headerParams}}
+ if ({{paramName}} != null) {
+ localVarRequestBuilder.header("{{baseName}}", {{paramName}}.toString());
+ }
+ {{/headerParams}}
+ {{#bodyParam}}
+ localVarRequestBuilder.header("Content-Type", "{{#hasConsumes}}{{#consumes}}{{#-first}}{{mediaType}}{{/-first}}{{/consumes}}{{/hasConsumes}}{{#hasConsumes}}{{^consumes}}application/json{{/consumes}}{{/hasConsumes}}{{^hasConsumes}}application/json{{/hasConsumes}}");
+ {{/bodyParam}}
+ String acceptHeaderValue = "{{#hasProduces}}{{#produces}}{{mediaType}}{{^-last}}, {{/-last}}{{/produces}}{{/hasProduces}}{{#hasProduces}}{{^produces}}application/json{{/produces}}{{/hasProduces}}{{^hasProduces}}application/json{{/hasProduces}}";
+ acceptHeaderValue += ",application/vnd.siesta-validation-errors-v1+json";
+ localVarRequestBuilder.header("Accept", acceptHeaderValue);
+ {{#bodyParam}}
+ {{#isString}}
+ localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.ofString({{paramName}}));
+ {{/isString}}
+ {{^isString}}
+ try {
+ localVarRequestBuilder.method("{{httpMethod}}", RequestBodyHandler.handle(memberVarObjectMapper, {{paramName}}));
+ } catch (IOException e) {
+ throw new ApiException(e);
+ }
+ {{/isString}}
+ {{/bodyParam}}
+ {{^bodyParam}}
+
+ {{#isMultipart}}
+ HttpEntity entity = MultipartRequestBodyHandler.handle(memberVarObjectMapper, multipartInput);
+ localVarRequestBuilder
+ .header("Content-Type", entity.contentType().toString())
+ .method("{{httpMethod}}", HttpRequest.BodyPublishers.ofInputStream(() -> {
+ try {
+ return entity.getContent();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }));
+ {{/isMultipart}}
+ {{^isMultipart}}
+ {{#hasFormParams}}
+ List formValues = new ArrayList<>();
+ {{#formParams}}
+ {{#isArray}}
+ for (int i=0; i < {{paramName}}.size(); i++) {
+ if ({{paramName}}.get(i) != null) {
+ formValues.add(new NameValuePair("{{{baseName}}}", {{paramName}}.get(i).toString()));
+ }
+ }
+ {{/isArray}}
+ {{^isArray}}
+ if ({{paramName}} != null) {
+ formValues.add(new NameValuePair("{{{baseName}}}", {{paramName}}.toString()));
+ }
+ {{/isArray}}
+ {{/formParams}}
+ HttpEntity entity = new UrlEncodedFormEntity(formValues, java.nio.charset.StandardCharsets.UTF_8);
+ ByteArrayOutputStream formOutputStream = new ByteArrayOutputStream();
+ try {
+ entity.writeTo(formOutputStream);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ localVarRequestBuilder
+ .header("Content-Type", entity.getContentType().toString())
+ .method("{{httpMethod}}", HttpRequest.BodyPublishers
+ .ofInputStream(() -> new ByteArrayInputStream(formOutputStream.toByteArray())));
+
+ {{/hasFormParams}}
+ {{^hasFormParams}}
+ localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.noBody());
+ {{/hasFormParams}}
+ {{/isMultipart}}
+
+
+ {{/bodyParam}}
+ if (memberVarReadTimeout != null) {
+ localVarRequestBuilder.timeout(memberVarReadTimeout);
+ }
+ if (memberVarInterceptor != null) {
+ memberVarInterceptor.accept(localVarRequestBuilder);
+ }
+ return localVarRequestBuilder;
+ }
+ {{#isMultipart}}
+ {{#hasParams}}
+
+ public static final class {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}Request {
+ {{#allParams}}
+ {{#isFormParam}}
+ private {{{dataType}}} {{paramName}};
+ {{/isFormParam}}
+ {{/allParams}}
+
+ {{#allParams}}
+ {{#isFormParam}}
+ public {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}Request {{paramName}}({{{dataType}}} {{paramName}}) {
+ this.{{paramName}} = {{paramName}};
+ return this;
+ }
+ {{/isFormParam}}
+ {{/allParams}}
+
+ public Map asMap() {
+ Map result = new HashMap<>();
+
+ {{#allParams}}
+ {{#isFormParam}}
+ if ({{paramName}} != null) {
+ result.put("{{baseName}}", {{paramName}});
+ }
+ {{/isFormParam}}
+ {{/allParams}}
+
+ return result;
+ }
+ }
+
+ {{/hasParams}}
+ {{/isMultipart}}
+ {{/operation}}
+}
+{{/operations}}
diff --git a/client2/src/main/template/libraries/native/api.mustache.orig b/client2/src/main/template/libraries/native/api.mustache.orig
new file mode 100644
index 0000000000..526e565234
--- /dev/null
+++ b/client2/src/main/template/libraries/native/api.mustache.orig
@@ -0,0 +1,591 @@
+{{>licenseInfo}}
+package {{package}};
+
+import {{invokerPackage}}.ApiClient;
+import {{invokerPackage}}.ApiException;
+import {{invokerPackage}}.ApiResponse;
+import {{invokerPackage}}.Pair;
+
+{{#imports}}
+import {{import}};
+{{/imports}}
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+{{#hasFormParamsInSpec}}
+import org.apache.http.HttpEntity;
+import org.apache.http.NameValuePair;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+
+{{/hasFormParamsInSpec}}
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.http.HttpRequest;
+import java.nio.channels.Channels;
+import java.nio.channels.Pipe;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.time.Duration;
+
+import java.util.ArrayList;
+import java.util.StringJoiner;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+{{#asyncNative}}
+
+import java.util.concurrent.CompletableFuture;
+{{/asyncNative}}
+
+{{>generatedAnnotation}}
+{{#operations}}
+public class {{classname}} {
+ private final HttpClient memberVarHttpClient;
+ private final ObjectMapper memberVarObjectMapper;
+ private final String memberVarBaseUri;
+ private final Consumer memberVarInterceptor;
+ private final Duration memberVarReadTimeout;
+ private final Consumer> memberVarResponseInterceptor;
+ private final Consumer> memberVarAsyncResponseInterceptor;
+
+ public {{classname}}() {
+ this(new ApiClient());
+ }
+
+ public {{classname}}(ApiClient apiClient) {
+ memberVarHttpClient = apiClient.getHttpClient();
+ memberVarObjectMapper = apiClient.getObjectMapper();
+ memberVarBaseUri = apiClient.getBaseUri();
+ memberVarInterceptor = apiClient.getRequestInterceptor();
+ memberVarReadTimeout = apiClient.getReadTimeout();
+ memberVarResponseInterceptor = apiClient.getResponseInterceptor();
+ memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor();
+ }
+ {{#asyncNative}}
+
+ private ApiException getApiException(String operationId, HttpResponse response) {
+ String message = formatExceptionMessage(operationId, response.statusCode(), response.body());
+ return new ApiException(response.statusCode(), message, response.headers(), response.body());
+ }
+ {{/asyncNative}}
+ {{^asyncNative}}
+
+ protected ApiException getApiException(String operationId, HttpResponse response) throws IOException {
+ String body = response.body() == null ? null : new String(response.body().readAllBytes());
+ String message = formatExceptionMessage(operationId, response.statusCode(), body);
+ return new ApiException(response.statusCode(), message, response.headers(), body);
+ }
+ {{/asyncNative}}
+
+ private String formatExceptionMessage(String operationId, int statusCode, String body) {
+ if (body == null || body.isEmpty()) {
+ body = "[no body]";
+ }
+ return operationId + " call failed with: " + statusCode + " - " + body;
+ }
+
+ {{#operation}}
+ {{#vendorExtensions.x-group-parameters}}
+ {{#hasParams}}
+ /**
+ * {{summary}}
+ * {{notes}}
+ * @param apiRequest {@link API{{operationId}}Request}
+ {{#returnType}}
+ * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}{{returnType}}{{#asyncNative}}>{{/asyncNative}}
+ {{/returnType}}
+ {{^returnType}}
+ {{#asyncNative}}
+ * @return CompletableFuture<Void>
+ {{/asyncNative}}
+ {{/returnType}}
+ * @throws ApiException if fails to make API call
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ {{#externalDocs}}
+ * {{description}}
+ * @see {{summary}} Documentation
+ {{/externalDocs}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}(API{{operationId}}Request apiRequest) throws ApiException {
+ {{#allParams}}
+ {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}();
+ {{/allParams}}
+ {{#returnType}}return {{/returnType}}{{^returnType}}{{#asyncNative}}return {{/asyncNative}}{{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+ }
+
+ /**
+ * {{summary}}
+ * {{notes}}
+ * @param apiRequest {@link API{{operationId}}Request}
+ * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}}
+ * @throws ApiException if fails to make API call
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ {{#externalDocs}}
+ * {{description}}
+ * @see {{summary}} Documentation
+ {{/externalDocs}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo(API{{operationId}}Request apiRequest) throws ApiException {
+ {{#allParams}}
+ {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}();
+ {{/allParams}}
+ return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+ }
+
+ {{/hasParams}}
+ {{/vendorExtensions.x-group-parameters}}
+ /**
+ * {{summary}}
+ * {{notes}}
+ {{#allParams}}
+ * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}}
+ {{/allParams}}
+ {{#returnType}}
+ * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}{{returnType}}{{#asyncNative}}>{{/asyncNative}}
+ {{/returnType}}
+ {{^returnType}}
+ {{#asyncNative}}
+ * @return CompletableFuture<Void>
+ {{/asyncNative}}
+ {{/returnType}}
+ * @throws ApiException if fails to make API call
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ {{#externalDocs}}
+ * {{description}}
+ * @see {{summary}} Documentation
+ {{/externalDocs}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException {
+ {{^asyncNative}}
+ {{#returnType}}ApiResponse<{{{.}}}> localVarResponse = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+ {{#returnType}}
+ return localVarResponse.getData();
+ {{/returnType}}
+ {{/asyncNative}}
+ {{#asyncNative}}
+ try {
+ HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+ return memberVarHttpClient.sendAsync(
+ localVarRequestBuilder.build(),
+ HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> {
+ if (localVarResponse.statusCode()/ 100 != 2) {
+ return CompletableFuture.failedFuture(getApiException("{{operationId}}", localVarResponse));
+ }
+ {{#returnType}}
+ try {
+ String responseBody = localVarResponse.body();
+ return CompletableFuture.completedFuture(
+ responseBody == null || responseBody.isBlank() ? null : memberVarObjectMapper.readValue(responseBody, new TypeReference<{{{returnType}}}>() {})
+ );
+ } catch (IOException e) {
+ return CompletableFuture.failedFuture(new ApiException(e));
+ }
+ {{/returnType}}
+ {{^returnType}}
+ return CompletableFuture.completedFuture(null);
+ {{/returnType}}
+ });
+ }
+ catch (ApiException e) {
+ return CompletableFuture.failedFuture(e);
+ }
+ {{/asyncNative}}
+ }
+
+ /**
+ * {{summary}}
+ * {{notes}}
+ {{#allParams}}
+ * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}}
+ {{/allParams}}
+ * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}}
+ * @throws ApiException if fails to make API call
+ {{#isDeprecated}}
+ * @deprecated
+ {{/isDeprecated}}
+ {{#externalDocs}}
+ * {{description}}
+ * @see {{summary}} Documentation
+ {{/externalDocs}}
+ */
+ {{#isDeprecated}}
+ @Deprecated
+ {{/isDeprecated}}
+ public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException {
+ {{^asyncNative}}
+ HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+ try {
+ HttpResponse localVarResponse = memberVarHttpClient.send(
+ localVarRequestBuilder.build(),
+ HttpResponse.BodyHandlers.ofInputStream());
+ if (memberVarResponseInterceptor != null) {
+ memberVarResponseInterceptor.accept(localVarResponse);
+ }
+ try {
+ if (localVarResponse.statusCode()/ 100 != 2) {
+ throw getApiException("{{operationId}}", localVarResponse);
+ }
+ {{#vendorExtensions.x-java-text-plain-string}}
+ // for plain text response
+ if (localVarResponse.headers().map().containsKey("Content-Type") &&
+ "text/plain".equalsIgnoreCase(localVarResponse.headers().map().get("Content-Type").get(0).split(";")[0].trim())) {
+ java.util.Scanner s = new java.util.Scanner(localVarResponse.body()).useDelimiter("\\A");
+ String responseBodyText = s.hasNext() ? s.next() : "";
+ return new ApiResponse(
+ localVarResponse.statusCode(),
+ localVarResponse.headers().map(),
+ responseBodyText
+ );
+ } else {
+ throw new RuntimeException("Error! The response Content-Type is supposed to be `text/plain` but it's not: " + localVarResponse);
+ }
+ {{/vendorExtensions.x-java-text-plain-string}}
+ {{^vendorExtensions.x-java-text-plain-string}}
+ return new ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>(
+ localVarResponse.statusCode(),
+ localVarResponse.headers().map(),
+ {{#returnType}}
+ localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}) // closes the InputStream
+ {{/returnType}}
+ {{^returnType}}
+ null
+ {{/returnType}}
+ );
+ {{/vendorExtensions.x-java-text-plain-string}}
+ } finally {
+ {{^returnType}}
+ // Drain the InputStream
+ while (localVarResponse.body().read() != -1) {
+ // Ignore
+ }
+ localVarResponse.body().close();
+ {{/returnType}}
+ }
+ } catch (IOException e) {
+ throw new ApiException(e);
+ }
+ catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new ApiException(e);
+ }
+ {{/asyncNative}}
+ {{#asyncNative}}
+ try {
+ HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+ return memberVarHttpClient.sendAsync(
+ localVarRequestBuilder.build(),
+ HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> {
+ if (memberVarAsyncResponseInterceptor != null) {
+ memberVarAsyncResponseInterceptor.accept(localVarResponse);
+ }
+ if (localVarResponse.statusCode()/ 100 != 2) {
+ return CompletableFuture.failedFuture(getApiException("{{operationId}}", localVarResponse));
+ }
+ {{#returnType}}
+ try {
+ String responseBody = localVarResponse.body();
+ return CompletableFuture.completedFuture(
+ new ApiResponse<{{{returnType}}}>(
+ localVarResponse.statusCode(),
+ localVarResponse.headers().map(),
+ responseBody == null || responseBody.isBlank() ? null : memberVarObjectMapper.readValue(responseBody, new TypeReference<{{{returnType}}}>() {}))
+ );
+ } catch (IOException e) {
+ return CompletableFuture.failedFuture(new ApiException(e));
+ }
+ {{/returnType}}
+ {{^returnType}}
+ return CompletableFuture.completedFuture(
+ new ApiResponse(localVarResponse.statusCode(), localVarResponse.headers().map(), null)
+ );
+ {{/returnType}}
+ }
+ );
+ }
+ catch (ApiException e) {
+ return CompletableFuture.failedFuture(e);
+ }
+ {{/asyncNative}}
+ }
+
+ private HttpRequest.Builder {{operationId}}RequestBuilder({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException {
+ {{#allParams}}
+ {{#required}}
+ // verify the required parameter '{{paramName}}' is set
+ if ({{paramName}} == null) {
+ throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}");
+ }
+ {{/required}}
+ {{/allParams}}
+
+ HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder();
+
+ {{! Switch delimiters for baseName so we can write constants like "{query}" }}
+ String localVarPath = "{{{path}}}"{{#pathParams}}
+ .replace({{=<% %>=}}"{<%baseName%>}"<%={{ }}=%>, ApiClient.urlEncode({{{paramName}}}.toString())){{/pathParams}};
+
+ {{#hasQueryParams}}
+ List localVarQueryParams = new ArrayList<>();
+ StringJoiner localVarQueryStringJoiner = new StringJoiner("&");
+ String localVarQueryParameterBaseName;
+ {{#queryParams}}
+ localVarQueryParameterBaseName = "{{{baseName}}}";
+ {{#collectionFormat}}
+ localVarQueryParams.addAll(ApiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{paramName}}));
+ {{/collectionFormat}}
+ {{^collectionFormat}}
+ {{#isDeepObject}}
+ if ({{paramName}} != null) {
+ {{#isArray}}
+ for (int i=0; i < {{paramName}}.size(); i++) {
+ localVarQueryStringJoiner.add({{paramName}}.get(i).toUrlQueryString(String.format("{{baseName}}[%d]", i)));
+ }
+ {{/isArray}}
+ {{^isArray}}
+ localVarQueryStringJoiner.add({{paramName}}.toUrlQueryString("{{baseName}}"));
+ {{/isArray}}
+ }
+ {{/isDeepObject}}
+ {{^isDeepObject}}
+ {{#isExplode}}
+ {{#hasVars}}
+ {{#vars}}
+ {{#isArray}}
+ localVarQueryParams.addAll(ApiClient.parameterToPairs("multi", "{{baseName}}", {{paramName}}.{{getter}}()));
+ {{/isArray}}
+ {{^isArray}}
+ localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}}.{{getter}}()));
+ {{/isArray}}
+ {{/vars}}
+ {{/hasVars}}
+ {{^hasVars}}
+ {{#isModel}}
+ localVarQueryStringJoiner.add({{paramName}}.toUrlQueryString());
+ {{/isModel}}
+ {{^isModel}}
+ localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}}));
+ {{/isModel}}
+ {{/hasVars}}
+ {{/isExplode}}
+ {{^isExplode}}
+ localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}}));
+ {{/isExplode}}
+ {{/isDeepObject}}
+ {{/collectionFormat}}
+ {{/queryParams}}
+
+ if (!localVarQueryParams.isEmpty() || localVarQueryStringJoiner.length() != 0) {
+ StringJoiner queryJoiner = new StringJoiner("&");
+ localVarQueryParams.forEach(p -> queryJoiner.add(p.getName() + '=' + p.getValue()));
+ if (localVarQueryStringJoiner.length() != 0) {
+ queryJoiner.add(localVarQueryStringJoiner.toString());
+ }
+ localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath + '?' + queryJoiner.toString()));
+ } else {
+ localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath));
+ }
+ {{/hasQueryParams}}
+ {{^hasQueryParams}}
+ localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath));
+ {{/hasQueryParams}}
+
+ {{#headerParams}}
+ if ({{paramName}} != null) {
+ localVarRequestBuilder.header("{{baseName}}", {{paramName}}.toString());
+ }
+ {{/headerParams}}
+ {{#bodyParam}}
+ localVarRequestBuilder.header("Content-Type", "{{#hasConsumes}}{{#consumes}}{{#-first}}{{mediaType}}{{/-first}}{{/consumes}}{{/hasConsumes}}{{#hasConsumes}}{{^consumes}}application/json{{/consumes}}{{/hasConsumes}}{{^hasConsumes}}application/json{{/hasConsumes}}");
+ {{/bodyParam}}
+ localVarRequestBuilder.header("Accept", "{{#hasProduces}}{{#produces}}{{mediaType}}{{^-last}}, {{/-last}}{{/produces}}{{/hasProduces}}{{#hasProduces}}{{^produces}}application/json{{/produces}}{{/hasProduces}}{{^hasProduces}}application/json{{/hasProduces}}");
+
+ {{#bodyParam}}
+ {{#isString}}
+ localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.ofString({{paramName}}));
+ {{/isString}}
+ {{^isString}}
+ try {
+ byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes({{paramName}});
+ localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody));
+ } catch (IOException e) {
+ throw new ApiException(e);
+ }
+ {{/isString}}
+ {{/bodyParam}}
+ {{^bodyParam}}
+ {{#hasFormParams}}
+ {{#isMultipart}}
+ MultipartEntityBuilder multiPartBuilder = MultipartEntityBuilder.create();
+ boolean hasFiles = false;
+ {{#formParams}}
+ {{#isArray}}
+ for (int i=0; i < {{paramName}}.size(); i++) {
+ {{#isFile}}
+ multiPartBuilder.addBinaryBody("{{{baseName}}}", {{paramName}}.get(i));
+ hasFiles = true;
+ {{/isFile}}
+ {{^isFile}}
+ multiPartBuilder.addTextBody("{{{baseName}}}", {{paramName}}.get(i).toString());
+ {{/isFile}}
+ }
+ {{/isArray}}
+ {{^isArray}}
+ {{#isFile}}
+ multiPartBuilder.addBinaryBody("{{{baseName}}}", {{paramName}});
+ hasFiles = true;
+ {{/isFile}}
+ {{^isFile}}
+ multiPartBuilder.addTextBody("{{{baseName}}}", {{paramName}}.toString());
+ {{/isFile}}
+ {{/isArray}}
+ {{/formParams}}
+ HttpEntity entity = multiPartBuilder.build();
+ HttpRequest.BodyPublisher formDataPublisher;
+ if (hasFiles) {
+ Pipe pipe;
+ try {
+ pipe = Pipe.open();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ new Thread(() -> {
+ try (OutputStream outputStream = Channels.newOutputStream(pipe.sink())) {
+ entity.writeTo(outputStream);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }).start();
+ formDataPublisher = HttpRequest.BodyPublishers.ofInputStream(() -> Channels.newInputStream(pipe.source()));
+ } else {
+ ByteArrayOutputStream formOutputStream = new ByteArrayOutputStream();
+ try {
+ entity.writeTo(formOutputStream);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ formDataPublisher = HttpRequest.BodyPublishers
+ .ofInputStream(() -> new ByteArrayInputStream(formOutputStream.toByteArray()));
+ }
+ localVarRequestBuilder
+ .header("Content-Type", entity.getContentType().getValue())
+ .method("{{httpMethod}}", formDataPublisher);
+ {{/isMultipart}}
+ {{^isMultipart}}
+ List formValues = new ArrayList<>();
+ {{#formParams}}
+ {{#isArray}}
+ for (int i=0; i < {{paramName}}.size(); i++) {
+ if ({{paramName}}.get(i) != null) {
+ formValues.add(new BasicNameValuePair("{{{baseName}}}", {{paramName}}.get(i).toString()));
+ }
+ }
+ {{/isArray}}
+ {{^isArray}}
+ if ({{paramName}} != null) {
+ formValues.add(new BasicNameValuePair("{{{baseName}}}", {{paramName}}.toString()));
+ }
+ {{/isArray}}
+ {{/formParams}}
+ HttpEntity entity = new UrlEncodedFormEntity(formValues, java.nio.charset.StandardCharsets.UTF_8);
+ ByteArrayOutputStream formOutputStream = new ByteArrayOutputStream();
+ try {
+ entity.writeTo(formOutputStream);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ localVarRequestBuilder
+ .header("Content-Type", entity.getContentType().getValue())
+ .method("{{httpMethod}}", HttpRequest.BodyPublishers
+ .ofInputStream(() -> new ByteArrayInputStream(formOutputStream.toByteArray())));
+ {{/isMultipart}}
+ {{/hasFormParams}}
+ {{^hasFormParams}}
+ localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.noBody());
+ {{/hasFormParams}}
+ {{/bodyParam}}
+ if (memberVarReadTimeout != null) {
+ localVarRequestBuilder.timeout(memberVarReadTimeout);
+ }
+ if (memberVarInterceptor != null) {
+ memberVarInterceptor.accept(localVarRequestBuilder);
+ }
+ return localVarRequestBuilder;
+ }
+ {{#vendorExtensions.x-group-parameters}}
+ {{#hasParams}}
+
+ public static final class API{{operationId}}Request {
+ {{#requiredParams}}
+ private {{{dataType}}} {{paramName}}; // {{description}} (required)
+ {{/requiredParams}}
+ {{#optionalParams}}
+ private {{{dataType}}} {{paramName}}; // {{description}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}
+ {{/optionalParams}}
+
+ private API{{operationId}}Request(Builder builder) {
+ {{#requiredParams}}
+ this.{{paramName}} = builder.{{paramName}};
+ {{/requiredParams}}
+ {{#optionalParams}}
+ this.{{paramName}} = builder.{{paramName}};
+ {{/optionalParams}}
+ }
+ {{#allParams}}
+ public {{{dataType}}} {{paramName}}() {
+ return {{paramName}};
+ }
+ {{/allParams}}
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ {{#requiredParams}}
+ private {{{dataType}}} {{paramName}};
+ {{/requiredParams}}
+ {{#optionalParams}}
+ private {{{dataType}}} {{paramName}};
+ {{/optionalParams}}
+
+ {{#allParams}}
+ public Builder {{paramName}}({{{dataType}}} {{paramName}}) {
+ this.{{paramName}} = {{paramName}};
+ return this;
+ }
+ {{/allParams}}
+ public API{{operationId}}Request build() {
+ return new API{{operationId}}Request(this);
+ }
+ }
+ }
+
+ {{/hasParams}}
+ {{/vendorExtensions.x-group-parameters}}
+ {{/operation}}
+}
+{{/operations}}
diff --git a/client2/src/main/template/libraries/native/pojo.mustache b/client2/src/main/template/libraries/native/pojo.mustache
new file mode 100644
index 0000000000..5dd97018f5
--- /dev/null
+++ b/client2/src/main/template/libraries/native/pojo.mustache
@@ -0,0 +1,596 @@
+{{#discriminator}}
+import {{invokerPackage}}.JSON;
+{{/discriminator}}
+/**
+ * {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}}
+ * @deprecated{{/isDeprecated}}
+ */{{#isDeprecated}}
+@Deprecated{{/isDeprecated}}
+{{#swagger1AnnotationLibrary}}
+{{#description}}
+@ApiModel(description = "{{{.}}}")
+{{/description}}
+{{/swagger1AnnotationLibrary}}
+{{#swagger2AnnotationLibrary}}
+{{#description}}
+@Schema(description = "{{{.}}}")
+{{/description}}
+{{/swagger2AnnotationLibrary}}
+{{#jackson}}
+@JsonPropertyOrder({
+{{#vars}}
+ {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}}
+{{/vars}}
+})
+{{/jackson}}
+{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}}
+{{#vendorExtensions.x-class-extra-annotation}}
+{{{vendorExtensions.x-class-extra-annotation}}}
+{{/vendorExtensions.x-class-extra-annotation}}
+public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{
+{{#serializableModel}}
+ private static final long serialVersionUID = 1L;
+
+{{/serializableModel}}
+ {{#vars}}
+ {{#isEnum}}
+ {{^isContainer}}
+ {{^vendorExtensions.x-enum-as-string}}
+{{>modelInnerEnum}}
+ {{/vendorExtensions.x-enum-as-string}}
+ {{/isContainer}}
+ {{#isContainer}}
+ {{#mostInnerItems}}
+{{>modelInnerEnum}}
+ {{/mostInnerItems}}
+ {{/isContainer}}
+ {{/isEnum}}
+ {{#gson}}
+ public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}";
+ {{/gson}}
+ {{#jackson}}
+ public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}";
+ {{/jackson}}
+ {{#withXml}}
+ {{#isXmlAttribute}}
+ @XmlAttribute(name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}")
+ {{/isXmlAttribute}}
+ {{^isXmlAttribute}}
+ {{^isContainer}}
+ @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}")
+ {{/isContainer}}
+ {{#isContainer}}
+ // Is a container wrapped={{isXmlWrapped}}
+ {{#items}}
+ // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}}
+ // items.example={{example}} items.type={{dataType}}
+ @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}")
+ {{/items}}
+ {{#isXmlWrapped}}
+ @XmlElementWrapper({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}")
+ {{/isXmlWrapped}}
+ {{/isContainer}}
+ {{/isXmlAttribute}}
+ {{/withXml}}
+ {{#gson}}
+ @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}})
+ {{/gson}}
+ {{#vendorExtensions.x-field-extra-annotation}}
+ {{{vendorExtensions.x-field-extra-annotation}}}
+ {{/vendorExtensions.x-field-extra-annotation}}
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ {{#isContainer}}
+ private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined();
+ {{/isContainer}}
+ {{^isContainer}}
+ private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}};
+ {{/isContainer}}
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+
+ {{/vars}}
+ public {{classname}}() { {{#parent}}{{#parcelableModel}}
+ super();{{/parcelableModel}}{{/parent}}{{#gson}}{{#discriminator}}
+ this.{{{discriminatorName}}} = this.getClass().getSimpleName();{{/discriminator}}{{/gson}}
+ }{{#vendorExtensions.x-has-readonly-properties}}{{^withXml}}
+
+ {{#jackson}}@JsonCreator{{/jackson}}
+ public {{classname}}(
+ {{#readOnlyVars}}
+ @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}}
+ {{/readOnlyVars}}
+ ) {
+ this();
+ {{#readOnlyVars}}
+ this.{{name}} = {{#vendorExtensions.x-is-jackson-optional-nullable}}{{name}} == null ? JsonNullable.<{{{datatypeWithEnum}}}>undefined() : JsonNullable.of({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{name}}{{/vendorExtensions.x-is-jackson-optional-nullable}};
+ {{/readOnlyVars}}
+ }{{/withXml}}{{/vendorExtensions.x-has-readonly-properties}}
+ {{#vars}}
+
+ {{^isReadOnly}}
+ {{#vendorExtensions.x-enum-as-string}}
+ public static final Set {{{nameInSnakeCase}}}_VALUES = new HashSet<>(Arrays.asList(
+ {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}
+ ));
+
+ {{/vendorExtensions.x-enum-as-string}}
+ public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) {
+ {{#vendorExtensions.x-enum-as-string}}
+ if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) {
+ throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES));
+ }
+
+ {{/vendorExtensions.x-enum-as-string}}
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ this.{{name}} = {{name}};
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ return this;
+ }
+ {{#isArray}}
+
+ public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ if (this.{{name}} == null || !this.{{name}}.isPresent()) {
+ this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}});
+ }
+ try {
+ this.{{name}}.get().add({{name}}Item);
+ } catch (java.util.NoSuchElementException e) {
+ // this can never happen, as we make sure above that the value is present
+ }
+ return this;
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ if (this.{{name}} == null) {
+ this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}};
+ }
+ this.{{name}}.add({{name}}Item);
+ return this;
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ }
+ {{/isArray}}
+ {{#isMap}}
+
+ public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) {
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ if (this.{{name}} == null || !this.{{name}}.isPresent()) {
+ this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}});
+ }
+ try {
+ this.{{name}}.get().put(key, {{name}}Item);
+ } catch (java.util.NoSuchElementException e) {
+ // this can never happen, as we make sure above that the value is present
+ }
+ return this;
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ if (this.{{name}} == null) {
+ this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}};
+ }
+ this.{{name}}.put(key, {{name}}Item);
+ return this;
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ }
+ {{/isMap}}
+
+ {{/isReadOnly}}
+ /**
+ {{#description}}
+ * {{.}}
+ {{/description}}
+ {{^description}}
+ * Get {{name}}
+ {{/description}}
+ {{#minimum}}
+ * minimum: {{.}}
+ {{/minimum}}
+ {{#maximum}}
+ * maximum: {{.}}
+ {{/maximum}}
+ * @return {{name}}
+ {{#deprecated}}
+ * @deprecated
+ {{/deprecated}}
+ **/
+{{#deprecated}}
+ @Deprecated
+{{/deprecated}}
+// {{#required}}
+// {{#isNullable}}
+// @{{javaxPackage}}.annotation.Nullable
+// {{/isNullable}}
+// {{^isNullable}}
+// @{{javaxPackage}}.annotation.Nonnull
+// {{/isNullable}}
+// {{/required}}
+// {{^required}}
+// @{{javaxPackage}}.annotation.Nullable
+// {{/required}}
+{{#useBeanValidation}}
+{{>beanValidation}}
+{{/useBeanValidation}}
+{{#swagger1AnnotationLibrary}}
+ @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
+{{/swagger1AnnotationLibrary}}
+{{#swagger2AnnotationLibrary}}
+ @Schema({{#example}}example = "{{{.}}}", {{/example}}requiredMode = {{#required}}Schema.RequiredMode.REQUIRED{{/required}}{{^required}}Schema.RequiredMode.NOT_REQUIRED{{/required}}, description = "{{{description}}}")
+{{/swagger2AnnotationLibrary}}
+{{#vendorExtensions.x-extra-annotation}}
+ {{{vendorExtensions.x-extra-annotation}}}
+{{/vendorExtensions.x-extra-annotation}}
+{{#vendorExtensions.x-is-jackson-optional-nullable}}
+ {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}}
+ @JsonIgnore
+{{/vendorExtensions.x-is-jackson-optional-nullable}}
+{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}}
+ public {{{datatypeWithEnum}}} {{getter}}() {
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}}
+ if ({{name}} == null) {
+ {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}};
+ }
+ {{/isReadOnly}}
+ return {{name}}.orElse(null);
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ return {{name}};
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ }
+
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+{{> jackson_annotations}}
+ public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() {
+ return {{name}};
+ }
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}}
+ @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}})
+ {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) {
+ {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}}
+ this.{{name}} = {{name}};
+ }
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+
+ {{^isReadOnly}}
+{{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}}
+{{/vendorExtensions.x-setter-extra-annotation}}{{#jackson}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{> jackson_annotations}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{/jackson}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) {
+ {{#vendorExtensions.x-enum-as-string}}
+ if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) {
+ throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES));
+ }
+
+ {{/vendorExtensions.x-enum-as-string}}
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ this.{{name}} = {{name}};
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ }
+ {{/isReadOnly}}
+
+ {{/vars}}
+{{>libraries/native/additional_properties}}
+ {{#parent}}
+ {{#allVars}}
+ {{#isOverridden}}
+ @Override
+ public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) {
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ this.{{setter}}(JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}));
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ this.{{setter}}({{name}});
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ return this;
+ }
+
+ {{/isOverridden}}
+ {{/allVars}}
+ {{/parent}}
+ /**
+ * Return true if this {{name}} object is equal to o.
+ */
+ @Override
+ public boolean equals(Object o) {
+ {{#useReflectionEqualsHashCode}}
+ return EqualsBuilder.reflectionEquals(this, o, false, null, true);
+ {{/useReflectionEqualsHashCode}}
+ {{^useReflectionEqualsHashCode}}
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }{{#hasVars}}
+ {{classname}} {{classVarName}} = ({{classname}}) o;
+ return {{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}equalsNullable(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}} &&
+ {{/-last}}{{/vars}}{{#additionalPropertiesType}}&&
+ Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/additionalPropertiesType}}{{#parent}} &&
+ super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}}
+ return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}}
+ {{/useReflectionEqualsHashCode}}
+ }{{#vendorExtensions.x-jackson-optional-nullable-helpers}}
+
+ private static boolean equalsNullable(JsonNullable a, JsonNullable b) {
+ return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get()));
+ }{{/vendorExtensions.x-jackson-optional-nullable-helpers}}
+
+ @Override
+ public int hashCode() {
+ {{#useReflectionEqualsHashCode}}
+ return HashCodeBuilder.reflectionHashCode(this);
+ {{/useReflectionEqualsHashCode}}
+ {{^useReflectionEqualsHashCode}}
+ return Objects.hash({{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}hashCodeNullable({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#additionalPropertiesType}}, additionalProperties{{/additionalPropertiesType}});
+ {{/useReflectionEqualsHashCode}}
+ }{{#vendorExtensions.x-jackson-optional-nullable-helpers}}
+
+ private static int hashCodeNullable(JsonNullable a) {
+ if (a == null) {
+ return 1;
+ }
+ return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31;
+ }{{/vendorExtensions.x-jackson-optional-nullable-helpers}}
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("class {{classname}} {\n");
+ {{#parent}}
+ sb.append(" ").append(toIndentedString(super.toString())).append("\n");
+ {{/parent}}
+ {{#vars}}
+ sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n");
+ {{/vars}}
+ {{#additionalPropertiesType}}
+ sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n");
+ {{/additionalPropertiesType}}
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(Object o) {
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+{{#supportUrlQuery}}
+
+ /**
+ * Convert the instance into URL query string.
+ *
+ * @return URL query string
+ */
+ public String toUrlQueryString() {
+ return toUrlQueryString(null);
+ }
+
+ /**
+ * Convert the instance into URL query string.
+ *
+ * @param prefix prefix of the query string
+ * @return URL query string
+ */
+ public String toUrlQueryString(String prefix) {
+ String suffix = "";
+ String containerSuffix = "";
+ String containerPrefix = "";
+ if (prefix == null) {
+ // style=form, explode=true, e.g. /pet?name=cat&type=manx
+ prefix = "";
+ } else {
+ // deepObject style e.g. /pet?id[name]=cat&id[type]=manx
+ prefix = prefix + "[";
+ suffix = "]";
+ containerSuffix = "]";
+ containerPrefix = "[";
+ }
+
+ StringJoiner joiner = new StringJoiner("&");
+
+ {{#allVars}}
+ // add `{{baseName}}` to the URL query string
+ {{#isArray}}
+ {{#items.isPrimitiveType}}
+ {{#uniqueItems}}
+ if ({{getter}}() != null) {
+ int i = 0;
+ for ({{{items.dataType}}} _item : {{getter}}()) {
+ joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix),
+ URLEncoder.encode(String.valueOf(_item), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
+ }
+ i++;
+ }
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ if ({{getter}}() != null) {
+ for (int i = 0; i < {{getter}}().size(); i++) {
+ joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix),
+ URLEncoder.encode(String.valueOf({{getter}}().get(i)), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
+ }
+ }
+ {{/uniqueItems}}
+ {{/items.isPrimitiveType}}
+ {{^items.isPrimitiveType}}
+ {{#items.isModel}}
+ {{#uniqueItems}}
+ if ({{getter}}() != null) {
+ int i = 0;
+ for ({{{items.dataType}}} _item : {{getter}}()) {
+ if (_item != null) {
+ joiner.add(_item.toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix))));
+ }
+ }
+ i++;
+ }
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ if ({{getter}}() != null) {
+ for (int i = 0; i < {{getter}}().size(); i++) {
+ if ({{getter}}().get(i) != null) {
+ joiner.add({{getter}}().get(i).toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix))));
+ }
+ }
+ }
+ {{/uniqueItems}}
+ {{/items.isModel}}
+ {{^items.isModel}}
+ {{#uniqueItems}}
+ if ({{getter}}() != null) {
+ int i = 0;
+ for ({{{items.dataType}}} _item : {{getter}}()) {
+ if (_item != null) {
+ joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix),
+ URLEncoder.encode(String.valueOf(_item), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
+ }
+ i++;
+ }
+ }
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ if ({{getter}}() != null) {
+ for (int i = 0; i < {{getter}}().size(); i++) {
+ if ({{getter}}().get(i) != null) {
+ joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix),
+ URLEncoder.encode(String.valueOf({{getter}}().get(i)), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
+ }
+ }
+ }
+ {{/uniqueItems}}
+ {{/items.isModel}}
+ {{/items.isPrimitiveType}}
+ {{/isArray}}
+ {{^isArray}}
+ {{#isMap}}
+ {{^items.isModel}}
+ if ({{getter}}() != null) {
+ for (String _key : {{getter}}().keySet()) {
+ joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, _key, containerSuffix),
+ {{getter}}().get(_key), URLEncoder.encode(String.valueOf({{getter}}().get(_key)), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
+ }
+ }
+ {{/items.isModel}}
+ {{#items.isModel}}
+ if ({{getter}}() != null) {
+ for (String _key : {{getter}}().keySet()) {
+ if ({{getter}}().get(_key) != null) {
+ joiner.add({{getter}}().get(_key).toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, _key, containerSuffix))));
+ }
+ }
+ }
+ {{/items.isModel}}
+ {{/isMap}}
+ {{^isMap}}
+ {{#isPrimitiveType}}
+ if ({{getter}}() != null) {
+ joiner.add(String.format("%s{{{baseName}}}%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf({{{getter}}}()), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
+ }
+ {{/isPrimitiveType}}
+ {{^isPrimitiveType}}
+ {{#isModel}}
+ if ({{getter}}() != null) {
+ joiner.add({{getter}}().toUrlQueryString(prefix + "{{{baseName}}}" + suffix));
+ }
+ {{/isModel}}
+ {{^isModel}}
+ if ({{getter}}() != null) {
+ joiner.add(String.format("%s{{{baseName}}}%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf({{{getter}}}()), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
+ }
+ {{/isModel}}
+ {{/isPrimitiveType}}
+ {{/isMap}}
+ {{/isArray}}
+
+ {{/allVars}}
+ return joiner.toString();
+ }
+{{/supportUrlQuery}}
+{{#parcelableModel}}
+
+ public void writeToParcel(Parcel out, int flags) {
+{{#model}}
+{{#isArray}}
+ out.writeList(this);
+{{/isArray}}
+{{^isArray}}
+{{#parent}}
+ super.writeToParcel(out, flags);
+{{/parent}}
+{{#vars}}
+ out.writeValue({{name}});
+{{/vars}}
+{{/isArray}}
+{{/model}}
+ }
+
+ {{classname}}(Parcel in) {
+{{#isArray}}
+ in.readTypedList(this, {{arrayModelType}}.CREATOR);
+{{/isArray}}
+{{^isArray}}
+{{#parent}}
+ super(in);
+{{/parent}}
+{{#vars}}
+{{#isPrimitiveType}}
+ {{name}} = ({{{datatypeWithEnum}}})in.readValue(null);
+{{/isPrimitiveType}}
+{{^isPrimitiveType}}
+ {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader());
+{{/isPrimitiveType}}
+{{/vars}}
+{{/isArray}}
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() {
+ public {{classname}} createFromParcel(Parcel in) {
+{{#model}}
+{{#isArray}}
+ {{classname}} result = new {{classname}}();
+ result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader()));
+ return result;
+{{/isArray}}
+{{^isArray}}
+ return new {{classname}}(in);
+{{/isArray}}
+{{/model}}
+ }
+ public {{classname}}[] newArray(int size) {
+ return new {{classname}}[size];
+ }
+ };
+{{/parcelableModel}}
+{{#discriminator}}
+static {
+ // Initialize and register the discriminator mappings.
+ Map> mappings = new HashMap>();
+ {{#mappedModels}}
+ mappings.put("{{mappingName}}", {{modelName}}.class);
+ {{/mappedModels}}
+ mappings.put("{{name}}", {{classname}}.class);
+ JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings);
+}
+{{/discriminator}}
+}
diff --git a/client2/src/main/template/libraries/native/pojo.mustache.orig b/client2/src/main/template/libraries/native/pojo.mustache.orig
new file mode 100644
index 0000000000..a0c77d53c1
--- /dev/null
+++ b/client2/src/main/template/libraries/native/pojo.mustache.orig
@@ -0,0 +1,596 @@
+{{#discriminator}}
+import {{invokerPackage}}.JSON;
+{{/discriminator}}
+/**
+ * {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}}
+ * @deprecated{{/isDeprecated}}
+ */{{#isDeprecated}}
+@Deprecated{{/isDeprecated}}
+{{#swagger1AnnotationLibrary}}
+{{#description}}
+@ApiModel(description = "{{{.}}}")
+{{/description}}
+{{/swagger1AnnotationLibrary}}
+{{#swagger2AnnotationLibrary}}
+{{#description}}
+@Schema(description = "{{{.}}}")
+{{/description}}
+{{/swagger2AnnotationLibrary}}
+{{#jackson}}
+@JsonPropertyOrder({
+{{#vars}}
+ {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}}
+{{/vars}}
+})
+{{/jackson}}
+{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}}
+{{#vendorExtensions.x-class-extra-annotation}}
+{{{vendorExtensions.x-class-extra-annotation}}}
+{{/vendorExtensions.x-class-extra-annotation}}
+public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{
+{{#serializableModel}}
+ private static final long serialVersionUID = 1L;
+
+{{/serializableModel}}
+ {{#vars}}
+ {{#isEnum}}
+ {{^isContainer}}
+ {{^vendorExtensions.x-enum-as-string}}
+{{>modelInnerEnum}}
+ {{/vendorExtensions.x-enum-as-string}}
+ {{/isContainer}}
+ {{#isContainer}}
+ {{#mostInnerItems}}
+{{>modelInnerEnum}}
+ {{/mostInnerItems}}
+ {{/isContainer}}
+ {{/isEnum}}
+ {{#gson}}
+ public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}";
+ {{/gson}}
+ {{#jackson}}
+ public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}";
+ {{/jackson}}
+ {{#withXml}}
+ {{#isXmlAttribute}}
+ @XmlAttribute(name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}")
+ {{/isXmlAttribute}}
+ {{^isXmlAttribute}}
+ {{^isContainer}}
+ @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}")
+ {{/isContainer}}
+ {{#isContainer}}
+ // Is a container wrapped={{isXmlWrapped}}
+ {{#items}}
+ // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}}
+ // items.example={{example}} items.type={{dataType}}
+ @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}")
+ {{/items}}
+ {{#isXmlWrapped}}
+ @XmlElementWrapper({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}")
+ {{/isXmlWrapped}}
+ {{/isContainer}}
+ {{/isXmlAttribute}}
+ {{/withXml}}
+ {{#gson}}
+ @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}})
+ {{/gson}}
+ {{#vendorExtensions.x-field-extra-annotation}}
+ {{{vendorExtensions.x-field-extra-annotation}}}
+ {{/vendorExtensions.x-field-extra-annotation}}
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ {{#isContainer}}
+ private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined();
+ {{/isContainer}}
+ {{^isContainer}}
+ private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}};
+ {{/isContainer}}
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+
+ {{/vars}}
+ public {{classname}}() { {{#parent}}{{#parcelableModel}}
+ super();{{/parcelableModel}}{{/parent}}{{#gson}}{{#discriminator}}
+ this.{{{discriminatorName}}} = this.getClass().getSimpleName();{{/discriminator}}{{/gson}}
+ }{{#vendorExtensions.x-has-readonly-properties}}{{^withXml}}
+
+ {{#jackson}}@JsonCreator{{/jackson}}
+ public {{classname}}(
+ {{#readOnlyVars}}
+ @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}}
+ {{/readOnlyVars}}
+ ) {
+ this();
+ {{#readOnlyVars}}
+ this.{{name}} = {{#vendorExtensions.x-is-jackson-optional-nullable}}{{name}} == null ? JsonNullable.<{{{datatypeWithEnum}}}>undefined() : JsonNullable.of({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{name}}{{/vendorExtensions.x-is-jackson-optional-nullable}};
+ {{/readOnlyVars}}
+ }{{/withXml}}{{/vendorExtensions.x-has-readonly-properties}}
+ {{#vars}}
+
+ {{^isReadOnly}}
+ {{#vendorExtensions.x-enum-as-string}}
+ public static final Set {{{nameInSnakeCase}}}_VALUES = new HashSet<>(Arrays.asList(
+ {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}
+ ));
+
+ {{/vendorExtensions.x-enum-as-string}}
+ public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) {
+ {{#vendorExtensions.x-enum-as-string}}
+ if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) {
+ throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES));
+ }
+
+ {{/vendorExtensions.x-enum-as-string}}
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ this.{{name}} = {{name}};
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ return this;
+ }
+ {{#isArray}}
+
+ public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ if (this.{{name}} == null || !this.{{name}}.isPresent()) {
+ this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}});
+ }
+ try {
+ this.{{name}}.get().add({{name}}Item);
+ } catch (java.util.NoSuchElementException e) {
+ // this can never happen, as we make sure above that the value is present
+ }
+ return this;
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ if (this.{{name}} == null) {
+ this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}};
+ }
+ this.{{name}}.add({{name}}Item);
+ return this;
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ }
+ {{/isArray}}
+ {{#isMap}}
+
+ public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) {
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ if (this.{{name}} == null || !this.{{name}}.isPresent()) {
+ this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}});
+ }
+ try {
+ this.{{name}}.get().put(key, {{name}}Item);
+ } catch (java.util.NoSuchElementException e) {
+ // this can never happen, as we make sure above that the value is present
+ }
+ return this;
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ if (this.{{name}} == null) {
+ this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}};
+ }
+ this.{{name}}.put(key, {{name}}Item);
+ return this;
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ }
+ {{/isMap}}
+
+ {{/isReadOnly}}
+ /**
+ {{#description}}
+ * {{.}}
+ {{/description}}
+ {{^description}}
+ * Get {{name}}
+ {{/description}}
+ {{#minimum}}
+ * minimum: {{.}}
+ {{/minimum}}
+ {{#maximum}}
+ * maximum: {{.}}
+ {{/maximum}}
+ * @return {{name}}
+ {{#deprecated}}
+ * @deprecated
+ {{/deprecated}}
+ **/
+{{#deprecated}}
+ @Deprecated
+{{/deprecated}}
+{{#required}}
+{{#isNullable}}
+ @{{javaxPackage}}.annotation.Nullable
+{{/isNullable}}
+{{^isNullable}}
+ @{{javaxPackage}}.annotation.Nonnull
+{{/isNullable}}
+{{/required}}
+{{^required}}
+ @{{javaxPackage}}.annotation.Nullable
+{{/required}}
+{{#useBeanValidation}}
+{{>beanValidation}}
+{{/useBeanValidation}}
+{{#swagger1AnnotationLibrary}}
+ @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
+{{/swagger1AnnotationLibrary}}
+{{#swagger2AnnotationLibrary}}
+ @Schema({{#example}}example = "{{{.}}}", {{/example}}requiredMode = {{#required}}Schema.RequiredMode.REQUIRED{{/required}}{{^required}}Schema.RequiredMode.NOT_REQUIRED{{/required}}, description = "{{{description}}}")
+{{/swagger2AnnotationLibrary}}
+{{#vendorExtensions.x-extra-annotation}}
+ {{{vendorExtensions.x-extra-annotation}}}
+{{/vendorExtensions.x-extra-annotation}}
+{{#vendorExtensions.x-is-jackson-optional-nullable}}
+ {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}}
+ @JsonIgnore
+{{/vendorExtensions.x-is-jackson-optional-nullable}}
+{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}}
+ public {{{datatypeWithEnum}}} {{getter}}() {
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}}
+ if ({{name}} == null) {
+ {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}};
+ }
+ {{/isReadOnly}}
+ return {{name}}.orElse(null);
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ return {{name}};
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ }
+
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+{{> jackson_annotations}}
+ public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() {
+ return {{name}};
+ }
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}}
+ @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}})
+ {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) {
+ {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}}
+ this.{{name}} = {{name}};
+ }
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+
+ {{^isReadOnly}}
+{{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}}
+{{/vendorExtensions.x-setter-extra-annotation}}{{#jackson}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{> jackson_annotations}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{/jackson}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) {
+ {{#vendorExtensions.x-enum-as-string}}
+ if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) {
+ throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES));
+ }
+
+ {{/vendorExtensions.x-enum-as-string}}
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ this.{{name}} = {{name}};
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ }
+ {{/isReadOnly}}
+
+ {{/vars}}
+{{>libraries/native/additional_properties}}
+ {{#parent}}
+ {{#allVars}}
+ {{#isOverridden}}
+ @Override
+ public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) {
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ this.{{setter}}(JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}));
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ this.{{setter}}({{name}});
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ return this;
+ }
+
+ {{/isOverridden}}
+ {{/allVars}}
+ {{/parent}}
+ /**
+ * Return true if this {{name}} object is equal to o.
+ */
+ @Override
+ public boolean equals(Object o) {
+ {{#useReflectionEqualsHashCode}}
+ return EqualsBuilder.reflectionEquals(this, o, false, null, true);
+ {{/useReflectionEqualsHashCode}}
+ {{^useReflectionEqualsHashCode}}
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }{{#hasVars}}
+ {{classname}} {{classVarName}} = ({{classname}}) o;
+ return {{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}equalsNullable(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}} &&
+ {{/-last}}{{/vars}}{{#additionalPropertiesType}}&&
+ Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/additionalPropertiesType}}{{#parent}} &&
+ super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}}
+ return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}}
+ {{/useReflectionEqualsHashCode}}
+ }{{#vendorExtensions.x-jackson-optional-nullable-helpers}}
+
+ private static boolean equalsNullable(JsonNullable a, JsonNullable b) {
+ return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get()));
+ }{{/vendorExtensions.x-jackson-optional-nullable-helpers}}
+
+ @Override
+ public int hashCode() {
+ {{#useReflectionEqualsHashCode}}
+ return HashCodeBuilder.reflectionHashCode(this);
+ {{/useReflectionEqualsHashCode}}
+ {{^useReflectionEqualsHashCode}}
+ return Objects.hash({{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}hashCodeNullable({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#additionalPropertiesType}}, additionalProperties{{/additionalPropertiesType}});
+ {{/useReflectionEqualsHashCode}}
+ }{{#vendorExtensions.x-jackson-optional-nullable-helpers}}
+
+ private static int hashCodeNullable(JsonNullable a) {
+ if (a == null) {
+ return 1;
+ }
+ return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31;
+ }{{/vendorExtensions.x-jackson-optional-nullable-helpers}}
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("class {{classname}} {\n");
+ {{#parent}}
+ sb.append(" ").append(toIndentedString(super.toString())).append("\n");
+ {{/parent}}
+ {{#vars}}
+ sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n");
+ {{/vars}}
+ {{#additionalPropertiesType}}
+ sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n");
+ {{/additionalPropertiesType}}
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private String toIndentedString(Object o) {
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+{{#supportUrlQuery}}
+
+ /**
+ * Convert the instance into URL query string.
+ *
+ * @return URL query string
+ */
+ public String toUrlQueryString() {
+ return toUrlQueryString(null);
+ }
+
+ /**
+ * Convert the instance into URL query string.
+ *
+ * @param prefix prefix of the query string
+ * @return URL query string
+ */
+ public String toUrlQueryString(String prefix) {
+ String suffix = "";
+ String containerSuffix = "";
+ String containerPrefix = "";
+ if (prefix == null) {
+ // style=form, explode=true, e.g. /pet?name=cat&type=manx
+ prefix = "";
+ } else {
+ // deepObject style e.g. /pet?id[name]=cat&id[type]=manx
+ prefix = prefix + "[";
+ suffix = "]";
+ containerSuffix = "]";
+ containerPrefix = "[";
+ }
+
+ StringJoiner joiner = new StringJoiner("&");
+
+ {{#allVars}}
+ // add `{{baseName}}` to the URL query string
+ {{#isArray}}
+ {{#items.isPrimitiveType}}
+ {{#uniqueItems}}
+ if ({{getter}}() != null) {
+ int i = 0;
+ for ({{{items.dataType}}} _item : {{getter}}()) {
+ joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix),
+ URLEncoder.encode(String.valueOf(_item), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
+ }
+ i++;
+ }
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ if ({{getter}}() != null) {
+ for (int i = 0; i < {{getter}}().size(); i++) {
+ joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix),
+ URLEncoder.encode(String.valueOf({{getter}}().get(i)), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
+ }
+ }
+ {{/uniqueItems}}
+ {{/items.isPrimitiveType}}
+ {{^items.isPrimitiveType}}
+ {{#items.isModel}}
+ {{#uniqueItems}}
+ if ({{getter}}() != null) {
+ int i = 0;
+ for ({{{items.dataType}}} _item : {{getter}}()) {
+ if (_item != null) {
+ joiner.add(_item.toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix))));
+ }
+ }
+ i++;
+ }
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ if ({{getter}}() != null) {
+ for (int i = 0; i < {{getter}}().size(); i++) {
+ if ({{getter}}().get(i) != null) {
+ joiner.add({{getter}}().get(i).toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix))));
+ }
+ }
+ }
+ {{/uniqueItems}}
+ {{/items.isModel}}
+ {{^items.isModel}}
+ {{#uniqueItems}}
+ if ({{getter}}() != null) {
+ int i = 0;
+ for ({{{items.dataType}}} _item : {{getter}}()) {
+ if (_item != null) {
+ joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix),
+ URLEncoder.encode(String.valueOf(_item), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
+ }
+ i++;
+ }
+ }
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ if ({{getter}}() != null) {
+ for (int i = 0; i < {{getter}}().size(); i++) {
+ if ({{getter}}().get(i) != null) {
+ joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix),
+ URLEncoder.encode(String.valueOf({{getter}}().get(i)), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
+ }
+ }
+ }
+ {{/uniqueItems}}
+ {{/items.isModel}}
+ {{/items.isPrimitiveType}}
+ {{/isArray}}
+ {{^isArray}}
+ {{#isMap}}
+ {{^items.isModel}}
+ if ({{getter}}() != null) {
+ for (String _key : {{getter}}().keySet()) {
+ joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, _key, containerSuffix),
+ {{getter}}().get(_key), URLEncoder.encode(String.valueOf({{getter}}().get(_key)), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
+ }
+ }
+ {{/items.isModel}}
+ {{#items.isModel}}
+ if ({{getter}}() != null) {
+ for (String _key : {{getter}}().keySet()) {
+ if ({{getter}}().get(_key) != null) {
+ joiner.add({{getter}}().get(_key).toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, _key, containerSuffix))));
+ }
+ }
+ }
+ {{/items.isModel}}
+ {{/isMap}}
+ {{^isMap}}
+ {{#isPrimitiveType}}
+ if ({{getter}}() != null) {
+ joiner.add(String.format("%s{{{baseName}}}%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf({{{getter}}}()), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
+ }
+ {{/isPrimitiveType}}
+ {{^isPrimitiveType}}
+ {{#isModel}}
+ if ({{getter}}() != null) {
+ joiner.add({{getter}}().toUrlQueryString(prefix + "{{{baseName}}}" + suffix));
+ }
+ {{/isModel}}
+ {{^isModel}}
+ if ({{getter}}() != null) {
+ joiner.add(String.format("%s{{{baseName}}}%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf({{{getter}}}()), StandardCharsets.UTF_8).replaceAll("\\+", "%20")));
+ }
+ {{/isModel}}
+ {{/isPrimitiveType}}
+ {{/isMap}}
+ {{/isArray}}
+
+ {{/allVars}}
+ return joiner.toString();
+ }
+{{/supportUrlQuery}}
+{{#parcelableModel}}
+
+ public void writeToParcel(Parcel out, int flags) {
+{{#model}}
+{{#isArray}}
+ out.writeList(this);
+{{/isArray}}
+{{^isArray}}
+{{#parent}}
+ super.writeToParcel(out, flags);
+{{/parent}}
+{{#vars}}
+ out.writeValue({{name}});
+{{/vars}}
+{{/isArray}}
+{{/model}}
+ }
+
+ {{classname}}(Parcel in) {
+{{#isArray}}
+ in.readTypedList(this, {{arrayModelType}}.CREATOR);
+{{/isArray}}
+{{^isArray}}
+{{#parent}}
+ super(in);
+{{/parent}}
+{{#vars}}
+{{#isPrimitiveType}}
+ {{name}} = ({{{datatypeWithEnum}}})in.readValue(null);
+{{/isPrimitiveType}}
+{{^isPrimitiveType}}
+ {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader());
+{{/isPrimitiveType}}
+{{/vars}}
+{{/isArray}}
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() {
+ public {{classname}} createFromParcel(Parcel in) {
+{{#model}}
+{{#isArray}}
+ {{classname}} result = new {{classname}}();
+ result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader()));
+ return result;
+{{/isArray}}
+{{^isArray}}
+ return new {{classname}}(in);
+{{/isArray}}
+{{/model}}
+ }
+ public {{classname}}[] newArray(int size) {
+ return new {{classname}}[size];
+ }
+ };
+{{/parcelableModel}}
+{{#discriminator}}
+static {
+ // Initialize and register the discriminator mappings.
+ Map> mappings = new HashMap>();
+ {{#mappedModels}}
+ mappings.put("{{mappingName}}", {{modelName}}.class);
+ {{/mappedModels}}
+ mappings.put("{{name}}", {{classname}}.class);
+ JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings);
+}
+{{/discriminator}}
+}
diff --git a/client2/src/test/java/com/walmartlabs/concord/client2/ApiClientJsonTest.java b/client2/src/test/java/com/walmartlabs/concord/client2/ApiClientJsonTest.java
new file mode 100644
index 0000000000..56b3afe081
--- /dev/null
+++ b/client2/src/test/java/com/walmartlabs/concord/client2/ApiClientJsonTest.java
@@ -0,0 +1,61 @@
+package com.walmartlabs.concord.client2;
+
+/*-
+ * *****
+ * Concord
+ * -----
+ * Copyright (C) 2017 - 2020 Walmart Inc.
+ * -----
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =====
+ */
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.Test;
+
+import java.text.SimpleDateFormat;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.util.Date;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class ApiClientJsonTest {
+
+ @Test
+ public void testParseDate() throws Exception {
+ ObjectMapper om = ApiClient.createDefaultObjectMapper();
+
+ Date date = new Date(1587500112000L);
+ OffsetDateTime offsetDateTime = date.toInstant().atOffset(ZoneOffset.UTC);
+
+
+ String toParse = om.writeValueAsString(offsetDateTime);
+ toParse = toParse.substring(1, toParse.length() - 1);
+
+ // format like a sever entries
+ Date parsed = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX").
+ parse(toParse);
+
+ assertEquals(date, parsed);
+ }
+
+ @Test
+ public void testObjectSerialize() throws Exception {
+ ProjectEntry project = new ProjectEntry()
+ .name("");
+
+ String str = ApiClient.createDefaultObjectMapper().writeValueAsString(project);
+ assertEquals("{\"name\":\"\"}", str);
+ }
+}
diff --git a/client2/src/test/java/com/walmartlabs/concord/client2/ProcessApiTest.java b/client2/src/test/java/com/walmartlabs/concord/client2/ProcessApiTest.java
new file mode 100644
index 0000000000..6fb4f5458e
--- /dev/null
+++ b/client2/src/test/java/com/walmartlabs/concord/client2/ProcessApiTest.java
@@ -0,0 +1,55 @@
+package com.walmartlabs.concord.client2;
+
+/*-
+ * *****
+ * Concord
+ * -----
+ * Copyright (C) 2017 - 2023 Walmart Inc.
+ * -----
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =====
+ */
+
+import com.walmartlabs.concord.client2.impl.auth.ApiKey;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import javax.xml.bind.DatatypeConverter;
+import java.util.UUID;
+
+public class ProcessApiTest {
+
+ @Test
+ @Disabled
+ public void testDecrypt() throws Exception {
+ ApiClient apiClient = new DefaultApiClientFactory("http://localhost:8001").create();
+ apiClient.setAuth(new ApiKey("cTFxMXExcTE="));
+
+ ProjectsApi projectsApi = new ProjectsApi(apiClient);
+ EncryptValueResponse encrypted = projectsApi.encrypt("org_1692633472807_3d32f7", "project_1692633472833_a1a531", "123qwe");
+
+ String encryptedValue = encrypted.getData();
+ System.out.println(">>>" + encryptedValue);
+ byte[] input;
+
+ try {
+ input = DatatypeConverter.parseBase64Binary(encryptedValue);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Invalid encrypted string value, please verify that it was specified/copied correctly: " + e.getMessage());
+ }
+
+ ProcessApi api = new ProcessApi(apiClient);
+ UUID pid = UUID.fromString("f891d797-d97e-4724-b0ba-91d48efce6d8");
+ System.out.println(">>>'" + new String(api.decryptString(pid, input)) + "'");
+ }
+}
diff --git a/client2/src/test/java/com/walmartlabs/concord/client2/SecretClientTest.java b/client2/src/test/java/com/walmartlabs/concord/client2/SecretClientTest.java
new file mode 100644
index 0000000000..cdfea2ebd0
--- /dev/null
+++ b/client2/src/test/java/com/walmartlabs/concord/client2/SecretClientTest.java
@@ -0,0 +1,68 @@
+package com.walmartlabs.concord.client2;
+
+/*-
+ * *****
+ * Concord
+ * -----
+ * Copyright (C) 2017 - 2020 Walmart Inc.
+ * -----
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =====
+ */
+
+import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
+import com.github.tomakehurst.wiremock.junit5.WireMockTest;
+import com.walmartlabs.concord.client2.impl.auth.ApiKey;
+import com.walmartlabs.concord.common.secret.BinaryDataSecret;
+import com.walmartlabs.concord.sdk.Constants;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.*;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@WireMockTest
+public class SecretClientTest {
+
+ @Test
+ public void testInvalidSecretType(WireMockRuntimeInfo wmRuntimeInfo) throws Exception {
+ String orgName = "org_" + System.currentTimeMillis();
+ String secretName = "secret_" + System.currentTimeMillis();
+
+ stubFor(post(urlEqualTo("/api/v1/org/" + orgName + "/secret/" + secretName + "/data"))
+ .willReturn(aResponse()
+ .withStatus(200)
+ .withHeader(Constants.Headers.SECRET_TYPE, SecretEntryV2.TypeEnum.DATA.name())
+ .withBody("Hello!")));
+
+ ApiClient apiClient = new DefaultApiClientFactory("http://localhost:" + wmRuntimeInfo.getHttpPort()).create();
+ SecretClient secretClient = new SecretClient(apiClient);
+
+ try {
+ secretClient.getData(orgName, secretName, null, SecretEntryV2.TypeEnum.KEY_PAIR);
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("Unexpected type of " + orgName + "/" + secretName));
+ }
+ }
+
+ @Test
+ @Disabled
+ public void testGetSecret() throws Exception {
+ ApiClient apiClient = new DefaultApiClientFactory("http://localhost:8001").create();
+ apiClient.setAuth(new ApiKey("cTFxMXExcTE"));
+ SecretClient secretClient = new SecretClient(apiClient);
+
+ BinaryDataSecret result = secretClient.getData("Default", "test", null, SecretEntryV2.TypeEnum.DATA);
+ System.out.println(">>> '" + new String(result.getData()) + "'");
+ }
+}
diff --git a/client2/src/test/java/com/walmartlabs/concord/client2/impl/MultipartRequestBodyHandlerTest.java b/client2/src/test/java/com/walmartlabs/concord/client2/impl/MultipartRequestBodyHandlerTest.java
new file mode 100644
index 0000000000..7a01c20061
--- /dev/null
+++ b/client2/src/test/java/com/walmartlabs/concord/client2/impl/MultipartRequestBodyHandlerTest.java
@@ -0,0 +1,101 @@
+package com.walmartlabs.concord.client2.impl;
+
+/*-
+ * *****
+ * Concord
+ * -----
+ * Copyright (C) 2017 - 2023 Walmart Inc.
+ * -----
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =====
+ */
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class MultipartRequestBodyHandlerTest {
+
+ @Test
+ public void test2() throws Exception {
+ Map data = new LinkedHashMap<>();
+ data.put("string-field", "this stuff");
+ data.put("byte[]-field", "byte array".getBytes());
+ data.put("inputstream-field", new ByteArrayInputStream("my input stream".getBytes()));
+ data.put("boolean-field", true);
+ data.put("json-field", Collections.singletonMap("k", "v"));
+ data.put("string[]-field", new String[] {"one", "two"});
+ data.put("uuid-field", UUID.fromString("f8d30c37-4c84-4817-9cb8-23b27a54c459"));
+
+ MultipartBuilder mpb = new MultipartBuilder("e572b648-941a-4648-97ed-0e3c5350f0ad");
+ HttpEntity entity = MultipartRequestBodyHandler.handle(mpb, new ObjectMapper(), data);
+
+ try (InputStream is = entity.getContent()) {
+ String str = new String(is.readAllBytes(), StandardCharsets.UTF_8);
+
+ assertEquals(body, str);
+ assertEquals("multipart/form-data; boundary=e572b648-941a-4648-97ed-0e3c5350f0ad", entity.contentType().toString());
+ }
+ }
+
+ private static final String body = "--e572b648-941a-4648-97ed-0e3c5350f0ad\r\n" +
+ "Content-Disposition: form-data; name=\"string-field\"\r\n" +
+ "Content-Length: 10\r\n" +
+ "\r\n" +
+ "this stuff\r\n" +
+ "--e572b648-941a-4648-97ed-0e3c5350f0ad\r\n" +
+ "Content-Disposition: form-data; name=\"byte[]-field\"\r\n" +
+ "Content-Type: application/octet-stream\r\n" +
+ "Content-Length: 10\r\n" +
+ "\r\n" +
+ "byte array\r\n" +
+ "--e572b648-941a-4648-97ed-0e3c5350f0ad\r\n" +
+ "Content-Disposition: form-data; name=\"inputstream-field\"\r\n" +
+ "Content-Type: application/octet-stream\r\n" +
+ "\r\n" +
+ "my input stream\r\n" +
+ "--e572b648-941a-4648-97ed-0e3c5350f0ad\r\n" +
+ "Content-Disposition: form-data; name=\"boolean-field\"\r\n" +
+ "Content-Type: text/plain; charset=utf-8\r\n" +
+ "Content-Length: 4\r\n" +
+ "\r\n" +
+ "true\r\n" +
+ "--e572b648-941a-4648-97ed-0e3c5350f0ad\r\n" +
+ "Content-Disposition: form-data; name=\"json-field\"\r\n" +
+ "Content-Type: application/json; charset=utf-8\r\n" +
+ "Content-Length: 9\r\n" +
+ "\r\n" +
+ "{\"k\":\"v\"}\r\n" +
+ "--e572b648-941a-4648-97ed-0e3c5350f0ad\r\n" +
+ "Content-Disposition: form-data; name=\"string[]-field\"\r\n" +
+ "Content-Type: text/plain; charset=utf-8\r\n" +
+ "Content-Length: 7\r\n" +
+ "\r\n" +
+ "one,two\r\n" +
+ "--e572b648-941a-4648-97ed-0e3c5350f0ad\r\n" +
+ "Content-Disposition: form-data; name=\"uuid-field\"\r\n" +
+ "Content-Length: 36\r\n" +
+ "\r\n" +
+ "f8d30c37-4c84-4817-9cb8-23b27a54c459\r\n" +
+ "--e572b648-941a-4648-97ed-0e3c5350f0ad--" +
+ "\r\n";
+}
diff --git a/common/pom.xml b/common/pom.xml
index d787956fd8..d3800d275d 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -6,7 +6,7 @@
com.walmartlabs.concord
parent
- 2.0.1-SNAPSHOT
+ 2.1.1-SNAPSHOT
../pom.xml
diff --git a/common/src/main/java/com/walmartlabs/concord/common/IOUtils.java b/common/src/main/java/com/walmartlabs/concord/common/IOUtils.java
index 8263e084a8..d54a350b0f 100644
--- a/common/src/main/java/com/walmartlabs/concord/common/IOUtils.java
+++ b/common/src/main/java/com/walmartlabs/concord/common/IOUtils.java
@@ -150,6 +150,13 @@ public static void unzip(Path in, Path targetDir, boolean skipExisting, CopyOpti
unzip(in, targetDir, skipExisting, null, options);
}
+ public static void unzip(InputStream in, Path targetDir, boolean skipExisting, FileVisitor visitor, CopyOption... options) throws IOException {
+ try (TemporaryPath tmpZip = new TemporaryPath(IOUtils.createTempFile("unzip", "zip"))) {
+ Files.copy(in, tmpZip.path(), StandardCopyOption.REPLACE_EXISTING);
+ IOUtils.unzip(tmpZip.path(), targetDir, skipExisting, visitor, options);
+ }
+ }
+
public static void unzip(Path in, Path targetDir, boolean skipExisting, FileVisitor visitor, CopyOption... options) throws IOException {
targetDir = targetDir.normalize().toAbsolutePath();
diff --git a/console2/pom.xml b/console2/pom.xml
index 6b29604e50..3df2f8be18 100644
--- a/console2/pom.xml
+++ b/console2/pom.xml
@@ -5,7 +5,7 @@
com.walmartlabs.concord
parent
- 2.0.1-SNAPSHOT
+ 2.1.1-SNAPSHOT
../pom.xml
diff --git a/console2/src/components/molecules/ProcessStatusTable/index.tsx b/console2/src/components/molecules/ProcessStatusTable/index.tsx
index 7243498a4d..050523866e 100644
--- a/console2/src/components/molecules/ProcessStatusTable/index.tsx
+++ b/console2/src/components/molecules/ProcessStatusTable/index.tsx
@@ -48,13 +48,13 @@ const kindToDescription = (k: ProcessKind): string => {
class ProcessStatusTable extends React.PureComponent {
static renderCommitId(process?: ProcessEntry) {
- if (!process || !process.commitId) {
+ if (!process || !process.commitId || !process.repoUrl) {
return ' - ';
}
return (
@@ -217,7 +217,7 @@ class ProcessStatusTable extends React.PureComponent {
}
static renderRepoPath(process?: ProcessEntry) {
- if (!process || !process.commitId) {
+ if (!process || !process.commitId || !process.repoUrl) {
return '-';
}
diff --git a/console2/src/components/organisms/NewSecretActivity/index.tsx b/console2/src/components/organisms/NewSecretActivity/index.tsx
index 47103ec711..9b5a487907 100644
--- a/console2/src/components/organisms/NewSecretActivity/index.tsx
+++ b/console2/src/components/organisms/NewSecretActivity/index.tsx
@@ -18,88 +18,69 @@
* =====
*/
-import * as copyToClipboard from 'copy-to-clipboard';
+import copyToClipboard from 'copy-to-clipboard';
import * as React from 'react';
-import { connect } from 'react-redux';
-import { AnyAction, Dispatch } from 'redux';
-import { push as pushHistory } from 'connected-react-router';
-import { Button, Message, Modal, TextArea } from 'semantic-ui-react';
+import {Button, Message, TextArea} from 'semantic-ui-react';
-import { ConcordKey, RequestError } from '../../../api/common';
+import {ConcordKey} from '../../../api/common';
import {
- NewSecretEntry,
SecretStoreType,
SecretTypeExt,
SecretVisibility
} from '../../../api/org/secret';
-import { validatePassword } from '../../../api/service/console';
-import { actions, State } from '../../../state/data/secrets';
-import { CreateSecretResponse } from '../../../state/data/secrets';
-import { passwordTooWeakError } from '../../../validation';
-import { NewSecretForm, NewSecretFormValues, RequestErrorMessage } from '../../molecules';
+import {CreateSecretResponse} from '../../../state/data/secrets';
+import {
+ NewSecretFormValues
+} from '../../molecules';
import './styles.css';
-import { RequestErrorActivity } from '../index';
-
-interface OwnState {
- showPasswordConfirm: boolean;
- currentEntry?: NewSecretEntry;
-}
+import {RequestErrorActivity} from '../index';
+import NewSecretForm from '../../molecules/NewSecretForm';
+import {LoadingDispatch} from "../../../App";
+import {useCallback, useState} from "react";
+import {create as apiCreate} from "../../../api/org/secret";
+import {useApi} from "../../../hooks/useApi";
+import {useHistory} from "react-router";
interface ExternalProps {
orgName: ConcordKey;
}
-interface StateProps {
- submitting: boolean;
- error: RequestError;
- response?: CreateSecretResponse;
+const INIT_VALUES: NewSecretFormValues = {
+ name: '',
+ visibility: SecretVisibility.PRIVATE,
+ type: SecretTypeExt.NEW_KEY_PAIR,
+ storeType: SecretStoreType.CONCORD
}
-interface DispatchProps {
- submit: (values: NewSecretFormValues) => void;
- reset: () => void;
- done: (secretName: ConcordKey) => void;
-}
+const NewSecretActivity = (props: ExternalProps) => {
+ const history = useHistory();
-type Props = ExternalProps & StateProps & DispatchProps;
+ const {orgName} = props;
-class NewSecretActivity extends React.Component {
- constructor(props: Props) {
- super(props);
- this.state = { showPasswordConfirm: false };
- }
-
- componentDidMount() {
- this.props.reset();
- }
-
- async handleSubmit(entry: NewSecretEntry, confirm?: boolean) {
- if (confirm) {
- this.setState({ showPasswordConfirm: false });
- } else if (entry.type === SecretTypeExt.USERNAME_PASSWORD && entry.password) {
- const valid = await validatePassword(entry.password);
- if (!valid) {
- this.setState({ showPasswordConfirm: true, currentEntry: entry });
- return;
- }
- }
-
- this.props.submit(entry);
- }
+ const dispatch = React.useContext(LoadingDispatch);
+ const [values, setValues] = useState(INIT_VALUES);
- renderResponse() {
- const { response, done, error } = this.props;
+ const postQuery = useCallback(() => {
+ return apiCreate(orgName, values);
+ }, [orgName, values]);
- if (!response) {
- return;
- }
+ const {error, isLoading, data, fetch} = useApi(postQuery, {
+ fetchOnMount: false,
+ requestByFetch: true,
+ dispatch: dispatch
+ });
- if (error) {
- return ;
- }
+ const handleSubmit = useCallback(
+ (values: NewSecretFormValues) => {
+ setValues(values);
+ fetch();
+ },
+ [fetch]
+ );
- const { name: secretName, publicKey, password } = response;
+ if (data) {
+ const {publicKey, password} = data;
return (
<>
@@ -115,7 +96,7 @@ class NewSecretActivity extends React.Component {
basic={true}
onClick={() => (copyToClipboard as any)(publicKey)}
/>
-
+