github.com/phrase/openapi@v0.0.0-20240514140800-49e8a106740e/openapi-generator/templates/java/libraries/native/ApiClient.mustache (about)

     1  {{>licenseInfo}}
     2  package {{invokerPackage}};
     3  
     4  import com.fasterxml.jackson.annotation.JsonInclude;
     5  import com.fasterxml.jackson.databind.DeserializationFeature;
     6  import com.fasterxml.jackson.databind.ObjectMapper;
     7  import com.fasterxml.jackson.databind.SerializationFeature;
     8  import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
     9  import org.openapitools.jackson.nullable.JsonNullableModule;
    10  
    11  import java.io.InputStream;
    12  import java.net.URI;
    13  import java.net.URLEncoder;
    14  import java.net.http.HttpClient;
    15  import java.net.http.HttpRequest;
    16  import java.net.http.HttpResponse;
    17  import java.nio.charset.Charset;
    18  import java.time.Duration;
    19  import java.util.Collection;
    20  import java.util.Collections;
    21  import java.util.List;
    22  import java.util.StringJoiner;
    23  import java.util.function.Consumer;
    24  import java.util.stream.Collectors;
    25  
    26  /**
    27   * Configuration and utility class for API clients.
    28   *
    29   * <p>This class can be constructed and modified, then used to instantiate the
    30   * various API classes. The API classes use the settings in this class to
    31   * configure themselves, but otherwise do not store a link to this class.</p>
    32   *
    33   * <p>This class is mutable and not synchronized, so it is not thread-safe.
    34   * The API classes generated from this are immutable and thread-safe.</p>
    35   *
    36   * <p>The setter methods of this class return the current object to facilitate
    37   * a fluent style of configuration.</p>
    38   */
    39  {{>generatedAnnotation}}
    40  public class ApiClient {
    41  
    42    private static final Charset UTF_8 = Charset.forName("UTF-8");
    43  
    44    private HttpClient.Builder builder;
    45    private ObjectMapper mapper;
    46    private String scheme;
    47    private String host;
    48    private int port;
    49    private String basePath;
    50    private Consumer<HttpRequest.Builder> interceptor;
    51    private Consumer<HttpResponse<InputStream>> responseInterceptor;
    52    private Duration readTimeout;
    53  
    54    private static String valueToString(Object value) {
    55      if (value == null) {
    56        return "";
    57      }
    58      return value.toString();
    59    }
    60  
    61    /**
    62     * URL encode a string in the UTF-8 encoding.
    63     *
    64     * @param s String to encode.
    65     * @return URL-encoded representation of the input string.
    66     */
    67    public static String urlEncode(String s) {
    68      return URLEncoder.encode(s, UTF_8);
    69    }
    70  
    71    /**
    72     * Convert a URL query name/value parameter to a list of encoded {@link Pair}
    73     * objects.
    74     *
    75     * <p>The value can be null, in which case an empty list is returned.</p>
    76     *
    77     * @param name The query name parameter.
    78     * @param value The query value, which may not be a collection but may be
    79     *              null.
    80     * @return A singleton list of the {@link Pair} objects representing the input
    81     * parameters, which is encoded for use in a URL. If the value is null, an
    82     * empty list is returned.
    83     */
    84    public static List<Pair> parameterToPairs(String name, Object value) {
    85      if (name == null || name.isEmpty() || value == null) {
    86        return Collections.emptyList();
    87      }
    88      return Collections.singletonList(new Pair(urlEncode(name), urlEncode(value.toString())));
    89    }
    90  
    91    /**
    92     * Convert a URL query name/collection parameter to a list of encoded
    93     * {@link Pair} objects.
    94     *
    95     * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc).
    96     * @param name The query name parameter.
    97     * @param values A collection of values for the given query name, which may be
    98     *               null.
    99     * @return A list of {@link Pair} objects representing the input parameters,
   100     * which is encoded for use in a URL. If the values collection is null, an
   101     * empty list is returned.
   102     */
   103    public static List<Pair> parameterToPairs(
   104        String collectionFormat, String name, Collection<?> values) {
   105      if (name == null || name.isEmpty() || values == null || values.isEmpty()) {
   106        return Collections.emptyList();
   107      }
   108  
   109      // get the collection format (default: csv)
   110      String format = collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat;
   111  
   112      // create the params based on the collection format
   113      if ("multi".equals(format)) {
   114        return values.stream()
   115            .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value))))
   116            .collect(Collectors.toList());
   117      }
   118  
   119      String delimiter;
   120      switch(format) {
   121        case "csv":
   122          delimiter = urlEncode(",");
   123          break;
   124        case "ssv":
   125          delimiter = urlEncode(" ");
   126          break;
   127        case "tsv":
   128          delimiter = urlEncode("\t");
   129          break;
   130        case "pipes":
   131          delimiter = urlEncode("|");
   132          break;
   133        default:
   134          throw new IllegalArgumentException("Illegal collection format: " + collectionFormat);
   135      }
   136  
   137      StringJoiner joiner = new StringJoiner(delimiter);
   138      for (Object value : values) {
   139        joiner.add(urlEncode(valueToString(value)));
   140      }
   141  
   142      return Collections.singletonList(new Pair(urlEncode(name), joiner.toString()));
   143    }
   144  
   145    /**
   146     * Ctor.
   147     */
   148    public ApiClient() {
   149      builder = HttpClient.newBuilder();
   150      mapper = new ObjectMapper();
   151      mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
   152      mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
   153      mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
   154      mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
   155      mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
   156      mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
   157      mapper.registerModule(new JavaTimeModule());
   158      JsonNullableModule jnm = new JsonNullableModule();
   159      mapper.registerModule(jnm);
   160      URI baseURI = URI.create("{{{basePath}}}");
   161      scheme = baseURI.getScheme();
   162      host = baseURI.getHost();
   163      port = baseURI.getPort();
   164      basePath = baseURI.getRawPath();
   165      interceptor = null;
   166      readTimeout = null;
   167      responseInterceptor = null;
   168    }
   169  
   170    /**
   171     * Set a custom {@link HttpClient.Builder} object to use when creating the
   172     * {@link HttpClient} that is used by the API client.
   173     *
   174     * @param builder Custom client builder.
   175     * @return This object.
   176     */
   177    public ApiClient setHttpClientBuilder(HttpClient.Builder builder) {
   178      this.builder = builder;
   179      return this;
   180    }
   181  
   182    /**
   183     * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}.
   184     *
   185     * <p>The returned object is immutable and thread-safe.</p>
   186     *
   187     * @return The HTTP client.
   188     */
   189    public HttpClient getHttpClient() {
   190      return builder.build();
   191    }
   192  
   193    /**
   194     * Set a custom {@link ObjectMapper} to serialize and deserialize the request
   195     * and response bodies.
   196     *
   197     * @param mapper Custom object mapper.
   198     * @return This object.
   199     */
   200    public ApiClient setObjectMapper(ObjectMapper mapper) {
   201      this.mapper = mapper;
   202      return this;
   203    }
   204  
   205    /**
   206     * Get a copy of the current {@link ObjectMapper}.
   207     *
   208     * @return A copy of the current object mapper.
   209     */
   210    public ObjectMapper getObjectMapper() {
   211      return mapper.copy();
   212    }
   213  
   214    /**
   215     * Set a custom host name for the target service.
   216     *
   217     * @param host The host name of the target service.
   218     * @return This object.
   219     */
   220    public ApiClient setHost(String host) {
   221      this.host = host;
   222      return this;
   223    }
   224  
   225    /**
   226     * Set a custom port number for the target service.
   227     *
   228     * @param port The port of the target service. Set this to -1 to reset the
   229     *             value to the default for the scheme.
   230     * @return This object.
   231     */
   232    public ApiClient setPort(int port) {
   233      this.port = port;
   234      return this;
   235    }
   236  
   237    /**
   238     * Set a custom base path for the target service, for example '/v2'.
   239     *
   240     * @param basePath The base path against which the rest of the path is
   241     *                 resolved.
   242     * @return This object.
   243     */
   244    public ApiClient setBasePath(String basePath) {
   245      this.basePath = basePath;
   246      return this;
   247    }
   248  
   249    /**
   250     * Get the base URI to resolve the endpoint paths against.
   251     *
   252     * @return The complete base URI that the rest of the API parameters are
   253     * resolved against.
   254     */
   255    public String getBaseUri() {
   256      return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath;
   257    }
   258  
   259    /**
   260     * Set a custom scheme for the target service, for example 'https'.
   261     *
   262     * @param scheme The scheme of the target service
   263     * @return This object.
   264     */
   265    public ApiClient setScheme(String scheme){
   266      this.scheme = scheme;
   267      return this;
   268    }
   269  
   270    /**
   271     * Set a custom request interceptor.
   272     *
   273     * <p>A request interceptor is a mechanism for altering each request before it
   274     * is sent. After the request has been fully configured but not yet built, the
   275     * request builder is passed into this function for further modification,
   276     * after which it is sent out.</p>
   277     *
   278     * <p>This is useful for altering the requests in a custom manner, such as
   279     * adding headers. It could also be used for logging and monitoring.</p>
   280     *
   281     * @param interceptor A function invoked before creating each request. A value
   282     *                    of null resets the interceptor to a no-op.
   283     * @return This object.
   284     */
   285    public ApiClient setRequestInterceptor(Consumer<HttpRequest.Builder> interceptor) {
   286      this.interceptor = interceptor;
   287      return this;
   288    }
   289  
   290    /**
   291     * Get the custom interceptor.
   292     *
   293     * @return The custom interceptor that was set, or null if there isn't any.
   294     */
   295    public Consumer<HttpRequest.Builder> getRequestInterceptor() {
   296      return interceptor;
   297    }
   298  
   299    /**
   300     * Set a custom response interceptor.
   301     *
   302     * <p>This is useful for logging, monitoring or extraction of header variables</p>
   303     *
   304     * @param interceptor A function invoked before creating each request. A value
   305     *                    of null resets the interceptor to a no-op.
   306     * @return This object.
   307     */
   308    public ApiClient setResponseInterceptor(Consumer<HttpResponse<InputStream>> interceptor) {
   309      this.responseInterceptor = interceptor;
   310      return this;
   311    }
   312  
   313   /**
   314     * Get the custom response interceptor.
   315     *
   316     * @return The custom interceptor that was set, or null if there isn't any.
   317     */
   318    public Consumer<HttpResponse<InputStream>> getResponseInterceptor() {
   319      return responseInterceptor;
   320    }
   321  
   322    /**
   323     * Set the read timeout for the http client.
   324     *
   325     * <p>This is the value used by default for each request, though it can be
   326     * overridden on a per-request basis with a request interceptor.</p>
   327     *
   328     * @param readTimeout The read timeout used by default by the http client.
   329     *                    Setting this value to null resets the timeout to an
   330     *                    effectively infinite value.
   331     * @return This object.
   332     */
   333    public ApiClient setReadTimeout(Duration readTimeout) {
   334      this.readTimeout = readTimeout;
   335      return this;
   336    }
   337    
   338    /**
   339     * Get the read timeout that was set.
   340     *
   341     * @return The read timeout, or null if no timeout was set. Null represents
   342     * an infinite wait time.
   343     */
   344    public Duration getReadTimeout() {
   345      return readTimeout;
   346    }
   347  }