Skip to content

Commit 698ed97

Browse files
committed
Merge pull request #1124 from boazsapir/binary
support binary input and output
2 parents 3f8dbf4 + 564dffa commit 698ed97

File tree

9 files changed

+228
-38
lines changed

9 files changed

+228
-38
lines changed

modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenParameter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
public class CodegenParameter {
99
public Boolean isFormParam, isQueryParam, isPathParam, isHeaderParam,
10-
isCookieParam, isBodyParam, isFile, notFile, hasMore, isContainer, secondaryParam;
10+
isCookieParam, isBodyParam, isFile, notFile, hasMore, isContainer, secondaryParam, isBinary;
1111
public String baseName, paramName, dataType, collectionFormat, description, baseType, defaultValue;
1212
public String jsonSchema;
1313
public boolean isEnum;

modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenResponse.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public class CodegenResponse {
1515
public Boolean primitiveType;
1616
public Boolean isMapContainer;
1717
public Boolean isListContainer;
18+
public Boolean isBinary;
1819
public Object schema;
1920
public String jsonSchema;
2021

modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import io.swagger.models.properties.AbstractNumericProperty;
2828
import io.swagger.models.properties.ArrayProperty;
2929
import io.swagger.models.properties.BooleanProperty;
30+
import io.swagger.models.properties.ByteArrayProperty;
3031
import io.swagger.models.properties.DateProperty;
3132
import io.swagger.models.properties.DateTimeProperty;
3233
import io.swagger.models.properties.DecimalProperty;
@@ -311,6 +312,8 @@ public DefaultCodegen() {
311312
typeMapping.put("double", "Double");
312313
typeMapping.put("object", "Object");
313314
typeMapping.put("integer", "Integer");
315+
typeMapping.put("ByteArray", "byte[]");
316+
314317

315318
instantiationTypes = new HashMap<String, String>();
316319

@@ -447,6 +450,8 @@ public String getSwaggerType(Property p) {
447450
String datatype = null;
448451
if (p instanceof StringProperty) {
449452
datatype = "string";
453+
} else if (p instanceof ByteArrayProperty) {
454+
datatype = "ByteArray";
450455
} else if (p instanceof BooleanProperty) {
451456
datatype = "boolean";
452457
} else if (p instanceof DateProperty) {
@@ -529,6 +534,7 @@ public CodegenModel fromModel(String name, Model model, Map<String, Model> allDe
529534
if (model instanceof ArrayModel) {
530535
ArrayModel am = (ArrayModel) model;
531536
ArrayProperty arrayProperty = new ArrayProperty(am.getItems());
537+
m.hasEnums = false; // Otherwise there will be a NullPointerException in JavaClientCodegen.fromModel
532538
addParentContainer(m, name, arrayProperty);
533539
} else if (model instanceof RefModel) {
534540
// TODO
@@ -974,6 +980,7 @@ public CodegenResponse fromResponse(String responseCode, Response response) {
974980
}
975981
}
976982
r.dataType = cm.datatype;
983+
r.isBinary = cm.datatype.equals("byte[]");
977984
if (cm.isContainer != null) {
978985
r.simpleType = false;
979986
r.containerType = cm.containerType;
@@ -1070,12 +1077,17 @@ public CodegenParameter fromParameter(Parameter param, Set<String> imports) {
10701077
p.dataType = getTypeDeclaration(cm.classname);
10711078
imports.add(p.dataType);
10721079
} else {
1073-
// TODO: missing format, so this will not always work
1074-
Property prop = PropertyBuilder.build(impl.getType(), null, null);
1080+
Property prop = PropertyBuilder.build(impl.getType(), impl.getFormat(), null);
10751081
prop.setRequired(bp.getRequired());
10761082
CodegenProperty cp = fromProperty("property", prop);
10771083
if (cp != null) {
10781084
p.dataType = cp.datatype;
1085+
if (p.dataType.equals("byte[]")) {
1086+
p.isBinary = true;
1087+
}
1088+
else {
1089+
p.isBinary = false;
1090+
}
10791091
}
10801092
}
10811093
} else if (model instanceof ArrayModel) {

modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
3636
protected String sourceFolder = "src/main/java";
3737
protected String localVariablePrefix = "";
3838
protected Boolean serializableModel = false;
39-
39+
4040
public JavaClientCodegen() {
4141
super();
4242
outputFolder = "generated-code/java";
@@ -66,7 +66,8 @@ public JavaClientCodegen() {
6666
"Integer",
6767
"Long",
6868
"Float",
69-
"Object")
69+
"Object",
70+
"byte[]")
7071
);
7172
instantiationTypes.put("array", "ArrayList");
7273
instantiationTypes.put("map", "HashMap");
@@ -137,7 +138,7 @@ public void processOpts() {
137138
if (additionalProperties.containsKey("localVariablePrefix")) {
138139
this.setLocalVariablePrefix((String) additionalProperties.get("localVariablePrefix"));
139140
}
140-
141+
141142
if (additionalProperties.containsKey("serializableModel")) {
142143
this.setSerializableModel(Boolean.valueOf((String)additionalProperties.get("serializableModel").toString()));
143144
}
@@ -282,7 +283,7 @@ public String getSwaggerType(Property p) {
282283
if (typeMapping.containsKey(swaggerType)) {
283284
type = typeMapping.get(swaggerType);
284285
if (languageSpecificPrimitives.contains(type)) {
285-
return toModelName(type);
286+
return type;
286287
}
287288
} else {
288289
type = swaggerType;
@@ -380,14 +381,15 @@ public void setLocalVariablePrefix(String localVariablePrefix) {
380381
this.localVariablePrefix = localVariablePrefix;
381382
}
382383

384+
383385
public Boolean getSerializableModel() {
384386
return serializableModel;
385387
}
386388

387389
public void setSerializableModel(Boolean serializableModel) {
388390
this.serializableModel = serializableModel;
389391
}
390-
392+
391393
private String sanitizePackageName(String packageName) {
392394
packageName = packageName.trim();
393395
packageName = packageName.replaceAll("[^a-zA-Z0-9_\\.]", "_");

modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache

Lines changed: 93 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import java.net.URLEncoder;
2828
import java.io.IOException;
2929
import java.io.File;
3030
import java.io.UnsupportedEncodingException;
31+
import java.io.DataInputStream;
3132

3233
import java.text.DateFormat;
3334
import java.text.SimpleDateFormat;
@@ -372,22 +373,12 @@ public class ApiClient {
372373
}
373374
}
374375

375-
/**
376-
* Invoke API by sending HTTP request with the given options.
377-
*
378-
* @param path The sub-path of the HTTP URL
379-
* @param method The request method, one of "GET", "POST", "PUT", and "DELETE"
380-
* @param queryParams The query parameters
381-
* @param body The request body object
382-
* @param headerParams The header parameters
383-
* @param formParams The form parameters
384-
* @param accept The request's Accept header
385-
* @param contentType The request's Content-Type header
386-
* @param authNames The authentications to apply
387-
* @param returnType The return type into which to deserialize the response
388-
* @return The response body in type of string
389-
*/
390-
public <T> T invokeAPI(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames, TypeRef returnType) throws ApiException {
376+
private ClientResponse getAPIResponse(String path, String method, List<Pair> queryParams, Object body, byte[] binaryBody, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames) throws ApiException {
377+
378+
if (body != null && binaryBody != null){
379+
throw new ApiException(500, "either body or binaryBody must be null");
380+
}
381+
391382
updateParamsForAuth(authNames, queryParams, headerParams);
392383

393384
Client client = getClient();
@@ -447,7 +438,10 @@ public class ApiClient {
447438
if (encodedFormParams != null) {
448439
response = builder.type(contentType).post(ClientResponse.class, encodedFormParams);
449440
} else if (body == null) {
450-
response = builder.post(ClientResponse.class, null);
441+
if(binaryBody == null)
442+
response = builder.post(ClientResponse.class, null);
443+
else
444+
response = builder.type(contentType).post(ClientResponse.class, binaryBody);
451445
} else if (body instanceof FormDataMultiPart) {
452446
response = builder.type(contentType).post(ClientResponse.class, body);
453447
} else {
@@ -457,23 +451,50 @@ public class ApiClient {
457451
if (encodedFormParams != null) {
458452
response = builder.type(contentType).put(ClientResponse.class, encodedFormParams);
459453
} else if(body == null) {
460-
response = builder.put(ClientResponse.class, serialize(body, contentType));
454+
if(binaryBody == null)
455+
response = builder.put(ClientResponse.class, null);
456+
else
457+
response = builder.type(contentType).put(ClientResponse.class, binaryBody);
461458
} else {
462459
response = builder.type(contentType).put(ClientResponse.class, serialize(body, contentType));
463460
}
464461
} else if ("DELETE".equals(method)) {
465462
if (encodedFormParams != null) {
466463
response = builder.type(contentType).delete(ClientResponse.class, encodedFormParams);
467464
} else if(body == null) {
468-
response = builder.delete(ClientResponse.class);
465+
if(binaryBody == null)
466+
response = builder.delete(ClientResponse.class);
467+
else
468+
response = builder.type(contentType).delete(ClientResponse.class, binaryBody);
469469
} else {
470470
response = builder.type(contentType).delete(ClientResponse.class, serialize(body, contentType));
471471
}
472472
} else {
473473
throw new ApiException(500, "unknown method type " + method);
474474
}
475+
return response;
476+
}
477+
478+
/**
479+
* Invoke API by sending HTTP request with the given options.
480+
*
481+
* @param path The sub-path of the HTTP URL
482+
* @param method The request method, one of "GET", "POST", "PUT", and "DELETE"
483+
* @param queryParams The query parameters
484+
* @param body The request body object - if it is not binary, otherwise null
485+
* @param binaryBody The request body object - if it is binary, otherwise null
486+
* @param headerParams The header parameters
487+
* @param formParams The form parameters
488+
* @param accept The request's Accept header
489+
* @param contentType The request's Content-Type header
490+
* @param authNames The authentications to apply
491+
* @return The response body in type of string
492+
*/
493+
public <T> T invokeAPI(String path, String method, List<Pair> queryParams, Object body, byte[] binaryBody, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames, TypeRef returnType) throws ApiException {
475494
476-
if (response.getStatusInfo() == ClientResponse.Status.NO_CONTENT) {
495+
ClientResponse response = getAPIResponse(path, method, queryParams, body, binaryBody, headerParams, formParams, accept, contentType, authNames);
496+
497+
if(response.getStatusInfo() == ClientResponse.Status.NO_CONTENT) {
477498
return null;
478499
} else if (response.getStatusInfo().getFamily() == Family.SUCCESSFUL) {
479500
if (returnType == null)
@@ -498,6 +519,58 @@ public class ApiClient {
498519
respBody);
499520
}
500521
}
522+
/**
523+
* Invoke API by sending HTTP request with the given options - return binary result
524+
*
525+
* @param path The sub-path of the HTTP URL
526+
* @param method The request method, one of "GET", "POST", "PUT", and "DELETE"
527+
* @param queryParams The query parameters
528+
* @param body The request body object - if it is not binary, otherwise null
529+
* @param binaryBody The request body object - if it is binary, otherwise null
530+
* @param headerParams The header parameters
531+
* @param formParams The form parameters
532+
* @param accept The request's Accept header
533+
* @param contentType The request's Content-Type header
534+
* @param authNames The authentications to apply
535+
* @return The response body in type of string
536+
*/
537+
public byte[] invokeBinaryAPI(String path, String method, List<Pair> queryParams, Object body, byte[] binaryBody, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[]authNames) throws ApiException {
538+
539+
ClientResponse response = getAPIResponse(path, method, queryParams, body, binaryBody, headerParams, formParams, accept, contentType, authNames);
540+
541+
if(response.getStatusInfo() == ClientResponse.Status.NO_CONTENT) {
542+
return null;
543+
}
544+
else if(response.getStatusInfo().getFamily() == Family.SUCCESSFUL) {
545+
if(response.hasEntity()) {
546+
DataInputStream stream = new DataInputStream(response.getEntityInputStream());
547+
byte[] data = new byte[response.getLength()];
548+
try {
549+
stream.readFully(data);
550+
} catch (IOException ex) {
551+
throw new ApiException(500, "Error obtaining binary response data");
552+
}
553+
return data;
554+
}
555+
else {
556+
return new byte[0];
557+
}
558+
}
559+
else {
560+
String message = "error";
561+
if(response.hasEntity()) {
562+
try{
563+
message = String.valueOf(response.getEntity(String.class));
564+
}
565+
catch (RuntimeException e) {
566+
// e.printStackTrace();
567+
}
568+
}
569+
throw new ApiException(
570+
response.getStatusInfo().getStatusCode(),
571+
message);
572+
}
573+
}
501574

502575
/**
503576
* Update query and header parameters based on authentication settings.

modules/swagger-codegen/src/main/resources/Java/api.mustache

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,16 @@ public class {{classname}} {
4646
{{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
4747
*/
4848
public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException {
49-
Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
49+
Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{^isBinary}}{{paramName}}{{/isBinary}}{{#isBinary}}null{{/isBinary}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
50+
byte[] {{localVariablePrefix}}postBinaryBody = {{#bodyParam}}{{#isBinary}}{{paramName}}{{/isBinary}}{{^isBinary}}null{{/isBinary}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
5051
{{#allParams}}{{#required}}
51-
// verify the required parameter '{{paramName}}' is set
52-
if ({{paramName}} == null) {
53-
throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{nickname}}");
54-
}
55-
{{/required}}{{/allParams}}
56-
52+
// verify the required parameter '{{paramName}}' is set
53+
if ({{paramName}} == null) {
54+
throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{nickname}}");
55+
}
56+
{{/required}}{{/allParams}}
5757
// create path and map variables
58-
String {{localVariablePrefix}}path = "{{path}}".replaceAll("\\{format\\}","json"){{#pathParams}}
58+
String {{localVariablePrefix}}path = "{{{path}}}".replaceAll("\\{format\\}","json"){{#pathParams}}
5959
.replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}};
6060

6161
// query params
@@ -86,12 +86,26 @@ public class {{classname}} {
8686
final String {{localVariablePrefix}}contentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}contentTypes);
8787

8888
String[] {{localVariablePrefix}}authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };
89+
{{#responses}}
90+
{{#isDefault}}
91+
92+
{{#isBinary}}
93+
byte[] {{localVariablePrefix}}response = null;
94+
{{localVariablePrefix}}response = {{localVariablePrefix}}apiClient.invokeBinaryAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams,{{localVariablePrefix}} postBody, {{localVariablePrefix}}postBinaryBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames);
95+
return {{localVariablePrefix}}response;
96+
{{/isBinary}}
97+
98+
{{^isBinary}}
8999
{{#returnType}}
90100
TypeRef {{localVariablePrefix}}returnType = new TypeRef<{{{returnType}}}>() {};
91-
return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, {{localVariablePrefix}}returnType);
101+
return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}postBinaryBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, {{localVariablePrefix}}returnType);
92102
{{/returnType}}{{^returnType}}
93-
{{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, null);
103+
{{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}postBinaryBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, null);
94104
{{/returnType}}
105+
{{/isBinary}}
106+
107+
{{/isDefault}}
108+
{{/responses}}
95109
}
96110
{{/operation}}
97111
}

0 commit comments

Comments
 (0)