Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ else if (MICROPROFILE.equals(getLibrary())) {
writeOptional(outputFolder, new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
supportingFiles.add(new SupportingFile("travis.mustache", "", ".travis.yml"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerFolder, "ApiClient.java"));
supportingFiles.add(new SupportingFile("ServerConfiguration.mustache", invokerFolder, "ServerConfiguration.java"));
supportingFiles.add(new SupportingFile("ServerVariable.mustache", invokerFolder, "ServerVariable.java"));
if (!(RESTTEMPLATE.equals(getLibrary()) || REST_ASSURED.equals(getLibrary()) || NATIVE.equals(getLibrary()) || MICROPROFILE.equals(getLibrary()))) {
supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Date;
import java.util.TimeZone;
Expand All @@ -63,6 +65,33 @@ public class ApiClient {
private Map<String, String> defaultHeaderMap = new HashMap<String, String>();
private Map<String, String> defaultCookieMap = new HashMap<String, String>();
private String basePath = "{{{basePath}}}";
protected List<ServerConfiguration> servers = new ArrayList<ServerConfiguration>({{#servers}}{{#-first}}Arrays.asList(
{{/-first}} new ServerConfiguration(
"{{{url}}}",
"{{{description}}}{{^description}}No description provided{{/description}}",
new HashMap<String, ServerVariable>(){{#variables}}{{#-first}} {{
{{/-first}} put("{{{name}}}", new ServerVariable(
"{{{description}}}{{^description}}No description provided{{/description}}",
"{{{defaultValue}}}",
new HashSet<String>(
{{#enumValues}}
{{#-first}}
Arrays.asList(
{{/-first}}
"{{{.}}}"{{^-last}},{{/-last}}
{{#-last}}
)
{{/-last}}
{{/enumValues}}
)
));
{{#-last}}
}}{{/-last}}{{/variables}}
){{^-last}},{{/-last}}
{{#-last}}
){{/-last}}{{/servers}});
protected Integer serverIndex = 0;
protected Map<String, String> serverVariables = null;
private boolean debugging = false;
private int connectionTimeout = 0;

Expand Down Expand Up @@ -177,6 +206,33 @@ public class ApiClient {
return this;
}

public List<ServerConfiguration> getServers() {
return servers;
}

public ApiClient setServers(List<ServerConfiguration> servers) {
this.servers = servers;
return this;
}

public Integer getServerIndex() {
return serverIndex;
}

public ApiClient setServerIndex(Integer serverIndex) {
this.serverIndex = serverIndex;
return this;
}

public Map<String, String> getServerVariables() {
return serverVariables;
}

public ApiClient setServerVariables(Map<String, String> serverVariables) {
this.serverVariables = serverVariables;
return this;
}

/**
* Gets the status code of the previous request
* @return Status code
Expand Down Expand Up @@ -252,7 +308,7 @@ public class ApiClient {
}
throw new RuntimeException("No API key authentication configured!");
}

/**
* Helper method to set API key prefix for the first API key authentication.
* @param apiKeyPrefix API key prefix
Expand Down Expand Up @@ -626,8 +682,20 @@ public class ApiClient {
* @return The full URL
*/
private String buildUrl(String path, List<Pair> queryParams, List<Pair> collectionQueryParams) {
String baseURL;
if (serverIndex != null) {
if (serverIndex < 0 || serverIndex >= servers.size()) {
throw new ArrayIndexOutOfBoundsException(String.format(
"Invalid index %d when selecting the host settings. Must be less than %d", serverIndex, servers.size()
));
}
baseURL = servers.get(serverIndex).URL(serverVariables);
} else {
baseURL = basePath;
}

final StringBuilder url = new StringBuilder();
url.append(basePath).append(path);
url.append(baseURL).append(path);

if (queryParams != null && !queryParams.isEmpty()) {
// support (constant) query string in `path`, e.g. "/posts?draft=1"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package {{invokerPackage}};

import java.util.Map;

/**
* Representing a Server configuration.
*/
public class ServerConfiguration {
public String URL;
public String description;
public Map<String, ServerVariable> variables;

/**
* @param URL A URL to the target host.
* @param description A describtion of the host designated by the URL.
* @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template.
*/
public ServerConfiguration(String URL, String description, Map<String, ServerVariable> variables) {
this.URL = URL;
this.description = description;
this.variables = variables;
}

/**
* Format URL template using given variables.
*
* @param variables A map between a variable name and its value.
* @return Formatted URL.
*/
public String URL(Map<String, String> variables) {
String url = this.URL;

// go through variables and replace placeholders
for (Map.Entry<String, ServerVariable> variable: this.variables.entrySet()) {
String name = variable.getKey();
ServerVariable serverVariable = variable.getValue();
String value = serverVariable.defaultValue;

if (variables != null && variables.containsKey(name)) {
value = variables.get(name);
if (serverVariable.enumValues.size() > 0 && !serverVariable.enumValues.contains(value)) {
throw new RuntimeException("The variable " + name + " in the server URL has invalid value " + value + ".");
}
}
url = url.replaceAll("\\{" + name + "\\}", value);
}
return url;
}

/**
* Format URL template using default server variables.
*
* @return Formatted URL.
*/
public String URL() {
return URL(null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package {{invokerPackage}};

import java.util.HashSet;

/**
* Representing a Server Variable for server URL template substitution.
*/
public class ServerVariable {
public String description;
public String defaultValue;
public HashSet<String> enumValues = null;

/**
* @param description A description for the server variable.
* @param defaultValue The default value to use for substitution.
* @param enumValues An enumeration of string values to be used if the substitution options are from a limited set.
*/
public ServerVariable(String description, String defaultValue, HashSet<String> enumValues) {
this.description = description;
this.defaultValue = defaultValue;
this.enumValues = enumValues;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Date;
import java.util.TimeZone;
Expand All @@ -55,6 +57,7 @@ import {{invokerPackage}}.auth.Authentication;
import {{invokerPackage}}.auth.HttpBasicAuth;
import {{invokerPackage}}.auth.HttpBearerAuth;
import {{invokerPackage}}.auth.ApiKeyAuth;

{{#hasOAuthMethods}}
import {{invokerPackage}}.auth.OAuth;
{{/hasOAuthMethods}}
Expand All @@ -64,6 +67,74 @@ public class ApiClient {
protected Map<String, String> defaultHeaderMap = new HashMap<String, String>();
protected Map<String, String> defaultCookieMap = new HashMap<String, String>();
protected String basePath = "{{{basePath}}}";
protected List<ServerConfiguration> servers = new ArrayList<ServerConfiguration>({{#servers}}{{#-first}}Arrays.asList(
{{/-first}} new ServerConfiguration(
"{{{url}}}",
"{{{description}}}{{^description}}No description provided{{/description}}",
new HashMap<String, ServerVariable>(){{#variables}}{{#-first}} {{
{{/-first}} put("{{{name}}}", new ServerVariable(
"{{{description}}}{{^description}}No description provided{{/description}}",
"{{{defaultValue}}}",
new HashSet<String>(
{{#enumValues}}
{{#-first}}
Arrays.asList(
{{/-first}}
"{{{.}}}"{{^-last}},{{/-last}}
{{#-last}}
)
{{/-last}}
{{/enumValues}}
)
));
{{#-last}}
}}{{/-last}}{{/variables}}
){{^-last}},{{/-last}}
{{#-last}}
){{/-last}}{{/servers}});
protected Integer serverIndex = 0;
protected Map<String, String> serverVariables = null;
protected Map<String, List<ServerConfiguration>> operationServers = new HashMap<String, List<ServerConfiguration>>() {{
{{#apiInfo}}
{{#apis}}
{{#operations}}
{{#operation}}
{{#servers}}
{{#-first}}
put("{{{classname}}}.{{{operationId}}}", new ArrayList<ServerConfiguration>(Arrays.asList(
{{/-first}}
new ServerConfiguration(
"{{{url}}}",
"{{{description}}}{{^description}}No description provided{{/description}}",
new HashMap<String, ServerVariable>(){{#variables}}{{#-first}} {{
{{/-first}} put("{{{name}}}", new ServerVariable(
"{{{description}}}{{^description}}No description provided{{/description}}",
"{{{defaultValue}}}",
new HashSet<String>(
{{#enumValues}}
{{#-first}}
Arrays.asList(
{{/-first}}
"{{{.}}}"{{^-last}},{{/-last}}
{{#-last}}
)
{{/-last}}
{{/enumValues}}
)
));
{{#-last}}
}}{{/-last}}{{/variables}}
){{^-last}},{{/-last}}
{{#-last}}
)));{{/-last}}
{{/servers}}
{{/operation}}
{{/operations}}
{{/apis}}
{{/apiInfo}}
}};
protected Map<String, Integer> operationServerIndex = new HashMap<String, Integer>();
protected Map<String, Map<String, String>> operationServerVariables = new HashMap<String, Map<String, String>>();
protected boolean debugging = false;
protected int connectionTimeout = 0;
private int readTimeout = 0;
Expand Down Expand Up @@ -121,6 +192,33 @@ public class ApiClient {
return this;
}

public List<ServerConfiguration> getServers() {
return servers;
}

public ApiClient setServers(List<ServerConfiguration> servers) {
this.servers = servers;
return this;
}

public Integer getServerIndex() {
return serverIndex;
}

public ApiClient setServerIndex(Integer serverIndex) {
this.serverIndex = serverIndex;
return this;
}

public Map<String, String> getServerVariables() {
return serverVariables;
}

public ApiClient setServerVariables(Map<String, String> serverVariables) {
this.serverVariables = serverVariables;
return this;
}

/**
* Get authentications (key: authentication name, value: authentication).
* @return Map of authentication object
Expand Down Expand Up @@ -670,6 +768,7 @@ public class ApiClient {
* Invoke API by sending HTTP request with the given options.
*
* @param <T> Type
* @param operation The qualified name of the operation
* @param path The sub-path of the HTTP URL
* @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE"
* @param queryParams The query parameters
Expand All @@ -684,12 +783,36 @@ public class ApiClient {
* @return The response body in type of string
* @throws ApiException API exception
*/
public <T> ApiResponse<T> invokeAPI(String path, String method, List<Pair> queryParams, 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 {
public <T> ApiResponse<T> invokeAPI(String operation, String path, String method, List<Pair> queryParams, 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 {
updateParamsForAuth(authNames, queryParams, headerParams, cookieParams);

// Not using `.target(this.basePath).path(path)` below,
// Not using `.target(targetURL).path(path)` below,
// to support (constant) query string in `path`, e.g. "/posts?draft=1"
WebTarget target = httpClient.target(this.basePath + path);
String targetURL;
if (serverIndex != null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notice here to consumers that if new server variable functionality causes issue, one may call setServerIndex(null) to revert to previous behavior. Current default behavior with the server index 0 behaves in the same way as before, but moves the URL configuration to the servers array.

Integer index;
List<ServerConfiguration> serverConfigurations;
Map<String, String> variables;

if (operationServers.containsKey(operation)) {
index = operationServerIndex.getOrDefault(operation, serverIndex);
variables = operationServerVariables.getOrDefault(operation, serverVariables);
serverConfigurations = operationServers.get(operation);
} else {
index = serverIndex;
variables = serverVariables;
serverConfigurations = servers;
}
if (index < 0 || index >= serverConfigurations.size()) {
throw new ArrayIndexOutOfBoundsException(String.format(
"Invalid index %d when selecting the host settings. Must be less than %d", index, serverConfigurations.size()
));
}
targetURL = serverConfigurations.get(index).URL(variables) + path;
} else {
targetURL = this.basePath + path;
}
WebTarget target = httpClient.target(targetURL);

if (queryParams != null) {
for (Pair queryParam : queryParams) {
Expand Down Expand Up @@ -793,6 +916,14 @@ public class ApiClient {
}
}

/**
* @deprecated Add qualified name of the operation as a first parameter.
*/
@Deprecated
public <T> ApiResponse<T> invokeAPI(String path, String method, List<Pair> queryParams, 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 {
return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType);
}

/**
* Build the Client used to make HTTP requests.
* @param debugging Debug setting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ public class {{classname}} {
String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };

{{#returnType}}GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {};{{/returnType}}
return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}});
return apiClient.invokeAPI("{{classname}}.{{operationId}}", localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}});
}
{{#vendorExtensions.x-group-parameters}}

Expand Down
Loading