diff --git a/README.md b/README.md index ef321e4bb59..4738f114cea 100644 --- a/README.md +++ b/README.md @@ -277,6 +277,7 @@ FlaskConnexionCodegen.java JavaClientCodegen.java JavaInflectorServerCodegen.java JaxRSServerCodegen.java +JMeterCodegen.java NodeJSServerCodegen.java ObjcClientCodegen.java PerlClientCodegen.java @@ -353,9 +354,10 @@ CONFIG OPTIONS library template (sub-template) to use: - HTTP client: Jersey client 1.18. JSON processing: Jackson 2.4.2 jersey2 - HTTP client: Jersey client 2.6 + feign - HTTP client: Netflix Feign 8.1.1. JSON processing: Jackson 2.6.3 okhttp-gson - HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1 retrofit - HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1 (Retrofit 1.9.0) - retrofit2 - HTTP client: OkHttp 2.5.0. JSON processing: Gson 2.4 (Retrofit 2.0.0-beta2) + retrofit2 - HTTP client: OkHttp 2.5.0. JSON processing: Gson 2.4 (Retrofit 2.0.0-beta2) ``` Your config file for java can look like @@ -364,7 +366,8 @@ Your config file for java can look like { "groupId":"com.my.company", "artifactId":"MyClent", - "artifactVersion":"1.2.0" + "artifactVersion":"1.2.0", + "library":"feign" } ``` diff --git a/bin/java-petstore-feign.json b/bin/java-petstore-feign.json new file mode 100644 index 00000000000..5502ee3bbad --- /dev/null +++ b/bin/java-petstore-feign.json @@ -0,0 +1,4 @@ +{ + "library": "feign", + "artifactId": "swagger-petstore-feign" +} diff --git a/bin/java-petstore-feign.sh b/bin/java-petstore-feign.sh new file mode 100755 index 00000000000..6f0a5fdf8ff --- /dev/null +++ b/bin/java-petstore-feign.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +SCRIPT="$0" + +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=`dirname "$SCRIPT"`/.. + APP_DIR=`cd "${APP_DIR}"; pwd` +fi + +executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar" + +if [ ! -f "$executable" ] +then + mvn clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" +ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l java -c bin/java-petstore-feign.json -o samples/client/petstore/java/feign" + +java $JAVA_OPTS -jar $executable $ags diff --git a/config-feign.json b/config-feign.json new file mode 100644 index 00000000000..3b8c48c3caa --- /dev/null +++ b/config-feign.json @@ -0,0 +1 @@ +{"library":"feign"} \ No newline at end of file diff --git a/modules/swagger-codegen/pom.xml b/modules/swagger-codegen/pom.xml index fc51a41fcdf..656223ff42b 100644 --- a/modules/swagger-codegen/pom.xml +++ b/modules/swagger-codegen/pom.xml @@ -154,6 +154,7 @@ target/site + org.apache.maven.plugins maven-javadoc-plugin diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JMeterCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JMeterCodegen.java new file mode 100644 index 00000000000..fb167477214 --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JMeterCodegen.java @@ -0,0 +1,183 @@ +package io.swagger.codegen.languages; + +import io.swagger.codegen.*; +import io.swagger.models.Operation; +import io.swagger.models.Path; +import io.swagger.models.Swagger; +import io.swagger.models.properties.*; +import org.apache.commons.lang.StringUtils; + +import java.util.*; +import java.io.File; + +public class JMeterCodegen extends DefaultCodegen implements CodegenConfig { + + // source folder where to write the files + protected String sourceFolder = ""; + protected String apiVersion = "1.0.0"; + + /** + * Configures the type of generator. + * + * @return the CodegenType for this generator + * @see io.swagger.codegen.CodegenType + */ + public CodegenType getTag() { + return CodegenType.CLIENT; + } + + /** + * Configures a friendly name for the generator. This will be used by the generator + * to select the library with the -l flag. + * + * @return the friendly name for the generator + */ + public String getName() { + return "jmeter"; + } + + /** + * Returns human-friendly help for the generator. Provide the consumer with help + * tips, parameters here + * + * @return A string value for the help message + */ + public String getHelp() { + return "Generates a JMeter .jmx file."; + } + + public JMeterCodegen() { + super(); + + // set the output folder here + outputFolder = "generated-code/JMeterCodegen"; + + /** + * Api classes. You can write classes for each Api file with the apiTemplateFiles map. + * as with models, add multiple entries with different extensions for multiple files per + * class + */ + apiTemplateFiles.put( + "api.mustache", // the template to use + ".jmx"); // the extension for each file to write + + apiTemplateFiles.put("testdata-localhost.mustache", ".csv"); + + /** + * Template Location. This is the location which templates will be read from. The generator + * will use the resource stream to attempt to read the templates. + */ + templateDir = "JMeter"; + + /** + * Api Package. Optional, if needed, this can be used in templates + */ + apiPackage = ""; + + /** + * Model Package. Optional, if needed, this can be used in templates + */ + modelPackage = ""; + + /** + * Reserved words. Override this with reserved words specific to your language + */ + reservedWords = new HashSet ( + Arrays.asList( + "sample1", // replace with static values + "sample2") + ); + + /** + * Additional Properties. These values can be passed to the templates and + * are available in models, apis, and supporting files + */ + additionalProperties.put("apiVersion", apiVersion); + +// supportingFiles.add(new SupportingFile("testdata-localhost.mustache", "input", "testdata-localhost.csv")); + } + + public void preprocessSwagger(Swagger swagger) { + if (swagger != null && swagger.getPaths() != null) { + for (String pathname : swagger.getPaths().keySet()) { + Path path = swagger.getPath(pathname); + if (path.getOperations() != null) { + for (Operation operation : path.getOperations()) { + String pathWithDollars = pathname.replaceAll("\\{", "\\$\\{"); + operation.setVendorExtension("x-path", pathWithDollars); + } + } + } + } + } + + /** + * Escapes a reserved word as defined in the `reservedWords` array. Handle escaping + * those terms here. This logic is only called if a variable matches the reseved words + * + * @return the escaped term + */ + @Override + public String escapeReservedWord(String name) { + return "_" + name; // add an underscore to the name + } + + /** + * Location to write model files. You can use the modelPackage() as defined when the class is + * instantiated + */ + public String modelFileFolder() { + return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar); + } + + /** + * Location to write api files. You can use the apiPackage() as defined when the class is + * instantiated + */ + @Override + public String apiFileFolder() { + return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar); + } + + /** + * Optional - type declaration. This is a String which is used by the templates to instantiate your + * types. There is typically special handling for different property types + * + * @return a string value used as the `dataType` field for model templates, `returnType` for api templates + */ + @Override + public String getTypeDeclaration(Property p) { + if(p instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) p; + Property inner = ap.getItems(); + return getSwaggerType(p) + "[" + getTypeDeclaration(inner) + "]"; + } + else if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + return getSwaggerType(p) + "[String, " + getTypeDeclaration(inner) + "]"; + } + return super.getTypeDeclaration(p); + } + + /** + * Optional - swagger type conversion. This is used to map swagger types in a `Property` into + * either language specific types via `typeMapping` or into complex models if there is not a mapping. + * + * @return a string value of the type or complex model for this property + * @see io.swagger.models.properties.Property + */ + @Override + public String getSwaggerType(Property p) { + String swaggerType = super.getSwaggerType(p); + String type = null; + if(typeMapping.containsKey(swaggerType)) { + type = typeMapping.get(swaggerType); + if(languageSpecificPrimitives.contains(type)) + return toModelName(type); + } + else + type = swaggerType; + return toModelName(type); + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java index 636f0157a52..254bedf4708 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java @@ -11,6 +11,12 @@ import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.SupportingFile; import io.swagger.models.Model; +import io.swagger.models.Operation; +import io.swagger.models.Path; +import io.swagger.models.Swagger; +import io.swagger.models.parameters.BodyParameter; +import io.swagger.models.parameters.FormParameter; +import io.swagger.models.parameters.Parameter; import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.BooleanProperty; import io.swagger.models.properties.DoubleProperty; @@ -98,6 +104,7 @@ public JavaClientCodegen() { .defaultValue("false")); supportedLibraries.put(DEFAULT_LIBRARY, "HTTP client: Jersey client 1.18. JSON processing: Jackson 2.4.2"); + supportedLibraries.put("feign", "HTTP client: Netflix Feign 8.1.1"); supportedLibraries.put("jersey2", "HTTP client: Jersey client 2.6"); supportedLibraries.put("okhttp-gson", "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1"); supportedLibraries.put("retrofit", "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1 (Retrofit 1.9.0)"); @@ -215,12 +222,16 @@ public void processOpts() { supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java")); final String authFolder = (sourceFolder + '/' + invokerPackage + ".auth").replace(".", "/"); - supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java")); - supportingFiles.add(new SupportingFile("auth/ApiKeyAuth.mustache", authFolder, "ApiKeyAuth.java")); - supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java")); - supportingFiles.add(new SupportingFile("auth/OAuthFlow.mustache", authFolder, "OAuthFlow.java")); + if ("feign".equals(getLibrary())) { + supportingFiles.add(new SupportingFile("FormAwareEncoder.mustache", invokerFolder, "FormAwareEncoder.java")); + } else { + supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java")); + supportingFiles.add(new SupportingFile("auth/ApiKeyAuth.mustache", authFolder, "ApiKeyAuth.java")); + supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java")); + supportingFiles.add(new SupportingFile("auth/OAuthFlow.mustache", authFolder, "OAuthFlow.java")); + } - if (!("retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary()))) { + if (!("feign".equals(getLibrary()) || "retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary()))) { supportingFiles.add(new SupportingFile("apiException.mustache", invokerFolder, "ApiException.java")); supportingFiles.add(new SupportingFile("Configuration.mustache", invokerFolder, "Configuration.java")); supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java")); @@ -237,7 +248,7 @@ public void processOpts() { } else if ("retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary())) { supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java")); supportingFiles.add(new SupportingFile("CollectionFormats.mustache", invokerFolder, "CollectionFormats.java")); - } else { + } else if (!"feign".equals(getLibrary())) { supportingFiles.add(new SupportingFile("TypeRef.mustache", invokerFolder, "TypeRef.java")); } } @@ -541,6 +552,57 @@ public Map postProcessOperations(Map objs) { return objs; } + public void preprocessSwagger(Swagger swagger) { + if (swagger != null && swagger.getPaths() != null) { + for (String pathname : swagger.getPaths().keySet()) { + Path path = swagger.getPath(pathname); + if (path.getOperations() != null) { + for (Operation operation : path.getOperations()) { + boolean hasFormParameters = false; + for (Parameter parameter : operation.getParameters()) { + if (parameter instanceof FormParameter) { + hasFormParameters = true; + } + } + + String defaultContentType = hasFormParameters ? "application/x-www-form-urlencoded" : "application/json"; + String contentType = operation.getConsumes() == null || operation.getConsumes().isEmpty() + ? defaultContentType : operation.getConsumes().get(0); + String accepts = getAccept(operation); + operation.setVendorExtension("x-contentType", contentType); + operation.setVendorExtension("x-accepts", accepts); + } + } + } + } + } + + private String getAccept(Operation operation) { + String accepts = null; + String defaultContentType = "application/json"; + if (operation.getProduces() != null && !operation.getProduces().isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (String produces : operation.getProduces()) { + if (defaultContentType.equalsIgnoreCase(produces)) { + accepts = defaultContentType; + break; + } else { + if (sb.length() > 0) { + sb.append(","); + } + sb.append(produces); + } + } + if (accepts == null) { + accepts = sb.toString(); + } + } else { + accepts = defaultContentType; + } + + return accepts; + } + protected boolean needToImport(String type) { return super.needToImport(type) && type.indexOf(".") < 0; } diff --git a/modules/swagger-codegen/src/main/resources/JMeter/api.mustache b/modules/swagger-codegen/src/main/resources/JMeter/api.mustache new file mode 100644 index 00000000000..1af63c2d66d --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/JMeter/api.mustache @@ -0,0 +1,178 @@ + + + + + + false + false + + + + host + localhost + = + + + port + 8080 + = + + + + + + + + + + testCases + ${__P(host,10)} + = + + + host + ${__P(host,localhost)} + = + + + port + ${__P(port,8080)} + = + {{#operations}}{{#operation}} + + testData.{{operationId}}File + ${__P(testData.{{operationId}}File,{{classname}}.csv)} + = + {{/operation}}{{/operations}} + + + + + + + + ${host} + ${port} + + + + + + 4 + + + {{#operations}}{{#operation}} + continue + + false + ${testCases} + + 1 + 1 + 1448391617000 + 1448391617000 + false + + + + + + {{#headerParams}} + + {{paramName}} + ${__RandomString(10,qwertyuiopasdfghjklzxcvbnm)} + {{/headerParams}} + + + + + + {{#queryParams}} + + false + 0 + = + true + {{paramName}} + {{/queryParams}} + + + + + + + + + {{vendorExtensions.x-path}} + {{httpMethod}} + true + false + true + false + HttpClient3.1 + false + + {{summary}} {{notes}} + + + + , + + ${testData.{{operationId}}File} + true + true + shareMode.all + false + + + + + + + ${httpStatusCode} + + Assertion.response_code + false + 8 + + + + {{/operation}} + {{/operations}} + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + false + false + false + false + false + 0 + true + true + + + + + + + + diff --git a/modules/swagger-codegen/src/main/resources/JMeter/testdata-localhost.mustache b/modules/swagger-codegen/src/main/resources/JMeter/testdata-localhost.mustache new file mode 100644 index 00000000000..48708a1d0fa --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/JMeter/testdata-localhost.mustache @@ -0,0 +1,2 @@ +testCase,httpStatusCode{{#operations}}{{#operation}}{{#hasParams}},{{/hasParams}}{{#allParams}}{{paramName}}{{#hasMore}},{{/hasMore}}{{/allParams}}{{/operation}}{{/operations}} +Success,200{{#operations}}{{#operation}}{{#hasParams}},{{/hasParams}}{{#allParams}}0{{#hasMore}},{{/hasMore}}{{/allParams}}{{/operation}}{{/operations}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/Java/libraries/feign/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/Java/libraries/feign/ApiClient.mustache new file mode 100644 index 00000000000..3f2bfcebd5b --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Java/libraries/feign/ApiClient.mustache @@ -0,0 +1,86 @@ +package {{invokerPackage}}; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import feign.Feign; +import feign.jackson.JacksonDecoder; +import feign.jackson.JacksonEncoder; +import feign.slf4j.Slf4jLogger; + +{{>generatedAnnotation}} +public class ApiClient { + public interface Api {} + + private ObjectMapper objectMapper; + private String basePath = "{{basePath}}"; + + public ApiClient() { + objectMapper = createObjectMapper(); + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + private ObjectMapper createObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + return objectMapper; + } + + /** + * Creates a feign client for given API interface. + * + * Usage: + * ApiClient apiClient = new ApiClient(); + * apiClient.setBasePath("http://localhost:8080"); + * XYZApi api = apiClient.buildClient(XYZApi.class); + * XYZResponse response = api.someMethod(...); + */ + public T buildClient(Class clientClass) { + return Feign.builder() + .encoder(new FormAwareEncoder(new JacksonEncoder(objectMapper))) + .decoder(new JacksonDecoder(objectMapper)) +// enable for basic auth: +// .requestInterceptor(new feign.auth.BasicAuthRequestInterceptor(username, password)) + .logger(new Slf4jLogger()) + .target(clientClass, basePath); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + public String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) return null; + if (StringUtil.containsIgnoreCase(accepts, "application/json")) return "application/json"; + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) return "application/json"; + if (StringUtil.containsIgnoreCase(contentTypes, "application/json")) return "application/json"; + return contentTypes[0]; + } +} diff --git a/modules/swagger-codegen/src/main/resources/Java/libraries/feign/FormAwareEncoder.mustache b/modules/swagger-codegen/src/main/resources/Java/libraries/feign/FormAwareEncoder.mustache new file mode 100644 index 00000000000..822aad582d4 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Java/libraries/feign/FormAwareEncoder.mustache @@ -0,0 +1,197 @@ +package {{invokerPackage}}; + +import java.io.*; +import java.lang.reflect.Type; +import java.net.URLEncoder; +import java.net.URLConnection; +import java.nio.charset.Charset; +import java.util.*; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +import feign.codec.EncodeException; +import feign.codec.Encoder; +import feign.RequestTemplate; + +{{>generatedAnnotation}} +public class FormAwareEncoder implements Encoder { + public static final String UTF_8 = "utf-8"; + private static final String LINE_FEED = "\r\n"; + private static final String TWO_DASH = "--"; + private static final String BOUNDARY = "----------------314159265358979323846"; + + private byte[] lineFeedBytes; + private byte[] boundaryBytes; + private byte[] twoDashBytes; + private byte[] atBytes; + private byte[] eqBytes; + + private final Encoder delegate; + private final DateFormat dateFormat; + + public FormAwareEncoder(Encoder delegate) { + this.delegate = delegate; + // Use RFC3339 format for date and datetime. + // See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 + this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + + // Use UTC as the default time zone. + this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + try { + this.lineFeedBytes = LINE_FEED.getBytes(UTF_8); + this.boundaryBytes = BOUNDARY.getBytes(UTF_8); + this.twoDashBytes = TWO_DASH.getBytes(UTF_8); + this.atBytes = "&".getBytes(UTF_8); + this.eqBytes = "=".getBytes(UTF_8); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException { + if (object instanceof Map) { + try { + encodeFormParams(template, (Map) object); + } catch (IOException e) { + throw new EncodeException("Failed to create request", e); + } + } else { + delegate.encode(object, bodyType, template); + } + } + + private void encodeFormParams(RequestTemplate template, Map formParams) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + boolean isMultiPart = isMultiPart(formParams); + boolean isFirstField = true; + for (Map.Entry param : formParams.entrySet()) { + String keyStr = param.getKey(); + if (param.getValue() instanceof File) { + addFilePart(baos, keyStr, (File) param.getValue()); + } else { + String valueStr = parameterToString(param.getValue()); + if (isMultiPart) { + addMultiPartFormField(baos, keyStr, valueStr); + } else { + addEncodedFormField(baos, keyStr, valueStr, isFirstField); + isFirstField = false; + } + } + } + + if (isMultiPart) { + baos.write(lineFeedBytes); + baos.write(twoDashBytes); + baos.write(boundaryBytes); + baos.write(twoDashBytes); + baos.write(lineFeedBytes); + } + + String contentType = isMultiPart ? "multipart/form-data; boundary=" + BOUNDARY : "application/x-www-form-urlencoded"; + template.header("Content-type"); + template.header("Content-type", contentType); + template.header("MIME-Version", "1.0"); + template.body(baos.toByteArray(), Charset.forName(UTF_8)); + } + + /* + * Currently only supports text files + */ + private void addFilePart(ByteArrayOutputStream baos, String fieldName, File uploadFile) throws IOException { + String fileName = uploadFile.getName(); + baos.write(twoDashBytes); + baos.write(boundaryBytes); + baos.write(lineFeedBytes); + + String contentDisposition = "Content-Disposition: form-data; name=\"" + fieldName + + "\"; filename=\"" + fileName + "\""; + baos.write(contentDisposition.getBytes(UTF_8)); + baos.write(lineFeedBytes); + String contentType = "Content-Type: " + URLConnection.guessContentTypeFromName(fileName); + baos.write(contentType.getBytes(UTF_8)); + baos.write(lineFeedBytes); + baos.write(lineFeedBytes); + + BufferedReader reader = new BufferedReader(new FileReader(uploadFile)); + InputStream input = new FileInputStream(uploadFile); + byte[] bytes = new byte[4096]; + int len = bytes.length; + while ((len = input.read(bytes)) != -1) { + baos.write(bytes, 0, len); + baos.write(lineFeedBytes); + } + + baos.write(lineFeedBytes); + } + + private void addEncodedFormField(ByteArrayOutputStream baos, String name, String value, boolean isFirstField) throws IOException { + if (!isFirstField) { + baos.write(atBytes); + } + + String encodedName = URLEncoder.encode(name, UTF_8); + String encodedValue = URLEncoder.encode(value, UTF_8); + baos.write(encodedName.getBytes(UTF_8)); + baos.write("=".getBytes(UTF_8)); + baos.write(encodedValue.getBytes(UTF_8)); + } + + private void addMultiPartFormField(ByteArrayOutputStream baos, String name, String value) throws IOException { + baos.write(twoDashBytes); + baos.write(boundaryBytes); + baos.write(lineFeedBytes); + + String contentDisposition = "Content-Disposition: form-data; name=\"" + name + "\""; + String contentType = "Content-Type: text/plain; charset=utf-8"; + + baos.write(contentDisposition.getBytes(UTF_8)); + baos.write(lineFeedBytes); + baos.write(contentType.getBytes(UTF_8)); + baos.write(lineFeedBytes); + baos.write(lineFeedBytes); + baos.write(value.getBytes(UTF_8)); + baos.write(lineFeedBytes); + } + + private boolean isMultiPart(Map formParams) { + boolean isMultiPart = false; + for (Map.Entry entry : formParams.entrySet()) { + if (entry.getValue() instanceof File) { + isMultiPart = true; + break; + } + } + return isMultiPart; + } + + /** + * Format the given parameter object into string. + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate((Date) param); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection)param) { + if(b.length() > 0) { + b.append(","); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /** + * Format the given Date object into string. + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } +} diff --git a/modules/swagger-codegen/src/main/resources/Java/libraries/feign/api.mustache b/modules/swagger-codegen/src/main/resources/Java/libraries/feign/api.mustache new file mode 100644 index 00000000000..729320bd2e5 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Java/libraries/feign/api.mustache @@ -0,0 +1,32 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}}import java.util.*; +{{/fullJavaUtil}} +import feign.*; + +{{>generatedAnnotation}} +public interface {{classname}} extends ApiClient.Api { + +{{#operations}}{{#operation}} + /** + * {{summary}} + * {{notes}} +{{#allParams}} * @param {{paramName}} {{description}} +{{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} + */ + @RequestLine("{{httpMethod}} {{{path}}}{{#hasQueryParams}}?{{/hasQueryParams}}{{#queryParams}}{{paramName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{#hasMore}}&{{/hasMore}}{{/queryParams}}") + @Headers({ + "Content-type: {{vendorExtensions.x-contentType}}", + "Accepts: {{vendorExtensions.x-accepts}}",{{#headerParams}} + "{{paramName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, + {{/hasMore}}{{/headerParams}} + }) + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}@Param("{{paramName}}") {{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/operation}} +{{/operations}} +} diff --git a/modules/swagger-codegen/src/main/resources/Java/libraries/feign/build.gradle.mustache b/modules/swagger-codegen/src/main/resources/Java/libraries/feign/build.gradle.mustache new file mode 100644 index 00000000000..a528180df28 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Java/libraries/feign/build.gradle.mustache @@ -0,0 +1,113 @@ +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.2.2' + classpath 'com.github.dcendents:android-maven-plugin:1.2' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 22 + buildToolsVersion '22.0.0' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 22 + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.0" + jackson_version = "2.6.3" + feign_version = "8.1.1" + jodatime_version = "2.5" + junit_version = "4.12" +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.netflix.feign:feign-core:$feign_version" + compile "com.netflix.feign:feign-jackson:$feign_version" + compile "com.netflix.feign:feign-slf4j:$feign_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:2.1.5" + compile "joda-time:joda-time:$jodatime_version" + compile "com.brsanthu:migbase64:2.2" + testCompile "junit:junit:$junit_version" +} diff --git a/modules/swagger-codegen/src/main/resources/Java/libraries/feign/pom.mustache b/modules/swagger-codegen/src/main/resources/Java/libraries/feign/pom.mustache new file mode 100644 index 00000000000..e8069b82931 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Java/libraries/feign/pom.mustache @@ -0,0 +1,183 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + + scm:git:git@github.com:swagger-api/swagger-mustache.git + scm:git:git@github.com:swagger-api/swagger-codegen.git + https://github.com/swagger-api/swagger-codegen + + + 2.2.0 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add_sources + generate-sources + + add-source + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + + com.netflix.feign + feign-core + ${feign-version} + + + com.netflix.feign + feign-jackson + ${feign-version} + + + com.netflix.feign + feign-slf4j + ${feign-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + + com.fasterxml.jackson.datatype + jackson-datatype-joda + 2.1.5 + + + joda-time + joda-time + ${jodatime-version} + + + + + com.brsanthu + migbase64 + 2.2 + + + + + junit + junit + ${junit-version} + test + + + + 1.5.0 + 8.1.1 + 2.6.3 + 2.5 + 4.12 + 1.0.0 + + diff --git a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig index 5c607488d9b..de31683a15f 100644 --- a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig +++ b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig @@ -7,6 +7,7 @@ io.swagger.codegen.languages.FlaskConnexionCodegen io.swagger.codegen.languages.JavaClientCodegen io.swagger.codegen.languages.JaxRSServerCodegen io.swagger.codegen.languages.JavaInflectorServerCodegen +io.swagger.codegen.languages.JMeterCodegen io.swagger.codegen.languages.NodeJSServerCodegen io.swagger.codegen.languages.ObjcClientCodegen io.swagger.codegen.languages.PerlClientCodegen diff --git a/samples/client/petstore/java/feign/README.md b/samples/client/petstore/java/feign/README.md new file mode 100644 index 00000000000..8afc37518fc --- /dev/null +++ b/samples/client/petstore/java/feign/README.md @@ -0,0 +1,43 @@ +# swagger-java-client + +## Requirements + +Building the API client library requires [Maven](https://maven.apache.org/) to be installed. + +## Installation & Usage + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn deploy +``` + +Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. + +After the client libarary is installed/deployed, you can use it in your Maven project by adding the following to your *pom.xml*: + +```xml + + io.swagger + swagger-java-client + 1.0.0 + compile + + +``` + +## Recommendation + +It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issue. + +## Author + +apiteam@swagger.io + + diff --git a/samples/client/petstore/java/feign/build.gradle b/samples/client/petstore/java/feign/build.gradle new file mode 100644 index 00000000000..383e0a1dc95 --- /dev/null +++ b/samples/client/petstore/java/feign/build.gradle @@ -0,0 +1,113 @@ +group = 'io.swagger' +version = '1.0.0' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.2.2' + classpath 'com.github.dcendents:android-maven-plugin:1.2' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 22 + buildToolsVersion '22.0.0' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 22 + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + + install { + repositories.mavenInstaller { + pom.artifactId = 'swagger-java-client' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.0" + jackson_version = "2.6.3" + feign_version = "8.1.1" + jodatime_version = "2.5" + junit_version = "4.12" +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.netflix.feign:feign-core:$feign_version" + compile "com.netflix.feign:feign-jackson:$feign_version" + compile "com.netflix.feign:feign-slf4j:$feign_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:2.1.5" + compile "joda-time:joda-time:$jodatime_version" + compile "com.brsanthu:migbase64:2.2" + testCompile "junit:junit:$junit_version" +} diff --git a/samples/client/petstore/java/feign/gradle.properties b/samples/client/petstore/java/feign/gradle.properties new file mode 100644 index 00000000000..05644f0754a --- /dev/null +++ b/samples/client/petstore/java/feign/gradle.properties @@ -0,0 +1,2 @@ +# Uncomment to build for Android +#target = android \ No newline at end of file diff --git a/samples/client/petstore/java/feign/pom.xml b/samples/client/petstore/java/feign/pom.xml new file mode 100644 index 00000000000..967bdabcc6b --- /dev/null +++ b/samples/client/petstore/java/feign/pom.xml @@ -0,0 +1,183 @@ + + 4.0.0 + io.swagger + swagger-java-client + jar + swagger-java-client + 1.0.0 + + scm:git:git@github.com:swagger-api/swagger-mustache.git + scm:git:git@github.com:swagger-api/swagger-codegen.git + https://github.com/swagger-api/swagger-codegen + + + 2.2.0 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add_sources + generate-sources + + add-source + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + + com.netflix.feign + feign-core + ${feign-version} + + + com.netflix.feign + feign-jackson + ${feign-version} + + + com.netflix.feign + feign-slf4j + ${feign-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + + com.fasterxml.jackson.datatype + jackson-datatype-joda + 2.1.5 + + + joda-time + joda-time + ${jodatime-version} + + + + + com.brsanthu + migbase64 + 2.2 + + + + + junit + junit + ${junit-version} + test + + + + 1.5.0 + 8.1.1 + 2.6.3 + 2.5 + 4.12 + 1.0.0 + + diff --git a/samples/client/petstore/java/feign/settings.gradle b/samples/client/petstore/java/feign/settings.gradle new file mode 100644 index 00000000000..55640f75122 --- /dev/null +++ b/samples/client/petstore/java/feign/settings.gradle @@ -0,0 +1 @@ +rootProject.name = "swagger-java-client" \ No newline at end of file diff --git a/samples/client/petstore/java/feign/src/main/AndroidManifest.xml b/samples/client/petstore/java/feign/src/main/AndroidManifest.xml new file mode 100644 index 00000000000..465dcb520c4 --- /dev/null +++ b/samples/client/petstore/java/feign/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + + diff --git a/samples/client/petstore/java/feign/src/main/java/io/swagger/client/ApiClient.java b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/ApiClient.java new file mode 100644 index 00000000000..42439dbdf24 --- /dev/null +++ b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/ApiClient.java @@ -0,0 +1,86 @@ +package io.swagger.client; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import feign.Feign; +import feign.jackson.JacksonDecoder; +import feign.jackson.JacksonEncoder; +import feign.slf4j.Slf4jLogger; + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-12-09T22:59:22.180-05:00") +public class ApiClient { + public interface Api {} + + private ObjectMapper objectMapper; + private String basePath = "http://petstore.swagger.io/v2"; + + public ApiClient() { + objectMapper = createObjectMapper(); + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + private ObjectMapper createObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + return objectMapper; + } + + /** + * Creates a feign client for given API interface. + * + * Usage: + * ApiClient apiClient = new ApiClient(); + * apiClient.setBasePath("http://localhost:8080"); + * XYZApi api = apiClient.buildClient(XYZApi.class); + * XYZResponse response = api.someMethod(...); + */ + public T buildClient(Class clientClass) { + return Feign.builder() + .encoder(new FormAwareEncoder(new JacksonEncoder(objectMapper))) + .decoder(new JacksonDecoder(objectMapper)) +// enable for basic auth: +// .requestInterceptor(new feign.auth.BasicAuthRequestInterceptor(username, password)) + .logger(new Slf4jLogger()) + .target(clientClass, basePath); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + public String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) return null; + if (StringUtil.containsIgnoreCase(accepts, "application/json")) return "application/json"; + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) return "application/json"; + if (StringUtil.containsIgnoreCase(contentTypes, "application/json")) return "application/json"; + return contentTypes[0]; + } +} diff --git a/samples/client/petstore/java/feign/src/main/java/io/swagger/client/FormAwareEncoder.java b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/FormAwareEncoder.java new file mode 100644 index 00000000000..e38faaf009a --- /dev/null +++ b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/FormAwareEncoder.java @@ -0,0 +1,197 @@ +package io.swagger.client; + +import java.io.*; +import java.lang.reflect.Type; +import java.net.URLEncoder; +import java.net.URLConnection; +import java.nio.charset.Charset; +import java.util.*; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +import feign.codec.EncodeException; +import feign.codec.Encoder; +import feign.RequestTemplate; + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-12-09T22:59:22.180-05:00") +public class FormAwareEncoder implements Encoder { + public static final String UTF_8 = "utf-8"; + private static final String LINE_FEED = "\r\n"; + private static final String TWO_DASH = "--"; + private static final String BOUNDARY = "----------------314159265358979323846"; + + private byte[] lineFeedBytes; + private byte[] boundaryBytes; + private byte[] twoDashBytes; + private byte[] atBytes; + private byte[] eqBytes; + + private final Encoder delegate; + private final DateFormat dateFormat; + + public FormAwareEncoder(Encoder delegate) { + this.delegate = delegate; + // Use RFC3339 format for date and datetime. + // See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 + this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + + // Use UTC as the default time zone. + this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + try { + this.lineFeedBytes = LINE_FEED.getBytes(UTF_8); + this.boundaryBytes = BOUNDARY.getBytes(UTF_8); + this.twoDashBytes = TWO_DASH.getBytes(UTF_8); + this.atBytes = "&".getBytes(UTF_8); + this.eqBytes = "=".getBytes(UTF_8); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException { + if (object instanceof Map) { + try { + encodeFormParams(template, (Map) object); + } catch (IOException e) { + throw new EncodeException("Failed to create request", e); + } + } else { + delegate.encode(object, bodyType, template); + } + } + + private void encodeFormParams(RequestTemplate template, Map formParams) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + boolean isMultiPart = isMultiPart(formParams); + boolean isFirstField = true; + for (Map.Entry param : formParams.entrySet()) { + String keyStr = param.getKey(); + if (param.getValue() instanceof File) { + addFilePart(baos, keyStr, (File) param.getValue()); + } else { + String valueStr = parameterToString(param.getValue()); + if (isMultiPart) { + addMultiPartFormField(baos, keyStr, valueStr); + } else { + addEncodedFormField(baos, keyStr, valueStr, isFirstField); + isFirstField = false; + } + } + } + + if (isMultiPart) { + baos.write(lineFeedBytes); + baos.write(twoDashBytes); + baos.write(boundaryBytes); + baos.write(twoDashBytes); + baos.write(lineFeedBytes); + } + + String contentType = isMultiPart ? "multipart/form-data; boundary=" + BOUNDARY : "application/x-www-form-urlencoded"; + template.header("Content-type"); + template.header("Content-type", contentType); + template.header("MIME-Version", "1.0"); + template.body(baos.toByteArray(), Charset.forName(UTF_8)); + } + + /* + * Currently only supports text files + */ + private void addFilePart(ByteArrayOutputStream baos, String fieldName, File uploadFile) throws IOException { + String fileName = uploadFile.getName(); + baos.write(twoDashBytes); + baos.write(boundaryBytes); + baos.write(lineFeedBytes); + + String contentDisposition = "Content-Disposition: form-data; name=\"" + fieldName + + "\"; filename=\"" + fileName + "\""; + baos.write(contentDisposition.getBytes(UTF_8)); + baos.write(lineFeedBytes); + String contentType = "Content-Type: " + URLConnection.guessContentTypeFromName(fileName); + baos.write(contentType.getBytes(UTF_8)); + baos.write(lineFeedBytes); + baos.write(lineFeedBytes); + + BufferedReader reader = new BufferedReader(new FileReader(uploadFile)); + InputStream input = new FileInputStream(uploadFile); + byte[] bytes = new byte[4096]; + int len = bytes.length; + while ((len = input.read(bytes)) != -1) { + baos.write(bytes, 0, len); + baos.write(lineFeedBytes); + } + + baos.write(lineFeedBytes); + } + + private void addEncodedFormField(ByteArrayOutputStream baos, String name, String value, boolean isFirstField) throws IOException { + if (!isFirstField) { + baos.write(atBytes); + } + + String encodedName = URLEncoder.encode(name, UTF_8); + String encodedValue = URLEncoder.encode(value, UTF_8); + baos.write(encodedName.getBytes(UTF_8)); + baos.write("=".getBytes(UTF_8)); + baos.write(encodedValue.getBytes(UTF_8)); + } + + private void addMultiPartFormField(ByteArrayOutputStream baos, String name, String value) throws IOException { + baos.write(twoDashBytes); + baos.write(boundaryBytes); + baos.write(lineFeedBytes); + + String contentDisposition = "Content-Disposition: form-data; name=\"" + name + "\""; + String contentType = "Content-Type: text/plain; charset=utf-8"; + + baos.write(contentDisposition.getBytes(UTF_8)); + baos.write(lineFeedBytes); + baos.write(contentType.getBytes(UTF_8)); + baos.write(lineFeedBytes); + baos.write(lineFeedBytes); + baos.write(value.getBytes(UTF_8)); + baos.write(lineFeedBytes); + } + + private boolean isMultiPart(Map formParams) { + boolean isMultiPart = false; + for (Map.Entry entry : formParams.entrySet()) { + if (entry.getValue() instanceof File) { + isMultiPart = true; + break; + } + } + return isMultiPart; + } + + /** + * Format the given parameter object into string. + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate((Date) param); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection)param) { + if(b.length() > 0) { + b.append(","); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /** + * Format the given Date object into string. + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } +} diff --git a/samples/client/petstore/java/feign/src/main/java/io/swagger/client/StringUtil.java b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/StringUtil.java new file mode 100644 index 00000000000..cc437fee0c0 --- /dev/null +++ b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/StringUtil.java @@ -0,0 +1,51 @@ +package io.swagger.client; + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-12-09T22:59:22.180-05:00") +public class StringUtil { + /** + * Check if the given array contains the given value (with case-insensitive comparison). + * + * @param array The array + * @param value The value to search + * @return true if the array contains the value + */ + public static boolean containsIgnoreCase(String[] array, String value) { + for (String str : array) { + if (value == null && str == null) return true; + if (value != null && value.equalsIgnoreCase(str)) return true; + } + return false; + } + + /** + * Join an array of strings with the given separator. + *

+ * Note: This might be replaced by utility method from commons-lang or guava someday + * if one of those libraries is added as dependency. + *

+ * + * @param array The array of strings + * @param separator The separator + * @return the resulting string + */ + public static String join(String[] array, String separator) { + int len = array.length; + if (len == 0) return ""; + + StringBuilder out = new StringBuilder(); + out.append(array[0]); + for (int i = 1; i < len; i++) { + out.append(separator).append(array[i]); + } + return out.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + public static String toIndentedString(Object o) { + if (o == null) return "null"; + return o.toString().replace("\n", "\n "); + } +} diff --git a/samples/client/petstore/java/feign/src/main/java/io/swagger/client/api/PetApi.java b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/api/PetApi.java new file mode 100644 index 00000000000..536e953e699 --- /dev/null +++ b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/api/PetApi.java @@ -0,0 +1,129 @@ +package io.swagger.client.api; + +import io.swagger.client.ApiClient; + +import io.swagger.client.model.Pet; +import java.io.File; +import io.swagger.client.model.ApiResponse; + + +import java.util.*; + +import feign.*; + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-12-09T22:59:22.180-05:00") +public interface PetApi extends ApiClient.Api { + + + /** + * Update an existing pet + * + * @param body Pet object that needs to be added to the store + * @return void + */ + @RequestLine("PUT /pet") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + void updatePet(Pet body); + + /** + * Add a new pet to the store + * + * @param body Pet object that needs to be added to the store + * @return void + */ + @RequestLine("POST /pet") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + void addPet(Pet body); + + /** + * Finds Pets by status + * Multiple status values can be provided with comma seperated strings + * @param status Status values that need to be considered for filter + * @return List + */ + @RequestLine("GET /pet/findByStatus?status={status}") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + List findPetsByStatus(@Param("status") List status); + + /** + * Finds Pets by tags + * Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing. + * @param tags Tags to filter by + * @return List + */ + @RequestLine("GET /pet/findByTags?tags={tags}") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + List findPetsByTags(@Param("tags") List tags); + + /** + * Find pet by ID + * Returns a single pet + * @param petId ID of pet to return + * @return Pet + */ + @RequestLine("GET /pet/{petId}") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + Pet getPetById(@Param("petId") Long petId); + + /** + * Updates a pet in the store with form data + * + * @param petId ID of pet that needs to be updated + * @param name Updated name of the pet + * @param status Updated status of the pet + * @return void + */ + @RequestLine("POST /pet/{petId}") + @Headers({ + "Content-type: application/x-www-form-urlencoded", + "Accepts: application/json", + }) + void updatePetWithForm(@Param("petId") Long petId, @Param("name") String name, @Param("status") String status); + + /** + * Deletes a pet + * + * @param petId Pet id to delete + * @param apiKey + * @return void + */ + @RequestLine("DELETE /pet/{petId}") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + "apiKey: {apiKey}" + }) + void deletePet(@Param("petId") Long petId, @Param("apiKey") String apiKey); + + /** + * uploads an image + * + * @param petId ID of pet to update + * @param additionalMetadata Additional data to pass to server + * @param file file to upload + * @return ApiResponse + */ + @RequestLine("POST /pet/{petId}/uploadImage") + @Headers({ + "Content-type: multipart/form-data", + "Accepts: application/json", + }) + ApiResponse uploadFile(@Param("petId") Long petId, @Param("additionalMetadata") String additionalMetadata, @Param("file") File file); + + +} diff --git a/samples/client/petstore/java/feign/src/main/java/io/swagger/client/api/StoreApi.java b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/api/StoreApi.java new file mode 100644 index 00000000000..552c62db919 --- /dev/null +++ b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/api/StoreApi.java @@ -0,0 +1,69 @@ +package io.swagger.client.api; + +import io.swagger.client.ApiClient; + +import java.util.Map; +import io.swagger.client.model.Order; + + +import java.util.*; + +import feign.*; + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-12-09T22:59:22.180-05:00") +public interface StoreApi extends ApiClient.Api { + + + /** + * Returns pet inventories by status + * Returns a map of status codes to quantities + * @return Map + */ + @RequestLine("GET /store/inventory") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + Map getInventory(); + + /** + * Place an order for a pet + * + * @param body order placed for purchasing the pet + * @return Order + */ + @RequestLine("POST /store/order") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + Order placeOrder(Order body); + + /** + * Find purchase order by ID + * For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + * @param orderId ID of pet that needs to be fetched + * @return Order + */ + @RequestLine("GET /store/order/{orderId}") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + Order getOrderById(@Param("orderId") Long orderId); + + /** + * Delete purchase order by ID + * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + * @param orderId ID of the order that needs to be deleted + * @return void + */ + @RequestLine("DELETE /store/order/{orderId}") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + void deleteOrder(@Param("orderId") String orderId); + + +} diff --git a/samples/client/petstore/java/feign/src/main/java/io/swagger/client/api/UserApi.java b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/api/UserApi.java new file mode 100644 index 00000000000..610bd399700 --- /dev/null +++ b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/api/UserApi.java @@ -0,0 +1,123 @@ +package io.swagger.client.api; + +import io.swagger.client.ApiClient; + +import io.swagger.client.model.User; +import java.util.*; + + +import java.util.*; + +import feign.*; + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-12-09T22:59:22.180-05:00") +public interface UserApi extends ApiClient.Api { + + + /** + * Create user + * This can only be done by the logged in user. + * @param body Created user object + * @return void + */ + @RequestLine("POST /user") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + void createUser(User body); + + /** + * Creates list of users with given input array + * + * @param body List of user object + * @return void + */ + @RequestLine("POST /user/createWithArray") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + void createUsersWithArrayInput(List body); + + /** + * Creates list of users with given input array + * + * @param body List of user object + * @return void + */ + @RequestLine("POST /user/createWithList") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + void createUsersWithListInput(List body); + + /** + * Logs user into the system + * + * @param username The user name for login + * @param password The password for login in clear text + * @return String + */ + @RequestLine("GET /user/login?username={username}&password={password}") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + String loginUser(@Param("username") String username, @Param("password") String password); + + /** + * Logs out current logged in user session + * + * @return void + */ + @RequestLine("GET /user/logout") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + void logoutUser(); + + /** + * Get user by user name + * + * @param username The name that needs to be fetched. Use user1 for testing. + * @return User + */ + @RequestLine("GET /user/{username}") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + User getUserByName(@Param("username") String username); + + /** + * Updated user + * This can only be done by the logged in user. + * @param username name that need to be deleted + * @param body Updated user object + * @return void + */ + @RequestLine("PUT /user/{username}") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + void updateUser(@Param("username") String username, User body); + + /** + * Delete user + * This can only be done by the logged in user. + * @param username The name that needs to be deleted + * @return void + */ + @RequestLine("DELETE /user/{username}") + @Headers({ + "Content-type: application/json", + "Accepts: application/json", + }) + void deleteUser(@Param("username") String username); + + +} diff --git a/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/ApiResponse.java b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/ApiResponse.java new file mode 100644 index 00000000000..ab98bf61e89 --- /dev/null +++ b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/ApiResponse.java @@ -0,0 +1,92 @@ +package io.swagger.client.model; + +import io.swagger.client.StringUtil; + + + +import java.util.Objects; + +import io.swagger.annotations.*; +import com.fasterxml.jackson.annotation.JsonProperty; + + + +@ApiModel(description = "") +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-12-09T22:59:22.180-05:00") +public class ApiResponse { + + private Integer code = null; + private String type = null; + private String message = null; + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("code") + public Integer getCode() { + return code; + } + public void setCode(Integer code) { + this.code = code; + } + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("type") + public String getType() { + return type; + } + public void setType(String type) { + this.type = type; + } + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("message") + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ApiResponse apiResponse = (ApiResponse) o; + return Objects.equals(code, apiResponse.code) && + Objects.equals(type, apiResponse.type) && + Objects.equals(message, apiResponse.message); + } + + @Override + public int hashCode() { + return Objects.hash(code, type, message); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ApiResponse {\n"); + + sb.append(" code: ").append(StringUtil.toIndentedString(code)).append("\n"); + sb.append(" type: ").append(StringUtil.toIndentedString(type)).append("\n"); + sb.append(" message: ").append(StringUtil.toIndentedString(message)).append("\n"); + sb.append("}"); + return sb.toString(); + } +} + + diff --git a/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/Category.java b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/Category.java new file mode 100644 index 00000000000..3a22c2b9c60 --- /dev/null +++ b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/Category.java @@ -0,0 +1,77 @@ +package io.swagger.client.model; + +import io.swagger.client.StringUtil; + + + +import java.util.Objects; + +import io.swagger.annotations.*; +import com.fasterxml.jackson.annotation.JsonProperty; + + + +@ApiModel(description = "") +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-12-09T22:59:22.180-05:00") +public class Category { + + private Long id = null; + private String name = null; + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("id") + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("name") + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Category category = (Category) o; + return Objects.equals(id, category.id) && + Objects.equals(name, category.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Category {\n"); + + sb.append(" id: ").append(StringUtil.toIndentedString(id)).append("\n"); + sb.append(" name: ").append(StringUtil.toIndentedString(name)).append("\n"); + sb.append("}"); + return sb.toString(); + } +} + + diff --git a/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/Order.java b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/Order.java new file mode 100644 index 00000000000..9b87b66c9e6 --- /dev/null +++ b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/Order.java @@ -0,0 +1,157 @@ +package io.swagger.client.model; + +import io.swagger.client.StringUtil; +import java.util.Date; + + + +import java.util.Objects; + +import io.swagger.annotations.*; +import com.fasterxml.jackson.annotation.JsonProperty; + + + +@ApiModel(description = "") +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-12-09T22:59:22.180-05:00") +public class Order { + + private Long id = null; + private Long petId = null; + private Integer quantity = null; + private Date shipDate = null; + +public enum StatusEnum { + PLACED("placed"), + APPROVED("approved"), + DELIVERED("delivered"); + + private String value; + + StatusEnum(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } +} + + private StatusEnum status = null; + private Boolean complete = false; + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("id") + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("petId") + public Long getPetId() { + return petId; + } + public void setPetId(Long petId) { + this.petId = petId; + } + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("quantity") + public Integer getQuantity() { + return quantity; + } + public void setQuantity(Integer quantity) { + this.quantity = quantity; + } + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("shipDate") + public Date getShipDate() { + return shipDate; + } + public void setShipDate(Date shipDate) { + this.shipDate = shipDate; + } + + + /** + * Order Status + **/ + @ApiModelProperty(value = "Order Status") + @JsonProperty("status") + public StatusEnum getStatus() { + return status; + } + public void setStatus(StatusEnum status) { + this.status = status; + } + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("complete") + public Boolean getComplete() { + return complete; + } + public void setComplete(Boolean complete) { + this.complete = complete; + } + + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Order order = (Order) o; + return Objects.equals(id, order.id) && + Objects.equals(petId, order.petId) && + Objects.equals(quantity, order.quantity) && + Objects.equals(shipDate, order.shipDate) && + Objects.equals(status, order.status) && + Objects.equals(complete, order.complete); + } + + @Override + public int hashCode() { + return Objects.hash(id, petId, quantity, shipDate, status, complete); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Order {\n"); + + sb.append(" id: ").append(StringUtil.toIndentedString(id)).append("\n"); + sb.append(" petId: ").append(StringUtil.toIndentedString(petId)).append("\n"); + sb.append(" quantity: ").append(StringUtil.toIndentedString(quantity)).append("\n"); + sb.append(" shipDate: ").append(StringUtil.toIndentedString(shipDate)).append("\n"); + sb.append(" status: ").append(StringUtil.toIndentedString(status)).append("\n"); + sb.append(" complete: ").append(StringUtil.toIndentedString(complete)).append("\n"); + sb.append("}"); + return sb.toString(); + } +} + + diff --git a/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/Pet.java b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/Pet.java new file mode 100644 index 00000000000..07c18075bd2 --- /dev/null +++ b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/Pet.java @@ -0,0 +1,159 @@ +package io.swagger.client.model; + +import io.swagger.client.StringUtil; +import io.swagger.client.model.Category; +import java.util.*; +import io.swagger.client.model.Tag; + + + +import java.util.Objects; + +import io.swagger.annotations.*; +import com.fasterxml.jackson.annotation.JsonProperty; + + + +@ApiModel(description = "") +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-12-09T22:59:22.180-05:00") +public class Pet { + + private Long id = null; + private Category category = null; + private String name = null; + private List photoUrls = new ArrayList(); + private List tags = new ArrayList(); + +public enum StatusEnum { + AVAILABLE("available"), + PENDING("pending"), + SOLD("sold"); + + private String value; + + StatusEnum(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } +} + + private StatusEnum status = null; + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("id") + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("category") + public Category getCategory() { + return category; + } + public void setCategory(Category category) { + this.category = category; + } + + + /** + **/ + @ApiModelProperty(required = true, value = "") + @JsonProperty("name") + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + + /** + **/ + @ApiModelProperty(required = true, value = "") + @JsonProperty("photoUrls") + public List getPhotoUrls() { + return photoUrls; + } + public void setPhotoUrls(List photoUrls) { + this.photoUrls = photoUrls; + } + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("tags") + public List getTags() { + return tags; + } + public void setTags(List tags) { + this.tags = tags; + } + + + /** + * pet status in the store + **/ + @ApiModelProperty(value = "pet status in the store") + @JsonProperty("status") + public StatusEnum getStatus() { + return status; + } + public void setStatus(StatusEnum status) { + this.status = status; + } + + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Pet pet = (Pet) o; + return Objects.equals(id, pet.id) && + Objects.equals(category, pet.category) && + Objects.equals(name, pet.name) && + Objects.equals(photoUrls, pet.photoUrls) && + Objects.equals(tags, pet.tags) && + Objects.equals(status, pet.status); + } + + @Override + public int hashCode() { + return Objects.hash(id, category, name, photoUrls, tags, status); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Pet {\n"); + + sb.append(" id: ").append(StringUtil.toIndentedString(id)).append("\n"); + sb.append(" category: ").append(StringUtil.toIndentedString(category)).append("\n"); + sb.append(" name: ").append(StringUtil.toIndentedString(name)).append("\n"); + sb.append(" photoUrls: ").append(StringUtil.toIndentedString(photoUrls)).append("\n"); + sb.append(" tags: ").append(StringUtil.toIndentedString(tags)).append("\n"); + sb.append(" status: ").append(StringUtil.toIndentedString(status)).append("\n"); + sb.append("}"); + return sb.toString(); + } +} + + diff --git a/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/Tag.java b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/Tag.java new file mode 100644 index 00000000000..80b3919e532 --- /dev/null +++ b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/Tag.java @@ -0,0 +1,77 @@ +package io.swagger.client.model; + +import io.swagger.client.StringUtil; + + + +import java.util.Objects; + +import io.swagger.annotations.*; +import com.fasterxml.jackson.annotation.JsonProperty; + + + +@ApiModel(description = "") +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-12-09T22:59:22.180-05:00") +public class Tag { + + private Long id = null; + private String name = null; + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("id") + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("name") + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tag tag = (Tag) o; + return Objects.equals(id, tag.id) && + Objects.equals(name, tag.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Tag {\n"); + + sb.append(" id: ").append(StringUtil.toIndentedString(id)).append("\n"); + sb.append(" name: ").append(StringUtil.toIndentedString(name)).append("\n"); + sb.append("}"); + return sb.toString(); + } +} + + diff --git a/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/User.java b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/User.java new file mode 100644 index 00000000000..efa18d38dcf --- /dev/null +++ b/samples/client/petstore/java/feign/src/main/java/io/swagger/client/model/User.java @@ -0,0 +1,168 @@ +package io.swagger.client.model; + +import io.swagger.client.StringUtil; + + + +import java.util.Objects; + +import io.swagger.annotations.*; +import com.fasterxml.jackson.annotation.JsonProperty; + + + +@ApiModel(description = "") +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-12-09T22:59:22.180-05:00") +public class User { + + private Long id = null; + private String username = null; + private String firstName = null; + private String lastName = null; + private String email = null; + private String password = null; + private String phone = null; + private Integer userStatus = null; + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("id") + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("username") + public String getUsername() { + return username; + } + public void setUsername(String username) { + this.username = username; + } + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("firstName") + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("lastName") + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("email") + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("password") + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + + + /** + **/ + @ApiModelProperty(value = "") + @JsonProperty("phone") + public String getPhone() { + return phone; + } + public void setPhone(String phone) { + this.phone = phone; + } + + + /** + * User Status + **/ + @ApiModelProperty(value = "User Status") + @JsonProperty("userStatus") + public Integer getUserStatus() { + return userStatus; + } + public void setUserStatus(Integer userStatus) { + this.userStatus = userStatus; + } + + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + User user = (User) o; + return Objects.equals(id, user.id) && + Objects.equals(username, user.username) && + Objects.equals(firstName, user.firstName) && + Objects.equals(lastName, user.lastName) && + Objects.equals(email, user.email) && + Objects.equals(password, user.password) && + Objects.equals(phone, user.phone) && + Objects.equals(userStatus, user.userStatus); + } + + @Override + public int hashCode() { + return Objects.hash(id, username, firstName, lastName, email, password, phone, userStatus); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class User {\n"); + + sb.append(" id: ").append(StringUtil.toIndentedString(id)).append("\n"); + sb.append(" username: ").append(StringUtil.toIndentedString(username)).append("\n"); + sb.append(" firstName: ").append(StringUtil.toIndentedString(firstName)).append("\n"); + sb.append(" lastName: ").append(StringUtil.toIndentedString(lastName)).append("\n"); + sb.append(" email: ").append(StringUtil.toIndentedString(email)).append("\n"); + sb.append(" password: ").append(StringUtil.toIndentedString(password)).append("\n"); + sb.append(" phone: ").append(StringUtil.toIndentedString(phone)).append("\n"); + sb.append(" userStatus: ").append(StringUtil.toIndentedString(userStatus)).append("\n"); + sb.append("}"); + return sb.toString(); + } +} + + diff --git a/samples/client/petstore/java/feign/src/test/java/io/swagger/client/StringUtilTest.java b/samples/client/petstore/java/feign/src/test/java/io/swagger/client/StringUtilTest.java new file mode 100644 index 00000000000..c93908b8482 --- /dev/null +++ b/samples/client/petstore/java/feign/src/test/java/io/swagger/client/StringUtilTest.java @@ -0,0 +1,32 @@ +package io.swagger.client; + +import org.junit.*; +import static org.junit.Assert.*; + +public class StringUtilTest { + @Test + public void testContainsIgnoreCase() { + assertTrue(StringUtil.containsIgnoreCase(new String[]{"abc"}, "abc")); + assertTrue(StringUtil.containsIgnoreCase(new String[]{"abc"}, "ABC")); + assertTrue(StringUtil.containsIgnoreCase(new String[]{"ABC"}, "abc")); + assertTrue(StringUtil.containsIgnoreCase(new String[]{null, "abc"}, "ABC")); + assertTrue(StringUtil.containsIgnoreCase(new String[]{null, "abc"}, null)); + + assertFalse(StringUtil.containsIgnoreCase(new String[]{"abc"}, "def")); + assertFalse(StringUtil.containsIgnoreCase(new String[]{}, "ABC")); + assertFalse(StringUtil.containsIgnoreCase(new String[]{}, null)); + } + + @Test + public void testJoin() { + String[] array = {"aa", "bb", "cc"}; + assertEquals("aa,bb,cc", StringUtil.join(array, ",")); + assertEquals("aa, bb, cc", StringUtil.join(array, ", ")); + assertEquals("aabbcc", StringUtil.join(array, "")); + assertEquals("aa bb cc", StringUtil.join(array, " ")); + assertEquals("aa\nbb\ncc", StringUtil.join(array, "\n")); + + assertEquals("", StringUtil.join(new String[]{}, ",")); + assertEquals("abc", StringUtil.join(new String[]{"abc"}, ",")); + } +} \ No newline at end of file diff --git a/samples/client/petstore/java/feign/src/test/java/io/swagger/petstore/test/PetApiTest.java b/samples/client/petstore/java/feign/src/test/java/io/swagger/petstore/test/PetApiTest.java new file mode 100644 index 00000000000..402d60b37c2 --- /dev/null +++ b/samples/client/petstore/java/feign/src/test/java/io/swagger/petstore/test/PetApiTest.java @@ -0,0 +1,199 @@ +package io.swagger.petstore.test; + +import io.swagger.client.ApiClient; + +import io.swagger.client.api.*; +import io.swagger.client.model.*; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.*; +import static org.junit.Assert.*; + +public class PetApiTest { + ApiClient apiClient; + PetApi api; + + @Before + public void setup() { + apiClient = new ApiClient(); + api = apiClient.buildClient(PetApi.class); + } + + @Test + public void testApiClient() { + // the default api client is used + assertEquals("http://petstore.swagger.io/v2", apiClient.getBasePath()); + + ApiClient newClient = new ApiClient(); + newClient.setBasePath("http://example.com"); + + assertEquals("http://example.com", newClient.getBasePath()); + } + + @Test + public void testCreateAndGetPet() throws Exception { + Pet pet = createRandomPet(); + api.addPet(pet); + + Pet fetched = api.getPetById(pet.getId()); + assertNotNull(fetched); + assertEquals(pet.getId(), fetched.getId()); + assertNotNull(fetched.getCategory()); + assertEquals(fetched.getCategory().getName(), pet.getCategory().getName()); + } + + @Test + public void testUpdatePet() throws Exception { + Pet pet = createRandomPet(); + pet.setName("programmer"); + + api.updatePet(pet); + + Pet fetched = api.getPetById(pet.getId()); + assertNotNull(fetched); + assertEquals(pet.getId(), fetched.getId()); + assertNotNull(fetched.getCategory()); + assertEquals(fetched.getCategory().getName(), pet.getCategory().getName()); + } + + @Test + public void testFindPetsByStatus() throws Exception { + Pet pet = createRandomPet(); + pet.setName("programmer"); + pet.setStatus(Pet.StatusEnum.AVAILABLE); + + api.updatePet(pet); + + List pets = api.findPetsByStatus(Arrays.asList(new String[]{"available"})); + assertNotNull(pets); + + boolean found = false; + for (Pet fetched : pets) { + if (fetched.getId().equals(pet.getId())) { + found = true; + break; + } + } + + assertTrue(found); + } + + @Test + public void testFindPetsByTags() throws Exception { + Pet pet = createRandomPet(); + pet.setName("monster"); + pet.setStatus(Pet.StatusEnum.AVAILABLE); + + List tags = new ArrayList(); + Tag tag1 = new Tag(); + tag1.setName("friendly"); + tags.add(tag1); + pet.setTags(tags); + + api.updatePet(pet); + + List pets = api.findPetsByTags(Arrays.asList(new String[]{"friendly"})); + assertNotNull(pets); + + boolean found = false; + for (Pet fetched : pets) { + if (fetched.getId().equals(pet.getId())) { + found = true; + break; + } + } + assertTrue(found); + } + + @Test + public void testUpdatePetWithForm() throws Exception { + Pet pet = createRandomPet(); + pet.setName("frank"); + api.addPet(pet); + + Pet fetched = api.getPetById(pet.getId()); + + api.updatePetWithForm(fetched.getId(), "furt", null); + Pet updated = api.getPetById(fetched.getId()); + + assertEquals(updated.getName(), "furt"); + } + + @Test + public void testDeletePet() throws Exception { + Pet pet = createRandomPet(); + api.addPet(pet); + + Pet fetched = api.getPetById(pet.getId()); + api.deletePet(fetched.getId(), null); + + try { + fetched = api.getPetById(fetched.getId()); + fail("expected an error"); + } catch (Exception e) { +// assertEquals(404, e.getCode()); + } + } + + @Test + public void testUploadFile() throws Exception { + Pet pet = createRandomPet(); + api.addPet(pet); + + File file = new File("hello.txt"); + BufferedWriter writer = new BufferedWriter(new FileWriter(file)); + writer.write("Hello world!"); + writer.close(); + + api.uploadFile(pet.getId(), "a test file", new File(file.getAbsolutePath())); + } + + @Test + public void testEqualsAndHashCode() { + Pet pet1 = new Pet(); + Pet pet2 = new Pet(); + assertTrue(pet1.equals(pet2)); + assertTrue(pet2.equals(pet1)); + assertTrue(pet1.hashCode() == pet2.hashCode()); + assertTrue(pet1.equals(pet1)); + assertTrue(pet1.hashCode() == pet1.hashCode()); + + pet2.setName("really-happy"); + pet2.setPhotoUrls(Arrays.asList(new String[]{"http://foo.bar.com/1", "http://foo.bar.com/2"})); + assertFalse(pet1.equals(pet2)); + assertFalse(pet2.equals(pet1)); + assertFalse(pet1.hashCode() == (pet2.hashCode())); + assertTrue(pet2.equals(pet2)); + assertTrue(pet2.hashCode() == pet2.hashCode()); + + pet1.setName("really-happy"); + pet1.setPhotoUrls(Arrays.asList(new String[]{"http://foo.bar.com/1", "http://foo.bar.com/2"})); + assertTrue(pet1.equals(pet2)); + assertTrue(pet2.equals(pet1)); + assertTrue(pet1.hashCode() == pet2.hashCode()); + assertTrue(pet1.equals(pet1)); + assertTrue(pet1.hashCode() == pet1.hashCode()); + } + + private Pet createRandomPet() { + Pet pet = new Pet(); + pet.setId(System.currentTimeMillis()); + pet.setName("gorilla"); + + Category category = new Category(); + category.setName("really-happy"); + + pet.setCategory(category); + pet.setStatus(Pet.StatusEnum.AVAILABLE); + List photos = Arrays.asList(new String[]{"http://foo.bar.com/1", "http://foo.bar.com/2"}); + pet.setPhotoUrls(photos); + + return pet; + } +} \ No newline at end of file diff --git a/samples/client/petstore/java/feign/src/test/java/io/swagger/petstore/test/StoreApiTest.java b/samples/client/petstore/java/feign/src/test/java/io/swagger/petstore/test/StoreApiTest.java new file mode 100644 index 00000000000..b91c391e991 --- /dev/null +++ b/samples/client/petstore/java/feign/src/test/java/io/swagger/petstore/test/StoreApiTest.java @@ -0,0 +1,64 @@ +package io.swagger.petstore.test; + +import io.swagger.client.*; +import io.swagger.client.api.*; +import io.swagger.client.model.*; + +import java.util.Map; + +import org.junit.*; +import static org.junit.Assert.*; + +public class StoreApiTest { + ApiClient apiClient; + StoreApi api; + + @Before + public void setup() { + apiClient = new ApiClient(); + api = apiClient.buildClient(StoreApi.class); + } + + @Test + public void testGetInventory() throws Exception { + Map inventory = api.getInventory(); + assertTrue(inventory.keySet().size() > 0); + } + + @Test + public void testPlaceOrder() throws Exception { + Order order = createOrder(); + api.placeOrder(order); + + Order fetched = api.getOrderById(order.getId()); + assertEquals(order.getId(), fetched.getId()); + assertEquals(order.getPetId(), fetched.getPetId()); + assertEquals(order.getQuantity(), fetched.getQuantity()); + } + + @Test + public void testDeleteOrder() throws Exception { + Order order = createOrder(); + api.placeOrder(order); + + Order fetched = api.getOrderById(order.getId()); + assertEquals(fetched.getId(), order.getId()); + + api.deleteOrder(String.valueOf(order.getId())); + + api.getOrderById(order.getId()); +// fail("expected an error"); + } + + private Order createOrder() { + Order order = new Order(); + order.setId(new Long(System.currentTimeMillis())); + order.setPetId(new Long(200)); + order.setQuantity(new Integer(13)); + order.setShipDate(new java.util.Date()); + order.setStatus(Order.StatusEnum.PLACED); + order.setComplete(true); + + return order; + } +} \ No newline at end of file diff --git a/samples/client/petstore/java/feign/src/test/java/io/swagger/petstore/test/UserApiTest.java b/samples/client/petstore/java/feign/src/test/java/io/swagger/petstore/test/UserApiTest.java new file mode 100644 index 00000000000..dc2d3ac17ca --- /dev/null +++ b/samples/client/petstore/java/feign/src/test/java/io/swagger/petstore/test/UserApiTest.java @@ -0,0 +1,85 @@ +package io.swagger.petstore.test; + +import io.swagger.client.ApiClient; +import io.swagger.client.api.*; +import io.swagger.client.model.*; + +import java.util.Arrays; + +import org.junit.*; +import static org.junit.Assert.*; + +public class UserApiTest { + ApiClient apiClient; + UserApi api; + + @Before + public void setup() { + apiClient = new ApiClient(); + api = apiClient.buildClient(UserApi.class); + } + + @Test + public void testCreateUser() throws Exception { + User user = createUser(); + + api.createUser(user); + + User fetched = api.getUserByName(user.getUsername()); + assertEquals(user.getId(), fetched.getId()); + } + + @Test + public void testCreateUsersWithArray() throws Exception { + User user1 = createUser(); + user1.setUsername("abc123"); + User user2 = createUser(); + user2.setUsername("123abc"); + + api.createUsersWithArrayInput(Arrays.asList(new User[]{user1, user2})); + + User fetched = api.getUserByName(user1.getUsername()); + assertEquals(user1.getId(), fetched.getId()); + } + + @Test + public void testCreateUsersWithList() throws Exception { + User user1 = createUser(); + user1.setUsername("abc123"); + User user2 = createUser(); + user2.setUsername("123abc"); + + api.createUsersWithListInput(Arrays.asList(new User[]{user1, user2})); + + User fetched = api.getUserByName(user1.getUsername()); + assertEquals(user1.getId(), fetched.getId()); + } + + @Test + public void testLoginUser() throws Exception { + User user = createUser(); + api.createUser(user); + + String token = api.loginUser(user.getUsername(), user.getPassword()); + assertTrue(token.startsWith("logged in user session:")); + } + + @Test + public void logoutUser() throws Exception { + api.logoutUser(); + } + + private User createUser() { + User user = new User(); + user.setId(System.currentTimeMillis()); + user.setUsername("fred" + user.getId()); + user.setFirstName("Fred"); + user.setLastName("Meyer"); + user.setEmail("fred@fredmeyer.com"); + user.setPassword("xxXXxx"); + user.setPhone("408-867-5309"); + user.setUserStatus(123); + + return user; + } +} \ No newline at end of file