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

     1  {{>licenseInfo}}
     2  package {{invokerPackage}};
     3  
     4  {{#threetenbp}}
     5  import org.threeten.bp.*;
     6  
     7  {{/threetenbp}}
     8  import com.fasterxml.jackson.annotation.*;
     9  import com.fasterxml.jackson.databind.*;
    10  {{#joda}}
    11  import com.fasterxml.jackson.datatype.joda.JodaModule;
    12  {{/joda}}
    13  {{#java8}}
    14  import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
    15  {{/java8}}
    16  {{#threetenbp}}
    17  import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule;
    18  {{/threetenbp}}
    19  import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
    20  
    21  import com.sun.jersey.api.client.Client;
    22  import com.sun.jersey.api.client.ClientResponse;
    23  import com.sun.jersey.api.client.GenericType;
    24  import com.sun.jersey.api.client.config.DefaultClientConfig;
    25  import com.sun.jersey.api.client.filter.GZIPContentEncodingFilter;
    26  import com.sun.jersey.api.client.filter.LoggingFilter;
    27  import com.sun.jersey.api.client.WebResource.Builder;
    28  
    29  import com.sun.jersey.multipart.FormDataMultiPart;
    30  import com.sun.jersey.multipart.file.FileDataBodyPart;
    31  
    32  import javax.ws.rs.core.Cookie;
    33  import javax.ws.rs.core.Response.Status.Family;
    34  import javax.ws.rs.core.MediaType;
    35  
    36  import java.util.Collection;
    37  import java.util.Collections;
    38  import java.util.Map;
    39  import java.util.Map.Entry;
    40  import java.util.HashMap;
    41  import java.util.HashSet;
    42  import java.util.List;
    43  import java.util.Arrays;
    44  import java.util.ArrayList;
    45  import java.util.Date;
    46  import java.util.TimeZone;
    47  
    48  import java.net.URLEncoder;
    49  
    50  import java.io.File;
    51  import java.io.UnsupportedEncodingException;
    52  
    53  import java.text.DateFormat;
    54  
    55  import {{invokerPackage}}.auth.Authentication;
    56  import {{invokerPackage}}.auth.HttpBasicAuth;
    57  import {{invokerPackage}}.auth.HttpBearerAuth;
    58  import {{invokerPackage}}.auth.ApiKeyAuth;
    59  {{#hasOAuthMethods}}
    60  import {{invokerPackage}}.auth.OAuth;
    61  {{/hasOAuthMethods}}
    62  
    63  {{>generatedAnnotation}}
    64  public class ApiClient {
    65    private Map<String, String> defaultHeaderMap = new HashMap<String, String>();
    66    private Map<String, String> defaultCookieMap = new HashMap<String, String>();
    67    private String basePath = "{{{basePath}}}";
    68    protected List<ServerConfiguration> servers = new ArrayList<ServerConfiguration>({{#servers}}{{#-first}}Arrays.asList(
    69  {{/-first}}    new ServerConfiguration(
    70        "{{{url}}}",
    71        "{{{description}}}{{^description}}No description provided{{/description}}",
    72        new HashMap<String, ServerVariable>(){{#variables}}{{#-first}} {{
    73  {{/-first}}        put("{{{name}}}", new ServerVariable(
    74            "{{{description}}}{{^description}}No description provided{{/description}}",
    75            "{{{defaultValue}}}",
    76            new HashSet<String>(
    77            {{#enumValues}}
    78            {{#-first}}
    79              Arrays.asList(
    80            {{/-first}}
    81                "{{{.}}}"{{^-last}},{{/-last}}
    82            {{#-last}}
    83              )
    84            {{/-last}}
    85            {{/enumValues}}
    86            )
    87          ));
    88        {{#-last}}
    89        }}{{/-last}}{{/variables}}
    90      ){{^-last}},{{/-last}}
    91    {{#-last}}
    92    ){{/-last}}{{/servers}});
    93    protected Integer serverIndex = 0;
    94    protected Map<String, String> serverVariables = null;
    95    private boolean debugging = false;
    96    private int connectionTimeout = 0;
    97  
    98    private Client httpClient;
    99    private ObjectMapper objectMapper;
   100  
   101    private Map<String, Authentication> authentications;
   102  
   103    private int statusCode;
   104    private Map<String, List<String>> responseHeaders;
   105  
   106    private DateFormat dateFormat;
   107  
   108    public ApiClient() {
   109      objectMapper = new ObjectMapper();
   110      objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
   111      objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
   112      objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
   113      objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
   114      objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
   115      objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
   116      {{#joda}}
   117      objectMapper.registerModule(new JodaModule());
   118      {{/joda}}
   119      {{#java8}}
   120      objectMapper.registerModule(new JavaTimeModule());
   121      {{/java8}}
   122      {{#threetenbp}}
   123      ThreeTenModule module = new ThreeTenModule();
   124      module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT);
   125      module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME);
   126      module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME);
   127      objectMapper.registerModule(module);
   128      {{/threetenbp}}
   129      objectMapper.setDateFormat(ApiClient.buildDefaultDateFormat());
   130  
   131      dateFormat = ApiClient.buildDefaultDateFormat();
   132  
   133      // Set default User-Agent.
   134      setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}");
   135  
   136      // Setup authentications (key: authentication name, value: authentication).
   137      authentications = new HashMap<String, Authentication>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}}
   138      authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}}
   139      authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}}
   140      authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}}
   141      authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}}
   142      // Prevent the authentications from being modified.
   143      authentications = Collections.unmodifiableMap(authentications);
   144  
   145      rebuildHttpClient();
   146    }
   147  
   148    public static DateFormat buildDefaultDateFormat() {
   149      return new RFC3339DateFormat();
   150    }
   151  
   152    /**
   153     * Build the Client used to make HTTP requests with the latest settings,
   154     * i.e. objectMapper and debugging.
   155     * TODO: better to use the Builder Pattern?
   156     * @return API client
   157     */
   158    public ApiClient rebuildHttpClient() {
   159      // Add the JSON serialization support to Jersey
   160      JacksonJsonProvider jsonProvider = new JacksonJsonProvider(objectMapper);
   161      DefaultClientConfig conf = new DefaultClientConfig();
   162      conf.getSingletons().add(jsonProvider);
   163      Client client = Client.create(conf);
   164      client.addFilter(new GZIPContentEncodingFilter({{#useGzipFeature}}true{{/useGzipFeature}}{{^useGzipFeature}}false{{/useGzipFeature}}));
   165      if (debugging) {
   166        client.addFilter(new LoggingFilter());
   167      }
   168      this.httpClient = client;
   169      return this;
   170    }
   171  
   172    /**
   173     * Returns the current object mapper used for JSON serialization/deserialization.
   174     * <p>
   175     * Note: If you make changes to the object mapper, remember to set it back via
   176     * <code>setObjectMapper</code> in order to trigger HTTP client rebuilding.
   177     * </p>
   178     * @return Object mapper
   179     */
   180    public ObjectMapper getObjectMapper() {
   181      return objectMapper;
   182    }
   183  
   184    public ApiClient setObjectMapper(ObjectMapper objectMapper) {
   185      this.objectMapper = objectMapper;
   186      // Need to rebuild the Client as it depends on object mapper.
   187      rebuildHttpClient();
   188      return this;
   189    }
   190  
   191    public Client getHttpClient() {
   192      return httpClient;
   193    }
   194  
   195    public ApiClient setHttpClient(Client httpClient) {
   196      this.httpClient = httpClient;
   197      return this;
   198    }
   199  
   200    public String getBasePath() {
   201      return basePath;
   202    }
   203  
   204    public ApiClient setBasePath(String basePath) {
   205      this.basePath = basePath;
   206      return this;
   207    }
   208  
   209    public List<ServerConfiguration> getServers() {
   210      return servers;
   211    }
   212  
   213    public ApiClient setServers(List<ServerConfiguration> servers) {
   214      this.servers = servers;
   215      return this;
   216    }
   217  
   218    public Integer getServerIndex() {
   219      return serverIndex;
   220    }
   221  
   222    public ApiClient setServerIndex(Integer serverIndex) {
   223      this.serverIndex = serverIndex;
   224      return this;
   225    }
   226  
   227    public Map<String, String> getServerVariables() {
   228      return serverVariables;
   229    }
   230  
   231    public ApiClient setServerVariables(Map<String, String> serverVariables) {
   232      this.serverVariables = serverVariables;
   233      return this;
   234    }
   235  
   236    /**
   237     * Gets the status code of the previous request
   238     * @return Status code
   239     */
   240    public int getStatusCode() {
   241      return statusCode;
   242    }
   243  
   244    /**
   245     * Gets the response headers of the previous request
   246     * @return Response headers
   247     */
   248    public Map<String, List<String>> getResponseHeaders() {
   249      return responseHeaders;
   250    }
   251  
   252    /**
   253     * Get authentications (key: authentication name, value: authentication).
   254     * @return Map of authentication
   255     */
   256    public Map<String, Authentication> getAuthentications() {
   257      return authentications;
   258    }
   259  
   260    /**
   261     * Get authentication for the given name.
   262     *
   263     * @param authName The authentication name
   264     * @return The authentication, null if not found
   265     */
   266    public Authentication getAuthentication(String authName) {
   267      return authentications.get(authName);
   268    }
   269  
   270    /**
   271     * Helper method to set username for the first HTTP basic authentication.
   272     * @param username Username
   273     */
   274    public void setUsername(String username) {
   275      for (Authentication auth : authentications.values()) {
   276        if (auth instanceof HttpBasicAuth) {
   277          ((HttpBasicAuth) auth).setUsername(username);
   278          return;
   279        }
   280      }
   281      throw new RuntimeException("No HTTP basic authentication configured!");
   282    }
   283  
   284    /**
   285     * Helper method to set password for the first HTTP basic authentication.
   286     * @param password Password
   287     */
   288    public void setPassword(String password) {
   289      for (Authentication auth : authentications.values()) {
   290        if (auth instanceof HttpBasicAuth) {
   291          ((HttpBasicAuth) auth).setPassword(password);
   292          return;
   293        }
   294      }
   295      throw new RuntimeException("No HTTP basic authentication configured!");
   296    }
   297  
   298    /**
   299     * Helper method to set API key value for the first API key authentication.
   300     * @param apiKey the API key
   301     */
   302    public void setApiKey(String apiKey) {
   303      for (Authentication auth : authentications.values()) {
   304        if (auth instanceof ApiKeyAuth) {
   305          ((ApiKeyAuth) auth).setApiKey(apiKey);
   306          return;
   307        }
   308      }
   309      throw new RuntimeException("No API key authentication configured!");
   310    }
   311  
   312    /**
   313     * Helper method to set API key prefix for the first API key authentication.
   314     * @param apiKeyPrefix API key prefix
   315     */
   316    public void setApiKeyPrefix(String apiKeyPrefix) {
   317      for (Authentication auth : authentications.values()) {
   318        if (auth instanceof ApiKeyAuth) {
   319          ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix);
   320          return;
   321        }
   322      }
   323      throw new RuntimeException("No API key authentication configured!");
   324    }
   325  
   326    {{#hasOAuthMethods}}
   327    /**
   328     * Helper method to set access token for the first OAuth2 authentication.
   329     * @param accessToken Access token
   330     */
   331    public void setAccessToken(String accessToken) {
   332      for (Authentication auth : authentications.values()) {
   333        if (auth instanceof OAuth) {
   334          ((OAuth) auth).setAccessToken(accessToken);
   335          return;
   336        }
   337      }
   338      throw new RuntimeException("No OAuth2 authentication configured!");
   339    }
   340  
   341    {{/hasOAuthMethods}}
   342  
   343    /**
   344     * Helper method to set access token for the first Bearer authentication.
   345     * @param bearerToken Bearer token
   346     */
   347    public void setBearerToken(String bearerToken) {
   348      for (Authentication auth : authentications.values()) {
   349        if (auth instanceof HttpBearerAuth) {
   350          ((HttpBearerAuth) auth).setBearerToken(bearerToken);
   351          return;
   352        }
   353      }
   354      throw new RuntimeException("No Bearer authentication configured!");
   355    }
   356  
   357    /**
   358     * Set the User-Agent header's value (by adding to the default header map).
   359     * @param userAgent User agent
   360     * @return API client
   361     */
   362    public ApiClient setUserAgent(String userAgent) {
   363      addDefaultHeader("User-Agent", userAgent);
   364      return this;
   365    }
   366  
   367    /**
   368     * Add a default header.
   369     *
   370     * @param key The header's key
   371     * @param value The header's value
   372     * @return API client
   373     */
   374    public ApiClient addDefaultHeader(String key, String value) {
   375      defaultHeaderMap.put(key, value);
   376      return this;
   377    }
   378  
   379    /**
   380     * Add a default cookie.
   381     *
   382     * @param key The cookie's key
   383     * @param value The cookie's value
   384     * @return API client
   385     */
   386    public ApiClient addDefaultCookie(String key, String value) {
   387      defaultCookieMap.put(key, value);
   388      return this;
   389    }
   390  
   391    /**
   392     * Check that whether debugging is enabled for this API client.
   393     * @return True if debugging is on
   394     */
   395    public boolean isDebugging() {
   396      return debugging;
   397    }
   398  
   399    /**
   400     * Enable/disable debugging for this API client.
   401     *
   402     * @param debugging To enable (true) or disable (false) debugging
   403     * @return API client
   404     */
   405    public ApiClient setDebugging(boolean debugging) {
   406      this.debugging = debugging;
   407      // Need to rebuild the Client as it depends on the value of debugging.
   408      rebuildHttpClient();
   409      return this;
   410    }
   411  
   412    /**
   413     * Connect timeout (in milliseconds).
   414     * @return Connection timeout
   415     */
   416    public int getConnectTimeout() {
   417      return connectionTimeout;
   418    }
   419  
   420    /**
   421     * Set the connect timeout (in milliseconds).
   422     * A value of 0 means no timeout, otherwise values must be between 1 and
   423     * {@link Integer#MAX_VALUE}.
   424     * @param connectionTimeout Connection timeout in milliseconds
   425     * @return API client
   426     */
   427     public ApiClient setConnectTimeout(int connectionTimeout) {
   428       this.connectionTimeout = connectionTimeout;
   429       httpClient.setConnectTimeout(connectionTimeout);
   430       return this;
   431     }
   432  
   433    /**
   434     * Get the date format used to parse/format date parameters.
   435     * @return Date format
   436     */
   437    public DateFormat getDateFormat() {
   438      return dateFormat;
   439    }
   440  
   441    /**
   442     * Set the date format used to parse/format date parameters.
   443     * @param dateFormat Date format
   444     * @return API client
   445     */
   446    public ApiClient setDateFormat(DateFormat dateFormat) {
   447      this.dateFormat = dateFormat;
   448      // Also set the date format for model (de)serialization with Date properties.
   449      this.objectMapper.setDateFormat((DateFormat) dateFormat.clone());
   450      // Need to rebuild the Client as objectMapper changes.
   451      rebuildHttpClient();
   452      return this;
   453    }
   454  
   455    /**
   456     * Parse the given string into Date object.
   457     * @param str String
   458     * @return Date
   459     */
   460    public Date parseDate(String str) {
   461      try {
   462        return dateFormat.parse(str);
   463      } catch (java.text.ParseException e) {
   464        throw new RuntimeException(e);
   465      }
   466    }
   467  
   468    /**
   469     * Format the given Date object into string.
   470     * @param date Date
   471     * @return Date in string format
   472     */
   473    public String formatDate(Date date) {
   474      return dateFormat.format(date);
   475    }
   476  
   477    /**
   478     * Format the given parameter object into string.
   479     * @param param Object
   480     * @return Object in string format
   481     */
   482    public String parameterToString(Object param) {
   483      if (param == null) {
   484        return "";
   485      } else if (param instanceof Date) {
   486        return formatDate((Date) param);
   487      } else if (param instanceof Collection) {
   488        StringBuilder b = new StringBuilder();
   489        for(Object o : (Collection<?>)param) {
   490          if(b.length() > 0) {
   491            b.append(',');
   492          }
   493          b.append(String.valueOf(o));
   494        }
   495        return b.toString();
   496      } else {
   497        return String.valueOf(param);
   498      }
   499    }
   500  
   501    /**
   502     * Formats the specified query parameter to a list containing a single {@code Pair} object.
   503     *
   504     * Note that {@code value} must not be a collection.
   505     *
   506     * @param name The name of the parameter.
   507     * @param value The value of the parameter.
   508     * @return A list containing a single {@code Pair} object.
   509     */
   510    public List<Pair> parameterToPair(String name, Object value) {
   511      List<Pair> params = new ArrayList<Pair>();
   512  
   513      // preconditions
   514      if (name == null || name.isEmpty() || value == null || value instanceof Collection) return params;
   515  
   516      params.add(new Pair(name, parameterToString(value)));
   517      return params;
   518    }
   519  
   520    /**
   521     * Formats the specified collection query parameters to a list of {@code Pair} objects.
   522     *
   523     * Note that the values of each of the returned Pair objects are percent-encoded.
   524     *
   525     * @param collectionFormat The collection format of the parameter.
   526     * @param name The name of the parameter.
   527     * @param value The value of the parameter.
   528     * @return A list of {@code Pair} objects.
   529     */
   530    public List<Pair> parameterToPairs(String collectionFormat, String name, Collection value) {
   531      List<Pair> params = new ArrayList<Pair>();
   532  
   533      // preconditions
   534      if (name == null || name.isEmpty() || value == null) {
   535        return params;
   536      }
   537  
   538      // create the params based on the collection format
   539      if ("multi".equals(collectionFormat)) {
   540        for (Object item : value) {
   541          params.add(new Pair(name, escapeString(parameterToString(item))));
   542        }
   543        return params;
   544      }
   545  
   546      // collectionFormat is assumed to be "csv" by default
   547      String delimiter = ",";
   548  
   549      // escape all delimiters except commas, which are URI reserved
   550      // characters
   551      if ("ssv".equals(collectionFormat)) {
   552        delimiter = escapeString(" ");
   553      } else if ("tsv".equals(collectionFormat)) {
   554        delimiter = escapeString("\t");
   555      } else if ("pipes".equals(collectionFormat)) {
   556        delimiter = escapeString("|");
   557      }
   558  
   559      StringBuilder sb = new StringBuilder() ;
   560      for (Object item : value) {
   561        sb.append(delimiter);
   562        sb.append(escapeString(parameterToString(item)));
   563      }
   564  
   565      params.add(new Pair(name, sb.substring(delimiter.length())));
   566  
   567      return params;
   568    }
   569  
   570    /**
   571     * Check if the given MIME is a JSON MIME.
   572     * JSON MIME examples:
   573     *   application/json
   574     *   application/json; charset=UTF8
   575     *   APPLICATION/JSON
   576     *   application/vnd.company+json
   577     * @param mime MIME
   578     * @return True if MIME type is boolean
   579     */
   580    public boolean isJsonMime(String mime) {
   581      String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$";
   582      return mime != null && (mime.matches(jsonMime) || mime.equals("*/*"));
   583    }
   584  
   585    /**
   586     * Select the Accept header's value from the given accepts array:
   587     *   if JSON exists in the given array, use it;
   588     *   otherwise use all of them (joining into a string)
   589     *
   590     * @param accepts The accepts array to select from
   591     * @return The Accept header to use. If the given array is empty,
   592     *   null will be returned (not to set the Accept header explicitly).
   593     */
   594    public String selectHeaderAccept(String[] accepts) {
   595      if (accepts.length == 0) {
   596        return null;
   597      }
   598      for (String accept : accepts) {
   599        if (isJsonMime(accept)) {
   600          return accept;
   601        }
   602      }
   603      return StringUtil.join(accepts, ",");
   604    }
   605  
   606    /**
   607     * Select the Content-Type header's value from the given array:
   608     *   if JSON exists in the given array, use it;
   609     *   otherwise use the first one of the array.
   610     *
   611     * @param contentTypes The Content-Type array to select from
   612     * @return The Content-Type header to use. If the given array is empty,
   613     *   or matches "any", JSON will be used.
   614     */
   615    public String selectHeaderContentType(String[] contentTypes) {
   616      if (contentTypes.length == 0 || contentTypes[0].equals("*/*")) {
   617        return "application/json";
   618      }
   619      for (String contentType : contentTypes) {
   620        if (isJsonMime(contentType)) {
   621          return contentType;
   622        }
   623      }
   624      return contentTypes[0];
   625    }
   626  
   627    /**
   628     * Escape the given string to be used as URL query value.
   629     * @param str String
   630     * @return Escaped string
   631     */
   632    public String escapeString(String str) {
   633      try {
   634        return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20");
   635      } catch (UnsupportedEncodingException e) {
   636        return str;
   637      }
   638    }
   639  
   640    /**
   641     * Serialize the given Java object into string according the given
   642     * Content-Type (only JSON is supported for now).
   643     * @param obj Object
   644     * @param contentType Content type
   645     * @param formParams Form parameters
   646     * @return Object
   647     * @throws ApiException API exception
   648     */
   649    public Object serialize(Object obj, String contentType, Map<String, Object> formParams) throws ApiException {
   650      if (contentType.startsWith("multipart/form-data")) {
   651        FormDataMultiPart mp = new FormDataMultiPart();
   652        for (Entry<String, Object> param: formParams.entrySet()) {
   653          if( param.getValue() instanceof List && !( ( List ) param.getValue() ).isEmpty()
   654                    && ( ( List ) param.getValue() ).get( 0 ) instanceof File ) {
   655              @SuppressWarnings( "unchecked" )
   656              List<File> files = ( List<File> ) param.getValue();
   657              for( File file : files ) {
   658                mp.bodyPart( new FileDataBodyPart( param.getKey(), file, MediaType.APPLICATION_OCTET_STREAM_TYPE ) );
   659              }
   660          } else if (param.getValue() instanceof File) {
   661            File file = (File) param.getValue();
   662            mp.bodyPart(new FileDataBodyPart(param.getKey(), file, MediaType.APPLICATION_OCTET_STREAM_TYPE));
   663          } else {
   664            mp.field(param.getKey(), parameterToString(param.getValue()), MediaType.MULTIPART_FORM_DATA_TYPE);
   665          }
   666        }
   667        return mp;
   668      } else if (contentType.startsWith("application/x-www-form-urlencoded")) {
   669        return this.getXWWWFormUrlencodedParams(formParams);
   670      } else {
   671        // We let Jersey attempt to serialize the body
   672        return obj;
   673      }
   674    }
   675  
   676    /**
   677     * Build full URL by concatenating base path, the given sub path and query parameters.
   678     *
   679     * @param path The sub path
   680     * @param queryParams The query parameters
   681     * @param collectionQueryParams The collection query parameters
   682     * @return The full URL
   683     */
   684    private String buildUrl(String path, List<Pair> queryParams, List<Pair> collectionQueryParams) {
   685      String baseURL;
   686      if (serverIndex != null) {
   687        if (serverIndex < 0 || serverIndex >= servers.size()) {
   688          throw new ArrayIndexOutOfBoundsException(String.format(
   689            "Invalid index %d when selecting the host settings. Must be less than %d", serverIndex, servers.size()
   690          ));
   691        }
   692        baseURL = servers.get(serverIndex).URL(serverVariables);
   693      } else {
   694        baseURL = basePath;
   695      }
   696  
   697      final StringBuilder url = new StringBuilder();
   698      url.append(baseURL).append(path);
   699  
   700      if (queryParams != null && !queryParams.isEmpty()) {
   701        // support (constant) query string in `path`, e.g. "/posts?draft=1"
   702        String prefix = path.contains("?") ? "&" : "?";
   703        for (Pair param : queryParams) {
   704          if (param.getValue() != null) {
   705            if (prefix != null) {
   706              url.append(prefix);
   707              prefix = null;
   708            } else {
   709              url.append("&");
   710            }
   711            String value = parameterToString(param.getValue());
   712            url.append(escapeString(param.getName())).append("=").append(escapeString(value));
   713          }
   714        }
   715      }
   716  
   717      if (collectionQueryParams != null && !collectionQueryParams.isEmpty()) {
   718        String prefix = url.toString().contains("?") ? "&" : "?";
   719        for (Pair param : collectionQueryParams) {
   720          if (param.getValue() != null) {
   721            if (prefix != null) {
   722              url.append(prefix);
   723              prefix = null;
   724            } else {
   725              url.append("&");
   726            }
   727            String value = parameterToString(param.getValue());
   728            // collection query parameter value already escaped as part of parameterToPairs
   729            url.append(escapeString(param.getName())).append("=").append(value);
   730          }
   731        }
   732      }
   733  
   734      return url.toString();
   735    }
   736  
   737    private ClientResponse getAPIResponse(String path, String method, List<Pair> queryParams, List<Pair> collectionQueryParams, Object body, Map<String, String> headerParams, Map<String, String> cookieParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames) throws ApiException {
   738      if (body != null && !formParams.isEmpty()) {
   739        throw new ApiException(500, "Cannot have body and form params");
   740      }
   741  
   742      updateParamsForAuth(authNames, queryParams, headerParams, cookieParams);
   743  
   744      final String url = buildUrl(path, queryParams, collectionQueryParams);
   745      Builder builder;
   746      if (accept == null) {
   747        builder = httpClient.resource(url).getRequestBuilder();
   748      } else {
   749        builder = httpClient.resource(url).accept(accept);
   750      }
   751  
   752      for (Entry<String, String> keyValue : headerParams.entrySet()) {
   753        builder = builder.header(keyValue.getKey(), keyValue.getValue());
   754      }
   755      for (Map.Entry<String,String> keyValue : defaultHeaderMap.entrySet()) {
   756        if (!headerParams.containsKey(keyValue.getKey())) {
   757          builder = builder.header(keyValue.getKey(), keyValue.getValue());
   758        }
   759      }
   760  
   761      for (Entry<String, String> keyValue : cookieParams.entrySet()) {
   762        builder = builder.cookie(new Cookie(keyValue.getKey(), keyValue.getValue()));
   763      }
   764      for (Map.Entry<String,String> keyValue : defaultCookieMap.entrySet()) {
   765        if (!cookieParams.containsKey(keyValue.getKey())) {
   766          builder = builder.cookie(new Cookie(keyValue.getKey(), keyValue.getValue()));
   767        }
   768      }
   769  
   770      ClientResponse response = null;
   771  
   772      if ("GET".equals(method)) {
   773        response = (ClientResponse) builder.get(ClientResponse.class);
   774      } else if ("POST".equals(method)) {
   775        response = builder.type(contentType).post(ClientResponse.class, serialize(body, contentType, formParams));
   776      } else if ("PUT".equals(method)) {
   777        response = builder.type(contentType).put(ClientResponse.class, serialize(body, contentType, formParams));
   778      } else if ("DELETE".equals(method)) {
   779        response = builder.type(contentType).delete(ClientResponse.class, serialize(body, contentType, formParams));
   780      } else if ("PATCH".equals(method)) {
   781        response = builder.type(contentType).header("X-HTTP-Method-Override", "PATCH").post(ClientResponse.class, serialize(body, contentType, formParams));
   782      } else if ("HEAD".equals(method)) {
   783        response = builder.head();
   784      } else {
   785        throw new ApiException(500, "unknown method type " + method);
   786      }
   787      return response;
   788    }
   789  
   790    /**
   791     * Invoke API by sending HTTP request with the given options.
   792     *
   793     * @param <T> Type
   794     * @param path The sub-path of the HTTP URL
   795     * @param method The request method, one of "GET", "POST", "PUT", and "DELETE"
   796     * @param queryParams The query parameters
   797     * @param collectionQueryParams The collection query parameters
   798     * @param body The request body object - if it is not binary, otherwise null
   799     * @param headerParams The header parameters
   800     * @param cookieParams The cookie parameters
   801     * @param formParams The form parameters
   802     * @param accept The request's Accept header
   803     * @param contentType The request's Content-Type header
   804     * @param authNames The authentications to apply
   805     * @param returnType Return type
   806     * @return The response body in type of string
   807     * @throws ApiException API exception
   808     */
   809     public <T> T invokeAPI(String path, String method, List<Pair> queryParams, List<Pair> collectionQueryParams, Object body, Map<String, String> headerParams, Map<String, String> cookieParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames, GenericType<T> returnType) throws ApiException {
   810  
   811      ClientResponse response = getAPIResponse(path, method, queryParams, collectionQueryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames);
   812  
   813      statusCode = response.getStatusInfo().getStatusCode();
   814      responseHeaders = response.getHeaders();
   815  
   816      if(response.getStatusInfo().getStatusCode() == ClientResponse.Status.NO_CONTENT.getStatusCode()) {
   817        return null;
   818      } else if (response.getStatusInfo().getFamily() == Family.SUCCESSFUL) {
   819        if (returnType == null)
   820          return null;
   821        else
   822          return response.getEntity(returnType);
   823      } else {
   824        String message = "error";
   825        String respBody = null;
   826        if (response.hasEntity()) {
   827          try {
   828            respBody = response.getEntity(String.class);
   829            message = respBody;
   830          } catch (RuntimeException e) {
   831            // e.printStackTrace();
   832          }
   833        }
   834        throw new ApiException(
   835          response.getStatusInfo().getStatusCode(),
   836          message,
   837          response.getHeaders(),
   838          respBody);
   839      }
   840    }
   841  
   842    /**
   843     * Update query and header parameters based on authentication settings.
   844     *
   845     * @param authNames The authentications to apply
   846     * @param queryParams Query parameters
   847     * @param headerParams Header parameters
   848     * @param cookieParams Cookie parameters
   849     */
   850    private void updateParamsForAuth(String[] authNames, List<Pair> queryParams, Map<String, String> headerParams, Map<String, String> cookieParams) {
   851      for (String authName : authNames) {
   852        Authentication auth = authentications.get(authName);
   853        if (auth == null) throw new RuntimeException("Authentication undefined: " + authName);
   854        auth.applyToParams(queryParams, headerParams, cookieParams);
   855      }
   856    }
   857  
   858    /**
   859     * Encode the given form parameters as request body.
   860     * @param formParams Form parameters
   861     * @return HTTP form encoded parameters
   862     */
   863    private String getXWWWFormUrlencodedParams(Map<String, Object> formParams) {
   864      StringBuilder formParamBuilder = new StringBuilder();
   865  
   866      for (Entry<String, Object> param : formParams.entrySet()) {
   867        String valueStr = parameterToString(param.getValue());
   868        try {
   869          formParamBuilder.append(URLEncoder.encode(param.getKey(), "utf8"))
   870              .append("=")
   871              .append(URLEncoder.encode(valueStr, "utf8"));
   872          formParamBuilder.append("&");
   873        } catch (UnsupportedEncodingException e) {
   874          // move on to next
   875        }
   876      }
   877  
   878      String encodedFormParams = formParamBuilder.toString();
   879      if (encodedFormParams.endsWith("&")) {
   880        encodedFormParams = encodedFormParams.substring(0, encodedFormParams.length() - 1);
   881      }
   882  
   883      return encodedFormParams;
   884    }
   885  }